Repository navigation
Sync bridge: request_sync/send_sync from plain-def handlers, with the sync-vs-async rationale documented - #18
Merged
Merged
Conversation
Python's synchronous ecosystem (requests, NumPy/ML inference, database drivers) is why plain def handlers are first-class; they run in the executor so blocking work never stalls the event loop - the analog of the Java engine's virtual threads. This adds the missing composition piece: PostOffice.request_sync()/send_sync() submit the same calls onto the host loop (stamped by the bus into the handler's context) while blocking only the worker thread; the caller's trace context is re-established inside the submitted task so the chain is unbroken. Calling the bridge on the event loop, or off-host, raises a teaching error. Rationale documented in README and the registry module; hello.sync.chain added to the demo. Co-Authored-By: Claude Code <noreply@anthropic.com>
Co-Authored-By: Claude Code <noreply@anthropic.com>
Co-Authored-By: Claude Code <noreply@anthropic.com>
Co-Authored-By: Claude Code <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
PostOffice.request_sync()/send_sync(): a plaindefhandler(which runs on an executor thread with no event loop of its own) can now call sibling
or remote functions. The bus stamps the host loop into the handler's context at
dispatch; the bridge submits the same coroutines onto that loop via
run_coroutine_threadsafe, blocking only the handler's worker thread — never theevent loop. The caller's trace context is re-established inside the submitted task
(contextvars do not cross
run_coroutine_threadsafeon their own), so the tracechain is unbroken end to end. Misuse teaches: calling the bridge on the event loop →
"await request()/send() instead"; calling it outside a hosted function → points at
asyncio.run(po.request(...)). Errors stay envelope-shaped (404/408/202), identicalto the async path.
the registry module docstring): plain
defhandlers are first-class because Python'ssynchronous ecosystem —
requests, NumPy/pandas and most ML inference stacks,database drivers — must be wrappable without stalling the event loop that hosts every
other function; the executor dispatch is the Python analog of the Java engine's
virtual threads.
async defserves asyncio-native I/O and composition. Detectionstays automatic; a rule of thumb closes the section.
hello.sync.chain(plaindef→request_sync→ private sibling);PostOfficehoisted to the demo's module-level import.Why
The design review ratified supporting both handler styles, but sync handlers had a
composition gap:
PostOffice.request()is a coroutine and an executor thread cannotawait it — so the synchronous half of the ecosystem could wrap libraries yet not call
sibling functions. The bridge closes that gap with the same envelope contract, keeping
the two styles fully symmetric for developers.
Verification
request_sync→ private helper with the fulltrace/cid chain; refused-on-event-loop teaching error; off-host teaching error;
404/202 envelope shaping +
send_syncdelivery. ruff clean, basedpyright 0.hello.sync.chaindriven over/api/event→{'text': 'polyglot!', 'language': 'python'}; re-verified after each follow-up commit._run_syncstatic, demo import hoist,unshadowed test locals.
Co-Authored-By: Claude Code noreply@anthropic.com
🤖 Generated with Claude Code