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
{{ message }}
Repository navigation
Commit da93e87
Browse filesBrowse the repository at this point in the historyBrowse files
fix(batchTrigger): clear idempotency key when previous run failed + dedupe replacement ids (closestriggerdotdev#4819)
batchTrigger silently returned stale failed runs as isCached: true, so a
caller re-batching with the same idempotency key never got a retry. The
single-trigger path has done the right thing since day one via
`IdempotencyKeyConcern.handleExistingRun` ->
`shouldIdempotencyKeyBeCleared`
(apps/webapp/app/runEngine/concerns/idempotencyKeys.server.ts:463). The
batch path at batchTriggerV3.server.ts:450 just ignored the status.
Root cause (as @Jaimin2687 identified on the issue):
* `PostgresRunStore.findRunsByIdempotencyKeys` SELECTed 5 columns —
id, createdAt, friendlyId, idempotencyKey, idempotencyKeyExpiresAt.
* `status` was missing, and `IdempotencyKeyRunMatch` did not type it.
* `#prepareRunData` therefore had only time-based expiry to work with
and no way to see that the cached run was CRASHED / SYSTEM_FAILURE /
COMPLETED_WITH_ERRORS / INTERRUPTED / TIMED_OUT / EXPIRED.
Fix (additive, five files):
- internal-packages/run-store/src/types.ts
* `IdempotencyKeyRunMatch` gains a required `status: TaskRunStatus`.
* Comment explains the invariant for the next reader.
- internal-packages/run-store/src/PostgresRunStore.ts
* The hot-path UNION ALL SQL now also selects `"status"`. One token
added per branch, no new rows read, no index change needed —
(runtimeEnvironmentId, taskIdentifier, idempotencyKey) already
uniquely identifies the row.
- apps/webapp/app/v3/services/batchTriggerV3.server.ts
* `#prepareRunData` imports `shouldIdempotencyKeyBeCleared` and ORs
it with the existing time-based expiry check. A cached run whose
status is in the "clear me" set is treated exactly like an expired
cache entry.
* **Dedupe replacement ids per (task, idempotencyKey)**: when two
items share a key AND the cached run is cleared, downstream
`#processBatchTaskRunItem` only creates ONE run per key
(TriggerTaskService.call honours the key and reuses the first
fresh run for subsequent items). Allocating distinct minted ids
per item left the response referencing ghost ids. We now pre-
allocate one replacement id per (task, key) combo and reuse it
for every matching item. This also fixes the pre-existing time-
expiration branch — the status-based branch exposed the same bug
on more inputs. (Devin review on triggerdotdev#5014.)
- internal-packages/run-store/src/PostgresRunStore.findRunsByIdempotencyKeys.test.ts
* `createRun` helper gains an optional `status` param.
* New postgresTest "returns run status so callers can honour
shouldIdempotencyKeyBeCleared" creates four seed rows (PENDING,
CRASHED, COMPLETED_WITH_ERRORS, COMPLETED_SUCCESSFULLY) and
asserts the store surfaces each status in the result. Locks the
contract batchTrigger depends on.
- .server-changes/batchtrigger-clears-failed-idempotency-key.md
* User-facing release note per `.server-changes/README.md`.
Reporter: @Jaimin2687 (full RCA in the issue). Devin reviewed the first
revision and surfaced the dedupe gap + the TIMED_OUT comment typo + the
missing release note — all addressed here. The one remaining Devin
suggestion (full integration test calling `BatchTriggerV3Service.call`
with a failed-key batch) is deferred; happy to split it out if a
maintainer prefers it in this PR.
return`SELECT "id", "createdAt", "friendlyId", "idempotencyKey", "idempotencyKeyExpiresAt" FROM "TaskRun" WHERE "runtimeEnvironmentId" = $${base+1} AND "taskIdentifier" = $${base+2} AND "idempotencyKey" = $${base+3}`;
1927
+
// "status" is required so callers can honour shouldIdempotencyKeyBeCleared
1928
+
// (closes #4819 — batchTrigger previously returned stale failed runs as cached).
1929
+
return`SELECT "id", "createdAt", "friendlyId", "idempotencyKey", "idempotencyKeyExpiresAt", "status" FROM "TaskRun" WHERE "runtimeEnvironmentId" = $${base+1} AND "taskIdentifier" = $${base+2} AND "idempotencyKey" = $${base+3}`;
0 commit comments