Package com.enhancedechest.crossserver
Interface CrossServerCoordinator
- All Known Implementing Classes:
RedisCoordinator
public interface CrossServerCoordinator
Coordination contract that makes the lazy write-back cache safe to run on several servers sharing
one database (
cross-server.enabled). The rule the storage layer enforces with it:
an owner may be resident in this server's cache only while this server holds that owner's
distributed lock — acquired before the rows are read from SQL, released only after the owner's
dirty rows have been flushed back and evicted. Since eviction takes only clean owners, whoever
acquires the lock next always reads current SQL rows, so two servers can never hold (and later
flush) conflicting authoritative copies of the same player.
Release is split in two so the cache can keep its lock discipline: beginRelease(java.util.UUID) is the
cheap local intent, called inside the cache's state lock in the same critical section that
drops the owner's rows (so a concurrent load's isHeld(java.util.UUID) re-check under that lock can never
see stale ownership); finishRelease(java.util.UUID) does the actual network release and is called after
the lock is dropped (never network I/O inside the cache lock).
The NOOP instance is the single-server mode: every acquire succeeds instantly and
isHeld(java.util.UUID) is always true, which collapses the whole protocol to the pre-cross-server
behavior. Call sites never null-check or branch (same pattern as Telemetry).
-
Field Summary
FieldsModifier and TypeFieldDescriptionstatic final CrossServerCoordinatorSingle-server no-op: acquires always succeed, nothing is ever released. -
Method Summary
Modifier and TypeMethodDescriptionvoidacquireOwner(UUID owner) Blocks until this server holdsowner's lock.voidbeginRelease(UUID owner) Marksowner's lock as no longer held locally.voidfinishRelease(UUID owner) Completes abeginRelease(java.util.UUID): deletes the lock key and notifies waiting servers.booleanWhether this server currently holdsowner's lock (cheap, local — no network I/O).booleanisHeldElsewhere(UUID owner) Whetherowner's lock is currently held by a different server (network read).
-
Field Details
-
NOOP
Single-server no-op: acquires always succeed, nothing is ever released.
-
-
Method Details
-
acquireOwner
Blocks until this server holdsowner's lock. Called on the async storage executor by the cache's load-on-miss path, never on a tick thread. If another server holds the lock, that server is asked (pub/sub) to flush + hand the owner over, which it does as soon as the player has fully quit there; on a crashed holder the lock's TTL expires instead.- Throws:
CrossServerLockException- if the lock cannot be obtained within the acquire timeout — e.g. the player is still online on the other server. The caller treats this like a failed SQL read: the operation fails loudly instead of proceeding on stale data.
-
isHeld
Whether this server currently holdsowner's lock (cheap, local — no network I/O). The cache re-checks this under its state lock right before flipping an owner resident, closing the race where an eviction releases the lock between a load's acquire and its apply. -
isHeldElsewhere
Whetherowner's lock is currently held by a different server (network read). Used by the expiry sweep to skip candidates whose owner is online on another server — that server's own sweep handles them — instead of blocking a full acquire timeout on each. -
beginRelease
Marksowner's lock as no longer held locally. Must be called inside the cache's state lock, in the same critical section that evicts the owner's rows. Pure local bookkeeping. -
finishRelease
Completes abeginRelease(java.util.UUID): deletes the lock key and notifies waiting servers. Called outside the cache's state lock (network I/O). Failures are logged, never thrown — a lost release degrades to the lock's TTL expiry.
-