Skip to content

Commit 113b5a0

Browse files
committed
refactor: Remove retainChunks option and update response handling for improved memory management
1 parent 3eff2fc commit 113b5a0

9 files changed

Lines changed: 16 additions & 54 deletions

File tree

packages/aws/src/overrides/converters/aws-streaming.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ const converter: Converter = {
3131
responseStream.write(new Uint8Array(8));
3232
return writable;
3333
},
34-
retainChunks: false,
3534
};
3635

3736
return { type: "stream" as const, streamCreator };

packages/aws/src/overrides/converters/response-stream.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ export function createBufferedStreamCreator<T>(
3939
},
4040
});
4141
},
42-
retainChunks: false,
4342
};
4443

4544
return { streamCreator, output };

packages/aws/src/overrides/wrappers/aws-lambda-streaming.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ const handler: WrapperHandler = async (handler, converter) =>
8080
}
8181

8282
const response = await handler(internalEvent, { streamCreator: output.streamCreator });
83-
if (globalThis.isEdgeRuntime ?? false) {
83+
if ((globalThis.isEdgeRuntime ?? false) && response.body) {
8484
const stream = output.streamCreator.writeHeaders({
8585
statusCode: response.statusCode,
8686
headers: response.headers as Record<string, string>,

packages/core/src/core/requestHandler.ts

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -135,12 +135,14 @@ export async function openNextHandler(
135135
);
136136
response.statusCode = routingResult.statusCode;
137137
response.flushHeaders();
138-
const [bodyToConsume, bodyToReturn] = routingResult.body.tee();
139-
for await (const chunk of bodyToConsume) {
140-
response.write(chunk);
138+
if (routingResult.body) {
139+
const [bodyToConsume, bodyToReturn] = routingResult.body.tee();
140+
for await (const chunk of bodyToConsume) {
141+
response.write(chunk);
142+
}
143+
routingResult.body = bodyToReturn;
141144
}
142145
response.end();
143-
routingResult.body = bodyToReturn;
144146
}
145147
return routingResult;
146148
}
@@ -181,8 +183,10 @@ export async function openNextHandler(
181183
if (routingResult.initialResponse) {
182184
res.statusCode = routingResult.initialResponse.statusCode;
183185
res.flushHeaders();
184-
for await (const chunk of routingResult.initialResponse.body) {
185-
res.write(chunk);
186+
if (routingResult.initialResponse.body) {
187+
for await (const chunk of routingResult.initialResponse.body) {
188+
res.write(chunk);
189+
}
186190
}
187191

188192
//We create a special response for the PPR resume request
@@ -218,13 +222,12 @@ export async function openNextHandler(
218222
});
219223
//#endOverride
220224

221-
const { statusCode, headers: responseHeaders, isBase64Encoded, body } = convertRes(res);
225+
const { statusCode, headers: responseHeaders, isBase64Encoded } = convertRes(res);
222226

223227
const internalResult = {
224228
type: internalEvent.type,
225229
statusCode,
226230
headers: responseHeaders,
227-
body,
228231
isBase64Encoded,
229232
};
230233

packages/core/src/core/routing/util.ts

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -104,21 +104,10 @@ export function convertRes(res: OpenNextNodeResponse): InternalResult {
104104
// Probably some kind of race condition
105105
const headers = parseHeaders(res.getFixedHeaders());
106106
const isBase64Encoded = isBinaryContentType(headers["content-type"]) || !!headers["content-encoding"];
107-
const body = new ReadableStream({
108-
pull(controller) {
109-
if (!res._chunks || res._chunks.length === 0) {
110-
controller.close();
111-
return;
112-
}
113-
114-
controller.enqueue(res._chunks.shift());
115-
},
116-
});
117107
return {
118108
type: "core",
119109
statusCode,
120110
headers,
121-
body,
122111
isBase64Encoded,
123112
};
124113
}

packages/core/src/http/openNextResponse.ts

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ export class OpenNextNodeResponse extends Transform implements ServerResponse {
1818
statusMessage = "";
1919
headers: OutgoingHttpHeaders = {};
2020
headersSent = false;
21-
_chunks: Buffer[] = [];
2221
headersAlreadyFixed = false;
2322

2423
private _cookies: string[] = [];
@@ -255,21 +254,13 @@ export class OpenNextNodeResponse extends Transform implements ServerResponse {
255254
return this.headers;
256255
}
257256

258-
getBody() {
259-
return Buffer.concat(this._chunks);
260-
}
261-
262257
private _internalWrite(chunk: Buffer | string, encoding: BufferEncoding) {
263258
// When encoding === 'buffer', chunk is already a Buffer
264259
// and does not need to be converted again.
265260
// @ts-expect-error TS2367 'encoding' can be 'buffer', but it's not in the
266261
// official type definition
267262
const buffer = encoding === "buffer" ? (chunk as Buffer) : Buffer.from(chunk, encoding);
268263
this.bodyLength += buffer.length;
269-
if (this.streamCreator?.retainChunks !== false) {
270-
// Avoid keeping chunks around when the `StreamCreator` supports it to save memory
271-
this._chunks.push(buffer);
272-
}
273264
// No need to pass the encoding for buffers
274265
this.push(buffer);
275266
this.streamCreator?.onWrite?.();
@@ -342,9 +333,6 @@ export class OpenNextNodeResponse extends Transform implements ServerResponse {
342333
}
343334

344335
send() {
345-
for (const chunk of this._chunks) {
346-
this.write(chunk);
347-
}
348336
this.end();
349337
}
350338

packages/core/src/overrides/converters/edge.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,6 @@ const converter: Converter<InternalEvent, InternalResult | MiddlewareResult> = {
112112
});
113113
},
114114
abortSignal,
115-
retainChunks: false,
116115
};
117116

118117
return {

packages/core/src/types/open-next.ts

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ export type MiddlewareEvent = InternalEvent & {
4343
export type InternalResult = {
4444
statusCode: number;
4545
headers: Record<string, string | string[]>;
46-
body: ReadableStream;
46+
body?: ReadableStream;
4747
isBase64Encoded: boolean;
4848
rewriteStatusCode?: number;
4949
} & BaseEventOrResult<"core">;
@@ -72,18 +72,6 @@ export interface StreamCreator {
7272
onWrite?: () => void;
7373
onFinish?: (length: number) => void;
7474
abortSignal?: AbortSignal;
75-
/**
76-
* Normally there is no need to retain the chunks that have been pushed to the response stream.
77-
*
78-
* However some implementations use a fake `StreamCreator` and expect the chunks to be retained.
79-
* When your stream controller implementation doesn't need to retain the chunk, you can set this
80-
* to `false` to reduce memory usage.
81-
*
82-
* @see https://github.com/opennextjs/opennextjs-aws/blob/main/packages/open-next/src/overrides/wrappers/aws-lambda.ts
83-
*
84-
* @default true for backward compatibility.
85-
*/
86-
retainChunks?: boolean;
8775
}
8876

8977
export type WaitUntil = (promise: Promise<void>) => void;

packages/tests-unit/tests/core/routing/util.test.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,6 @@ function createResponse(res: Partial<Res>) {
4949
return {
5050
statusCode: res.statusCode,
5151
getFixedHeaders: () => res.headers ?? {},
52-
body: res.body ?? "",
53-
getBody: () => Buffer.from(res.body ?? ""),
54-
_chunks: res.body ? [Buffer.from(res.body)] : [],
5552
};
5653
}
5754

@@ -237,7 +234,7 @@ describe("convertRes", () => {
237234
isBase64Encoded: false,
238235
})
239236
);
240-
expect(await fromReadableStream(result.body)).toEqual(res.getBody().toString());
237+
expect(result.body).toBeUndefined();
241238
});
242239

243240
it("convert a response with default status code", async () => {
@@ -260,7 +257,7 @@ describe("convertRes", () => {
260257
isBase64Encoded: false,
261258
})
262259
);
263-
expect(await fromReadableStream(result.body)).toEqual(res.getBody().toString());
260+
expect(result.body).toBeUndefined();
264261
});
265262

266263
it("convert a response with base64 encoding", async () => {
@@ -283,7 +280,7 @@ describe("convertRes", () => {
283280
isBase64Encoded: true,
284281
})
285282
);
286-
expect(await fromReadableStream(result.body)).toEqual(res.getBody().toString());
283+
expect(result.body).toBeUndefined();
287284
});
288285
});
289286

0 commit comments

Comments
 (0)