本文次要钻研一下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