feat: gamemaster
This commit is contained in:
@@ -0,0 +1,127 @@
|
||||
package ports
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"galaxy/gamemaster/internal/domain/engineversion"
|
||||
)
|
||||
|
||||
//go:generate go run go.uber.org/mock/mockgen -destination=../adapters/mocks/mock_engineversionstore.go -package=mocks galaxy/gamemaster/internal/ports EngineVersionStore
|
||||
|
||||
// EngineVersionStore stores the engine version registry rows used by
|
||||
// Game Lobby's start flow and by GM's admin patch and registry CRUD
|
||||
// surface. Adapters must preserve domain semantics:
|
||||
//
|
||||
// - Get returns engineversion.ErrNotFound when no row exists for
|
||||
// version.
|
||||
// - List with a nil status filter returns every row; with a non-nil
|
||||
// filter, only rows whose status matches are returned.
|
||||
// - Insert installs a fresh row and returns engineversion.ErrConflict
|
||||
// when a row with the same `version` already exists. Adapters
|
||||
// surface PostgreSQL unique violations through that sentinel so
|
||||
// the service layer maps them to a `conflict` REST envelope.
|
||||
// - Update applies a partial update; only fields whose pointer is
|
||||
// non-nil are mutated. The `updated_at` column is always refreshed
|
||||
// from input.Now.
|
||||
// - Deprecate sets `status=deprecated` for an existing version with
|
||||
// `updated_at = now`. It returns engineversion.ErrNotFound when no
|
||||
// row exists. The call is idempotent: deprecating an already
|
||||
// deprecated row succeeds with no further mutation.
|
||||
// - Delete removes the row identified by version. Returns
|
||||
// engineversion.ErrNotFound when no row matches. The service layer
|
||||
// gates Delete behind an explicit IsReferencedByActiveRuntime probe
|
||||
// so referenced rows surface engineversion.ErrInUse before the
|
||||
// adapter is touched; adapters do not enforce that guard themselves.
|
||||
// - IsReferencedByActiveRuntime reports whether any non-finished
|
||||
// `runtime_records` row currently references the version through
|
||||
// `current_engine_version`.
|
||||
type EngineVersionStore interface {
|
||||
// Get returns the row identified by version. Returns
|
||||
// engineversion.ErrNotFound when no row exists.
|
||||
Get(ctx context.Context, version string) (engineversion.EngineVersion, error)
|
||||
|
||||
// List returns every row whose status matches statusFilter when
|
||||
// non-nil, or every row when nil. The order is adapter-defined.
|
||||
List(ctx context.Context, statusFilter *engineversion.Status) ([]engineversion.EngineVersion, error)
|
||||
|
||||
// Insert installs record into the registry.
|
||||
Insert(ctx context.Context, record engineversion.EngineVersion) error
|
||||
|
||||
// Update applies a partial update to the row identified by
|
||||
// input.Version. Only fields whose pointer is non-nil are mutated.
|
||||
// Returns engineversion.ErrNotFound when no row exists.
|
||||
Update(ctx context.Context, input UpdateEngineVersionInput) error
|
||||
|
||||
// Deprecate sets `status=deprecated` for version and refreshes
|
||||
// `updated_at` from now. Returns engineversion.ErrNotFound when no
|
||||
// row exists. Calling Deprecate on an already-deprecated row
|
||||
// succeeds with no mutation (idempotent).
|
||||
Deprecate(ctx context.Context, version string, now time.Time) error
|
||||
|
||||
// Delete removes the row identified by version. Returns
|
||||
// engineversion.ErrNotFound when no row matches. Adapters do not
|
||||
// inspect runtime references; the service layer probes
|
||||
// IsReferencedByActiveRuntime first and surfaces
|
||||
// engineversion.ErrInUse independently.
|
||||
Delete(ctx context.Context, version string) error
|
||||
|
||||
// IsReferencedByActiveRuntime reports whether any non-finished
|
||||
// runtime row currently references version through
|
||||
// `current_engine_version`. Used by the registry hard-delete path
|
||||
// to surface engineversion.ErrInUse.
|
||||
IsReferencedByActiveRuntime(ctx context.Context, version string) (bool, error)
|
||||
}
|
||||
|
||||
// UpdateEngineVersionInput stores the arguments required to PATCH one
|
||||
// engine version row. Pointer fields communicate «leave alone» (nil)
|
||||
// vs. «write the value» (non-nil). At least one optional field must be
|
||||
// set; otherwise the call is a no-op and Validate rejects it.
|
||||
type UpdateEngineVersionInput struct {
|
||||
// Version identifies the row to mutate.
|
||||
Version string
|
||||
|
||||
// ImageRef is the new image reference. Nil leaves the column
|
||||
// unchanged; non-nil must be non-empty.
|
||||
ImageRef *string
|
||||
|
||||
// Options is the new options document (raw JSON). Nil leaves the
|
||||
// column unchanged; non-nil writes the value verbatim.
|
||||
Options *[]byte
|
||||
|
||||
// Status is the new status. Nil leaves the column unchanged;
|
||||
// non-nil must be a known status.
|
||||
Status *engineversion.Status
|
||||
|
||||
// Now stores the wall-clock used to refresh the `updated_at`
|
||||
// column on every successful update.
|
||||
Now time.Time
|
||||
}
|
||||
|
||||
// Validate reports whether input contains a structurally valid PATCH
|
||||
// request. Adapters call Validate before touching the store.
|
||||
func (input UpdateEngineVersionInput) Validate() error {
|
||||
if strings.TrimSpace(input.Version) == "" {
|
||||
return fmt.Errorf("update engine version: version must not be empty")
|
||||
}
|
||||
if input.ImageRef == nil && input.Options == nil && input.Status == nil {
|
||||
return fmt.Errorf("update engine version: at least one field must be set")
|
||||
}
|
||||
if input.ImageRef != nil && strings.TrimSpace(*input.ImageRef) == "" {
|
||||
return fmt.Errorf(
|
||||
"update engine version: image ref must not be empty when set",
|
||||
)
|
||||
}
|
||||
if input.Status != nil && !input.Status.IsKnown() {
|
||||
return fmt.Errorf(
|
||||
"update engine version: status %q is unsupported",
|
||||
*input.Status,
|
||||
)
|
||||
}
|
||||
if input.Now.IsZero() {
|
||||
return fmt.Errorf("update engine version: now must not be zero")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user