FdbTransaction

Namespace: FoundationDB.Client · class

Implements: IFdbTransaction, IFdbReadOnlyTransaction, IDisposable, IFdbTransactionOptions

FoundationDB transaction handle.

Remarks

An instance of this class can be used to read from and/or write to a snapshot of a FoundationDB database.

Properties

Cancellation

CancellationToken Cancellation { get; }

Cancellation Token linked to the lifetime of the transaction

Will be triggered if the transaction is aborted or disposed

Context

FdbOperationContext Context { get; }

Context of this transaction.

Database

FdbDatabase Database { get; }

Database instance that manages this transaction

Id

int Id { get; }

Local id of the transaction

This id is only guaranteed unique inside the current AppDomain or process and is reset on every restart. It should only be used for diagnostics and/or logging.

IsReadOnly

bool IsReadOnly { get; }

Returns true if this transaction instance only allows read operations

Attempting to call a write method on a read-only transaction will immediately throw an exception

IsSnapshot

bool IsSnapshot { get; }

If true, the transaction is operating in Snapshot mode

Log

FdbTransactionLog Log { get; }

Log of all operations performed on this transaction (if logging was enabled on the database or transaction)

MaxRetryDelay

int MaxRetryDelay { get; set; }

Maximum amount of back-off delay incurred in the call to onError if the error is retry-able. Defaults to 1000 ms. Valid parameter values are [0, int.MaxValue]. If the maximum retry delay is less than the current retry delay of the transaction, then the current retry delay will be clamped to the maximum retry delay.

Options

IFdbTransactionOptions Options { get; }

Helper that can set options for this transaction

RetryLimit

int RetryLimit { get; set; }

Maximum number of retries after which additional calls to onError will throw the most recently seen error code. Valid parameter values are [-1, int.MaxValue]. If set to -1, will disable the retry limit.

Size

long Size { get; }

Estimated payload size of the transaction (in bytes)

This is not guaranteed to be accurate, and should only be used as a hint.

Snapshot

IFdbReadOnlyTransaction Snapshot { get; }

Returns a version of this transaction that performs snapshot read operations

Tenant

FdbTenant Tenant { get; }

Tenant where this transaction will be executed

Timeout

int Timeout { get; set; }

Timeout in milliseconds which, when elapsed, will cause the transaction automatically to be cancelled. Valid parameter values are [0, int.MaxValue]. If set to 0, will disable all timeouts. All pending and any future uses of the transaction will throw an exception. The transaction can be used again after it is reset.

Tracing

FdbTracingOptions Tracing { get; set; }

Tracing options for this transaction.

Methods

AddConflictRange

void AddConflictRange(ReadOnlySpan<byte> beginKeyInclusive, ReadOnlySpan<byte> endKeyExclusive, FdbConflictRangeType type)

Adds a conflict range to a transaction without performing the associated read or write.

  • beginKeyInclusive — Key specifying the beginning of the conflict range. The key is included
  • endKeyExclusive — Key specifying the end of the conflict range. The key is excluded
  • type — One of the FdbConflictRangeType values indicating what type of conflict range is being set.

Annotate

void Annotate(string comment)

Add a comment to the transaction log

  • comment — Line of text that will be added to the log

This method does nothing if logging is disabled. To prevent unnecessary allocations, you may check first

tr.Annonate("Reticulating splines");

void Annotate(ref InvariantInterpolatedStringHandler comment)

Add a comment to the transaction log

  • comment — Line of text that will be added to the log

This method does nothing if logging is disabled. To prevent unnecessary allocations, you may check first

tr.Annonate($"Reticulated {splines.Count:N0} splines");

Atomic

void Atomic(ReadOnlySpan<byte> key, ReadOnlySpan<byte> param, FdbMutationType mutation)

Performs an atomic operation that will mutate a key in the database

  • key — Name of the key to be mutated in the database.
  • param — Parameter with which the atomic operation will mutate the value associated with key.
  • mutation — Type of mutation that should be performed on the key

Modifies the database snapshot represented by this transaction to perform the operation indicated by mutation with operand param to the value stored by the given key.

Cancel

void Cancel()

Cancels the transaction. All pending or future uses of the transaction will return a TransactionCancelled error code. The transaction can be used again after it is reset.

