blob: 92e05c90d23e205a4ae4fb2a38a1b1a876e7a725 [file] [log] [blame]
// Copyright 2016 The LUCI Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package dm
import (
"fmt"
)
// validAttemptStateEvolution defines all valid {From -> []To} state
// transitions. The identity transition (X -> X) is implied, as long as X has an
// entry in this mapping.
var validAttemptStateEvolution = map[Attempt_State][]Attempt_State{
Attempt_SCHEDULING: {
Attempt_EXECUTING, // scheduled
Attempt_ABNORMAL_FINISHED, // cancelled/timeout/err/etc.
},
Attempt_EXECUTING: {
Attempt_SCHEDULING, // Retry
Attempt_WAITING, // EnsureGraphData
Attempt_FINISHED, // FinishAttempt
Attempt_ABNORMAL_FINISHED, // cancel/timeout/err/etc.
},
Attempt_WAITING: {
Attempt_SCHEDULING, // unblocked
Attempt_ABNORMAL_FINISHED, // cancelled
},
Attempt_FINISHED: {},
Attempt_ABNORMAL_FINISHED: {},
}
// Evolve attempts to evolve the state of this Attempt. If the state evolution
// is not allowed (e.g. invalid state transition), this returns an error.
func (s *Attempt_State) Evolve(newState Attempt_State) error {
nextStates := validAttemptStateEvolution[*s]
if nextStates == nil {
return fmt.Errorf("invalid state transition: no transitions defined for %s", *s)
}
if newState == *s {
return nil
}
for _, val := range nextStates {
if newState == val {
*s = newState
return nil
}
}
return fmt.Errorf("invalid state transition %v -> %v", *s, newState)
}
// MustEvolve is a panic'ing version of Evolve.
func (s *Attempt_State) MustEvolve(newState Attempt_State) {
err := s.Evolve(newState)
if err != nil {
panic(err)
}
}
// Terminal returns true iff there are no valid evolutions from the current
// state.
func (s Attempt_State) Terminal() bool {
return len(validAttemptStateEvolution[s]) == 0
}