Apply through one queue, and order what is applied and reported (hq to-be 45 Phase 2)
A delivery and the five-minute reconcile were two paths that applied, ordered only by a lock, and each order it allowed was met live (issues 257, 261, 267). Now both only enqueue: one worker takes the newest declaration held when it starts, applies it once and makes one report, and reports leave in the order they are made. A declaration may carry the controller's lease epoch beside its sequence; one older than what this node applied is refused before anything is touched, counted, logged and reported. A report carries the declaration's epoch and sequence and the host's own report sequence, kept on disk so it goes on increasing across restarts and self-updates. Without an epoch, today's behaviour stands.
This commit is contained in:
@@ -1297,6 +1297,16 @@ type Declaration struct {
|
||||
// superseded.
|
||||
Sequence int64
|
||||
|
||||
// Epoch is the controller's lease epoch this declaration was sent under (novox/hq to-be 45 §6):
|
||||
// the revision at which the sending controller took the lease. A controller that lost its lease
|
||||
// and goes on sending sends an older epoch than the holder's, and the node-engine refuses what
|
||||
// is older than what it applied. Zero is a declaration from a controller without a lease — every
|
||||
// one sent before the lease existed — and carries no claim.
|
||||
//
|
||||
// Inside what is signed, beside the sequence, so a message cannot be given a newer epoch than
|
||||
// the controller gave it.
|
||||
Epoch int64
|
||||
|
||||
// LeftOut names the modules of this machine's set the mesh left out of this declaration,
|
||||
// because a setting stored for one cannot compose with its definition (novox/hq ADR 0163,
|
||||
// rule 6). A machine is told everything or nothing about what it IS told; this is what it is
|
||||
@@ -1462,6 +1472,10 @@ type envelope struct {
|
||||
// Sequence is optional on the wire, so a controller that does not send one is still
|
||||
// understood: absent reads as zero, which is "no ordering claimed" rather than "first".
|
||||
Sequence int64 `json:"sequence,omitempty"`
|
||||
// Epoch is optional on the wire as the sequence is: absent is a controller without a lease.
|
||||
// **An older host refuses this key**, decoding strictly; a controller sends it only to a host
|
||||
// whose reports carry a report sequence, which a host that reads it does.
|
||||
Epoch int64 `json:"epoch,omitempty"`
|
||||
// LeftOut is optional on the wire too, and absent when nothing was left out (ADR 0163).
|
||||
LeftOut []string `json:"left_out,omitempty"`
|
||||
}
|
||||
@@ -1481,8 +1495,14 @@ func parse(raw []byte, allowActions bool) (*Declaration, error) {
|
||||
}
|
||||
|
||||
d := &Declaration{Version: env.Version, For: env.For, Adoption: env.Adoption, Sequence: env.Sequence,
|
||||
LeftOut: env.LeftOut}
|
||||
Epoch: env.Epoch, LeftOut: env.LeftOut}
|
||||
var problems []string
|
||||
if env.Sequence < 0 || env.Epoch < 0 {
|
||||
// Below zero is no order any controller assigns, and read as "none claimed" it would let the
|
||||
// declaration past every refusal of what is older.
|
||||
problems = append(problems, fmt.Sprintf("an order below zero (epoch %d, sequence %d) is not "+
|
||||
"one the mesh assigns", env.Epoch, env.Sequence))
|
||||
}
|
||||
if len(env.LeftOut) > 0 && allowActions {
|
||||
// The bundle is carried with the binary and leaves nothing out: which module a setting
|
||||
// stopped composing for is the mesh's record (ADR 0163).
|
||||
|
||||
Reference in New Issue
Block a user