Transactions

Citeck implements transactions based on two-phase commit.

Entity descriptions:

  1. Transactional resource — a resource that supports transactional operations (e.g., a database);

  2. Transactional action — an action bound to the transaction lifecycle that is executed in one of three cases: before commit, after commit, or after transaction rollback;

  3. Transaction — an entity within which transactional resources and actions can be registered. If an error occurs during the transaction, it is rolled back and the system returns to the state before the transaction began;

  4. Transaction manager — a manager that controls transactions.

Transaction lifecycle:

../../_images/auth-ecos-proxy-app.drawio.png

General workflow:

../../_images/transaction-flow.drawio.png

How it works:

  1. The transaction starts.

  2. During execution, resources are worked with and registered in the transaction.

  3. Also during execution, actions arise that need to be performed before commit, after commit, or after transaction rollback.

  4. Before the commit, all transactional actions registered in the transaction are executed.

  5. Before the commit, the number of resources is checked. If there is only one resource, a single-phase commit is performed. If there are multiple resources, a prepare phase is executed followed by a commit of the prepared transaction.

  6. After the commit, all transactional actions registered in the transaction are executed.

  7. If something went wrong during the transaction, all resources are rolled back to their original state and the post-rollback actions that were registered during the transaction are executed.

Working with transactions in Kotlin code:

val result = TxnContext.doInTxn {
    "выполняем нужные действия и возвращаем результат"
}

Working with transactions in Java code:

String result = TxnContext.doInTxnJ(() -> {
    return "выполняем нужные действия и возвращаем результат";
});

These methods create a transaction if one does not exist, or use an existing one. If you need to forcibly execute an action in a new transaction, use the doInNewTxn and doInNewTxnJ methods respectively.

For the Records API, transactions are started automatically when a request arrives from outside the application.