CheckValueAsync

Task<(FdbValueCheckResult, Slice)> CheckValueAsync(ReadOnlySpan<byte> key, Slice expected)

Check if the value from the database snapshot represented by the current transaction is equal to some expected value.

  • key — Key to be looked up in the database
  • expected — Expected value for this key

Returns: Task that will return the value of the key if it is found, Slice.Nil if the key does not exist, or an exception

Clear

void Clear(ReadOnlySpan<byte> key)

Removes a key from the database.

  • key — Name of the key to be removed from the database.

Modifies the database snapshot represented by this transaction to remove the given key from the database.

If the key was not previously present in the database, there is no effect.

ClearRange

void ClearRange(ReadOnlySpan<byte> beginKeyInclusive, ReadOnlySpan<byte> endKeyExclusive)

Removes a range of keys from the database.

  • beginKeyInclusive — Name of the key specifying the beginning of the range to clear.
  • endKeyExclusive — Name of the key specifying the end of the range to clear.

Modifies the database snapshot represented by this transaction to remove all keys (if any) which are lexicographically greater than or equal to the given begin key and lexicographically less than the given end_key.

Sets and clears affect the actual database only if transaction is later committed with CommitAsync().

CommitAsync

Task CommitAsync()

Commits any changes performed by this transaction to the database.

Returns: Task that succeeds if the transaction was committed successfully, or fails if the transaction failed to commit.

Attempts to commit the sets and clears previously applied to the database snapshot represented by this transaction to the actual database.

The commit may or may not succeed – in particular, if a conflicting transaction previously committed, then the commit must fail in order to preserve transactional isolation.

If the commit does succeed, the transaction is durably committed to the database and all subsequently started transactions will observe its effects.

As with other client/server databases, in some failure scenarios a client may be unable to determine whether a transaction succeeded. In these cases, CommitAsync will throw CommitUnknownResult error. The OnErrorAsync function treats this error as retryable, so retry loops that don't check for CommitUnknownResult could execute the transaction twice. In these cases, you must consider the idempotence of the transaction.

CreateUniqueVersionStamp

VersionStamp CreateUniqueVersionStamp()

Returns a place-holder 96-bit VersionStamp with a unique user version per transaction.

Use this method, instead of if you intend to add multiple stamped keys to the same subspace, inside the same transaction!

CreateVersionStamp

VersionStamp CreateVersionStamp()

Returns a place-holder 80-bit VersionStamp, whose value is not yet known, but will be filled by the database at commit time.

Returns: This value can be used to generate temporary keys or value, for use with the VersionStampedKey or VersionStampedValue mutations

The generate placeholder will use a random value that is unique per transaction (and changes at each retry).

If you need to generate multiple different stamps per transaction (ex: adding multiple items to the same subspace), either call CreateVersionStamp or CreateUniqueVersionStamp!

If the key contains the exact 80-bit byte signature of this token, the corresponding location will be tagged and replaced with the actual VersionStamp at commit time.

If another part of the key contains (by random chance) the same exact byte sequence, then an error will be triggered, and hopefully the transaction will retry with another byte sequence.

VersionStamp CreateVersionStamp(int userVersion)

Returns a place-holder 96-bit VersionStamp with an attached user version, whose value is not yet known, but will be filled by the database at commit time.

Returns: This value can be used to generate temporary keys or value, for use with the VersionStampedKey or VersionStampedValue mutations

The generate placeholder will use a random value that is unique per transaction (and changes at reach retry).

If the key contains the exact 80-bit byte signature of this token, the corresponding location will be tagged and replaced with the actual VersionStamp at commit time.

If another part of the key contains (by random chance) the same exact byte sequence, then an error will be triggered, and hopefully the transaction will retry with another byte sequence.

Dispose

void Dispose()

Destroy the transaction and release all allocated resources, including all non-committed changes.

This instance will not be usable again and most methods will throw an ObjectDisposedException.

EnsureCanRead

void EnsureCanRead()

Throws if the transaction is not in a valid state (for reading/writing) and that we can proceed with a read operation

EnsureCanRetry

void EnsureCanRetry()

Throws if the transaction is not safely retryable

EnsureCanWrite

void EnsureCanWrite()

Throws if the transaction is not in a valid state (for writing) and that we can proceed with a write operation

