The view writes a reach or says an event again when the bus refused it, so a refused write never leaves the reach state at an older have (issue 1126)
mesh/delivery merged: source.main moved to novox/mesh-delivery@2ac146078f47
mesh/check being carried to 726bbf1f1ffa on 2ac146078f47 | from e753009fbc71

The view remembered a reach value, a reached head and a motion event as written or said before the bus took them; a write refused at its start (no responders) was never made again while the derivation stayed the same, and mesh-delivery.show said mesh-delivery-view not running on shanks while node_haves said it running.

Quick fix: forget only the refused reach write. Thorough fix, chosen: every write and event the view makes after its lock (reach, reached head, delivered revision, motion) answers its error, and the model forgets what was refused, so the next change it takes in makes it again; one place, the writer of the state both mesh-delivery.show and knowledge-base.progress read.
This commit is contained in:
2026-10-28 16:11:52 +01:00
parent e753009fbc
commit 726bbf1f1f
5 changed files with 140 additions and 41 deletions
@@ -75,12 +75,14 @@ func run(ctx context.Context, getenv func(string) string, logOut io.Writer) erro
}
defer conn.Close()
model.SetWriter(kvWriter{ctx: ctx, js: js})
model.SetMotionEvent(func(e view.MotionEvent) {
if err := emitEvent(ctx, js, cred, e.Type, e.Body, e.ID); err != nil {
logger.Printf("the %s of %s on %s could not be said: %v", e.Type, e.Body.Module, e.Body.Node, err)
model.SetMotionEvent(func(e view.MotionEvent) error {
err := emitEvent(ctx, js, cred, e.Type, e.Body, e.ID)
if err != nil {
logger.Printf("the %s of %s on %s could not be said (said again at its next change): %v", e.Type, e.Body.Module, e.Body.Node, err)
}
return err
})
model.SetDeliveredEvent(func(e view.DeliveredEvent) {
model.SetDeliveredEvent(func(e view.DeliveredEvent) error {
id := fmt.Sprintf("delivered.%d", e.Revision)
if e.Repository != "" { // a repository's reached head (ADR 0556 clause 3)
key, _ := delivery.RepositoryKey(e.Repository)
@@ -90,14 +92,18 @@ func run(ctx context.Context, getenv func(string) string, logOut io.Writer) erro
id += "." + hex.EncodeToString(sum[:6])
}
}
if err := emitEvent(ctx, js, cred, DeliveredEventType, e, id); err != nil {
logger.Printf("the delivery of source revision %d could not be said: %v", e.Revision, err)
err := emitEvent(ctx, js, cred, DeliveredEventType, e, id)
if err != nil {
logger.Printf("the delivery of source revision %d could not be said (said again at the next change the view takes in): %v", e.Revision, err)
}
return err
})
model.SetReachWriter(func(w view.ReachWrite) {
if err := putReach(ctx, js, w); err != nil {
logger.Printf("the reach of %s could not be written (written again at its next change): %v", w.Key, err)
model.SetReachWriter(func(w view.ReachWrite) error {
err := putReach(ctx, js, w)
if err != nil {
logger.Printf("the reach of %s could not be written (written again at the next change the view takes in): %v", w.Key, err)
}
return err
})
model.SetBacklog(view.BacklogOver(js, 5*time.Second))
for _, bucket := range []string{delivery.HaveBucket, view.AssignmentsBucket, view.BuildsBucket, delivery.PresenceBucket, delivery.StuckBucket, delivery.CandidatesBucket, delivery.ModulesBucket, delivery.AsksBucket, delivery.AnswersBucket, delivery.BuilderBuildsBucket, delivery.AssignerWantsBucket, delivery.SourceBucket, delivery.ControllerComposedBucket, delivery.AssignerAsksBucket, delivery.ViewAnswersBucket, delivery.TakenBucket} {