Improve event stream resilience
This commit is contained in:
@@ -6,6 +6,43 @@ import {
|
||||
shouldForwardProxyResponseHeader,
|
||||
} from '../../proxy-headers.js';
|
||||
|
||||
export const waitForSseDrain = (res, signal) => new Promise((resolve) => {
|
||||
if (signal?.aborted || res.writableEnded || res.destroyed) {
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
|
||||
const cleanup = () => {
|
||||
res.off?.('drain', onDone);
|
||||
res.off?.('close', onDone);
|
||||
res.off?.('error', onDone);
|
||||
signal?.removeEventListener?.('abort', onDone);
|
||||
};
|
||||
const onDone = () => {
|
||||
cleanup();
|
||||
resolve();
|
||||
};
|
||||
|
||||
res.once?.('drain', onDone);
|
||||
res.once?.('close', onDone);
|
||||
res.once?.('error', onDone);
|
||||
signal?.addEventListener?.('abort', onDone, { once: true });
|
||||
});
|
||||
|
||||
export const writeSseChunkWithBackpressure = async (res, value, signal) => {
|
||||
if (!value || value.length === 0 || signal?.aborted || res.writableEnded || res.destroyed) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const flushed = res.write(value);
|
||||
if (flushed !== false) {
|
||||
return true;
|
||||
}
|
||||
|
||||
await waitForSseDrain(res, signal);
|
||||
return !signal?.aborted && !res.writableEnded && !res.destroyed;
|
||||
};
|
||||
|
||||
export const registerOpenCodeProxy = (app, deps) => {
|
||||
const {
|
||||
fs,
|
||||
@@ -131,7 +168,10 @@ export const registerOpenCodeProxy = (app, deps) => {
|
||||
break;
|
||||
}
|
||||
if (value && value.length > 0) {
|
||||
res.write(value);
|
||||
const canContinue = await writeSseChunkWithBackpressure(res, value, abortController.signal);
|
||||
if (!canContinue) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user