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 includedendKeyExclusive— Key specifying the end of the conflict range. The key is excludedtype— 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 withkey.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 databaseexpected— 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 databasevalueDecoder— 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 databasevalueState— State that will be forwarded to thevalueDecodervalueDecoder— 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 rangeendKey— 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/metadataVersionkey
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 rangeendExclusive— key selector defining the end of the rangeoptions— 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 rangeendExclusive— key selector defining the end of the rangeselector— Selector used to convert each key-value pair into an element of typeTResultoptions— 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 rangeendExclusive— key selector defining the end of the rangestate— State that will be forwarded to theselectoroptions— 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 rangeendExclusive— key selector defining the end of the rangeoptions— 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 rangeendExclusive— key selector defining the end of the rangeoptions— 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 rangeendExclusive— key selector defining the end of the rangestate— State that will be forwarded to thedecoderdecoder— Decoder that will extract the result from the value found in the databaseoptions— 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 rangeendExclusive— key selector defining the end of the rangestate— State that will be forwarded to thedecoderdecoder— Decoder that will extract the result from the value found in the databaseoptions— 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 rangeendKey— Name of the key of the end of the rangechunkSize— 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 databaseresults— Buffer where the results will be written to (must be at least as large askeys). Each entry will contain the decoded value of the key at the same index inkeys.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 databaseresults— Buffer where the results will be written to (must be at least as large askeys). Each entry will contain the decoded value of the key at the same index inkeys.valueState— State that will be forwarded to thevalueDecodervalueDecoder— 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 setvalue— 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 setvalue— 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 setvalue— 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/metadataVersionkey
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 rangeendExclusive— key selector defining the end of the rangestate— State that will be forwarded to thevisitorvisitor— 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 watchedct— 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.