Repository navigation
feat(durable): wait for callbacks with ctx.wait_for_callback - #400
Conversation
AI review: no P0-P2 findingsThis PR adds Not checked: The AI review read the diff, the code, and the PR's text; it ran no tests or builds and read nothing outside this repository.
Human review: needed
The AI review found no P0-P2 problems at 0f5fd6e, so the code needs no second review for bugs. Decide the points above: approve to accept them, or request changes. Suggested reviewer: |
subnetmarco
left a comment
There was a problem hiding this comment.
This matches sdk-js#332 and the hosting contract where it matters:
- the same error codes and 30-second registration deadline;
- registration inside the checkpointed submitter step, so a replay doesn't register twice;
- a timeout returns
None, andcallback_closedskips the submitter; - failures surface as
CallbackFailedErrorfromerrorData; - the same name rules.
One real issue: async submitters (inline).
The Aikido finding on test_durable_callback_token.py:25 is a made-up fixture token against api.volcano.test, so it's safe to dismiss.
Release order matters here. Hosting#1966's cloud E2E pins volcano-sdk-python~=0.16.0, and sdk-python#398 (fix(sandboxes)!) would take 0.16.0 if it releases first. Release this one first, or re-pin hosting. Details on hosting#1966.
subnetmarco
left a comment
There was a problem hiding this comment.
Re-reviewed at 7279cfd. Refusing an async def submitter is the right call. Python durable authoring is synchronous throughout, and the runtime calls the submitter on a worker thread with no event loop, so running the coroutine there would break clients bound to another loop. The refusal is loud and comes before the callback opens, and it can be relaxed later without breaking anyone. Closing a returned coroutine in handed_off keeps the "never awaited" warning away, and the tests cover a coroutine function, a returned coroutine and a non-coroutine awaitable. CI is green apart from ai-review/human.
Release this before sdk-python#398. With bump-minor-pre-major, whichever releases first takes 0.16.0, so if #398 goes alone first, callbacks land in 0.17 and hosting#1966's docs are wrong. Note that 0.15.1 (Oct 21) satisfies hosting#1966's current >0.15.0 pin without callbacks; I've asked for that pin to name the actual release.
The description still says hosting pins ~=0.16.0. Please update it.
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
The runtime calls the submitter on a thread without an event loop, and its result was discarded, so an async def submitter returned a coroutine that never ran: the wait opened and nothing received the token. Refuse an async def submitter with a TypeError before the callback opens, and fail the hand-off when a submitter returns any other awaitable, closing a coroutine so it does not warn later. The submitter stays typed as returning object, as in the JavaScript SDK, so one written as an expression that returns what it started still type-checks. The token fixture now reads as the fake it is. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
7279cfd to
0f5fd6e
Compare
swkeever
left a comment
There was a problem hiding this comment.
Guided review of 0f5fd6e. The AI review cleared correctness with no P0-P2 findings; these are the decisions it left to a person.
- Should possession of a callback token alone authorize completing, failing, or heartbeating a durable wait? Accept.
Token-only is what lets a third party call back without a Volcano credential. Each token covers one step, takes one answer, and expires. Hardening, such as confirming a replayed registration, belongs on Kong/volcano-hosting#1966. - Should scoped service keys authorize client-IP forwarding on the synced authentication routes? Accept.
The contract already shipped in Kong/volcano-hosting#1747. This PR only regenerates the private_generatedclient, and no public SDK method sends the headers.
Generated by the guided-review skill. Install it with one command:
sh -c 'd=$(mktemp -d) && gh repo clone Kong/volcano-conventions "$d" -- --depth 1 -q && make -C "$d" install-skills guided-review pr-review explain-pr; s=$?; rm -rf "$d"; exit $s'Then ask your coding agent for a guided review of a PR or issue URL. Run the command again to update.
Why
Customers migrating workflows asked for task-token style callbacks: a durable step hands a token to another system, which later succeeds it, fails it, or heartbeats it. Hosting adds the token routes in Kong/volcano-hosting#1966. This PR is the Python authoring API for them.
Summary
ctx.wait_for_callback(name, submitter, *, timeout=None, heartbeat_timeout=None)registers the callback and hands itsvcb_token tosubmitter. It then suspends until the token is answered.None, the same aswait_for_message.CallbackFailedErrorfromvolcano_sdk.durable_authoring, with.typeand.message.chore(openapi)commits sync the spec and generated client from hosting.docs/functions.mdget a callbacks section.Rollout: merge this PR and JS first, then release (0.16.0 under release-please), then merge the hosting PR, whose cloud E2E pins
~=0.16.0.Verification
Tested commits:
f18a34b, onmain11655d3. The feature commit is2416ace;f18a34bonly syncs an error description in the spec.2bfbbffb3Results:
uv run --locked poe checkspasses: policy, audit, generated client, ruff, mypy, basedpyright, and the package checks.pytestpasses 2,995 tests at 100% coverage.poe mutationpasses on each changed module, with no survivors:_durable_callback_tokendurable_authoring_durable_modules_durable_engine_durable_protocolsholds only protocol declarations and has nothing to mutate.Hosting runs the four shared scenarios, SDK-DURABLE-022 to 025, against this binding.
Not run: cloud E2E and the live staging sdk-contract runner.
Related: Kong/volcano-hosting#1966, Kong/volcano-sdk-js#332.