序
本文次要钻研一下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")@TxIgnorepublic 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")@TxIgnorepublic 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")@TxIgnorepublic 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
doc
- transaction