Files
rvbox/internal/domain/lifecycle.go
T

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
}