Repository navigation
Bounded-wait RPC companions: _within with timeout and cancellation - #276
Merged
Merged
Conversation
The generated Windows/Linux C++ clients exposed only blocking calls, so hosts that poll or abandon an RPC spawned a detached std::thread per tick — threadly and movebit both churn one thread per 400 ms poll. Every RPC now also generates a bounded-wait companion, name_within(arguments, std::chrono::milliseconds): the completion resolves a promise, the call waits up to the timeout, and a miss cancels the pending request through Backend::cancel before returning. Void RPCs return bool (false = timed out); other results return std::optional<T>. Backend and decoding errors still throw from the final get, matching the blocking contract, and the naming collision check treats _within as a generated companion so a schema RPC named foo_within cannot collide. The checked-in Windows and Linux template headers gain the same shape in their own style (a shared unbox_string helper, greet_within and increment_within), and docs/windows-native-window.md documents the sanctioned polling pattern: completions when a push model works, _within when the UI owns a tick loop — never a detached thread per tick. Also fixes a latent generator defect the new Void fixture exposed: the Void async completion handler assigned into Result<void>, which has no value member — that generated header could not compile for any Void RPC (log-line in the fixture now pins the shape: the decode only validates arrival).
turinglambdaai
force-pushed
the
feat/winrpc-within
branch
from
October 16, 2026 15:58
8d39e79 to
323787c
Compare
The taskboard's timing-start family (zero-argument RPCs) broke CI: the generated signature was name_within(, std::chrono::milliseconds ...) — a stray comma where an empty parameter list meets the timeout. The within-params now emit the timeout alone when the RPC takes no arguments. Verified against the taskboard schema locally: all 16 companions generate and both platform headers compile with the fixed signatures; the test suite pins the zero-argument shape through the health fixture RPC.
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.
Closes #252.
What
The generated Windows/Linux C++ clients exposed only blocking calls, so hosts that poll or abandon an RPC spawned a detached
std::threadper tick — threadly (MainWindow.Update.cpp:384) and movebit both churn one thread per 400 ms poll. Every RPC now also generates a bounded-wait companion:The completion resolves a
std::promiseon the reader thread; the call waits up to the timeout and cancels the pending request throughBackend::cancelon a miss — the existing request table does the bookkeeping, no new native thread. Backend and decoding errors still throw from the final get, matching the blocking contract. The naming collision check treats_withinas a generated companion, so a schema RPC namedfoo_withinfails generation instead of silently shadowing.The checked-in Windows and Linux template headers gain the same shape in their own hand-written style, and
docs/windows-native-window.mddocuments the sanctioned polling pattern: completions when a push model works;_withinwhen the UI owns a tick loop — never a detached thread per tick.Latent defect fixed
The new Void fixture exposed a latent generator defect: the Void async completion handler assigned into
Result<void>, which has novaluemember — every generated header containing a Void RPC failed to compile (increment_within's fixture,log-line, now pins the corrected shape: the decode only validates arrival). Existing products with Void RPCs and generated_asynccalls were one regeneration away from this.Tests
rivet/tests/codegen.rkt: the fixture gains a Void RPC (log-line), assertingincrement_within/log_line_withinshapes, cancel-on-miss returns, promise decode wiring, and the Void handler fix; existing snapshot-compatibility scenarios keeplog-linepresent so their single-variable assertions stay single-variable. Full suite: 9868 pass.