55 lines
2.2 KiB
Go
55 lines
2.2 KiB
Go
package watch
|
|
|
|
import (
|
|
"git.novox.be/novox/mesh-sdk/go/delivery"
|
|
)
|
|
|
|
// A build ask taken by a node is a move (novox/hq ADR 0525 §4, issues 1887 A8b, 1908, 1909): the node writes the ask's step
|
|
// key `<node>.<ask id>` running in the build module's steps (delivery.StepsBucket) when it takes the ask, and writes it passed,
|
|
// failed or refused when the ask ends. The pulse of the move is the pulse of the bucket named as the seat's stream
|
|
// (delivery.AskStream), under the ask's id, and it begins when the node started the step.
|
|
//
|
|
// **An ask still waiting in the stream is a backlog, not a stall** (issue 1908): the rebuild after the switch puts about 170
|
|
// asks on a few nodes' slots, and most wait for hours with every worker healthy. No pulse is made for a waiting ask, so none
|
|
// can expire into a false stuck row; the view shows the backlog and the oldest waiting ask's age (delivery view, A8a). What
|
|
// is read of the steps at the watchman's start is mirrored the same way, so an ask running when the watchman was down is
|
|
// pulsed again (issue 1909).
|
|
|
|
// Step is a change of a key of the steps bucket of language's build module, read from the watch (at the start the keys that
|
|
// stand, then each change). A running step makes the pulse of its ask, from the step's own start; a step that ended, or a
|
|
// key deleted, ends it. The node's `paused.<node>` key, a key that is no step key and a value that cannot be read are left.
|
|
func (w *Watchman) Step(language, key string, value []byte, op Op) {
|
|
bucket, err := delivery.AskStream(language)
|
|
if err != nil {
|
|
w.say("no pulse for the step %s: %v", key, err)
|
|
return
|
|
}
|
|
node, id, err := delivery.ParseStepKey(key)
|
|
if err != nil {
|
|
return
|
|
}
|
|
w.mu.Lock()
|
|
defer w.mu.Unlock()
|
|
switch op {
|
|
case Expired:
|
|
return
|
|
case Delete:
|
|
w.moved(bucket, id)
|
|
return
|
|
}
|
|
step, err := delivery.DecodeStep(value)
|
|
if err != nil {
|
|
w.say("the step %s cannot be read, and is left: %v", key, err)
|
|
return
|
|
}
|
|
if step.State != delivery.StepRunning {
|
|
w.moved(bucket, id)
|
|
return
|
|
}
|
|
since := step.Started
|
|
if since.IsZero() {
|
|
since = w.now()
|
|
}
|
|
w.mirrorWithin(w.stepBound, bucket, id, describe("the ask %s to end on %s", id, node), node, since, 0)
|
|
}
|