序
本文主要研究一下claudb的transaction command
TransactionState
claudb-1.7.1/src/main/java/com/github/tonivade/claudb/TransactionState.java
public class TransactionState implements Iterable<Request> {
private List<Request> requests = new LinkedList<>();
public void enqueue(Request request) {
requests.add(request);
}
public int size() {
return requests.size();
}
@Override
public Iterator<Request> iterator() {
return requests.iterator();
}
}
- TransactionState实现了Iterable<Request>接口,它定义了requests属性,提供了enqueue方法将request添加到requests中
MultiCommand
claudb-1.7.1/src/main/java/com/github/tonivade/claudb/command/transaction/MultiCommand.java
@Command("multi")
@TxIgnore
public class MultiCommand implements DBCommand {
private static final String TRASACTION_KEY = "tx";
@Override
public RedisToken execute(Database db, Request request) {
if (!isTxActive(request.getSession())) {
createTransaction(request.getSession());
return responseOk();
} else {
return error("ERR MULTI calls can not be nested");
}
}
private void createTransaction(Session session) {
session.putValue(TRASACTION_KEY, new TransactionState());
}
private boolean isTxActive(Session session) {
return session.getValue(TRASACTION_KEY).isPresent();
}
}
- MultiCommand实现了DBCommand接口,其execute方法先判断isTxActive,非active的话才createTransaction
ExecCommand
claudb-1.7.1/src/main/java/com/github/tonivade/claudb/command/transaction/ExecCommand.java
@Command("exec")
@TxIgnore
public class ExecCommand implements DBCommand {
@Override
public RedisToken execute(Database db, Request request) {
Option<TransactionState> transaction = getTransactionIfExists(request.getSession());
if (transaction.isPresent()) {
DBServerContext server = getClauDB(request.getServerContext());
List<RedisToken> responses = new ArrayList<>();
for (Request queuedRequest : transaction.get()) {
responses.add(executeCommand(server, queuedRequest));
}
return RedisToken.array(responses);
} else {
return RedisToken.error("ERR EXEC without MULTI");
}
}
private RedisToken executeCommand(DBServerContext server, Request queuedRequest) {
RespCommand command = server.getCommand(queuedRequest.getCommand());
return command.execute(queuedRequest);
}
private Option<TransactionState> getTransactionIfExists(Session session) {
return session.removeValue("tx");
}
}
- ExecCommand实现了DBCommand接口,其execute方法先通过getTransactionIfExists获取transaction,若transaction不存在则报错,存在的话则遍历transaction的queuedRequest,挨个执行executeCommand(server, queuedRequest)
DiscardCommand
claudb-1.7.1/src/main/java/com/github/tonivade/claudb/command/transaction/DiscardCommand.java
@Command("discard")
@TxIgnore
public class DiscardCommand implements DBCommand {
private static final String TX_KEY = "tx";
@Override
public RedisToken execute(Database db, Request request) {
removeTransactionIfExists(request.getSession());
return RedisToken.responseOk();
}
private Option<TransactionState> removeTransactionIfExists(Session session) {
return session.removeValue(TX_KEY);
}
}
- DiscardCommand实现了DBCommand接口,其execute方法执行removeTransactionIfExists(request.getSession())
小结
claudb transaction相关的command有MultiCommand、ExecCommand、DiscardCommand
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。