package domain import ( "fmt" rvboxv1 "github.com/rvbox/rvbox/gen/go/rvbox/v1" ) // CanTransition reports whether a public lifecycle change is legal. Duplicate // events are handled by sequence validation and are not state transitions. func CanTransition(from, to rvboxv1.CommandLifecycle) bool { switch from { case rvboxv1.CommandLifecycle_COMMAND_QUEUED: return to == rvboxv1.CommandLifecycle_COMMAND_DISPATCHED || to == rvboxv1.CommandLifecycle_COMMAND_CANCELLED || to == rvboxv1.CommandLifecycle_COMMAND_EXPIRED case rvboxv1.CommandLifecycle_COMMAND_DISPATCHED: return to == rvboxv1.CommandLifecycle_COMMAND_QUEUED || to == rvboxv1.CommandLifecycle_COMMAND_ACCEPTED || to == rvboxv1.CommandLifecycle_COMMAND_REJECTED || to == rvboxv1.CommandLifecycle_COMMAND_CANCELLED || to == rvboxv1.CommandLifecycle_COMMAND_INTERRUPTED case rvboxv1.CommandLifecycle_COMMAND_ACCEPTED: return to == rvboxv1.CommandLifecycle_COMMAND_RUNNING || to == rvboxv1.CommandLifecycle_COMMAND_REJECTED || to == rvboxv1.CommandLifecycle_COMMAND_CANCELLED || to == rvboxv1.CommandLifecycle_COMMAND_INTERRUPTED case rvboxv1.CommandLifecycle_COMMAND_RUNNING: return to == rvboxv1.CommandLifecycle_COMMAND_SUCCEEDED || to == rvboxv1.CommandLifecycle_COMMAND_FAILED || to == rvboxv1.CommandLifecycle_COMMAND_TERMINATED || to == rvboxv1.CommandLifecycle_COMMAND_INTERRUPTED default: return false } } // ValidateTransition rejects unspecified, repeated, terminal-origin, and // otherwise impossible public lifecycle changes. func ValidateTransition(from, to rvboxv1.CommandLifecycle) error { if CanTransition(from, to) { return nil } return NewError( rvboxv1.ControlError_PROTOCOL_ERROR, fmt.Sprintf("illegal command lifecycle transition %s -> %s", from, to), "", ) } // IsTerminal reports whether no further public lifecycle transition is legal. func IsTerminal(state rvboxv1.CommandLifecycle) bool { switch state { case rvboxv1.CommandLifecycle_COMMAND_SUCCEEDED, rvboxv1.CommandLifecycle_COMMAND_FAILED, rvboxv1.CommandLifecycle_COMMAND_TERMINATED, rvboxv1.CommandLifecycle_COMMAND_CANCELLED, rvboxv1.CommandLifecycle_COMMAND_INTERRUPTED, rvboxv1.CommandLifecycle_COMMAND_EXPIRED, rvboxv1.CommandLifecycle_COMMAND_REJECTED: return true default: return false } } // LaunchPhase is durable client-only state between accepted and running. type LaunchPhase uint8 const ( LaunchPhaseNone LaunchPhase = iota LaunchPhasePrepared LaunchPhaseAuthorized ) // CanAdvanceLaunchPhase permits only the one-way launch barrier. func CanAdvanceLaunchPhase(from, to LaunchPhase) bool { return (from == LaunchPhaseNone && to == LaunchPhasePrepared) || (from == LaunchPhasePrepared && to == LaunchPhaseAuthorized) } // MayRedispatch is false once command code may have been released. func MayRedispatch(phase LaunchPhase) bool { return phase == LaunchPhaseNone || phase == LaunchPhasePrepared }