Commit 1e6af43
fix(webapp): IdempotencyKeyConcern honours buffered-run TTL on idempotency expiry
PG-resident path enforces `idempotencyKeyExpiresAt`: when an existing
PG row is found, the lookup compares its `expiresAt` against now,
clears the key on expiry, and lets a new run go through. The buffered
path was missing this — `findBufferedRunWithIdempotency` returned any
buffered run whose snapshot carried the key, regardless of how long
ago the customer's TTL had elapsed. `idempotencyKeyTTL: "2s"` plus
a second trigger 4s later would return the original buffered runId.
Two layers needed the fix:
1. **Read-side (this concern).** Surface
`idempotencyKeyExpiresAt` on `SyntheticRun` (the snapshot already
stores it; `findRunByIdWithMollifierFallback` just wasn't exposing
it). In `findBufferedRunWithIdempotency`, apply the same
`expiresAt < new Date()` check as the PG path and return null on
expiry.
2. **Write-side (the buffer's accept dedupe).** Returning null from
step 1 isn't enough: the trigger pipeline then proceeds to
`mollifyTrigger`, whose `buffer.accept` Lua dedupes by
`(envId, taskIdentifier, idempotencyKey)` via SETNX on the same
`mollifier:idempotency:*` key and would still echo the stale runId
as `duplicate_idempotency`. On expiry, clear the buffer-side
idempotency binding via `buffer.resetIdempotency` — the same
primitive `ResetIdempotencyKeyService` uses for the explicit
reset-via-API path. The next accept then goes through as a fresh
trigger.
Verified end-to-end: with mollifier active and
`idempotencyKeyTTL: "2s"`, a same-key retrigger after 4s returns a
new runId; same-key retriggers within the TTL still dedupe to the
original.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>1 parent 6458243 commit 1e6af43
2 files changed
Lines changed: 46 additions & 0 deletions
File tree
- apps/webapp/app
- runEngine/concerns
- v3/mollifier
Lines changed: 39 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
92 | 92 | | |
93 | 93 | | |
94 | 94 | | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
95 | 134 | | |
96 | 135 | | |
97 | 136 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
44 | 44 | | |
45 | 45 | | |
46 | 46 | | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
47 | 53 | | |
48 | 54 | | |
49 | 55 | | |
| |||
178 | 184 | | |
179 | 185 | | |
180 | 186 | | |
| 187 | + | |
181 | 188 | | |
182 | 189 | | |
183 | 190 | | |
| |||
0 commit comments