jsconsumer: report an unconfirmed final ack as uncertain, not stranded

Commit

nodo3w ago

DoubleAck failing does not prove the ack failed. It waits for the server's confirmation, and a lost or timed-out confirmation is indistinguishable from one the server never sent — the message may be settled and gone. Reporting that as OutcomeStranded claimed knowledge the client does not have, on the one field that drives alerts and runbooks.

The over-claim had a destructive remedy attached: "stranded" sends a responder to the break-glass removal, and removing a stream message this consumer has in fact acked takes it away from every OTHER consumer of that stream. So a final delivery whose capture succeeded but whose ack went unconfirmed is now OutcomeUncertain, and the log carries the check that resolves it — has the ack floor advanced past this sequence? If it has, the ack landed and there is nothing to do; if not, treat it as stranded and follow that runbook.

OutcomeStranded keeps its meaning for the case that IS provable: the capture itself failed, so nothing reached the DLQ and the stream copy is all there is.

Not given a third state: the same failure with deliveries remaining. Either the ack landed and the message is gone, or it redelivers and is captured again — both benign, neither wants an operator, so it stays OutcomeRetried with the ambiguity noted.

Also corrects a claim this package had started making about itself. The README said a second scheduler was "unrepresentable rather than merely rejected". RetryConfig has no ladder fields, so nothing configured there can schedule redelivery — but a handler still holds the jetstream.Msg and can NakWithDelay itself, and backoff.Policy remains exported for callers that predate this package. Single-scheduler is an adoption contract: route every failed delivery through Settle. Schedule flags the combination wherever a config is modelled; nothing stops it at runtime, and saying otherwise invites exactly the handler that does it.

Refs ENT-1601, ENT-1535.

Co-Authored-By: Claude Opus 5 (1M context) noreply@anthropic.com Claude-Session: https://claude.ai/code/session_01AJNdqGnT92NC2TRnpf8MNr Entire-Checkpoint: b64ecf03ddb2

Checkpoints

Fix NATS Consumer Retry Ladder Implementation

Claude CodeOpus 5
View session
Checkpoint 1