mesh/delivery merged: source.main moved to novox/mesh-sdk@7c015b652d36
mesh/delivery-group group feat/sdk1 merged: every member is merged
mesh/check failed: the composition: the composer at mesh-sdk f02f142af128b336c32a7f0059c5e1606bf9b1dc did not run: failed the composer git.novox.be/no…
The check of release sdk1 failed on TestStatePutWritesAKeyWhole: TestACallIsAskedAgainOnlyWhenItReachedNoOne left busretry's Bound at 50 ms, and on a loaded machine the state test's first pause overran it. Second failure of the kind "tests leave package-level state set". Quick fix: restore busretry's waits in the one test and lengthen the state test's bound. Thorough fix (chosen, the kind met twice): busretry.Waits sets the waits and returns their restore, used as t.Cleanup(busretry.Waits(...)) by every test that sets them, each with a bound of seconds where it waits to succeed; and servesAlone gives every test that serves its own runtime channel and Served, put back after it, instead of tests clearing the channel an earlier one left. A scan of every test assignment to a package-level variable found no other unrestored one. Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
55 lines
2.3 KiB
Go
55 lines
2.3 KiB
Go
package busretry
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/nats-io/nats.go"
|
|
"github.com/nats-io/nats.go/jetstream"
|
|
)
|
|
|
|
// Issue 774 (bus blackouts at every user-list reload): only a request that reached no one is asked again, within the
|
|
// bound; a blackout probe that says the bus answers ends the wait at once.
|
|
func TestABusThatAnswersNothingIsWaitedOut(t *testing.T) {
|
|
for _, row := range []struct {
|
|
name string
|
|
errs []error // what each try answers; the last repeats
|
|
blackout func() bool
|
|
tries int // at least
|
|
atMost int
|
|
delivered bool
|
|
}{
|
|
{"no responders, then an answer", []error{nats.ErrNoResponders, nats.ErrNoResponders, nil}, nil, 3, 3, true},
|
|
{"jetstream not enabled, then an answer", []error{jetstream.ErrJetStreamNotEnabled, nil}, nil, 2, 2, true},
|
|
{"said in words by a runtime", []error{errors.New("nats: no responders available for request"), nil}, nil, 2, 2, true},
|
|
{"a timeout may have been delivered: never asked again", []error{context.DeadlineExceeded}, nil, 1, 1, false},
|
|
{"an answer that refuses is an answer", []error{errors.New("refused")}, nil, 1, 1, false},
|
|
{"nobody answers on a bus that answers: the callee is not running", []error{nats.ErrNoResponders}, func() bool { return false }, 1, 1, false},
|
|
{"blacked out past the bound: said", []error{jetstream.ErrJetStreamNotEnabledForAccount}, func() bool { return true }, 2, 1000, false},
|
|
} {
|
|
// A row that ends in an answer waits on a bound of seconds, which no slow machine reaches; only the row that
|
|
// runs past it has a short one, and asks only that it was asked again at least once.
|
|
bound := 10 * time.Second
|
|
if strings.HasPrefix(row.name, "blacked out") {
|
|
bound = 100 * time.Millisecond
|
|
}
|
|
t.Cleanup(Waits(bound, time.Millisecond, 4*time.Millisecond))
|
|
tries := 0
|
|
_, err := Do("the test", func() (int, error) {
|
|
e := row.errs[min(tries, len(row.errs)-1)]
|
|
tries++
|
|
return tries, e
|
|
}, row.blackout)
|
|
if tries < row.tries || tries > row.atMost || (err == nil) != row.delivered {
|
|
t.Errorf("%s: %d tries, %v", row.name, tries, err)
|
|
}
|
|
if strings.HasPrefix(row.name, "blacked out") && (!Undelivered(err) || !strings.Contains(fmt.Sprint(err), "the bus answered nothing")) {
|
|
t.Errorf("%s: %v", row.name, err)
|
|
}
|
|
}
|
|
}
|