Skip to content

Commit

Permalink
Async iterable Endpoint handlers have back pressure
Browse files Browse the repository at this point in the history
Apply back pressure by pausing invocations of endpoint handler when
part of the written data was queued in user memory. Once the kernel
buffer is free to be written again, invocations will commence again.
  • Loading branch information
kjmph committed Jun 7, 2021
1 parent d87a869 commit 38c0d4a
Showing 1 changed file with 16 additions and 1 deletion.
17 changes: 16 additions & 1 deletion packages/adapter-node/src/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,24 @@ export function createServer({ render }) {
typeof rendered.body[Symbol.asyncIterator] === 'function'
) {
const flush = compressible(rendered.headers['content-type']) ? res.flush : null;
const drainers = [];
const writer = (event) =>
new Promise((resolve) => {
if (!res.write(event)) {
drainers.push(resolve);
} else {
resolve();
}
});
// FIXME: upstream bug in compression prevents usage
// of res.once('drain', resolve) in writer's curry.
// https://github.com/expressjs/compression/pull/153
res.on('drain', () => {
drainers.splice(0, drainers.length).forEach((resolve) => resolve());
});
for await (const event of rendered.body) {
if (res.connection.destroyed) break;
res.write(event);
await writer(event);
flush?.();
}
res.end();
Expand Down

0 comments on commit 38c0d4a

Please sign in to comment.