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 ff80d62
Browse filesBrowse the repository at this point in the historyBrowse files
authored
fix(core): repay a force-claim victim's wake independent of the claimer's log tail (#4398)
* fix(core): repay a force-claim victim's wake independent of the claimer's log tail
A replay republished the victim's wake only while the forced hook_created
was the last row the claimer itself wrote, so any own row landing between
the creation and the wake (a step or wait terminal from another invocation,
or, since #4392, a row the same suspension writes alongside the creation)
hid the debt, and a victim parked only on `await hook` never woke.
Every replay now republishes for each forced hook_created in the loaded log
whose createdAt is within 24 hours (the queue's message retention and
idempotency window), under the existing `hook-force-claim-<hookId>` key.
The node:vm handler sends it alongside the suspension's writes and at most
once per hook per invocation; QuickJS once per invocation on load. Both use
the shared rule in hook-wake.ts.
Closes#4393.
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Pranay Prakash <1797812+pranaygp@users.noreply.github.com>
* test(core): pin concurrent creation of forced hooks on different tokens
Both engines used to create forced hooks one token at a time, each group
waiting on its victim wake before the next started. That barrier is gone
(#4392); these tests hold the first forced create until the second is
issued, so a serial implementation deadlocks, and check that each victim
is still woken once under its own key.
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Pranay Prakash <1797812+pranaygp@users.noreply.github.com>
* Apply suggestion from @VaguelySerious
Signed-off-by: Peter Wielander <mittgfu@gmail.com>
---------
Signed-off-by: Peter Wielander <mittgfu@gmail.com>
Co-authored-by: vercel[bot] <35613825+vercel[bot]@users.noreply.github.com>
Co-authored-by: Pranay Prakash <1797812+pranaygp@users.noreply.github.com>
Co-authored-by: Peter Wielander <mittgfu@gmail.com>
Republish a force-claimed hook's victim wake on every replay within 24 hours of the takeover instead of only while the forced `hook_created` is the claimer's last own event, ensuring resilience against crashes
Copy file name to clipboardExpand all lines: docs/content/docs/v5/api-reference/workflow/create-hook.mdx
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -251,7 +251,7 @@ With `experimental_force`, this run always ends up owning the token:
251
251
- Any number of runs forcing the same token at the same time converge on a single owner. The takeovers form a chain: each run that loses the token gets `HookForceClaimedError`, exactly one run ends up owning it, and none of them can get stuck. Which run wins among simultaneous claimers is not defined; if the order matters, start them in order.
252
252
- A finished run that still holds the token under [`experimental_minRetention`](#keep-a-token-unavailable-after-the-run-ends) is taken over silently, since there is nothing left to wake. A run can also take over a token held by its own earlier Hook.
253
253
254
-
The takeover is durable. If either run's compute fails partway through, the next request for the token completes it, so the token never ends up held by nobody or by both runs. The previous owner's wake is repaired on a best-effort basis: if the new owner's compute fails between registering the Hook and waking the previous owner, the new owner's next invocation republishes the wake (idempotently), as long as the new owner has not recorded any other event since. If it has, for example a step it started alongside the Hook, the previous owner still sees the takeover, but only the next time something else invokes it.
254
+
The takeover is durable. If either run's compute fails partway through, the next request for the token completes it, so the token never ends up held by nobody or by both runs. The previous owner's wake is durable too: if the new owner's compute fails between registering the Hook and waking the previous owner, the new owner's next invocation republishes the wake, whatever else the new owner has recorded since (a step it started alongside the Hook, for example). Every invocation of the new owner within 24 hours of the takeover republishes it under the same idempotency key, which collapses the repeats into one wake; a repeat that does get through only replays the previous owner, which finds nothing new.
255
255
256
256
<Callouttype="info">
257
257
A token can only be taken from a run whose runtime understands being taken from. Runs started at a Workflow spec version below 8, which includes every run started by an older SDK release, a Python SDK run, or a deployment with `WORKFLOW_SEALED_LOG=0`, would never learn that their Hook was disposed. The World declines to take their token and the forced Hook rejects with the ordinary [`HookConflictError`](/docs/api-reference/workflow-errors/hook-conflict-error) instead, exactly as if `experimental_force` had not been set. Finished runs holding a retained token are taken over at any version.
0 commit comments