carlos / platform Public

Clone
git clone https://amadan.net/carlos/platform

Plain git — no account needed to clone.

Download

Download this file

1package activator
2
3import (
4 "context"
5
6 "github.com/carlosframework/platform/internal/registry"
7)
8
9// PlannedSelection is the planner's checked choice of a build in place of
10// another, for one exec (settings plan 4, ruling R-PLANNED-RECOVERY; zero-
11// downtime spec §8.2): Build is the good build the plan boots instead of
12// InPlaceOf. It is one of
13//
14// - a planned fallback: a first wake's B failed and was proven stopped,
15// and the good build starts in its place (spawnPlanned,
16// spawnPlannedWorker);
17// - the good build booted untried, when too little of B's health window
18// was left at its exec (spawnPlanned);
19// - a recovery boot: decideWake planned the good build in place of the
20// installed build, which the failure book blocks (settleWakeIdentity,
21// spawnPlanned, a claimed start).
22//
23// The activator puts it on the context of that exec's record only, after
24// the plan's selection gate (Check) passed for Build. The agent's pre-exec
25// revalidation (release.HeldExecStale) admits Build when the state read under
26// the lease holds InPlaceOf as the instance's target: the planner's reason
27// for leaving InPlaceOf is then the reason the held target is left, as
28// zero-downtime spec §6 and settings spec §6 require. The record is still
29// written. It never admits the good build in general: a context with no
30// selection, or one made in place of another build, is revalidated as
31// before.
32type PlannedSelection struct{ Build, InPlaceOf string }
33
34type plannedSelectionKey struct{}
35
36// WithPlannedSelection returns ctx carrying s. A selection with either part
37// empty reads back as none, so a caller can mask one it inherited.
38func WithPlannedSelection(ctx context.Context, s PlannedSelection) context.Context {
39 return context.WithValue(ctx, plannedSelectionKey{}, s)
40}
41
42// PlannedSelectionFrom is the selection ctx carries, if a whole one.
43func PlannedSelectionFrom(ctx context.Context) (PlannedSelection, bool) {
44 s, ok := ctx.Value(plannedSelectionKey{}).(PlannedSelection)
45 if !ok || s.Build == "" || s.InPlaceOf == "" {
46 return PlannedSelection{}, false
47 }
48 return s, true
49}
50
51// recoverySelection is the selection a recovery plan makes (decideWake's
52// recovery: the good build booted because the failure book blocks the
53// installed build, or the installed build is not staged correctly): plan
54// boots the route's good build, as no first wake, in place of the build root
55// installed (rt.Version, the planner's "installed"). A plan that boots the
56// installed build itself, the good build included, selects nothing in place
57// of anything, and its record is revalidated as any other.
58func recoverySelection(plan WakePlan, rt registry.Route) (PlannedSelection, bool) {
59 boot := plan.Boot.Version
60 if !plan.planned() || plan.FirstWake || boot == "" || boot != rt.GoodVersion || rt.Version == "" || rt.Version == boot {
61 return PlannedSelection{}, false
62 }
63 return PlannedSelection{Build: boot, InPlaceOf: rt.Version}, true
64}
65
66// withRecoverySelection is ctx carrying plan's recovery selection when plan
67// is a recovery and build is its boot; ctx itself otherwise.
68func withRecoverySelection(ctx context.Context, plan WakePlan, rt registry.Route, build string) context.Context {
69 if s, ok := recoverySelection(plan, rt); ok && s.Build == build {
70 return WithPlannedSelection(ctx, s)
71 }
72 return ctx
73}
74