EnsureNotFailedOrDisposed

void EnsureNotFailedOrDisposed()

Throws if the transaction is not in a valid state (for reading/writing)

GetAddressesForKeyAsync

Task<string[]> GetAddressesForKeyAsync(ReadOnlySpan<byte> key)

Returns a list of public network addresses as strings, one for each of the storage servers responsible for storing key and its associated value

  • key — Name of the key whose location is to be queried.

Returns: Task that will return an array of strings, or an exception

Depending on the API level or whether database option is set, the returned string may or may not include the port numbers

GetApproximateSizeAsync

Task<long> GetApproximateSizeAsync()

Returns the approximate size of the mutation list that this transaction will send to the server.

GetAsync

Task<Slice> GetAsync(ReadOnlySpan<byte> key)

Reads a value from the database snapshot represented by the current transaction.

  • key — Key to be looked up in the database

Returns: Task that will return the value of the key if it is found, Slice.Nil if the key does not exist, or an exception

Task<TResult> GetAsync<TResult>(ReadOnlySpan<byte> key, FdbValueDecoder<TResult> valueDecoder)

Reads a value from the database snapshot represented by the current transaction.

  • key — Key to be looked up in the database
  • valueDecoder — Decoder that will extract the result from the value found in the database

Returns: Task that will return the value of the key if it is found, Slice.Nil if the key does not exist, or an exception

Task<TResult> GetAsync<TState, TResult>(ReadOnlySpan<byte> key, TState valueState, FdbValueDecoder<TState, TResult> valueDecoder)

Reads a value from the database snapshot represented by the current transaction.

  • key — Key to be looked up in the database
  • valueState — State that will be forwarded to the valueDecoder
  • valueDecoder — Decoder that will extract the result from the value found in the database

Returns: Task that will return the value of the key if it is found, Slice.Nil if the key does not exist, or an exception

GetCommittedVersion

long GetCommittedVersion()

Retrieves the database version number at which a given transaction was committed.

Returns: Version of the database after a successful commit, or -1 if no commit has been performed yet, or if it was unsuccessful.

CommitAsync must have been called on this transaction and the resulting task must have completed successfully before this function is called, or the behavior is undefined.

Read-only transactions do not modify the database when committed and will have a committed version of -1.

Keep in mind that a transaction which reads keys and then sets them to their current values may be optimized to a read-only transaction.

GetEstimatedRangeSizeBytesAsync

Task<long> GetEstimatedRangeSizeBytesAsync(ReadOnlySpan<byte> beginKey, ReadOnlySpan<byte> endKey)

Returns an estimated byte size of the key range.

  • beginKey — Name of the key of the start of the range
  • endKey — Name of the key of the end of the range

Returns: Task that will return an estimated byte size of the key range, or an exception

The estimated size is calculated based on the sampling done by FDB server. The sampling algorithm works roughly in this way: the larger the key-value pair is, the more likely it would be sampled and the more accurate its sampled size would be. And due to that reason it is recommended to use this API to query against large ranges for accuracy considerations. For a rough reference, if the returned size is larger than 3MB, one can consider the size to be accurate.

GetKeyAsync

Task<Slice> GetKeyAsync(KeySelector selector)

Resolves a key selector against the keys in the database snapshot represented by the current transaction.

  • selector — Key selector to resolve

Returns: Task that will return the key matching the selector, or an exception

Task<Slice> GetKeyAsync(KeySpanSelector selector)

Resolves a key selector against the keys in the database snapshot represented by the current transaction.

  • selector — Key selector to resolve

Returns: Task that will return the key matching the selector, or an exception

GetKeysAsync

Task<Slice[]> GetKeysAsync(ReadOnlySpan<KeySelector> selectors)

Resolves several key selectors against the keys in the database snapshot represented by the current transaction.

  • selectors — Key selectors to resolve

Returns: Task that will return an array of keys matching the selectors, or an exception

GetMetadataVersionKeyAsync

Task<VersionStamp?> GetMetadataVersionKeyAsync(Slice key = null)

Safely read a key containing a VersionStamp representing the version of some metadata or schema information stored in the database.

  • key — Key to read. If Nil, read the global \xff/metadataVersion key

Either the current value of the key, or if the key has already changed in this transaction

