Class SynchronizedSession

java.lang.Object
com.apple.foundationdb.synchronizedsession.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 Details

    • 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 Details

    • 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