A read the bus did not answer is tried again after a bound, never kept as an answer: the shadow's answer, the node's composition and the own-secret step (issue 1126)
Met twice on 2026-10-28: shanks kept 'want.shanks.brother could not be read ... no responders' as the own-secret step's last word, and ace kept 'the vault's own: not yet ... no responders' as its answer to seed-7, each until another input moved. Every bus read of the composer (manifests, builds, archives, served values, the vault's own and credentials, the have of what runs) is noted (BusFailed); an answer or a pass that met one is made again after a growing bound (5 s to 5 min), and a pass is not handed when the have of its sealed values did not answer. The own-secret step tells a read or an ask that did not answer (Retry, taken again) from a key absent or the vault's word.
This commit is contained in:
@@ -75,8 +75,12 @@ func (h sessionHaves) Read(ctx context.Context, module string) (agent.Have, bool
|
||||
// ReadErr is Read telling a have absent from one the bus could not read (agent.HavesReadErr).
|
||||
func (h sessionHaves) ReadErr(ctx context.Context, module string) (agent.Have, bool, error) {
|
||||
if module == agent.NodeModule {
|
||||
got, ok := h.Read(ctx, module)
|
||||
return got, ok, nil
|
||||
// The node's own key, its read the bus did not answer told as such (issue 1126, 2026-10-28).
|
||||
got, ok, err := h.session.ReadNodeHaveErr(ctx)
|
||||
if !ok || err != nil || got.Composed == "" {
|
||||
return agent.Have{}, false, err
|
||||
}
|
||||
return agent.Have{Module: module, Composed: got.Composed, Sealed: got.SealedAt}, true, nil
|
||||
}
|
||||
got, ok, err := h.session.ReadHaveErr(ctx, module)
|
||||
if !ok || err != nil {
|
||||
@@ -535,16 +539,17 @@ func nodeAgent(ctx context.Context, opts options, signer ed25519.PublicKey, sess
|
||||
},
|
||||
unseal: sealOpener(opts.state),
|
||||
// And what each module's have says it runs sealed: after a restart the agent has applied nothing yet.
|
||||
held: func(module string) (delivery.Seals, []string) {
|
||||
// A have the bus did not answer for is said as such, never as one holding no seals (issue 1126, 2026-10-28).
|
||||
held: func(module string) (delivery.Seals, []string, error) {
|
||||
if module == agent.NodeModule {
|
||||
got, _ := session.ReadNodeHave(linked)
|
||||
return got.SealedAt, got.Sealed
|
||||
got, _, err := session.ReadNodeHaveErr(linked)
|
||||
return got.SealedAt, got.Sealed, err
|
||||
}
|
||||
got, ok := session.ReadHave(linked, module)
|
||||
got, ok, err := session.ReadHaveErr(linked, module)
|
||||
if !ok {
|
||||
return nil, nil
|
||||
return nil, nil, err
|
||||
}
|
||||
return got.SealedAt, got.Sealed
|
||||
return got.SealedAt, got.Sealed, nil
|
||||
},
|
||||
refused: func(why string) {
|
||||
if now := own.get(); now != nil && run.Err() == nil {
|
||||
@@ -879,7 +884,7 @@ type composerHooks struct {
|
||||
running func() []delivery.Composed
|
||||
unseal func(string) ([]byte, error)
|
||||
refused func(string)
|
||||
held func(module string) (delivery.Seals, []string)
|
||||
held func(module string) (delivery.Seals, []string, error)
|
||||
}
|
||||
|
||||
func selfComposer(ctx context.Context, session *link.Session, node string, say func(string), hooks composerHooks) (*selfcompose.Composer, string) {
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"git.novox.be/novox/mesh-sdk/go/delivery"
|
||||
|
||||
@@ -30,6 +31,10 @@ type resyncStep struct {
|
||||
one sync.Mutex
|
||||
mu sync.Mutex
|
||||
last map[string]delivery.CandidateAnswer
|
||||
// tries and pending are the step taken again after a bound when a read or an ask the bus did not answer stopped it
|
||||
// (Outcome.Retry, issue 1126, 2026-10-28), one wait at a time.
|
||||
tries int
|
||||
pending bool
|
||||
}
|
||||
|
||||
func ownResync(session *link.Session, node string, say func(string), env selfcompose.Env, composes *composesNow) *resyncStep {
|
||||
@@ -48,14 +53,42 @@ func (s *resyncStep) take(ctx context.Context, answers map[string]delivery.Candi
|
||||
s.again(ctx)
|
||||
}
|
||||
|
||||
// again takes the last answers.
|
||||
// again takes the last answers, and once more after a bound (selfcompose.LaterWait) while the bus did not answer for one.
|
||||
func (s *resyncStep) again(ctx context.Context) {
|
||||
s.one.Lock()
|
||||
defer s.one.Unlock()
|
||||
s.mu.Lock()
|
||||
last := s.last
|
||||
s.mu.Unlock()
|
||||
if last != nil {
|
||||
s.r.Take(ctx, last)
|
||||
if last == nil {
|
||||
return
|
||||
}
|
||||
retry := false
|
||||
for _, o := range s.r.Take(ctx, last) {
|
||||
retry = retry || o.Retry
|
||||
}
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
if !retry {
|
||||
s.tries = 0
|
||||
return
|
||||
}
|
||||
if s.pending || ctx.Err() != nil {
|
||||
return
|
||||
}
|
||||
wait := selfcompose.LaterWait(s.tries)
|
||||
s.tries++
|
||||
s.pending = true
|
||||
go func() {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
case <-time.After(wait):
|
||||
}
|
||||
s.mu.Lock()
|
||||
s.pending = false
|
||||
s.mu.Unlock()
|
||||
if ctx.Err() == nil {
|
||||
s.again(ctx)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user