Documentation
¶
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Config ¶
type Config struct {
// TTL is the lease duration for each EID lock row.
TTL time.Duration `yaml:"ttl"`
// AcquireBackoff is the wait between retry attempts when a lock is contended.
AcquireBackoff time.Duration `yaml:"acquireBackoff"`
// AcquireDeadline is the total time allowed to acquire all EID locks.
AcquireDeadline time.Duration `yaml:"acquireDeadline"`
// Heartbeat is the interval at which held leases are renewed (~TTL/3).
Heartbeat time.Duration `yaml:"heartbeat"`
// Owner identifies this replica. Defaults to the FSC node ID when empty.
Owner string `yaml:"owner"`
}
Config holds Postgres lease-table locking settings.
type Locker ¶
type Locker struct {
// contains filtered or unexported fields
}
Locker implements locker.Locker using a SQL lease table. Acquire and renew queries use Postgres-specific features (TIMESTAMPTZ, ON CONFLICT DO UPDATE … RETURNING, ::interval casts).
func New ¶
New creates a Postgres-backed distributed Locker. The table is created if it does not exist. db must be a *sql.DB connected to Postgres.
func (*Locker) AcquireLocks ¶
AcquireLocks claims a lease on every enrollment ID in eIDs for anchor, across all replicas sharing the table.
Implementation: the IDs are deduplicated and sorted (dedup.AndSort) for the same deadlock-free ordering the in-memory locker relies on. It then retries tryAcquireAll — a single atomic upsert that succeeds only if it can claim every ID — sleeping AcquireBackoff between attempts and giving up with a contention error once AcquireDeadline passes (or ctx is cancelled). On success it records the held IDs under anchor and starts a background heartbeat that renews the leases before they expire, so a long-running audit keeps its locks while a crashed replica's leases expire and become claimable by others. Any partial state is released on the give-up/cancel paths.
func (*Locker) AssertLocksHeld ¶
AssertLocksHeld verifies this replica still holds every lease it acquired for anchor. It compares the number of IDs recorded locally at acquisition time against the count of matching, non-expired, owner-scoped rows in the table. A mismatch (or no local record) means a lease expired and may have been taken over by another replica, so it returns ErrLockNotHeld. Callers use this after long-running work to confirm their locks were not silently lost.