Class SynchronizedSession


  • @API(EXPERIMENTAL)
    public class SynchronizedSession
    extends Object
    A SynchronizedSession is a concept introduced to avoid multiple attempts at performing the same operation (with each attempt opening multiple transactions running concurrently and/or consecutively) from running concurrently and contending for resources. Each attempt corresponds to a session identified by a session ID. Of the sessions with the same lock subspace, only the one holding the lock is allowed to work.

    Each session should and should only try to acquire the lock when the session is initialized.

    When a session holds the lock, it is protected from other sessions grabbing the same lock for an extended length of time (a.k.a lease). Another new session can only take lock if the lease of the original lock owner is outdated. (Note a session is allowed to work even if its lease is outdated, as long as no other session takes its lock.) In order to keep the lease, every time a session is used, it needs to update the lease's end time to some time (configured by leaseLengthMillis) later than current time. (The lease time is used only as an optimization. SynchronizedSession does not depend on synchronized clocks for the correctness of mutual exclusion.)

    If a session is not able to acquire the lock during the initialization or loses the lock later, it will get a SynchronizedSessionLockedException. The session is considered ended when it gets a such exception. It can neither try to acquire the lock again nor commit any work.

    initializeSessionAsync(com.apple.foundationdb.Transaction) should be used when initializing a session to acquire the lock, while checkLockAsync(Transaction) and updateLockSessionLeaseEndTime(Transaction) should be used in every other transactions to check the lock and keep the lease. Please refer to SynchronizedSessionRunner in fdb-record-layer-core for an example of using SynchronizedSession in practice.

    • Constructor Detail

      • SynchronizedSession

        public SynchronizedSession​(@Nonnull
                                   Subspace lockSubspace,
                                   @Nonnull
                                   UUID sessionId,
                                   long leaseLengthMillis)
        Construct a session. Remember to call initializeSessionAsync(Transaction) if the sessionId is newly generated.
        Parameters:
        lockSubspace - the lock for which this session contends
        sessionId - session ID
        leaseLengthMillis - length between last access and lease's end time in milliseconds
    • Method Detail

      • initializeSessionAsync

        public CompletableFuture<Void> initializeSessionAsync​(@Nonnull
                                                              Transaction tr)
        Initialize the session by acquiring the lock. This should be invoked before a new session is ever used.
        Parameters:
        tr - transaction to use
        Returns:
        a future that will return null when the session is initialized
      • getSessionId

        @Nonnull
        public UUID getSessionId()
        Get session ID.
        Returns:
        session ID
      • checkLockAsync

        public CompletableFuture<Void> checkLockAsync​(@Nonnull
                                                      Transaction tr)
        Check if the session still holds the lock. This should be invoked in every transaction in the session to follow the contract.
        Parameters:
        tr - transaction to use
        Returns:
        a future that will return null when the lock is checked
      • releaseLock

        public CompletableFuture<Void> releaseLock​(@Nonnull
                                                   Transaction tr)
        End the session by releasing the lock if it still holds the lock. Do nothing otherwise.
        Parameters:
        tr - transaction to use
        Returns:
        a future that will return null when the lock is no longer this session
      • endAnySession

        public void endAnySession​(@Nonnull
                                  Transaction tr)
        End any active session on the lock subspace by releasing the lock no matter whether this session holds the lock or not.

        It only takes place when the given transaction is committed. It will only be enforced when the other processes holding the lock go to check the lease in later transactions, where they will fail with SynchronizedSessionLockedException.

        Parameters:
        tr - transaction to use
      • endAnySession

        public static void endAnySession​(@Nonnull
                                         Transaction tr,
                                         @Nonnull
                                         Subspace lockSubspace)
        End any active session on the given lock subspace by releasing the lock.

        It only takes place when the given transaction is committed. It will only be enforced when the other processes holding the lock go to check the lease in later transactions, where they will fail with SynchronizedSessionLockedException.

        Parameters:
        tr - transaction to use
        lockSubspace - the lock whose active session needs to be ended
      • checkActiveSessionExists

        public static CompletableFuture<Boolean> checkActiveSessionExists​(@Nonnull
                                                                          Transaction tr,
                                                                          @Nonnull
                                                                          Subspace lockSubspace)
        Check if there is any active session on the given lock subspace, so that a new session would not able to be initialized.
        Parameters:
        tr - transaction to use
        lockSubspace - the lock whose active session needs to be checked
        Returns:
        true if there is any active session, otherwise false
      • updateLockSessionLeaseEndTime

        public void updateLockSessionLeaseEndTime​(@Nonnull
                                                  Transaction tr)
        Update the lease's end time. This should be invoked in every transaction in the session to keep the session alive.
        Parameters:
        tr - transaction to use