-
-
Notifications
You must be signed in to change notification settings - Fork 633
Add Async Props documentation with animated SVG diagrams #2265
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: upcoming-v16.3.0
Are you sure you want to change the base?
Conversation
- Introduced `IncrementalRenderRequestManager` to handle streaming NDJSON requests, managing state and processing of incremental render requests. - Added `validateBundlesExist` utility function to check for the existence of required bundles, improving error handling for missing assets. - Refactored the incremental render endpoint to utilize the new request manager, enhancing the response lifecycle and error management. - Updated tests to cover scenarios for missing bundles and validate the new request handling logic.
- Replaced the `IncrementalRenderRequestManager` with `handleIncrementalRenderStream` to manage streaming NDJSON requests more efficiently. - Enhanced error handling and validation during the rendering process. - Updated the `run` function to utilize the new stream handler, improving the response lifecycle and overall performance. - Removed the deprecated `IncrementalRenderRequestManager` class to streamline the codebase.
- Introduced improved error handling for malformed JSON chunks during the incremental rendering process. - Added logging and reporting for errors in subsequent chunks while allowing processing to continue. - Updated tests to verify behavior for malformed JSON in both initial and update chunks, ensuring robust error management.
…inability - Introduced helper functions to reduce redundancy in test setup, including `getServerAddress`, `createHttpRequest`, and `createInitialObject`. - Streamlined the handling of HTTP requests and responses in tests, enhancing clarity and organization. - Updated tests to utilize new helper functions, ensuring consistent structure and easier future modifications.
- Replaced inline wait functions with a new `waitFor` utility to improve test reliability and readability. - Updated tests to utilize `waitFor` for asynchronous expectations, ensuring proper handling of processing times. - Simplified the test structure by removing redundant wait logic, enhancing maintainability.
…processing - Introduced `createBasicTestSetup` and `createStreamingTestSetup` helper functions to streamline test initialization and improve readability. - Added `sendChunksAndWaitForProcessing` to handle chunk sending and processing verification, reducing redundancy in test logic. - Updated existing tests to utilize these new helpers, enhancing maintainability and clarity in the test structure.
- Added detailed error reporting in the `waitFor` function to include the last encountered error message when a timeout occurs. - Refactored the `createStreamingResponsePromise` function to improve clarity and maintainability by renaming variables and returning received chunks alongside the promise. - Updated tests to utilize the new structure, ensuring robust handling of streaming responses and error scenarios.
…ment - Removed unnecessary bundle validation checks from the incremental render request flow. - Enhanced the `handleIncrementalRenderRequest` function to directly call `handleRenderRequest`, streamlining the rendering process. - Updated the `IncrementalRenderInitialRequest` type to support a more flexible structure for dependency timestamps. - Improved error handling to capture unexpected errors during the rendering process, ensuring robust responses. - Added cleanup logic in tests to restore mocks after each test case.
- Removed individual protocol version and authentication checks from the request handling flow. - Introduced a new `performRequestPrechecks` function to streamline the validation process for incoming requests. - Updated the `authenticate` and `checkProtocolVersion` functions to accept request bodies directly, enhancing modularity. - Improved error handling by ensuring consistent response structures across precheck validations.
- Updated the `/upload-assets` endpoint to differentiate between assets and bundles, allowing for more flexible uploads. - Introduced logic to extract bundles prefixed with 'bundle_' and handle them separately. - Integrated the `handleNewBundlesProvided` function to manage the processing of new bundles. - Added comprehensive tests to verify the correct handling of uploads with various combinations of assets and bundles, including edge cases for empty requests and duplicate bundle hashes.
- Added tests to verify directory structure and file presence for uploaded bundles and assets. - Implemented checks for scenarios with empty requests and duplicate bundle hashes, ensuring correct behavior without overwriting existing files. - Improved coverage of the `/upload-assets` endpoint to handle various edge cases effectively.
- Implemented a new test case for the `/upload-assets` endpoint to verify that bundles are correctly placed in their own hash directories rather than the targetBundles directory. - Ensured that the test checks for the existence of the bundle in the appropriate directory and confirms that the target bundle directory remains empty, enhancing coverage for asset upload scenarios.
- Implemented a suite of tests for the `/bundles/:bundleTimestamp/incremental-render/:renderRequestDigest` endpoint to verify successful rendering under various conditions, including pre-uploaded bundles and assets. - Added scenarios to test failure cases, such as missing bundles, incorrect passwords, and invalid JSON payloads. - Enhanced coverage for handling multiple dependency bundles and processing NDJSON chunks, ensuring robust error management and response validation.
- Simplified test structure by introducing helper functions to reduce code duplication for creating worker apps and uploading bundles. - Improved test cases for the `/bundles/:bundleTimestamp/incremental-render/:renderRequestDigest` endpoint, ensuring robust validation of successful renders and error handling for various scenarios. - Added tests for handling invalid JSON and missing required fields, enhancing coverage for edge cases in the rendering process. - Updated tests to ensure proper handling of multiple dependency bundles and improved response validation for different payload conditions.
- Replaced the `runInVM` function with a new `ExecutionContext` class to manage VM contexts more effectively. - Updated the `handleRenderRequest` function to utilize the new `ExecutionContext`, improving the handling of rendering requests. - Enhanced error management by introducing `VMContextNotFoundError` for better clarity when VM contexts are missing. - Refactored tests to align with the new execution context structure, ensuring consistent behavior across rendering scenarios.
…andling - Updated the parameters for the `runOnOtherBundle` function to ensure correct execution order. - Introduced a reference to `globalThis.runOnOtherBundle` in the server rendering code for better accessibility. - Enhanced the test fixture to align with the changes in the global context, ensuring consistent behavior across rendering requests.
- Introduced `IncrementalRenderSink` type to manage streaming updates more effectively. - Updated `handleIncrementalRenderRequest` to return an optional sink and handle execution context errors gracefully. - Refactored the `run` function to utilize the new sink for processing updates, enhancing error logging for unexpected chunks. - Simplified test setup by removing unused sink methods, ensuring tests focus on relevant functionality.
- Updated the `setResponse` call in the `run` function to correctly use `result.response`. - Expanded the incremental render tests to cover new scenarios, including basic updates, multi-bundle interactions, and error handling for malformed update chunks. - Introduced new helper functions in test fixtures to streamline the creation of async values and streams, enhancing the robustness of the tests. - Improved the secondary bundle's functionality to support async value resolution and streaming, ensuring consistent behavior across bundles.
Fix tests and refactor fixtures after NDJSON renderer changes - Fix request_spec.rb, handleRenderRequest, and serverRenderRSCReactComponent tests for new response structure - Separate incremental render fixtures from base test fixtures to prevent interference - Remove obsolete promise-based incremental render tests - Refactor VM bundle creation to use serverBundleCachePath - Clean up unneeded buildConfig call
- Fix stream closed checks for compatibility with different stream implementations - Add tests for concurrent incremental HTML streaming - Fix race condition by using unique bundle paths per test - Add tests for handleRequestClosed on connection close
This PR fixes streaming request compatibility issues when using HTTPX with both `:stream` and `:stream_bidi` plugins loaded on the same connection. When the base branch combined two separate HTTPX connections into one (to use a single HTTP/2 connection for both standard and incremental requests), streaming requests started timing out. The root cause: 1. The `stream_bidi` plugin's `RequestBodyMethods#empty?` method always returns `false` when `stream: true` 2. This prevents the `END_STREAM` flag from being sent on the HTTP/2 DATA frame 3. The server waits indefinitely for more request data, causing a timeout Refactored `perform_request` to use the `build_request` pattern for both streaming and non-streaming requests: - **`execute_http_request`**: New helper that uses `build_request` instead of `connection.post` - **`encode_request_body`**: Manually encodes form/JSON data since `form:` option doesn't work with `stream: true` (Form::Encoder doesn't implement `<<`) - **For streaming requests**: Passes `stream: true` to `build_request` and calls `request.close` to explicitly send the `END_STREAM` flag - **Consolidated error handling**: Both streaming and non-streaming requests now share the same retry logic, timeout handling, and error handling Additionally, this PR includes a temporary patch for an [HTTPX stream_bidi plugin bug](HoneyryderChuck/httpx#124): **Problem:** When a streaming request fails and is retried, the `@headers_sent` flag is not reset. This causes the `:body` callback to fire prematurely on retry, leading to re-entrant `handle()` calls that crash with `HTTP2::Error::InternalError`. **Workaround:** The patch resets `@headers_sent` to `false` when transitioning back to `:idle` state. This can be removed once fixed upstream in the httpx gem. Added size limits to the NDJSON incremental render stream handler to prevent memory exhaustion from malicious or broken clients: **Problem:** The NDJSON endpoint buffers incoming data until a newline is encountered. A client sending continuous data without newlines would cause unbounded memory growth. Fastify's `bodyLimit` is not enforced for custom content type parsers that pass through raw streams. **Solution:** Added two size limits: - **`MAX_NDJSON_LINE_SIZE` (10MB)**: Limits single JSON line size (matches Fastify's `fieldSizeLimit`) - **`MAX_NDJSON_REQUEST_SIZE` (100MB)**: Limits total request size (matches Fastify's `bodyLimit`) - Updated `lib/react_on_rails_pro/request.rb`: - Consolidated `perform_request` and `perform_streaming_request` into one unified method - Added `execute_http_request` helper using `build_request` pattern - Added `encode_request_body` to handle both form and JSON encoding - Added `lib/react_on_rails_pro/httpx_stream_bidi_patch.rb`: - Temporary patch for HTTPX stream_bidi retry bug (resets `@headers_sent` on `:idle` transition) - Updated `packages/react-on-rails-pro-node-renderer/src/worker/handleIncrementalRenderStream.ts`: - Added `MAX_NDJSON_LINE_SIZE` (10MB) and `MAX_NDJSON_REQUEST_SIZE` (100MB) constants - Added buffer size checks to prevent memory exhaustion - Added `packages/react-on-rails-pro-node-renderer/tests/handleIncrementalRenderStream.test.ts`: - Unit tests for NDJSON buffer size protection - Updated `spec/react_on_rails_pro/request_spec.rb`: - Changed tests to check encoded body string instead of internal HTTPX structure - Tests now verify actual request content rather than implementation details - Other fixes: - Fixed fixture paths in incremental rendering integration spec - Fixed RSpec tests for incremental rendering - Ignored `hasVMContextForBundle` in knip production check - [x] Add/update test to cover these changes - ~[ ] Update documentation~ (No documentation changes needed) - ~[ ] Update CHANGELOG file~ (Internal fix, no user-facing changes) - [x] All 18 request spec tests pass - [x] RSC payload endpoint returns 200 OK with proper streamed JSON response - [x] Manual testing of streaming endpoints confirmed working - [x] NDJSON buffer protection unit tests pass (5 tests) --------- Co-authored-by: Claude <noreply@anthropic.com>
…cremental render stream
1. AsyncPropsManager: Add missing `resolved = true` in setProp()
- The resolved flag was never set, causing endStream() to incorrectly
reject already-resolved promises
2. handleIncrementalRenderRequest: Fix type mismatch
- Changed onRequestClosedUpdateChunk type from string to UpdateChunk
- Updated assertFirstIncrementalRenderRequestChunk to validate using
assertIsUpdateChunk (DRY principle)
- Removed redundant assertion in handleRequestClosed
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
errorReporter.message() already calls log.error() internally, so having both resulted in duplicate log entries. Removed the explicit log.error() calls and the unused log import. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Avoid type cast by using local variable for vmCreationPromises.get() - Simplify return: async functions auto-wrap return values in Promise 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Created shared constants file with BODY_SIZE_LIMIT (100MB) and FIELD_SIZE_LIMIT (10MB) to eliminate duplication between: - worker.ts (Fastify config) - handleIncrementalRenderStream.ts (NDJSON parsing) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add comprehensive documentation for the Async Props feature: - README.md: Overview, benefits, and quick start guide - how-it-works.md: Deep dive into streaming architecture - api-reference.md: Complete API reference for Rails and React - advanced-usage.md: Error handling, caching, optimization patterns SVG diagrams (GitHub-compatible): - traditional-vs-streaming-ssr.svg: Visual comparison of SSR approaches - timeline-comparison.svg: Gantt-style timing comparison - progressive-loading-sequence.svg: 3-stage loading visualization - architecture-flow.svg: Rails ↔ Node ↔ Browser data flow 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Animated SVG files using SMIL animations: - streaming-flow.svg: Shows data packets flowing from Rails → Node → Browser with timeline markers appearing as content loads - progressive-browser.svg: Browser mockup with skeleton shimmer effect, content sections appearing progressively with status badges - race-comparison.svg: Side-by-side Traditional vs Async Props race showing the dramatic TTFB difference (4000ms vs 50ms) - data-packets.svg: Dark-themed visualization of NDJSON protocol with animated packets traveling between Rails, Node, and Browser All animations use SMIL (<animate>, <animateTransform>) which can be converted to GIF using tools like svg2gif or Puppeteer. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Added 8 more animated SVG visualizations: - chunk-streaming.svg - HTML chunks flowing through streaming pipeline - error-handling.svg - Graceful error isolation visualization - full-request-lifecycle.svg - Complete request flow diagram - hydration-process.svg - React hydration with water effects - server-vs-client-components.svg - Server vs Client rendering - suspense-boundaries.svg - Suspense resolution timeline - user-experience-comparison.svg - UX comparison with metrics - waterfall-vs-parallel.svg - Fetching patterns comparison 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the You can disable this status message by setting the ✨ Finishing touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
📚 Documentation Review: Async Props with Animated SVG DiagramsThis is an excellent addition to the React on Rails Pro documentation! The comprehensive coverage with visual aids will greatly help users understand the streaming SSR feature. ✅ Strengths1. Outstanding Visual Documentation
2. Well-Structured Content
3. Comprehensive Coverage
4. Technical Accuracy
🔍 Suggestions for Improvement1. GitHub SVG Animation Compatibility
|
b0c9de1 to
f973013
Compare
Summary
Documentation Structure
Test plan
🤖 Generated with Claude Code