package ports import ( "context" "time" ) // GameLeaseStore guards every lifecycle operation Runtime Manager runs // against one game. The lease serialises starts, stops, restarts, patches, // and cleanup operations on the same `game_id` across all entry points // (Lobby stream consumer, GM REST handler, Admin REST handler, periodic // workers) so concurrent operations cannot corrupt each other's // intermediate Docker / PostgreSQL state. // // The lease is a per-game key with a random token. Adapters use SETNX with // PX TTL on TryAcquire and a compare-and-delete on Release so a publisher // that lost the lease (TTL expiry, replica swap) cannot clear another // caller's claim. // // In v1 the lease is not renewed mid-operation; callers must keep the // total operation duration below the configured TTL // (`RTMANAGER_GAME_LEASE_TTL_SECONDS`, default 60s). Multi-GB image pulls // can exceed this in production and remain a known limitation; later // stages may introduce a renewal helper if it bites. type GameLeaseStore interface { // TryAcquire attempts to acquire the per-game lease for gameID owned // by token for ttl. It returns true when the lease was acquired and // false when another holder still owns it. A non-nil error reports // transport-level failures (Redis unreachable, network timeout) and // must not be confused with a missed lease. TryAcquire(ctx context.Context, gameID, token string, ttl time.Duration) (acquired bool, err error) // Release removes the per-game lease for gameID only when token still // matches the stored owner value. Releasing a lease the caller no // longer owns is a silent no-op so a TTL-driven release race never // clears another caller's claim. Release(ctx context.Context, gameID, token string) error }