Files
poimen/tasks/T10.3-idempotent-run-admission.md

2.6 KiB

T10.3 — Idempotent run admission

Field Value
Phase P10 — Orchestration
Size S — under 1 day
Status Not started
Flags
Spec inlined below
Blocks T10.4, T10.7

Goal

dispatch_key on spawn requests: a redelivered spawn request (from Kafka at-least-once delivery, T10.7) becomes a no-op insert instead of a duplicate run.

Facts (inlined — no spec read needed)

  • Same principle as the outbox's (BranchKey, Lsn) fold-key idempotency (T7.4) — exactly-once is achieved at the admission boundary, not in transport.
  • dispatch_key is caller-supplied, opaque, unique per intended spawn — e.g. a Reconciler decision id.
  • Admission with no dispatch_key behaves exactly as today. This is additive, not a required field.

Steps

  1. Add optional dispatch_key: Option<String> to spawn-run input.
  2. Add a unique index on (TenantId, dispatch_key) where dispatch_key is set.
  3. On spawn: if dispatch_key is set and already seen, return the existing RunId instead of creating a new run — no error, no duplicate.
  4. Test redelivery: same dispatch_key submitted twice, concurrently and sequentially.

Acceptance

  • Two spawn calls with the same dispatch_key produce exactly one run; the second call returns the first run's RunId.
  • Spawn calls with no dispatch_key are unaffected.

Verify

Harness: spawn endpoint (T10.4) or direct kernel call, two concurrent callers.

Integration testtests/it_idempotent_admission.rs:

  1. Spawn with dispatch_key=K; assert one run created, RunId=R.
  2. Spawn again with dispatch_key=K; assert no new run created, returned RunId == R.
  3. Fire 20 concurrent spawn calls with the same dispatch_key; assert exactly one run exists after all resolve.
  4. Spawn with no dispatch_key twice; assert two distinct runs (unaffected baseline).

Command: cargo test -p kernel idempotent_admission -- --test-threads=1

False pass:

  • Testing only sequential redelivery. Concurrent redelivery is the actual failure mode under Kafka rebalance/retry and needs the unique-index race caught, not a check-then-insert race.

Traps

  • Making dispatch_key required. Breaks every direct/manual spawn call that isn't part of a goal chain.
  • Deduping by a hash of (workflow_ref, input) instead of the caller-supplied key. Two legitimately identical requests would then silently collapse into one run.

Background (not required to do this task): rust-agentic-sys.md §8.3, §9.3 · T7.4-outbox-relay.md · T3.6-version-pinning-at-spawn.md