A try's end is said on a context its own stop does not cancel (issue 1921)
mesh/check being carried to d58b71724312 on 2d201f781ced | from 205a3b37501f
mesh/delivery merged: source.main moved to novox/mesh-delivery@2d201f781ced

The end a run writes comes back on the key's watch, where Put stops the run's context and leaves the saying to the run, so the end was never said and the indexer kept the try's candidate. The group try's unit test now echoes the end on the watch while the run says it.

Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
This commit is contained in:
2026-11-06 10:33:49 +01:00
parent 29c525f48d
commit d58b717243
2 changed files with 17 additions and 2 deletions
@@ -711,7 +711,10 @@ func (tr *Tryer) run(ctx context.Context, key string) {
return
}
tr.logf("%s: %s", key, t.State)
tr.sendEnd(ctx, key)
// The end just written comes back on the key's watch, and Put then stops this run's context (it stops judging a try
// ended by hand) while this run says the end, which Put's own say leaves to it: the end is said on a context that
// stop does not cancel, or it is never said and the indexer keeps the candidate of the try's group.
tr.sendEnd(context.WithoutCancel(ctx), key)
}
// sendEnd says the end of an ended try whose start was said (Told) with the state it ended in, then clears Told in the try's
@@ -188,7 +188,19 @@ func TestATryIsJudgedAsAGroupsCheckAndOwesTheForgeNothing(t *testing.T) { // ADR
var waiting string
cands.during = func() { waiting = readTry(t, kv, id).Waiting } // ADR 0639 §5: the stored try says what it waits for
var said []string
tr := &Tryer{Tries: written, Judge: b.ex, Say: func(_ context.Context, event string, e tryevent.Event) error {
var tr *Tryer
echoed := false
tr = &Tryer{Tries: written, Judge: b.ex, Say: func(ctx context.Context, event string, e tryevent.Event) error {
if event == tryevent.Ended && !echoed {
// The end the run wrote comes back on the key's watch while the run says it: Put stops the run's context and
// leaves the saying to the run, whose say must not be stopped with it (issue 1921).
echoed = true
raw, _, _, _ := kv.Get(context.Background(), id)
tr.Put(context.Background(), id, raw)
}
if err := ctx.Err(); err != nil {
return err // a publish on a stopped context is never acknowledged
}
said = append(said, fmt.Sprintf("%s %s %d %s", event, e.ID, len(e.Members), e.State))
return nil
}}