Class FDBRecordContext

  • All Implemented Interfaces:
    AutoCloseable

    @API(STABLE)
    public class FDBRecordContext
    extends FDBTransactionContext
    implements AutoCloseable
    An open transaction against FDB.

    All reads and writes to the database are transactional: an open FDBRecordContext is needed. An FDBDatabase is needed to open an FDBRecordContext.

    
     final FDBDatabase fdb = FDBDatabaseFactory.instance().getDatabase();
     try (FDBRecordContext ctx = fdb.openContext()) {
         ...
     }
     
    See Also:
    FDBRecordStore
    • Method Detail

      • getTransactionId

        @Nullable
        public String getTransactionId()
        Get the ID used by FoundationDB to track this transaction. This can be used as a correlation key to correlate requests with their transactions. If this returns null, then no ID has been set. This means that it is unsafe to call logTransaction() on this context if this method returns null.

        This ID is used by FoundationDB internally in a few different places, including the transaction sample, large transaction monitoring, and client trace logs if transaction logging is enabled for that transaction. If the caller already has a notion of "request ID", then one strategy might be to set the transaction's ID to the initiating request's ID so that one can correlate requests and transactions.

        The transaction ID is limited in size to 100 bytes when encoded as UTF-8. In general, most callers should limit IDs to printable ASCII characters (as those are the only characters that are easily readable in the client trace logs). If the provided ID exceeds 100 bytes, it will be truncated or possibly ignored if truncating the ID cannot be done safely.

        To set this ID, the user can call either FDBDatabase.openContext(Map, FDBStoreTimer, FDBDatabase.WeakReadSemantics, FDBTransactionPriority, String) and provided a non-null transaction ID as a parameter, or the user can call FDBDatabase.openContext(Map, FDBStoreTimer) or FDBDatabase.openContext(Map, FDBStoreTimer, FDBDatabase.WeakReadSemantics) and set the "uuid" key to the desired transaction ID in the MDC context. In either case, note that the transaction ID is limited in size to 100 bytes when encoded in UTF-8. In general, most callers should limit IDs to printable ASCII characters (as those are the only characters that are easily readable in the client trace logs). If the provided ID exceeds 100 bytes, it will be truncated or possibly ignored if truncating the ID cannot be done safely.

        Returns:
        the ID used by FoundationDB to track this transaction or null if not set
        See Also:
        logTransaction()
      • isLogged

        public boolean isLogged()
        Get whether the current transaction details are logged to the client trace logs. Essentially, this returns if the transaction has been traced or if the user has (successfully) called logTransaction(). See logTransaction() for more details.
        Returns:
        whether this transaction is logged to the client trace logs
        See Also:
        logTransaction()
      • getTrackOpenTimeNanos

        @API(INTERNAL)
        public long getTrackOpenTimeNanos()
        Get the nanosecond time at which this context was opened.
        Returns:
        time opened
      • isClosed

        public boolean isClosed()
      • commit

        public void commit()
        Commit an open transaction.
      • setReadVersion

        public long setReadVersion​(long readVersion)
        Set the read version used by this transaction. All reads to the database will include only changes that were committed at this version or smaller. A transaction's read version can only be set once, so if this function is called multiple times, it will return the previously set read version. If this method is called and another caller has already called getReadVersionAsync() or getReadVersion(), this method may throw a RecordCoreException indicating that there is already an outstanding read version request if that request has not yet completed.
        Parameters:
        readVersion - the read version this transaction should use if is not already set
        Returns:
        this transaction's read version
        See Also:
        ReadTransaction.setReadVersion(long)
      • getReadVersionAsync

        @Nonnull
        public CompletableFuture<Long> getReadVersionAsync()
        Get the read version used by this transaction. All reads to the database will include only changes that were committed at this version or smaller. If the read version has not already been set or gotten, this may require talking to the database. If the read version has already been set or gotten, then this will return with an already completed future.

        Note that this method is synchronized, but only creating the future (not waiting on the future) will block other threads. Thus, while it is advised that this method only be called once and by only one caller at a time, if it safe to use this method in asynchronous contexts. If this method is called multiple times, then the same future will be returned each time.

        Returns:
        a future that will contain the read version of this transaction
        See Also:
        ReadTransaction.getReadVersion()
      • getTransactionAge

        public long getTransactionAge()
        Get the number of milliseconds since context was created.
        Returns:
        the number of milliseconds since context was created
      • getTransactionCreateTime

        public long getTransactionCreateTime()
      • setDirtyStoreState

        @API(INTERNAL)
        public void setDirtyStoreState​(boolean dirtyStoreState)
      • hasDirtyStoreState

        @API(INTERNAL)
        public boolean hasDirtyStoreState()
        Return whether any record store opened with this context has had its cache-able store state modified. This is then used to avoid using the cached state when there have been modifications to the cached state within this transaction. Note that if multiple record stores are opened within a single transaction and one (but not all of them) updates its state, then the other record stores will also eschew the cache.

        This method is internal to the Record Layer and should not be used by external consumers.

        Returns:
        whether the record store's state has been modified in the course of this transaction
      • addCommitCheck

        public void addCommitCheck​(@Nonnull
                                   CompletableFuture<Void> check)
        Add a check to be completed before commit() finishes. commit() will wait for the future to be completed (exceptionally if the check fails) before committing the underlying transaction.

        It is possible for this method to throw an exception caused by an earlier unsuccessful check that has become ready in the meantime.

        Parameters:
        check - the check to be performed
      • getPostCommit

        @Nullable
        public FDBRecordContext.PostCommit getPostCommit​(@Nonnull
                                                         String name)
        Fetches a previously installed post-commit hook.
        Parameters:
        name - the name of the post-commit hook
        Returns:
        the post-commit hook, if it was previously installed or null if there is no hook by the provided name
      • addPostCommit

        public void addPostCommit​(@Nonnull
                                  String name,
                                  @Nonnull
                                  FDBRecordContext.PostCommit postCommit)
        Adds a new post-commit hook. This method should only be used in cases in which you will be installing the post-commit hook exactly once. That is, due to race conditions, you should not be doing:
             if (context.getPostCommit("myPostCommit")) {
                 context.addPostCommit("myPostCommit", () -> ..);
             }
         
        if you need this behavior use getOrCreatePostCommit(String, Function) instead.
        Parameters:
        name - name of the post-commit
        postCommit - the post commit to install
      • addPostCommit

        public void addPostCommit​(@Nonnull
                                  FDBRecordContext.PostCommit postCommit)
        Install an anonymous post-commit hook. A post-commit hook installed in this fashion cannot be retrieved via getPostCommit(String).
        Parameters:
        postCommit - post-commit hook to install
      • removePostCommit

        @Nullable
        public FDBRecordContext.PostCommit removePostCommit​(@Nonnull
                                                            String name)
        Remove a previously installed post-commit hook.
        Parameters:
        name - the name of the hook to remove
        Returns:
        null if the hook does not exist, otherwise the handle to the previously installed hook
      • addAfterCommit

        public void addAfterCommit​(@Nonnull
                                   FDBRecordContext.AfterCommit afterCommit)
        Adds code to be executed immediately following a successful commit. All after-commit hooks are run serially within a single future immediately following the completion of the commit future.
        Parameters:
        afterCommit - code to be executed following successful commit
      • runAfterCommits

        @Deprecated
        @API(DEPRECATED)
        public void runAfterCommits()
        Deprecated.
        this method probably should never have been public
        Run all of the after commit hooks.
      • getCommittedVersion

        public long getCommittedVersion()
        Return the eight byte version assigned to this context at commit time. This version is used internally by the database to determine which transactions should be visible by which reads. (In other words, only transactions assigned a read version greater than or equal to this version will see the effects of this transaction). If this transaction is read only, then no version will ever be assigned to this commit, so this function will return -1.
        Returns:
        the eight byte version associated with this transaction or null
        Throws:
        IllegalStateException - if this is called prior to the transaction being committed
      • getVersionStamp

        @Nullable
        public byte[] getVersionStamp()
        Return the ten byte version-stamp assigned to this context at commit time. The first eight bytes will be the big-Endian byte representation of the result of getCommittedVersion(). This version is compatible with the "global version" that is required by the FDBRecordVersion class and can be used to construct a complete record version from an incomplete one. If this transaction is read only, then no version will ever be assigned to this commit, so this function will return null.
        Returns:
        the ten byte global version-stamp associated with this transaction or null
        Throws:
        IllegalStateException - if this is called prior to the transaction being committed
      • getMetaDataVersionStampAsync

        @Nonnull
        public CompletableFuture<byte[]> getMetaDataVersionStampAsync​(@Nonnull
                                                                      IsolationLevel isolationLevel)
        Get the database's meta-data version-stamp. This key is somewhat different from other keys in the database in that its value is returned to the client at the same time that the client receives its read version. This means that reading this key does not require querying any storage server, so the client can use this key as a kind of "cache invalidation" key without needing to worry about the extra reads to this key overloading the backing storage servers (which would be the case for other keys).

        This key can only be updated by calling setMetaDataVersionStamp(), which will set the key to the transaction's version-stamp when the transaction is committed. If the key is set within the context of this transaction, this method will return null.

        Parameters:
        isolationLevel - the isolation level at which to read the key
        Returns:
        a future that will complete with the current value of the meta-data version stamp or null if it is unset or has been updated during the course of this transaction
      • setMetaDataVersionStamp

        public void setMetaDataVersionStamp()
        Update the meta-data version-stamp. At commit time, the database will write to this key the commit version-stamp of this transaction. After this has been committed, any subsequent transaction will see an updated value when calling getMetaDataVersionStamp(IsolationLevel), and those transactions may use that value to invalidate any stale cache entries using the meta-data version-stamp key. After this method has been called, any calls to getMetaDataVersionStamp() will return null. After this context has been committed, one may call getVersionStamp() to get the value that this transaction wrote to the database.
        See Also:
        getMetaDataVersionStampAsync(IsolationLevel), getVersionStamp()
      • join

        public <T> T join​(CompletableFuture<T> future)
        Join a future following the same logic that asyncToSync() uses to validate that the operation isn't blocking in an asynchronous context.
        Type Parameters:
        T - the type of the value produced by the future
        Parameters:
        future - the future to be completed
        Returns:
        the result value
        See Also:
        FDBDatabase.join(CompletableFuture)
      • joinNow

        public <T> T joinNow​(CompletableFuture<T> future)
        Join a future but validate that the future is already completed. This can be used to unwrap a completed future while allowing for bugs caused by inadvertently waiting on incomplete futures to be caught. In particular, this will throw an exception if the BlockingInAsyncDetection behavior is set to throw an exception on incomplete futures and otherwise just log that future was waited on.
        Type Parameters:
        T - the type of the value produced by the future
        Parameters:
        future - the future that should already be completed
        Returns:
        the result value
        See Also:
        FDBDatabase.joinNow(CompletableFuture)
      • timeReadSampleKey

        public void timeReadSampleKey​(byte[] key)
      • claimLocalVersion

        public int claimLocalVersion()
        Claims a local version that is unique within a single transaction. This means that any two calls to this method will return a different value. If the ordering of these calls is deterministic, then it is also guaranteed that the earlier calls will receive a smaller version than the newer calls.
        Returns:
        an integer to version different records added to the database
      • addVersionMutation

        @Deprecated
        @Nullable
        public byte[] addVersionMutation​(@Nonnull
                                         byte[] key,
                                         @Nonnull
                                         byte[] value)
        Deprecated.
        use #addVersionMutation(MutationType, byte[], byte[]) instead
        Add a SET_VERSIONSTAMPED_KEY mutation to be run at commit time. This method is deprecated in favor of addVersionMutation(MutationType, byte[], byte[]) which behaves like this method except that the choice of SET_VERSIONSTAMPED_KEY as the mutation type must be made explicitly.
        Parameters:
        key - key bytes for the mutation
        value - parameter bytes for the mutation
        Returns:
        the previous value set for the given key or null if unset
      • addVersionMutation

        @Nullable
        public byte[] addVersionMutation​(@Nonnull
                                         MutationType mutationType,
                                         @Nonnull
                                         byte[] key,
                                         @Nonnull
                                         byte[] value)
        Add a SET_VERSIONSTAMPED_KEY or SET_VERSIONTSTAMPED_VALUE mutation to be run at commit time. When called, this updates a local cache of these mutations. The commitAsync method will then be sure to flush these mutations to the transaction prior to calling commit.
        Parameters:
        mutationType - the type of versionstamp mutation
        key - key bytes for the mutation
        value - parameter bytes for the mutation
        Returns:
        the previous value set for the given key or null if unset
      • removeVersionMutation

        @Nullable
        public byte[] removeVersionMutation​(@Nonnull
                                            byte[] key)
        Remove a SET_VERSIONSTAMPED_KEY mutation that would have been run at commit time. When called, this updates a local cache of these mutations. This will only work as expected if the dummy bytes included that stand in for the versionstamp within the key bytes are equal to the dummy bytes for whatever key is included in the cache already. (For example, one might use entirely 0xff bytes for those dummy bytes for all incomplete versions. This is what the FDBRecordVersion class does.)
        Parameters:
        key - key bytes appropriate for mutation to set
        Returns:
        the previous value set for the given key or null if unset
      • getPriority

        @Nonnull
        public FDBTransactionPriority getPriority()
        Get the priority of this transaction. This is used to determine what rate-limiting rules should be applied to this transaction by the database. In general, DEFAULT priority transactions are favored over BATCH priority transactions.
        Returns:
        this transaction's priority
        See Also:
        FDBTransactionPriority
      • hasHookForAsyncToSync

        public boolean hasHookForAsyncToSync()
      • getInSession

        @API(EXPERIMENTAL)
        public <T> T getInSession​(@Nonnull
                                  String key,
                                  @Nonnull
                                  Class<T> clazz)
        Retrieve a value from the session in the FDBRecordContext.
        Type Parameters:
        T - Class
        Parameters:
        key - key
        clazz - class
        Returns:
        value
      • putInSessionIfAbsent

        @API(EXPERIMENTAL)
        public <T> void putInSessionIfAbsent​(@Nonnull
                                             String key,
                                             @Nonnull
                                             T value)
        Put an object into the session of the FDBRecordContext.
        Type Parameters:
        T - the type of the value
        Parameters:
        key - key
        value - value
      • removeFromSession

        @API(EXPERIMENTAL)
        public <T> T removeFromSession​(@Nonnull
                                       String key,
                                       @Nonnull
                                       Class<T> clazz)
        Put an object into the session of the FDBRecordContext.
        Type Parameters:
        T - the type of the class
        Parameters:
        key - key
        clazz - class
        Returns:
        value