You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A deliberate DLQ replay can tell its handler to skip external side-effects that
already fired (don't re-charge/re-email) while the idempotent core still runs —
mirroring the Go reference. New src/replay.ts (HEADER_REPLAY_BYPASS + isReplay +
bypassExternalEffects) + redrive bypass wiring. Rides the out-of-band HeaderCarrier
seam beside the frozen envelope (GR-1), trace_id preserved (GR-4). Opt-in. v1.5.0.
Copy file name to clipboardExpand all lines: test/conformance/manifest.json
+74Lines changed: 74 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -68,6 +68,80 @@
68
68
"reason": "no 'job' or 'urn' — the message has no identity"
69
69
}
70
70
],
71
+
"idempotency": {
72
+
"description": "Consumer idempotency conformance (ADR-0022). Broker-free: locks the seen-set dedupe contract every SDK's optional idempotency helper (Go idempotency.Wrap, PHP Idempotent::wrap, Python idempotency.wrap, Node Wrap, Java Idempotent.wrap) MUST honour over the frozen schema_version-1 envelope, independent of any transport. The helper does NOT touch the wire envelope — the cases above stay byte-identical; this block governs the consume-side decision (run the handler, or skip-and-ack) keyed on meta.id.",
73
+
"dedup_key": {
74
+
"description": "The dedupe key is meta.id verbatim — the canonical per-message identity (distinct from trace_id, which spans a causal chain). A consumer MUST key its seen-set on exactly fixtures/order-created.json's meta.id; two deliveries with the same meta.id are the SAME message (a redelivery), even byte-for-byte identical, and dedupe to one effect. trace_id is NOT the key: messages sharing a trace_id but with distinct meta.id are distinct effects.",
"description": "Each sequence drives ONE handler wrapped by the SDK's idempotency helper, backed by ONE seen-set store, through an ordered list of deliveries. For each delivery the SDK MUST derive the effect: 'run' = the wrapped handler is invoked (the side-effect fires) and, on its outcome 'ok', the id is remembered; 'skip' = an already-remembered id is recognised, the handler is NOT invoked, and the delivery is acked (the runtime stops redelivering). 'outcome' is the handler's result for a 'run' delivery: 'ok' = returns/acks (remembered), 'throw' = raises/errors (the id is left UNMARKED so a later redelivery runs it again — retry/DLQ still apply). After replaying the whole sequence, total 'run'+'ok' invocations MUST equal expected_effects. This is at-least-once delivery collapsed to an exactly-once EFFECT by the consumer; it is seen-set post-success dedupe, NOT exactly-once delivery and NOT an in-flight concurrency lock.",
81
+
"cases": [
82
+
{
83
+
"name": "duplicate-delivery-runs-once",
84
+
"description": "The same meta.id delivered twice (a textbook at-least-once redelivery): first runs the effect, second is skipped. One effect.",
"description": "Three redeliveries of one id (a flaky broker / worker-crash-before-ack storm): the effect fires once; every subsequent redelivery is a no-op skip.",
"description": "A handler that throws does NOT remember the id, so the next redelivery runs it again (retry semantics survive the guard). The third delivery succeeds and is then deduped on a fourth.",
"description": "A message with no usable meta.id (empty/absent) CANNOT be deduped, so the helper fails open: every delivery runs the handler. The guard never silently drops work it cannot identify.",
"description": "forget(id) evicts an id from the seen-set, so a later delivery of that id runs again (manual replay / TTL expiry). Locks the third Store method.",
"description": "Amazon SQS binding conformance (broker-bindings.md §3). Every SDK that ships an SQS transport must satisfy these. The envelope body stays byte-identical (the 'cases' above); these lock the native projection + reconciliation the binding adds. Per-message values reuse fixtures/order-created.json so the expected attributes are deterministic.",
0 commit comments