From 5ab0d8ca888b84976109e81c901c5134b5f009d4 Mon Sep 17 00:00:00 2001 From: jochen Date: Mon, 9 Nov 2026 22:48:02 +0100 Subject: [PATCH] Subtask B: the teller says an assigner ask written again under the id the router kept is not asked, with a row per kind that a new asking is asked again (issue 1966) Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ --- .../cmd/mesh-delivery-teller/assignerasks.go | 4 ++ .../mesh-delivery-teller/assignerasks_test.go | 45 +++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/modules/mesh-delivery-teller/cmd/mesh-delivery-teller/assignerasks.go b/modules/mesh-delivery-teller/cmd/mesh-delivery-teller/assignerasks.go index 2fbc1626..5a500ce8 100644 --- a/modules/mesh-delivery-teller/cmd/mesh-delivery-teller/assignerasks.go +++ b/modules/mesh-delivery-teller/cmd/mesh-delivery-teller/assignerasks.go @@ -168,6 +168,10 @@ func (t *Teller) raiseAssignerAsk(key string) { } if open(k) { t.catchUp(id) + } else { + // Said, never silent (issue 1966: a record ask taken back when its key went was written again under the same id on + // 2026-11-09 and nothing said why the operator was never asked): the assigner numbers each writing (asks.Ask.Asking). + t.logf("%s: the ask %s ended (answered, lapsed or taken back) and the assigner wrote the key again under the same id: not asked again, the router would drop it; a writing under a new asking is asked", key, id) } return } diff --git a/modules/mesh-delivery-teller/cmd/mesh-delivery-teller/assignerasks_test.go b/modules/mesh-delivery-teller/cmd/mesh-delivery-teller/assignerasks_test.go index 9a878ce6..2ac7343d 100644 --- a/modules/mesh-delivery-teller/cmd/mesh-delivery-teller/assignerasks_test.go +++ b/modules/mesh-delivery-teller/cmd/mesh-delivery-teller/assignerasks_test.go @@ -209,3 +209,48 @@ func TestABurstOfHoldsLeavesRoomForAMergeAsk(t *testing.T) { t.Errorf("asked %v after the merge ask was answered, want no further hold", got) } } + +// Issue 1966 (nats on novox): an assigner ask taken back when its key went is asked again when the assigner writes the key +// again under a new asking, whatever its kind; written again under the id the router kept it is not (the router would drop it) +// and the teller says so, never silent. +func TestAnAssignerAskWrittenAgainAfterBeingTakenAwayIsAskedAgainUnderANewAsking(t *testing.T) { + digest := "sha256:" + strings.Repeat("e", 64) + fp := "src2:" + strings.Repeat("a", 64) + recordKey, _ := asks.RecordAskKey("novox", "nats", digest) + restoreKey, _ := asks.RestoreAskKey("novox", "nats", fp) + holdKey, _ := asks.HoldAskKey("nats", fp) + for kind, key := range map[string]string{"record": recordKey, "restore": restoreKey, "hold": holdKey} { + t.Run(kind, func(t *testing.T) { + write := func(assigner memGate, asking int) oc.Ask { + ask := oc.Ask{ID: meshdeliveryclient.AskingID(key, asking), Headline: "nats waits", Explanation: "e", Who: occ.Operator, + Expires: occ.FormatTime(now.Add(occ.ApproveLasts)), OnExpiry: "stays", + Options: []oc.Option{{ID: "yes", Label: "Yes", Does: "d", Level: occ.Acknowledge}, {ID: "no", Label: "No", Does: "d", Level: occ.Acknowledge}}} + value, err := asks.EncodeAsk(key, asks.Ask{Ask: rawAsk(t, ask), Asking: asking}) + if err != nil { + t.Fatal(err) + } + assigner[key] = value + return ask + } + b := newBed(t) + assigner, _ := withView(b) + first := write(assigner, 1000) + b.t.OnAssignerAsk(key) + delete(assigner, key) + b.t.OnAssignerAskGone(key) // the assigner took it away as stale: the router ask is taken back + second := write(assigner, 1060) + b.t.OnAssignerAsk(key) + if got := b.askedIDs(); len(got) != 2 || got[0] != first.ID || got[1] != second.ID || first.ID == second.ID { + t.Fatalf("asked %v, want %s then %s; log:\n%s", got, first.ID, second.ID, b.logs.String()) + } + // Written again under the id the router kept, after it was taken back: not asked, and said. + delete(assigner, key) + b.t.OnAssignerAskGone(key) + write(assigner, 1060) + b.t.OnAssignerAsk(key) + if got := b.askedIDs(); len(got) != 2 || !strings.Contains(b.logs.String(), "wrote the key again under the same id") { + t.Errorf("asked %v after the same id was written again; log:\n%s", got, b.logs.String()) + } + }) + } +}