Class TransactionManager

java.lang.Object
com.loomcache.server.transaction.TransactionManager

public final class TransactionManager extends Object
Manages active transactions, including timeout monitoring and statistics tracking.

Commit path — Raft-replicated atomic batch (v2.0): On commit(UUID) buffered operations are bundled into a single atomic, replicated batch and submitted to the Raft group via BatchExecutionHandler. Once the batch is committed to the Raft log, it is applied on every replica atomically by the state machine. This ensures transactional mutations survive a coordinator crash after commit is acknowledged.

When sharding is enabled and the transaction's keys span more than one Raft group, the manager delegates to CrossGroupTransactionExecutor which coordinates a Raft-serialized cross-group execution.

Local commit fallback is disabled by default because it is not replicated. Test-only harnesses can opt in with -Dloomcache.transactions.allow-local-commit-fallback=true.

Features:

  • Virtual thread-based timeout monitoring (no blocking of physical threads)
  • Automatic rollback of timed-out transactions
  • Transaction isolation and deadlock prevention via per-structure lock ordering
  • Comprehensive statistics tracking (started, committed, rolled back, timed out)

Thread Safety: This class is thread-safe. Multiple threads can safely begin, commit, and rollback transactions concurrently.

Since:
1.0
  • Constructor Details

    • TransactionManager

      public TransactionManager(DataStructureRegistry registry)
      Creates a new transaction manager with a local (non-replicated) commit path.

      This constructor is intended for unit tests that exercise the manager against an in-memory registry without a Raft node. Production wiring must use TransactionManager(DataStructureRegistry, BatchExecutionHandler, CrossGroupTransactionExecutor, PartitionRouter).

      Parameters:
      registry - the data structure registry (must not be null)
      Throws:
      NullPointerException - if registry is null
    • TransactionManager

      public TransactionManager(DataStructureRegistry registry, @Nullable BatchExecutionHandler batchHandler, @Nullable CrossGroupTransactionExecutor crossGroupExecutor, @Nullable PartitionRouter partitionRouter)
      Creates a new transaction manager with optional Raft-replicated commit.
      Parameters:
      registry - the data structure registry (must not be null)
      batchHandler - batch execution handler used to replicate atomic commits through Raft; null disables replication and falls back to local apply
      crossGroupExecutor - executor used when buffered operations span multiple Raft groups (sharding enabled); null disables cross-group routing
      partitionRouter - partition router used to detect multi-group transactions; null when sharding is disabled
      Throws:
      NullPointerException - if registry is null
  • Method Details

    • withLocalCommitFallbackForTests

      public static TransactionManager withLocalCommitFallbackForTests(DataStructureRegistry registry)
      Creates a manager that may use the legacy in-memory commit path when an operation is not representable as a replicated batch.

      This is intentionally named for tests so production wiring keeps using the fail-closed constructors unless an operator explicitly opts in via the local-fallback system property.

    • setShardedBatchHandlerResolver

      public void setShardedBatchHandlerResolver(@Nullable Function<Integer, BatchExecutionHandler> resolver)
      Installs an optional resolver that maps a single Raft group ID to the BatchExecutionHandler bound to that group's registry slice.

      When absent, replicated single-group commits continue to use the default batchHandler. CacheNode wires this only in sharded mode.

    • getKeyLockManager

      public TransactionKeyLockManager getKeyLockManager()
    • start

      public void start()
      Starts the timeout monitor thread as a virtual thread.

      The monitor runs periodically (every 100ms) to check for timed-out transactions and automatically rolls them back. Using a virtual thread avoids blocking physical threads.

    • stop

      public void stop()
      Stops the transaction manager and its timeout monitor.

      Waits up to 5 seconds for the monitor thread to gracefully terminate. After stopping, no new transactions can be started.

    • beginTransaction

      public TransactionContext beginTransaction(long timeoutMillis)
      Begins a new transaction with the specified timeout.
      Parameters:
      timeoutMillis - the timeout in milliseconds (must be positive)
      Returns:
      a new TransactionContext (never null)
      Throws:
      IllegalArgumentException - if timeoutMillis invalid input: '<'= 0
    • beginReplicatedTransaction

      public TransactionContext beginReplicatedTransaction(UUID transactionId, long timeoutMillis, long startTimeMillis)
      Restores or applies a Raft-replicated coordinator transaction session.

      Used by the legacy stateful transaction protocol, whose buffered pre-commit state now survives leader failover through Raft replication and state-machine snapshots.

    • bufferReplicatedOperation

      public void bufferReplicatedOperation(UUID transactionId, TransactionOp operation)
      Applies a buffered operation that was replicated through the coordinator log.
    • lockKeyForUpdate

      public @Nullable String lockKeyForUpdate(UUID transactionId, String mapName, String key)
      Replicated coordinator mutation for TransactionalMap.getForUpdate. Records transaction ownership of the map/key and returns the current value.
    • discardReplicatedTransaction

      public boolean discardReplicatedTransaction(UUID transactionId, boolean failIfMissing)
      Drops replicated coordinator state without replaying a data rollback.

      Used both for replicated TX_ROLLBACK and for post-commit cleanup of the replicated coordinator session.

    • snapshotRecoverableTransactions

      public List<TransactionManager.RecoverableTransactionState> snapshotRecoverableTransactions()
      Snapshots the currently active Raft-replicated coordinator sessions.
    • restoreRecoverableTransactions

      public void restoreRecoverableTransactions(@Nullable Object snapshotValue)
      Restores the Raft-replicated coordinator sessions from a state-machine snapshot.
    • commitBufferedTransaction

      public void commitBufferedTransaction(UUID transactionId, long timeoutMillis, List<TransactionOp> operations)
      Commits a stateless wire transaction whose operations were buffered client-side.

      This path avoids server-side session pinning: the client submits the full operation list at commit time, and the manager executes it through the same replicated commit logic used by stateful transactions.

      Parameters:
      transactionId - client-visible transaction id for logging and error reporting
      timeoutMillis - remaining transaction timeout in milliseconds
      operations - buffered operations to commit atomically
    • commitBufferedTransaction

      public void commitBufferedTransaction(UUID transactionId, long timeoutMillis, List<TransactionOp> operations, @Nullable String replicatedSenderId)
    • commit

      public void commit(UUID transactionId)
      Commits a transaction and cleans up internal state.

      Chooses one of three commit paths:

      1. Cross-group Raft: when sharding is enabled and the transaction's map-keys span more than one Raft group, the ops are translated into a Transaction and submitted via CrossGroupTransactionExecutor.
      2. Replicated atomic batch: when BatchExecutionHandler is wired and all buffered ops translate cleanly to batch opcodes, the whole batch is submitted to Raft and applied by the state machine on every node.
      3. Local fallback: disabled by default; only explicit test harnesses or operator opt-in may apply an unreplicated in-memory commit.
      Parameters:
      transactionId - the transaction ID (must not be null)
      Throws:
      IllegalArgumentException - if transaction not found
    • durableCoordinatorCommitSenderId

      public static String durableCoordinatorCommitSenderId(UUID transactionId)
      Stable idempotency sender metadata for the replicated batch generated by a durable stateful coordinator commit.

      CacheNode uses the same key to deduplicate ambiguous external TX_COMMIT retries after the first replicated batch outcome has already been learned through state-machine apply.

    • rollback

      public void rollback(UUID transactionId)
      Rolls back a transaction and cleans up internal state.
      Parameters:
      transactionId - the transaction ID (must not be null)
      Throws:
      IllegalArgumentException - if transaction not found
    • abortActiveTransactionsDueToLeadershipLoss

      public int abortActiveTransactionsDueToLeadershipLoss(@Nullable String newLeaderId)
      Best-effort abort of locally buffered transactions after this node loses leadership.

      Only transactions still in TransactionContext.TransactionState.ACTIVE are aborted here. Transactions already COMMITTING may have submitted their replicated command, so their final outcome is governed by the regular commit path.

      Parameters:
      newLeaderId - identifier of the new leader, if known
      Returns:
      number of transactions definitively rolled back on this node
    • getTransaction

      public @Nullable TransactionContext getTransaction(UUID transactionId)
      Gets a transaction by ID.
      Parameters:
      transactionId - the transaction ID (must not be null)
      Returns:
      the TransactionContext, or null if not found
    • getActiveTransactionIds

      public List<UUID> getActiveTransactionIds()
      Gets all active transaction IDs.
      Returns:
      a list of transaction IDs (never null, may be empty)
    • getStats

      Gets statistics about transaction execution.
      Returns:
      current transaction manager statistics (never null)