GetRange

IFdbKeyValueRangeQuery GetRange(KeySelector beginInclusive, KeySelector endExclusive, FdbRangeOptions options = null)

Creates a new range query that will read all key-value pairs in the database snapshot represented by the transaction

  • beginInclusive — key selector defining the beginning of the range
  • endExclusive — key selector defining the end of the range
  • options — Optional query options (Limit, TargetBytes, Mode, Reverse, ...)

Returns: Range query that, once executed, will return all the key-value pairs matching the providing selector pair

IFdbRangeQuery<TResult> GetRange<TResult>(KeySelector beginInclusive, KeySelector endExclusive, Func<KeyValuePair<Slice, Slice>, TResult> selector, FdbRangeOptions options = null)

Creates a new range query that will read all key-value pairs in the database snapshot represented by the transaction, and transform them into a result of type TResult

  • beginInclusive — key selector defining the beginning of the range
  • endExclusive — key selector defining the end of the range
  • selector — Selector used to convert each key-value pair into an element of type TResult
  • options — Optional query options (Limit, TargetBytes, Mode, Reverse, ...)

Returns: Range query that, once executed, will return all the key-value pairs matching the providing selector pair

IFdbRangeQuery<TResult> GetRange<TState, TResult>(KeySelector beginInclusive, KeySelector endExclusive, TState state, FdbKeyValueDecoder<TState, TResult> decoder, FdbRangeOptions options = null)

Creates a new range query that will read all key-value pairs in the database snapshot represented by the transaction, and transform them into a result of type TResult

  • beginInclusive — key selector defining the beginning of the range
  • endExclusive — key selector defining the end of the range
  • state — State that will be forwarded to the selector
  • options — Optional query options (Limit, TargetBytes, Mode, Reverse, ...)

Returns: Range query that, once executed, will return all the key-value pairs matching the providing selector pair

GetRangeAsync

Task<FdbRangeChunk> GetRangeAsync(KeySelector beginInclusive, KeySelector endExclusive, FdbRangeOptions options, int iteration)

Reads all key-value pairs in the database snapshot represented by transaction (potentially limited by Limit, TargetBytes, or Mode) which have a key lexicographically greater than or equal to the key resolved by the beginning key selector and lexicographically less than the key resolved by the end key selector.

  • beginInclusive — key selector defining the beginning of the range
  • endExclusive — key selector defining the end of the range
  • options — Optional query options (Limit, TargetBytes, Mode, Reverse, ...)
  • iteration — If streaming mode is Iterator, this parameter should start at 1 and be incremented by 1 for each successive call while reading this range. In all other cases it is ignored.

Returns: Chunk of results

Task<FdbRangeChunk> GetRangeAsync(KeySpanSelector beginInclusive, KeySpanSelector endExclusive, FdbRangeOptions options, int iteration)

Reads all key-value pairs in the database snapshot represented by transaction (potentially limited by Limit, TargetBytes, or Mode) which have a key lexicographically greater than or equal to the key resolved by the beginning key selector and lexicographically less than the key resolved by the end key selector.

  • beginInclusive — key selector defining the beginning of the range
  • endExclusive — key selector defining the end of the range
  • options — Optional query options (Limit, TargetBytes, Mode, Reverse, ...)
  • iteration — If streaming mode is Iterator, this parameter should start at 1 and be incremented by 1 for each successive call while reading this range. In all other cases it is ignored.

Returns: Chunk of results

Task<FdbRangeChunk<TResult>> GetRangeAsync<TState, TResult>(KeySelector beginInclusive, KeySelector endExclusive, TState state, FdbKeyValueDecoder<TState, TResult> decoder, FdbRangeOptions options, int iteration)

Reads all key-value pairs in the database snapshot represented by transaction (potentially limited by Limit, TargetBytes, or Mode) which have a key lexicographically greater than or equal to the key resolved by the beginning key selector and lexicographically less than the key resolved by the end key selector.

  • beginInclusive — key selector defining the beginning of the range
  • endExclusive — key selector defining the end of the range
  • state — State that will be forwarded to the decoder
  • decoder — Decoder that will extract the result from the value found in the database
  • options — Optional query options (Limit, TargetBytes, Mode, Reverse, ...)
  • iteration — If streaming mode is Iterator, this parameter should start at 1 and be incremented by 1 for each successive call while reading this range. In all other cases it is ignored.

