// Licensed to the Apache Software Foundation (ASF) under one or more
// contributor license agreements.  See the NOTICE file distributed with
// this work for additional information regarding copyright ownership.
// The ASF licenses this file to You under the Apache License, Version 2.0
// (the "License"); you may not use this file except in compliance with
// the License.  You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
= Performing Transactions

All queries in Ignite 3 are transactional. You can provide an explicit transaction as a first argument of any Table and SQL API call. If you do not provide an explicit transaction, an implicit one will be created for every call.

== Transaction Lifecycle

When the transaction is created, the node that the transaction was started from is chosen as *transaction coordinator*. The coordinator finds the required link:administrators-guide/data-partitions[partitions] and sends the read or write requests to the nodes holding primary partitions. For correct transaction operation, all nodes in cluster must have similar time, that can be different by no more than `schemaSync.maxClockSkewMillis`.

If the key is not locked by a different transaction, the node gets the locks on the involved keys, and attempts to apply the changes in the transaction. When the operation finishes, the lock is removed. This way, several transactions can work on the same partition, while changing separate keys. Additionally, some operations may perform *short-term* locks on the keys in advance, to ensure operations proceed correctly.

If the node with primary replica of the partition involved in the transaction fail, the transaction is eventually automatically rolled back. Ignite will return `TransactionException` on commit attempt.

== Transaction Isolation and Concurrency

All read-write transactions in Ignite acquire locks during the first read or write access, and hold the lock until the transaction is committed or rolled back. All read-write transactions are `SERIALIZABLE`, so as long as the lock persists, no other transaction can make changes to locked data, however data can still be read by <<Read-Only Transactions>>.

=== Deadlock Prevention

Ignite 3 uses the `WAIT_DIE` deadlock prevention algorithm. When a newer transaction requests data that is already locked by a different transaction, it is cancelled and the transaction operation is retried with the same timestamp. If the transaction is older, it is not cancelled and is allowed to wait for the lock to be freed.

== Executing Transactions

Here is how you  can provide a transaction explicitly:

[tabs]
--
tab:Java[]
[source, java]
----
KeyValueView<Long, Account> accounts =
  table.keyValueView(Mapper.of(Long.class), Mapper.of(Account.class));

accounts.put(null, 42, new Account(16_000));

var tx = client.transactions().begin();

Account account = accounts.get(tx, 42);
account.balance += 500;
accounts.put(tx, 42, account);

assert accounts.get(tx, 42).balance == 16_500;

tx.rollback();

assert accounts.get(tx, 42).balance == 16_000;
----

tab:.NET[]
[source, csharp]
----
var accounts = table.GetKeyValueView<long, Account>();
await accounts.PutAsync(transaction: null, 42, new Account(16_000));

await using ITransaction tx = await client.Transactions.BeginAsync();

(Account account, bool hasValue) = await accounts.GetAsync(tx, 42);
account = account with { Balance = account.Balance + 500 };

await accounts.PutAsync(tx, 42, account);

Debug.Assert((await accounts.GetAsync(tx, 42)).Value.Balance == 16_500);

await tx.RollbackAsync();

Debug.Assert((await accounts.GetAsync(null, 42)).Value.Balance == 16_000);

public record Account(decimal Balance);
----

tab:C++[]
[source, cpp]
----
auto accounts = table.get_key_value_view<account, account>();

account init_value(42, 16'000);
accounts.put(nullptr, {42}, init_value);

auto tx = client.get_transactions().begin();

std::optional<account> res_account = accounts.get(&tx, {42});
res_account->balance += 500;
accounts.put(&tx, {42}, res_account);

assert(accounts.get(&tx, {42})->balance == 16'500);

tx.rollback();

assert(accounts.get(&tx, {42})->balance == 16'000);
----

--

//== Transaction Timeouts

//Normally, transactions will be executed regardless of how long it takes it to arrive. You can set the transaction timeout in the `TransactionOptions`, in milliseconds. For example:

//[source, java]
//----
//var tx = client.transactions().begin(new TransactionOptions().timeoutMillis(1000));
//int balance = accounts.get(tx, 42).balance;
//tx.commit();
//----

== Transaction Management

You can also manage transactions by using the `runInTransaction` class. When using it, the following will be done automatically:

- The transaction is started and substituted to the closure.
- The transaction is committed if no exceptions were thrown during the closure.
- The transaction will be retried in case of recoverable error. Closure must be purely functional - not causing side effects.

Here is the example of a transaction that transfers money from one account to another, and handles a possible overdraft:

[tabs]
--
tab:Java[]
[source,java]
----
igniteTransactions.runInTransaction(tx -> {
    CompletableFuture<Tuple> fut1 = view.getAsync(tx, Tuple.create().set("accountId", 1));
    CompletableFuture<Tuple> fut2 = view.getAsync(tx, Tuple.create().set("accountId", 2)); // Read second balance concurrently
    if (fut1.join().doubleValue("balance") - amount < 0) {
        tx.rollback();
        return;
    }

    view.upsert(tx, Tuple.create().set("accountId", 1).set("balance", fut1.join().doubleValue("balance") - amount));
    view.upsert(tx, Tuple.create().set("accountId", 2).set("balance", fut2.join().doubleValue("balance") + amount);
});
----
--

== Read-Only Transactions

When starting a transaction, you can configure the transaction as a *read-only* transaction. In these transactions, no data modification can be performed, but they also do not secure locks and can be performed on non-primary link:administrators-guide/data-partitions[partitions], further improving their performance. Read-only transactions always check the data for the moment they were started, even if new data was written to the database.

Here is how you can make a read-only transaction:

[source, java]
----
var tx = client.transactions().begin(new TransactionOptions().readOnly(true));
int balance = accounts.get(tx, 42).balance;
tx.commit();
----

NOTE: Read-only transactions read data at a specific time. If new data was written since, old data will still be stored in link:administrators-guide/data-partitions#version-storage[Version Storage] and will be available until low watermark. If low watermark is reached during the transaction, data will be kept available until it is over.
