81 lines
2.4 KiB
Go
81 lines
2.4 KiB
Go
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
|
|
}
|