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 "errors"
6 "time"
7)
8
9// swapSettle is the canary's settle (spec §6.2, §7.5 step 4). A successor
10// that passed its health check must then stay up this long before the
11// switch. A var so tests can shrink it, like spawnHealthTimeout.
12var swapSettle = 10 * time.Second
13
14var errSettleExit = errors.New("swap: successor exited during its settle")
15
16type settleResult int
17
18const (
19 settleOK settleResult = iota // stayed up for the whole window
20 settleExited // died on its own: a failure of the build
21 settleCancelled // an intentional stop ended the observation
22)
23
24// observeSettle watches p for window after it became healthy (spec §6.2,
25// §6.4). Cancellation wins over an exit seen at the same moment. The
26// barrier cancels an attempt BEFORE anything is stopped, so a process that
27// dies once a stop has begun died of the stop, not of its build.
28func observeSettle(ctx context.Context, p Proc, window time.Duration) settleResult {
29 verdict := func() (settleResult, bool) {
30 if ctx.Err() != nil {
31 return settleCancelled, true
32 }
33 if p.Exited() {
34 return settleExited, true
35 }
36 return settleOK, false
37 }
38 if r, over := verdict(); over || window <= 0 {
39 return r
40 }
41 deadline := time.NewTimer(window)
42 defer deadline.Stop()
43 tick := time.NewTicker(settlePoll(window))
44 defer tick.Stop()
45 for {
46 select {
47 case <-ctx.Done():
48 return settleCancelled
49 case <-tick.C:
50 if r, over := verdict(); over {
51 return r
52 }
53 case <-deadline.C:
54 r, _ := verdict()
55 return r
56 }
57 }
58}
59