MediumSchedulingPython 3
Worker Lease Registry
Coordinate worker ownership with TTL leases, heartbeat extension, stale-worker rejection, and fencing tokens.
40m3 sample tests7 hidden tests
Implement LeaseRegistry, an in-memory lease table for long-running worker jobs.
Requirements
LeaseRegistry(ttl_seconds)initializes the registry with a default lease time-to-live in seconds.acquire(run_id, worker_id, now)returns a lease dictionary orNone.- A successful
acquirereturns a dict with at least:run_id,worker_id,lease_id,fencing_token, andexpires_at(now + ttl_seconds). lease_idis"{run_id}:{worker_id}:{fencing_token}"(e.g."run-1:worker-a:1").- Only one active lease may exist per run.
- An expired lease can be acquired by another worker.
- Expiry is inclusive: a lease is expired when
expires_at <= now. - Every new lease gets a monotonically increasing
fencing_token. - Fencing tokens are registry-wide: each successful
acquire(any run) receives the next integer after the previous successful acquire. Tokens start at1. heartbeat(lease_id, fencing_token, now)extends the current lease (expires_at = now + ttl_seconds) and returnsTrueorFalse. Heartbeat must not revive an expired lease; treat expiry likevalidate.validate(run_id, lease_id, fencing_token, now)returns whether a worker may still mutate the run (active lease for that run, matching ids/token, not expired).release(lease_id, fencing_token)releases only the current lease for that id/token and returns whether the release succeeded (bool). Release may succeed pastexpires_at, provided the lease remains current for its run.
Example
python
1registry = LeaseRegistry(ttl_seconds=10)
2lease = registry.acquire("run-1", "worker-a", now=0)
3assert lease["fencing_token"] == 1
4assert lease["lease_id"] == "run-1:worker-a:1"
5assert registry.acquire("run-1", "worker-b", now=5) is None
6assert registry.acquire("run-1", "worker-b", now=10)["fencing_token"] == 2Constraints
- Keep it single-process and in memory.
- Use the provided
nowvalue. Don't call wall-clock time.
Editor