Returns: Chunk of results

Task<FdbRangeChunk<TResult>> GetRangeAsync<TState, TResult>(KeySpanSelector beginInclusive, KeySpanSelector endExclusive, TState state, FdbKeyValueDecoder<TState, TResult> decoder, FdbRangeOptions options, int iteration)

Reads all key-value pairs in the database snapshot represented by transaction (potentially limited by Limit, TargetBytes, or Mode) which have a key lexicographically greater than or equal to the key resolved by the beginning key selector and lexicographically less than the key resolved by the end key selector.

  • beginInclusive — key selector defining the beginning of the range
  • endExclusive — key selector defining the end of the range
  • state — State that will be forwarded to the decoder
  • decoder — Decoder that will extract the result from the value found in the database
  • options — Optional query options (Limit, TargetBytes, Mode, Reverse, ...)
  • iteration — If streaming mode is Iterator, this parameter should start at 1 and be incremented by 1 for each successive call while reading this range. In all other cases it is ignored.

Returns: Chunk of results

GetRangeSplitPointsAsync

Task<Slice[]> GetRangeSplitPointsAsync(ReadOnlySpan<byte> beginKey, ReadOnlySpan<byte> endKey, long chunkSize)

Returns a list of keys that can split the given range into (roughly) equally sized chunks based on chunkSize.

  • beginKey — Name of the key of the start of the range
  • endKey — Name of the key of the end of the range
  • chunkSize — Size of chunks that will be used to split the range

Returns: Task that will return an array of keys that split the range in equally sized chunks, or an exception

The returned split points contain the start key and end key of the given range

GetReadStatistics

(int, long) GetReadStatistics()

Returns the number of keys read byte this transaction, as well as their total size

GetReadVersionAsync

Task<long> GetReadVersionAsync()

Returns this transaction snapshot read version.

GetValuesAsync

Task<Slice[]> GetValuesAsync(ReadOnlySpan<Slice> keys)

Reads several values from the database snapshot represented by the current transaction

  • keys — Keys to be looked up in the database

Returns: Task that will return an array of values, or an exception. Each item in the array will contain the value of the key at the same index in keys, or Slice.Nil if that key does not exist.

Task GetValuesAsync<TResult>(ReadOnlySpan<Slice> keys, Memory<TResult> results, FdbValueDecoder<TResult> valueDecoder)

Reads several values from the database snapshot represented by the current transaction

  • keys — Keys to be looked up in the database
  • results — Buffer where the results will be written to (must be at least as large as keys). Each entry will contain the decoded value of the key at the same index in keys.
  • valueDecoder — Decoder that will extract the result from the value found in the database.

Returns: Task that will complete once all the keys have been read and values decoded.

Task GetValuesAsync<TValueState, TResult>(ReadOnlySpan<Slice> keys, Memory<TResult> results, TValueState valueState, FdbValueDecoder<TValueState, TResult> valueDecoder)

Reads several values from the database snapshot represented by the current transaction

  • keys — Keys to be looked up in the database
  • results — Buffer where the results will be written to (must be at least as large as keys). Each entry will contain the decoded value of the key at the same index in keys.
  • valueState — State that will be forwarded to the valueDecoder
  • valueDecoder — Decoder that will extract the result from the value found in the database.

Returns: Task that will complete once all the keys have been read and values decoded.

GetVersionStampAsync

Task<VersionStamp> GetVersionStampAsync()

Returns the VersionStamp which was used by VersionStamped operations in this transaction.

The Task will be ready only after the successful completion of a call to CommitAsync on this transaction.

Read-only transactions do not modify the database when committed and will result in the Task completing with an error.

Keep in mind that a transaction which reads keys and then sets them to their current values may be optimized to a read-only transaction.

GetWriteStatistics

(int, long) GetWriteStatistics()

Returns the number of keys changed by this transaction, as well as the estimated payload size

The counters are reset everytime the transaction is recycled (either via on )

IsLogged

bool IsLogged()

Return true if logging is enabled on this transaction

If logging is enabled, the transaction will track all the operations performed by this transaction until it completes. The log can be accessed via the property. Comments can be added via the method.

OnErrorAsync

