Skip to content

Commit 951d34b

Browse files
Add tests for concurrent incremental HTML streaming to handle multiple parallel requests
1 parent 146a610 commit 951d34b

File tree

1 file changed

+53
-0
lines changed

1 file changed

+53
-0
lines changed

react_on_rails_pro/packages/node-renderer/tests/incrementalHtmlStreaming.test.ts

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,3 +178,56 @@ it('raises an error if a specific async prop is not sent', async () => {
178178
await expect(getNextChunk(request)).rejects.toThrow('Stream Closed');
179179
close();
180180
});
181+
182+
describe('concurrent incremental HTML streaming', () => {
183+
it('handles multiple parallel requests without race conditions', async () => {
184+
await makeRequest();
185+
186+
const numRequests = 5;
187+
const requests = [];
188+
189+
// Start all requests
190+
for (let i = 0; i < numRequests; i += 1) {
191+
const { request, close } = createHttpRequest(RSC_BUNDLE_TIMESTAMP, `concurrent-test-${i}`);
192+
request.write(`${JSON.stringify(createInitialObject())}\n`);
193+
requests.push({ request, close, id: i });
194+
}
195+
196+
// Wait for all to connect and get initial chunks
197+
await Promise.all(requests.map(({ request }) => waitForStatus(request)));
198+
await Promise.all(requests.map(({ request }) => getNextChunk(request)));
199+
200+
// Send update chunks to ALL requests before waiting for any responses
201+
// If sequential: second request wouldn't process until first completes
202+
// If concurrent: all process simultaneously
203+
requests.forEach(({ request, id }) => {
204+
request.write(
205+
`${JSON.stringify({
206+
bundleTimestamp: RSC_BUNDLE_TIMESTAMP,
207+
updateChunk: `
208+
(function(){
209+
var asyncPropsManager = sharedExecutionContext.get("asyncPropsManager");
210+
asyncPropsManager.setProp("books", ["Request-${id}-Book"]);
211+
asyncPropsManager.setProp("researches", ["Request-${id}-Research"]);
212+
})()
213+
`,
214+
})}\n`,
215+
);
216+
request.end();
217+
});
218+
219+
// Now wait for all responses - they should all succeed
220+
const results = await Promise.all(
221+
requests.map(async ({ request, close, id }) => {
222+
const chunk = await getNextChunk(request);
223+
close();
224+
return { id, chunk };
225+
}),
226+
);
227+
228+
results.forEach(({ id, chunk }) => {
229+
expect(chunk).toContain(`Request-${id}-Book`);
230+
expect(chunk).toContain(`Request-${id}-Research`);
231+
});
232+
});
233+
});

0 commit comments

Comments
 (0)