diff --git a/internal/link/asktool_nats_test.go b/internal/link/asktool_nats_test.go index 7e266cf..9d22019 100644 --- a/internal/link/asktool_nats_test.go +++ b/internal/link/asktool_nats_test.go @@ -2,10 +2,12 @@ package link import ( "context" + "errors" "strings" "testing" "time" + "git.novox.be/novox/mesh-sdk/go/busretry" "github.com/nats-io/nats.go" ) @@ -37,4 +39,11 @@ func TestNatsAToolCheckIsAskedOnTheLink(t *testing.T) { if err == nil || !strings.Contains(err.Error(), "nothing on this machine answers") { t.Fatalf("a tool nothing serves read as %v", err) } + // The bus's "no responders" is kept beside ErrNotAsked, so a reader that asks again while its request reached no one + // (busretry.Undelivered) sees it (issue 1966: the seat list's first read fell into its holder's re-serve and was never + // asked again). + _, err = (&natsLink{conn: conn, js: js, node: node}).Ask(ctx, ToolSubject("sensors", "nothing_serves_this", node), nil) + if !errors.Is(err, ErrNotAsked) || !errors.Is(err, nats.ErrNoResponders) || !busretry.Undelivered(err) { + t.Fatalf("an ask nothing serves read as %v: want ErrNotAsked and the bus's no responders, undelivered", err) + } } diff --git a/internal/link/hearing_nats.go b/internal/link/hearing_nats.go index e9f9fba..50fa1a9 100644 --- a/internal/link/hearing_nats.go +++ b/internal/link/hearing_nats.go @@ -324,8 +324,10 @@ func (l *natsLink) Ask(ctx context.Context, subject string, body []byte) ([]byte case err == nil: return reply, nil case errors.Is(err, nats.ErrNoResponders): - // The server says nobody subscribes the subject: delivered to no one. - return nil, fmt.Errorf("%w: nothing on this machine answers %s", ErrNotAsked, subject) + // The server says nobody subscribes the subject: delivered to no one. The bus's own error stays beside ErrNotAsked, + // so a caller that asks again while a request reached no one (mesh-sdk busretry.Undelivered, as the seat list's + // reader does while its holder re-serves; issue 1966) sees it. + return nil, fmt.Errorf("%w: nothing on this machine answers %s (%w)", ErrNotAsked, subject, err) } if refused := l.refusal(subject, before); refused != "" { return nil, fmt.Errorf("%s: %v%s", subject, err, refused)