The new node-backup and bus module holders run before a module whose kept data's form changes moves; at a revert the node-engine goes back last on its node; the reverted assigner and gate are wanted only once take-in.taken names the trunk's head (A-260). Kept in the state waits, said as wait-held and wait-ended, read and released by assigner_waits and assigner_release. The manifest consumes the indexer's take-in.taken and its version is 0.3 (A-245). Builds: design 47 G §298, A-245, A-258, A-259, A-260 Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
141 lines
5.8 KiB
Go
141 lines
5.8 KiB
Go
// Package acting is the assigner's wait for an acting part's new version (design 47 G §266, §268, §276): an entry of the assignment
|
|
// graph whose edge of kind acting names a step the assigner holds (composing, placing) waits until the acting part's version runs
|
|
// on the node of the edge, with the bound of the rule that gave the edge, or the step's default. The package holds the rules and
|
|
// the kept record; the assigner's process reads what runs, says the events and keeps the records in its state `waits`.
|
|
package acting
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"strings"
|
|
"time"
|
|
|
|
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-contracts/go/seats/meshwants"
|
|
"git.novox.be/novox/mesh-sdk/go/seatdef"
|
|
)
|
|
|
|
// HowNow is the `how` of assigner_release for a wait for an acting part: the entry is wanted now, with the version running.
|
|
const HowNow = "now"
|
|
|
|
// The ways a wait ends, as `wait-ended` says them.
|
|
const (
|
|
HowRan = "ran"
|
|
HowReleased = "released"
|
|
HowReplaced = "replaced"
|
|
)
|
|
|
|
// Prefix opens the key of an acting wait in the state, apart from the outside waits' `<node>.<module>.<fingerprint hex>`.
|
|
const Prefix = "acting."
|
|
|
|
// OrderPrefix opens the key of an order wait (design 47 G §298, A-259): a want held for the order of a delivery that crosses a form change,
|
|
// kept beside the acting waits in the state `waits`, as `order.<node>.<module>.<part>`.
|
|
const OrderPrefix = "order."
|
|
|
|
// The three order edges of §298, as a kept wait's Order names them.
|
|
const (
|
|
// OrderBackup: the new versions of the node-backup holder and of the holder of the bus module's seat run before a module whose kept
|
|
// data's form changes is moved.
|
|
OrderBackup = "backup-and-broker-first"
|
|
// OrderEngineLast: at a revert a node's node-engine goes back last on that node.
|
|
OrderEngineLast = "node-engine-last"
|
|
// OrderTakenIn: the reverted assigner and gate are wanted only once the reverted indexer took in the trunk's head.
|
|
OrderTakenIn = "taken-in-first"
|
|
)
|
|
|
|
// Held says whether the assigner holds the entries of step: composing and placing (§276's table).
|
|
func Held(step string) bool { return step == seatdef.StepCompose || step == seatdef.StepPlace }
|
|
|
|
// Wait is one wait as kept: Module's entry on Node waits for Part's version Fp to run on PartNode, in Step.
|
|
type Wait struct {
|
|
V int `json:"v"`
|
|
Step string `json:"step"`
|
|
Node string `json:"node"`
|
|
Module string `json:"module"`
|
|
Part string `json:"part"`
|
|
PartNode string `json:"part-node"`
|
|
Fp string `json:"fp"`
|
|
Entry string `json:"entry"`
|
|
Since time.Time `json:"since"`
|
|
ClockFrom time.Time `json:"clock-from"`
|
|
Bound string `json:"bound"`
|
|
// Released is a release by hand: the entry moves on with the part's old version; EndSaid says wait-ended was said for it.
|
|
// Order is which of §298's edges the wait stands on; empty for an acting wait.
|
|
Order string `json:"order,omitempty"`
|
|
Released bool `json:"released,omitempty"`
|
|
EndSaid bool `json:"end-said,omitempty"`
|
|
By string `json:"by,omitempty"`
|
|
Why string `json:"why,omitempty"`
|
|
}
|
|
|
|
// Key is the key of a wait in the state.
|
|
func Key(node, module, part string) string { return Prefix + node + "." + module + "." + part }
|
|
|
|
// OrderKey is the key of an order wait in the state.
|
|
func OrderKey(node, module, part string) string {
|
|
return OrderPrefix + node + "." + module + "." + part
|
|
}
|
|
|
|
// IsOrder says a kept value is an order wait's record.
|
|
func IsOrder(key string) bool { return strings.HasPrefix(key, OrderPrefix) }
|
|
|
|
// Is says a kept value is an acting wait's record.
|
|
func Is(key string) bool { return strings.HasPrefix(key, Prefix) }
|
|
|
|
// Encode is w as JSON.
|
|
func Encode(w Wait) ([]byte, error) { w.V = 1; return json.Marshal(w) }
|
|
|
|
// Decode reads a kept wait.
|
|
func Decode(raw []byte) (Wait, error) {
|
|
var w Wait
|
|
if err := json.Unmarshal(raw, &w); err != nil {
|
|
return w, err
|
|
}
|
|
if w.V != 1 || w.Step == "" || w.Node == "" || w.Module == "" || w.Part == "" {
|
|
return w, fmt.Errorf("acting: %q is not a kept acting wait", raw)
|
|
}
|
|
return w, nil
|
|
}
|
|
|
|
// BoundOf is the bound of the edge's wait: its rule's, else its step's default (seatdef.ActingRule.Wait).
|
|
func BoundOf(e meshwants.Edge) time.Duration {
|
|
return seatdef.ActingRule{Step: e.Step, Bound: e.Bound}.Wait()
|
|
}
|
|
|
|
// Pending are the acting edges of the assigner's steps whose part's version does not run yet: runs says the edge's part runs
|
|
// its version on the edge's node.
|
|
func Pending(edges []meshwants.Edge, runs func(e meshwants.Edge) bool) []meshwants.Edge {
|
|
var out []meshwants.Edge
|
|
for _, e := range edges {
|
|
if e.Kind == "acting" && Held(e.Step) && !runs(e) {
|
|
out = append(out, e)
|
|
}
|
|
}
|
|
return out
|
|
}
|
|
|
|
// Body is the wait as the seat mesh-wants says it.
|
|
func Body(w Wait, owner string) meshwants.Wait {
|
|
since, from := w.Since.UTC(), w.ClockFrom.UTC()
|
|
return meshwants.Wait{Step: w.Step, Owner: owner, Node: w.Node, Module: w.Module, Part: w.Part, Fp: w.Fp, Since: since, ClockFrom: &from, Bound: w.Bound,
|
|
Words: words(w)}
|
|
}
|
|
|
|
func words(w Wait) string {
|
|
switch w.Order {
|
|
case OrderBackup:
|
|
return fmt.Sprintf("%s on %s moves its kept data across a form change: it waits in %s for %s at %s to run on %s, which the restore point needs", w.Module, w.Node, w.Step, w.Part, short(w.Fp), w.PartNode)
|
|
case OrderEngineLast:
|
|
return fmt.Sprintf("%s on %s goes back last on its node: it waits in %s for %s at %s to run on %s, restored", w.Module, w.Node, w.Step, w.Part, short(w.Fp), w.PartNode)
|
|
case OrderTakenIn:
|
|
return fmt.Sprintf("%s on %s goes back only once the indexer took in the trunk's head: it waits in %s for source revision %s to be taken in", w.Module, w.Node, w.Step, w.Fp)
|
|
}
|
|
return fmt.Sprintf("%s on %s waits in %s for %s at %s to run on %s", w.Module, w.Node, w.Step, w.Part, short(w.Fp), w.PartNode)
|
|
}
|
|
|
|
func short(fp string) string {
|
|
if len(fp) > 19 {
|
|
return fp[:19]
|
|
}
|
|
return fp
|
|
}
|