Skip to content

Commit 624e26d

Browse files
docs(requester): document the no-graceful-drain-on-shutdown caveat
Audit concurrency finding (Low): on ctx cancellation processQueues returns immediately, so transactions still held in a queue are discarded without a WARN — the one gap in the no-silent-drops invariant, which holds in steady state but not across shutdown/restart. Document this at the ctx.Done() return and note the exception in the top-of-file invariant, so the limitation is discoverable and a future drain has an obvious home. Comment-only; no behavior change. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 22377e5 commit 624e26d

1 file changed

Lines changed: 11 additions & 1 deletion

File tree

services/requester/tx_mempool.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,9 @@ import (
101101
// Cross-cutting invariants
102102
// - No silent drops: for any accepted tx id you can either find it on-chain
103103
// (submitted) or find a WARN log saying it was dropped (submit failure or
104-
// stale prune) — never nothing. See logSubmission.
104+
// stale prune) — never nothing. See logSubmission. The one exception is
105+
// shutdown: held-but-not-yet-submitted txs are discarded without a WARN when
106+
// the pool's context is cancelled (no graceful drain — see processQueues).
105107
// - Failure handling: a failed submission drops the batch (clients resubmit)
106108
// and never wedges the EOA (the in-flight marker is rolled back). The pool
107109
// does NOT retry internally.
@@ -644,6 +646,14 @@ func (t *TxMemPool) processQueues(ctx context.Context) {
644646
for {
645647
select {
646648
case <-ctx.Done():
649+
// Shutdown is NOT a graceful drain: any transactions still held in a
650+
// queue (waiting on their collection window, gap fill, or TTL) are
651+
// dropped without a WARN, which is the one gap in the no-silent-drops
652+
// invariant — it holds during steady-state operation, not across a
653+
// shutdown/restart. This is acceptable because clients resubmit, and
654+
// a held tx has not been sent to Flow (nothing on-chain to reconcile
655+
// against). If this ever needs to change, drain due+held batches here
656+
// before returning rather than relying on resubmission.
647657
return
648658
case <-ticker.C:
649659
for _, w := range t.collectDueBatches() {

0 commit comments

Comments
 (0)