feat: game lobby service

This commit is contained in:
Ilia Denisov
2026-04-25 23:20:55 +02:00
committed by GitHub
parent 32dc29359a
commit 48b0056b49
336 changed files with 57074 additions and 1418 deletions
@@ -0,0 +1,80 @@
package membership
// Status identifies one lifecycle state of a Game Lobby membership record.
type Status string
const (
// StatusActive reports that the member is a full participant and may
// send commands through Game Master.
StatusActive Status = "active"
// StatusRemoved reports that the member was removed post-start. The
// engine slot is deactivated; the race name reservation is preserved
// until the game finishes.
StatusRemoved Status = "removed"
// StatusBlocked reports that the member is blocked at the platform
// level. The engine slot is retained; commands are blocked.
StatusBlocked Status = "blocked"
)
// IsKnown reports whether status belongs to the frozen membership status
// vocabulary.
func (status Status) IsKnown() bool {
switch status {
case StatusActive, StatusRemoved, StatusBlocked:
return true
default:
return false
}
}
// IsTerminal reports whether status can no longer accept lifecycle
// transitions.
func (status Status) IsTerminal() bool {
switch status {
case StatusRemoved, StatusBlocked:
return true
default:
return false
}
}
// transitionKey stores one `(from, to)` pair in the allowed-transitions
// table.
type transitionKey struct {
from Status
to Status
}
// allowedTransitions stores the set of permitted `(from, to)` status pairs.
// It mirrors the state machine frozen in lobby/README.md Membership Model
// section.
var allowedTransitions = map[transitionKey]struct{}{
{StatusActive, StatusRemoved}: {},
{StatusActive, StatusBlocked}: {},
}
// AllowedTransitions returns a copy of the `(from, to)` allowed-transitions
// table used by Transition. The returned map is safe to mutate.
func AllowedTransitions() map[Status][]Status {
result := make(map[Status][]Status)
for key := range allowedTransitions {
result[key.from] = append(result[key.from], key.to)
}
return result
}
// Transition reports whether from may transition to next. The function
// returns nil when the pair is permitted, and an *InvalidTransitionError
// wrapping ErrInvalidTransition otherwise. It does not touch any store and
// is safe to call from any layer.
func Transition(from Status, next Status) error {
if !from.IsKnown() || !next.IsKnown() {
return &InvalidTransitionError{From: from, To: next}
}
if _, ok := allowedTransitions[transitionKey{from: from, to: next}]; !ok {
return &InvalidTransitionError{From: from, To: next}
}
return nil
}