In-memory transaction log for the three-phase commit protocol.
Each in-flight transaction is stored as a map entry keyed by its
txn_id binary. The log is held in an ETS table owned by this
GenServer so that:
- Reads are lock-free (
:public+:read_concurrency). - The table survives coordinator or participant crashes as long as the owning VM is alive (the ETS table is linked to this GenServer's lifetime, not to the caller's).
- On node restart,
SuperCache.Cluster.ThreePhaseCommit.recover/0can iterate the table to resolve in-doubt transactions.
Transaction states
| State | Meaning |
|---|---|
:prepared | PREPARE accepted; waiting for PRE_COMMIT or ABORT |
:pre_committed | PRE_COMMIT acknowledged; commit is safe even after crash |
:committed | COMMIT applied; entry removed immediately after |
:aborted | ABORT received; entry removed immediately after |
Memory management
Committed and aborted entries are deleted synchronously by
ThreePhaseCommit after each successful/failed transaction.
Stale :prepared entries (e.g. from a coordinator crash before
PRE_COMMIT) are cleaned up by recover/0 on the next startup.
Summary
Functions
Returns a specification to start this module under a supervisor.
Return the number of in-flight transactions (useful for tests).
Look up a transaction by id. Returns the entry map or nil.
Return all transaction entries as [{txn_id, entry}].
Transition txn_id to :pre_committed.
Register a new transaction in state :prepared.
Remove a transaction entry (called after commit or abort).
Functions
Returns a specification to start this module under a supervisor.
See Supervisor.
@spec count() :: non_neg_integer()
Return the number of in-flight transactions (useful for tests).
Look up a transaction by id. Returns the entry map or nil.
Return all transaction entries as [{txn_id, entry}].
@spec mark_pre_committed(binary()) :: :ok
Transition txn_id to :pre_committed.
@spec register(binary(), non_neg_integer(), list(), [node()]) :: :ok
Register a new transaction in state :prepared.
replicas is the list of participant nodes (may be empty on participants
themselves — they only need ops and partition_idx).
@spec remove(binary()) :: :ok
Remove a transaction entry (called after commit or abort).