The one-push cascade compares against what was last sent (issue 057)
The first cut compared a before/after snapshot of the named push — but the provision is minted at assign or module-issue, before push runs, so by push time the provider is already behind with no delta to detect. Fixed to flush machines whose declaration differs from what they were last SENT (the same Waiting path --behind uses), which is the honest meaning of 'one push leaves the mesh consistent' (ADR 0083). Verified live on a kept two-node mesh: pushing the consumer populates the provider's grant and the vhost is minted.
This commit is contained in:
+26
-29
@@ -250,18 +250,6 @@ func pushCommand(ctx context.Context, args []string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// What every machine should be BEFORE this push composes anything. Composing a named node
|
|
||||||
// mints the provisions its consumers need, and a minted provision changes what the PROVIDER
|
|
||||||
// machine should be — its grant list is a pure read of secrets already issued (novox/hq
|
|
||||||
// issue 057). Captured now so that, after the send, "what changed because of this push" is
|
|
||||||
// a comparison rather than a guess.
|
|
||||||
var before map[string]string
|
|
||||||
if len(args) == 1 {
|
|
||||||
if before, err = wouldSend(ctx, open, nodes); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
server, err := link.Connect(nil, nil)
|
server, err := link.Connect(nil, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -334,38 +322,47 @@ func pushCommand(ctx context.Context, args []string) error {
|
|||||||
}
|
}
|
||||||
fmt.Printf("\n%d node(s) told\n", len(sending))
|
fmt.Printf("\n%d node(s) told\n", len(sending))
|
||||||
|
|
||||||
// **A push leaves the mesh consistent, not just the machine it named** (novox/hq issue 057).
|
// **A named push leaves the mesh consistent, not just the machine it named** (novox/hq
|
||||||
// The machines whose declaration changed because of THIS push — providers a provision was
|
// issue 057, ADR 0083). Assigning a cross-node consumer mints a provision, and the PROVIDER's
|
||||||
// just minted from — are sent theirs too, by name, never silently: the alternative was a
|
// grant list is a pure read of secrets already issued — so after the named node is current,
|
||||||
// consumer that retries forever while nothing says the provider was left blind, and a rule
|
// other machines can be behind *as a consequence*: their declaration now differs from what
|
||||||
// ("push the provider node too") enforced by nothing. Bounded: a cascade send may itself
|
// they were last sent. Those are flushed too, by name, in the push's own output.
|
||||||
// mint, so this converges over a few rounds, each naming what changed and why.
|
//
|
||||||
if len(args) == 1 && before != nil {
|
// Compared against what each machine was last SENT, not against a before/after of this push:
|
||||||
delivered := map[string]bool{args[0]: true}
|
// the mint usually happened at `assign` or `module issue`, before this command ran, so the
|
||||||
for round := 0; round < 3; round++ {
|
// only durable signal is "what it should be" versus "what it last received". A machine behind
|
||||||
after, err := wouldSend(ctx, open, nodes)
|
// for an unrelated reason is caught here too, which is not a cost — a named push that knew a
|
||||||
|
// machine was behind and left it so would be the very silence this removes. Bounded: a
|
||||||
|
// flushed send may itself mint, so this converges over a few rounds.
|
||||||
|
if len(args) == 1 {
|
||||||
|
flushed := map[string]bool{args[0]: true}
|
||||||
|
for round := 0; round < 4; round++ {
|
||||||
|
would, err := wouldSend(ctx, open, nodes)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
behind, err := inv.Waiting(ctx, would)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
var also []string
|
var also []string
|
||||||
for name, digest := range after {
|
for _, m := range behind {
|
||||||
if !delivered[name] && before[name] != "" && before[name] != digest {
|
if !flushed[m.Node] {
|
||||||
also = append(also, name)
|
also = append(also, m.Node)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(also) == 0 {
|
if len(also) == 0 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
sort.Strings(also)
|
sort.Strings(also)
|
||||||
fmt.Printf("\nthis push changed what %s should be — a provision granted from "+
|
fmt.Printf("\nthis push left %s behind — a provision granted from there, or a "+
|
||||||
"there; sending it too\n", strings.Join(also, ", "))
|
"declaration since changed; sending it too\n", strings.Join(also, ", "))
|
||||||
if err := sendTo(ctx, open, also); err != nil {
|
if err := sendTo(ctx, open, also); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
for _, name := range also {
|
for _, name := range also {
|
||||||
delivered[name] = true
|
flushed[name] = true
|
||||||
}
|
}
|
||||||
before = after
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user