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

93 lines
3.5 KiB
Go

package ports
import (
"context"
"fmt"
)
// StopReason classifies why Lobby asks Runtime Manager to stop a game
// container. The enum is part of the `runtime:stop_jobs` envelope and
// mirrors the AsyncAPI contract frozen in
// `rtmanager/api/runtime-jobs-asyncapi.yaml`.
//
// Lobby v1 produces only StopReasonOrphanCleanup (orphan-container path
// in the runtime-job-result worker) and StopReasonCancelled
// (user-lifecycle cascade). The remaining values are reserved in the
// shared contract for future producers (Game Master, Admin Service,
// enrollment automation).
type StopReason string
// StopReason enum values. The set is fixed by
// `rtmanager/api/runtime-jobs-asyncapi.yaml`; adding a new value is a
// contract bump that must be coordinated across producers and consumers.
const (
// StopReasonOrphanCleanup releases a container whose post-start
// metadata persistence failed in Lobby.
StopReasonOrphanCleanup StopReason = "orphan_cleanup"
// StopReasonCancelled covers user-lifecycle cascade and explicit
// cancel paths for in-flight games.
StopReasonCancelled StopReason = "cancelled"
// StopReasonFinished is reserved for engine-driven game finish
// flows; not produced by Lobby in v1.
StopReasonFinished StopReason = "finished"
// StopReasonAdminRequest is reserved for future admin-initiated
// stop paths through Lobby; not produced by Lobby in v1.
StopReasonAdminRequest StopReason = "admin_request"
// StopReasonTimeout is reserved for future enrollment-timeout-driven
// stop paths; not produced by Lobby in v1.
StopReasonTimeout StopReason = "timeout"
)
// String returns reason as its stored enum value.
func (reason StopReason) String() string {
return string(reason)
}
// Validate reports whether reason carries one of the five values fixed
// by the AsyncAPI contract.
func (reason StopReason) Validate() error {
switch reason {
case StopReasonOrphanCleanup,
StopReasonCancelled,
StopReasonFinished,
StopReasonAdminRequest,
StopReasonTimeout:
return nil
case "":
return fmt.Errorf("stop reason must not be empty")
default:
return fmt.Errorf("stop reason %q is not a recognised value", string(reason))
}
}
//go:generate go run go.uber.org/mock/mockgen -destination=../adapters/mocks/mock_runtimemanager.go -package=mocks galaxy/lobby/internal/ports RuntimeManager
// RuntimeManager publishes runtime jobs to Runtime Manager via Redis
// Streams. Lobby is the producer for both the start and the stop stream;
// Runtime Manager (Stages 13+) is the eventual consumer.
//
// Image-reference resolution is intentionally a Lobby concern: each
// game's `target_engine_version` is substituted into
// `LOBBY_ENGINE_IMAGE_TEMPLATE` and the resulting `image_ref` is handed
// to Runtime Manager verbatim on the start envelope. Runtime Manager
// never resolves engine versions itself.
type RuntimeManager interface {
// PublishStartJob enqueues one start job for gameID with the
// producer-resolved imageRef. Implementations must produce one
// event in the configured runtime start jobs stream per call. A
// zero-error return means the event is durably accepted into the
// stream (Redis XADD succeeded); it does not imply that the
// container has started.
PublishStartJob(ctx context.Context, gameID, imageRef string) error
// PublishStopJob enqueues one stop job for gameID with the
// classifying reason. Implementations must produce one event in the
// configured runtime stop jobs stream per call. The same durability
// semantics as PublishStartJob apply.
PublishStopJob(ctx context.Context, gameID string, reason StopReason) error
}