Files
galaxy-game/rtmanager/internal/ports/gamelease.go
T
2026-04-28 20:39:18 +02:00

39 lines
1.7 KiB
Go

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
}