Task OnErrorAsync(FdbError code)

Implements the recommended retry and back-off behavior for a transaction. This function knows which of the error codes generated by other query functions represent temporary error conditions and which represent application errors that should be handled by the application. It also implements an exponential back-off strategy to avoid swamping the database cluster with excessive retries when there is a high level of conflict between transactions.

  • code — FdbError code thrown by the previous command

Returns: Returns a task that completes if the operation can be safely retried, or that rethrows the original exception if the operation is not retry-able.

Reset

void Reset()

Reset transaction to its initial state.

This is similar to disposing the transaction and recreating a new one. The only state that persists through a transaction reset is that which is related to the back-off logic used by OnErrorAsync()

Set

void Set(ReadOnlySpan<byte> key, ReadOnlySpan<byte> value)

Sets the value of a key in the database.

  • key — Name of the key to be inserted into the database.
  • value — Value to be inserted into the database.

Modifies the database snapshot represented by transaction to change the given key to have the given value.

If the given key was not previously present in the database it is inserted.

The modification affects the actual database only if transaction is later committed with CommitAsync().

SetOption

IFdbTransactionOptions SetOption(FdbTransactionOption option)

Sets an option on this transaction that does not take any parameter

  • option — Option to set

IFdbTransactionOptions SetOption(FdbTransactionOption option, ReadOnlySpan<char> value)

Sets an option on this transaction that takes a string value

  • option — Option to set
  • value — Value of the parameter (can be null)

IFdbTransactionOptions SetOption(FdbTransactionOption option, ReadOnlySpan<byte> value)

Sets an option on this transaction that takes a byte array value

  • option — Option to set
  • value — Value of the parameter (can be null)

IFdbTransactionOptions SetOption(FdbTransactionOption option, long value)

Sets an option on this transaction that takes an integer value

  • option — Option to set
  • value — Value of the parameter

SetReadVersion

void SetReadVersion(long version)

Sets the snapshot read version used by a transaction. This is not needed in simple cases.

  • version — Read version to use in this transaction

If the given version is too old, subsequent reads will fail with error_code_past_version; if it is too new, subsequent reads may be delayed indefinitely and/or fail with error_code_future_version. If any of Get*() methods have been called on this transaction already, the result is undefined.

StopLogging

void StopLogging()

If logging was previously enabled on this transaction, clear the log and stop logging any new operations

Any log handler attached to this transaction will not be called

TouchMetadataVersionKey

void TouchMetadataVersionKey(Slice key = null)

Bumps the value of a metadata key of the database snapshot represented by the current transaction.

  • key — Key to mutate. If Nil, mutate the global \xff/metadataVersion key

The value of the key will be updated to a value higher than any previous value, once the transaction commits.

Until this happens, any additional call to GetMetadataVersionKeyAsync will return null.

If the value of the key is read via a regular GetAsync or GetRange call, the transaction will fail to commit!

This method requires API version 610 or greater.

VisitRangeAsync

Task<long> VisitRangeAsync<TState>(KeySelector beginInclusive, KeySelector endExclusive, TState state, FdbKeyValueAction<TState> visitor, FdbRangeOptions options = null)

Visits all key-value pairs in the database snapshot represent by the transaction

  • beginInclusive — key selector defining the beginning of the range
  • endExclusive — key selector defining the end of the range
  • state — State that will be forwarded to the visitor
  • visitor — Lambda called for each key-value pair, in order.
  • options — Optional query options (Limit, TargetBytes, Mode, Reverse, ...)

Returns: Number of key/value pairs visited

Watch

FdbWatch Watch(ReadOnlySpan<byte> key, CancellationToken ct)

Watches a key for any future change in the database.

  • key — Name of the key that will be watched
  • ct — Token used to abort the watch if the caller doesn't want to wait anymore.

Returns: FdbWatch instance that can be awaited and will complete when the key has changed in the database, or cancellation occurs.

The watch will only become active if the transaction successfully commits, and should NOT be awaited from within the same or another transaction.

You can directly await an FdbWatch, or use the Task property.

You can call Cancel> at any time if you are not interested in watching the key anymore.

You MUST always call Dispose if the watch completes or is cancelled, to ensure that resources are released properly.

It is possible (though rare) that a Watch fires even if the key did not change.