Share via


ITransaction Interface

Definition

A sequence of operations performed as a single logical unit of work.

public interface ITransaction : IDisposable
type ITransaction = interface
    interface IDisposable
Public Interface ITransaction
Implements IDisposable
Implements

Remarks

A transaction must exhibit the following ACID properties. (see: https://technet.microsoft.com/en-us/library/ms190612)

  • Atomicity - A transaction must be an atomic unit of work; either all of its data modifications are performed, or none of them is performed.
  • Consistency - When completed, a transaction must leave all data in a consistent state. All internal data structures must be correct at the end of the transaction.
  • Isolation - Modifications made by concurrent transactions must be isolated from the modifications made by any other concurrent transactions. The isolation level used for an operation within an ITransaction is determined by the IReliableState performing the operation.
  • Durability - After a transaction has completed, its effects are permanently in place in the system. The modifications persist even in the event of a system failure.

Any instance member of this type is not guaranteed to be thread safe. This makes transactions the unit of concurrency: Users can have multiple transactions in-flight at any given point of time, but for a given transaction each API must be called one at a time. All IReliableCollection{T} APIs that accept a transaction and return a Task must be awaited one at a time.

Following is an example of a correct usage.


while (true)
{
    cancellationToken.ThrowIfCancellationRequested();

    try
    {
        using (var tx = this.StateManager.CreateTransaction())
        {
            await concurrentQueue.EnqueueAsync(tx, 12L, cancellationToken);
            await tx.CommitAsync();

            return;
        }
    }
    catch (TransactionFaultedException e)
    {
        // This indicates that the transaction was internally faulted by the system. One possible cause for this is that the transaction was long running
        // and blocked a checkpoint. Increasing the "ReliableStateManagerReplicatorSettings.CheckpointThresholdInMB" will help reduce the chances of running into this exception
        Console.WriteLine("Transaction was internally faulted, retrying the transaction: " + e);
    }
    catch (FabricNotPrimaryException e)
    {
        // Gracefully exit RunAsync as the new primary should have RunAsync invoked on it and continue work.
        // If instead enqueue was being executed as part of a client request, the client would be signaled to re-resolve.
        Console.WriteLine("Replica is not primary, exiting RunAsync: " + e);
        return;
    }
    catch (FabricNotReadableException e)
    {
        // Retry until the queue is readable or a different exception is thrown.
        Console.WriteLine("Queue is not readable, retrying the transaction: " + e);
    }
    catch (FabricObjectClosedException e)
    {
        // Gracefully exit RunAsync as this is happening due to replica close.
        // If instead enqueue was being executed as part of a client request, the client would be signaled to re-resolve.
        Console.WriteLine("Replica is closing, exiting RunAsync: " + e);
        return;
    }
    catch (TimeoutException e)
    {
        Console.WriteLine("Encountered TimeoutException during EnqueueAsync, retrying the transaction: " + e);
    }

    // Delay and retry.
    await Task.Delay(TimeSpan.FromMilliseconds(100), cancellationToken);
}

The following is an example of incorrect usage that has undefined behavior.

using (var txn = this.StateManager.CreateTransaction())
{
    List<Task> taskList = new List<Task>();
    taskList.Add(concurrentQueue.DequeueAsync(txn, cancellationToken));
    taskList.Add(concurrentQueue.DequeueAsync(txn, cancellationToken));

    await Task.WhenAll(taskList);
    await txn.CommitAsync();
}

Properties

CommitSequenceNumber

Sequence number for the commit operation.

TransactionId

Gets a value identifying the transaction.

Methods

Abort()

Abort (rolls back) the transaction.

CommitAsync()

Commit the transaction.

GetVisibilitySequenceNumberAsync()

Gets the visibility sequence number.

Applies to