fix(ssr): make the render timeout cover rendering - #174
Open
bobzhang wants to merge 1 commit into
Open
Conversation
`App::render`'s `timeout` documents "Throws `@async.TimeoutError` if rendering does not complete within `timeout` milliseconds", but it could never fire. All of SSR's async work — graph evaluation, command draining, the HTTP fetches `create_resource` issues — happens inside `@runtime.SSRHost(...)`, on the line *before* `with_timeout`. What `with_timeout` wrapped was `render_to_string`, which is declared `pub fn`, not `pub async fn`: it has no suspension point, so the timer can never preempt it. A hanging SSR fetch hung forever no matter what `timeout` said. Wrap the `SSRHost` construction too, which is where the awaiting is. `defer host.cleanup()` moves inside the same closure so it still runs on both the success and the cancelled path. Verified with a probe that renders against an endpoint that sleeps 2s, with `timeout=100`: before RETURNED (no raise), after ~2s, with the fetched data after RAISED: TimeoutError and, with `SSRHost::cleanup` instrumented, cleanup still runs when the timeout cancels the render. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AmoyPMELemz5hdNNdXyAkm
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.
Fixes #173.
App::render'stimeoutcould never fire. All of SSR's async work — graph evaluation,drain_task, the HTTP fetchescreate_resourceissues — happens inside@runtime.SSRHost(...), on the line beforewith_timeout. Whatwith_timeoutwrapped wasrender_to_string, declaredpub fnrather thanpub async fn, so it has no suspension point and the timer can never preempt it.This moves the
SSRHostconstruction inside the timeout, where the awaiting actually is, and keepsdefer host.cleanup()in the same closure so it still runs on both the success and the cancelled path.Verification
Probe in #173 — render against an endpoint that sleeps 2s, with
timeout=100:rabbita@0.15.6RETURNED (no raise)after ~2s, with the fetched dataRAISED: TimeoutErrorCancellation does not leak the host: with
SSRHost::cleanupinstrumented with aprintln, the timeout path prints[probe] SSRHost::cleanup ranbefore the raise.moon check --target native --deny-warn— passmoon check --target wasm --deny-warn— passmoon test --target native— 86 passed, unchangedTwo things I deliberately did not do
No regression test.
@cmd.performand@cmd.effectare#cfg(target="js"), so the native async-command surface is effectively HTTP and a test needs a live server.moon testis also commented out incheck.yml, so it would not run in CI anyway. Rather than add a timing-sensitive test nobody runs, the reproduction is written out in full in #173 so it can be verified independently.No version bump. Left at 0.15.6 so the bump can be made at release time rather than going stale while this is reviewed.
🤖 Generated with Claude Code
https://claude.ai/code/session_01AmoyPMELemz5hdNNdXyAkm