86 lines
2.9 KiB
Go
86 lines
2.9 KiB
Go
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
|
|
}
|