package supervisor type ReleaseState string const ( ReleaseCandidate ReleaseState = "CANDIDATE" ReleaseHealthy ReleaseState = "HEALTHY" ReleaseFailed ReleaseState = "FAILED" ReleaseRolledBack ReleaseState = "ROLLED_BACK" ) type TrafficMode string const ( TrafficStable TrafficMode = "STABLE" TrafficCanaryHeader TrafficMode = "CANARY_HEADER" TrafficCandidate TrafficMode = "CANDIDATE" ) type Release struct { ID string `json:"id"` Version string `json:"version"` State ReleaseState `json:"state"` LastKnownGood bool `json:"last_known_good"` } type Observation struct { ReleaseID string `json:"release_id"` Ready bool `json:"ready"` Reason string `json:"reason"` ObservedAtUnixMillis int64 `json:"observed_at_unix_millis"` } type Lifeboat struct { Current Release `json:"current"` LastKnownGood Release `json:"last_known_good"` RollbackTarget Release `json:"rollback_target"` Observations []Observation `json:"observations"` TrafficMode TrafficMode `json:"traffic_mode"` StableUpstream string `json:"stable_upstream"` CandidateUpstream string `json:"candidate_upstream"` } func (l *Lifeboat) Start(candidate Release) bool { if candidate.ID == "" || candidate.Version == "" { return false } candidate.State = ReleaseCandidate if l.LastKnownGood.ID != "" { l.RollbackTarget = l.LastKnownGood } l.Current = candidate return true } func (l *Lifeboat) EstablishBaseline(release Release) bool { if release.ID == "" || release.Version == "" { return false } release.State = ReleaseHealthy release.LastKnownGood = true l.Current = release l.LastKnownGood = release l.RollbackTarget = Release{} l.TrafficMode = TrafficStable return true } func (l *Lifeboat) Record(o Observation) bool { if o.ReleaseID == "" { return false } l.Observations = append(l.Observations, o) if o.ReleaseID != l.Current.ID { return true } if o.Ready { l.Current.State = ReleaseHealthy l.Current.LastKnownGood = true l.LastKnownGood = l.Current } else { l.Current.State = ReleaseFailed } return true } func (l *Lifeboat) Rollback() bool { target := l.RollbackTarget if target.ID == "" { target = l.LastKnownGood } if target.ID == "" { return false } l.Current = target l.Current.State = ReleaseRolledBack l.Current.LastKnownGood = true l.LastKnownGood = l.Current l.RollbackTarget = Release{} return true } func (l *Lifeboat) SetTraffic(mode TrafficMode, stableUpstream, candidateUpstream string) bool { if mode != TrafficStable && mode != TrafficCanaryHeader && mode != TrafficCandidate { return false } if stableUpstream == "" || (mode != TrafficStable && candidateUpstream == "") { return false } l.TrafficMode = mode l.StableUpstream = stableUpstream l.CandidateUpstream = candidateUpstream return true }