mesh/delivery-group group feat/774-l3-reland rejected: composed together: the checker's verdict at the members' heads (b48c90fea31f): integration: mesh-self-ch…
mesh/delivery closed: a newer head of the same pull request
mesh/check failed: integration: mesh-self-check/cmd/mesh-self-check.TestTheSelfCheckWholeRunsOnTheBus: the run answered {Run:doctor-1793351737-1 At:20…
One commit with exactly the tree of the reviewed head35b4509c0a, on main12c2574c9d, so two compiled programs added and removed on the branch leave no trace in history (issue 1577).
60 lines
1.7 KiB
Go
60 lines
1.7 KiB
Go
package main
|
|
|
|
import (
|
|
"sync"
|
|
"time"
|
|
|
|
stdio "git.novox.be/novox/mesh-sdk/go"
|
|
"git.novox.be/novox/mesh-sdk/go/health"
|
|
)
|
|
|
|
// takeover is which self-check run the watcher hears: the controller's `doctor-heartbeat` until the keeper's
|
|
// take-over key names the keeper, then mesh-self-check's `checked`, whose body is the same run (novox/hq ADR 0564
|
|
// clause 9, issue 1952 W1). An absent key follows the controller.
|
|
type takeover struct {
|
|
mu sync.Mutex
|
|
t health.Takeover
|
|
}
|
|
|
|
func newTakeover() *takeover {
|
|
return &takeover{t: health.Takeover{V: health.TakeoverVersion, Follow: health.FollowController}}
|
|
}
|
|
|
|
// heard says whether key is the followed self-check event.
|
|
func (f *takeover) heard(key string) bool {
|
|
f.mu.Lock()
|
|
defer f.mu.Unlock()
|
|
seat, event := f.t.SelfCheckEvent()
|
|
return key == seat+"."+event
|
|
}
|
|
|
|
func (f *takeover) set(value []byte, found bool) error {
|
|
t, err := health.DecodeTakeover(value, found)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
f.mu.Lock()
|
|
f.t = t
|
|
f.mu.Unlock()
|
|
return nil
|
|
}
|
|
|
|
// followTakeover watches the key for the life of the process; one it cannot read leaves the event it heard.
|
|
func followTakeover(f *takeover) {
|
|
for wait := 2 * time.Second; ; wait = min(wait*2, time.Minute) {
|
|
err := stdio.State(health.KeeperModule+"."+health.TakeoverState).Watch(health.TakeoverKey, func(c stdio.StateChange) error {
|
|
if err := f.set(c.Value, c.Op != "delete" && len(c.Value) > 0); err != nil {
|
|
logf("[mesh-watcher] the take-over key is unreadable (%v); no change in what it hears", err)
|
|
} else {
|
|
logf("[mesh-watcher] the take-over key now follows %s", f.t.Follow)
|
|
}
|
|
return nil
|
|
})
|
|
if err == nil {
|
|
return
|
|
}
|
|
logf("[mesh-watcher] not watching the take-over key yet (%v)", err)
|
|
time.Sleep(wait)
|
|
}
|
|
}
|