Begin the shadow composer again with a backoff when an input cannot be watched yet, and pin mesh-sdk's fixed head, so a node answers candidates for the whole link (issue 1126, review of L2b round 1)

This commit is contained in:
2026-10-27 02:44:39 +01:00
parent fbc6d6330f
commit d56c576e9a
5 changed files with 56 additions and 7 deletions
+32
View File
@@ -5,6 +5,7 @@ import (
"fmt"
"sort"
"sync"
"time"
"git.novox.be/novox/mesh-sdk/go/compose/frombus"
"git.novox.be/novox/mesh-sdk/go/delivery"
@@ -44,6 +45,37 @@ func NewShadow(env Env, answer func(ctx context.Context, answers map[string]deli
answers: map[string]delivery.CandidateAnswer{}}
}
// Keep runs the shadow until ctx ends, beginning again after backoff(try) whenever it stops: an input it cannot watch
// yet (the candidates' state not made, or the node's grant of it not loaded at a delivery) or a watch that ended is
// tried again rather than leaving the node answering nothing for the rest of the link (review of L2b, round 1, finding
// 2). Each distinct reason is said once.
func (s *Shadow) Keep(ctx context.Context, backoff func(try int) time.Duration) {
said := ""
for try := 1; ctx.Err() == nil; try++ {
began := time.Now()
err := s.Run(ctx)
if ctx.Err() != nil {
return
}
if time.Since(began) > time.Minute {
try = 1 // it ran: a later stop begins the waits again
}
why := "it stopped"
if err != nil {
why = err.Error()
}
if why != said {
s.c.env.Say("this node answers no placement candidate for now, and tries again: " + why)
said = why
}
select {
case <-ctx.Done():
return
case <-time.After(backoff(try)):
}
}
}
// Run answers until ctx ends or an input's watch ends.
func (s *Shadow) Run(ctx context.Context) error {
c := s.c