JetStreamAsks.WatchAsk opens the watch as a kept call and takes a closed watch up after the last revision heard; the first fault arms a key of the state bounds with its own time to live (StepsBoundKey), whose end while the read is unanswered raises call-unanswered about the ask, and the answer ends it. Builds: design 47 G §568, A-77 Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
44 lines
2.1 KiB
Go
44 lines
2.1 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/nats-io/nats.go/jetstream"
|
|
|
|
"git.novox.be/novox/mesh-contracts/health-and-repair/go/clients/meshconditionsclient"
|
|
|
|
"mesh-delivery-builder/internal/versions"
|
|
)
|
|
|
|
// Design 47 G §568, A-77: the first fault of the read of an ask's steps arms a bound key with its own time to live; its end
|
|
// while the read is unanswered raises call-unanswered about the ask; the answer deletes the bound and clears the finding.
|
|
func TestTheStepsReadIsCallUnansweredAfterItsBound(t *testing.T) {
|
|
st := &memFindings{vals: map[string][]byte{}}
|
|
f := &findings{w: st, logf: t.Logf, now: func() time.Time { return time.Unix(0, 0) }}
|
|
marks := &memBounds{keys: map[string]bool{}}
|
|
s := &stepsRead{bounds: func() jetstream.KeyValue { return marks }, findings: f, bound: meshconditionsclient.CallUnansweredAfter,
|
|
now: func() time.Time { return time.Unix(600, 0) }, logf: t.Logf}
|
|
ask := "mvl0frv18d1958"
|
|
callKey := meshconditionsclient.Key(meshconditionsclient.ScopeCall, ask, meshconditionsclient.KindCallUnanswered)
|
|
s.unanswered("mesh-build-go", ask, errors.New("nats: no responders available for request"))
|
|
if !marks.keys[versions.StepsBoundKey("mesh-build-go", ask)] || st.vals[callKey] != nil {
|
|
t.Fatalf("a first fault: bound %v, finding %v; want the bound armed, no finding yet", marks.keys, st.vals[callKey] != nil)
|
|
}
|
|
s.expired(context.Background(), purged{key: versions.StepsBoundKey("mesh-build-go", ask)})
|
|
if got, err := decodeFinding(st.vals[callKey]); err != nil || got.Kind != meshconditionsclient.KindCallUnanswered || !strings.Contains(got.Summary, "the steps of mesh-build-go") || !strings.Contains(got.Summary, ask) {
|
|
t.Fatalf("the bound's end: the finding = %+v, %v", got, err)
|
|
}
|
|
s.answered("mesh-build-go", ask)
|
|
if marks.keys[versions.StepsBoundKey("mesh-build-go", ask)] || st.vals[callKey] != nil {
|
|
t.Errorf("the read answered: bound %v, finding left %v", marks.keys, st.vals[callKey] != nil)
|
|
}
|
|
s.expired(context.Background(), purged{key: versions.StepsBoundKey("mesh-build-go", ask)})
|
|
if st.vals[callKey] != nil {
|
|
t.Error("a bound's end after the answer raised call-unanswered")
|
|
}
|
|
}
|