Streaming not compatible with logging: 'per-route'
mateogianolio opened this issue · comments
Using NextjsSite with streaming: true
and logging: 'per-route'
breaks logging.
The problem is here: https://github.com/sst/sst/blob/master/packages/sst/src/constructs/SsrFunction.ts#L424
The function passed to streamifyResponse
:
awslambda.streamifyResponse(async (event, context) => { /* ... */ }
... has the wrong arguments (see https://docs.aws.amazon.com/lambda/latest/dg/configuration-response-streaming.html).
Correct code:
awslambda.streamifyResponse(async (event, responseStream, context) => {
/* ... */
return rawHandler(event, responseStream);
}
They also recommend closing the response stream using Never mind, I guess responseStream.end()
or by using pipe/pipeline
but that's unrelated to this issue. open-next
does this correctly but it seems sst does not use the open-next server handler?rawHandler
is the openNext server handler?
If you've already posted your issue on Discord, make sure to leave a link to it here.
https://discord.com/channels/983865673656705025/1083422760111439973/threads/1196815754230771712
Yup saw this on Discord.
Ah this problem also causes the warmer function to time out if using streaming: true
. Streaming responses ignore return types and must be explicitly closed with responseStream.end()
:
if (event.type === "warmer") {
return new Promise((resolve) => {
setTimeout(() => {
resolve({ serverId: "server-" + Math.random().toString(36).slice(2, 8) });
}, event.delay);
});
}
Here's the patch I applied for sst@2.39.6:
diff --git a/node_modules/sst/constructs/SsrFunction.js b/node_modules/sst/constructs/SsrFunction.js
index 5d8cbb1..ebbd05a 100644
--- a/node_modules/sst/constructs/SsrFunction.js
+++ b/node_modules/sst/constructs/SsrFunction.js
@@ -274,10 +274,10 @@ export class SsrFunction extends Construct {
const newHandlerFunction = "handler";
await fs.writeFile(path.join(bundle, handlerDir, `${newHandlerName}.mjs`), streaming
? [
- `export const ${newHandlerFunction} = awslambda.streamifyResponse(async (event, context) => {`,
+ `export const ${newHandlerFunction} = awslambda.streamifyResponse(async (event, responseStream, context) => {`,
...injections,
` const { ${oldHandlerFunction}: rawHandler} = await import("./${oldHandlerName}.mjs");`,
- ` return rawHandler(event, context);`,
+ ` return rawHandler(event, responseStream);`,
`});`,
].join("\n")
: [
diff --git a/node_modules/sst/constructs/SsrSite.js b/node_modules/sst/constructs/SsrSite.js
index af27a7d..0446d1f 100644
--- a/node_modules/sst/constructs/SsrSite.js
+++ b/node_modules/sst/constructs/SsrSite.js
@@ -452,7 +452,7 @@ function handler(event) {
...cdk?.server,
streaming: props.streaming,
injections: [
- ...(warm ? [useServerFunctionWarmingInjection()] : []),
+ ...(warm ? [useServerFunctionWarmingInjection(props)] : []),
...(props.injections || []),
],
prefetchSecrets: regional?.prefetchSecrets,
@@ -645,14 +645,25 @@ function handler(event) {
OriginRequestPolicy.fromOriginRequestPolicyId(self, "ServerOriginRequestPolicy", "b689b0a8-53d0-40ab-baf2-68738e2966ac");
return singletonOriginRequestPolicy;
}
- function useServerFunctionWarmingInjection() {
- return `
+ function useServerFunctionWarmingInjection(props) {
+ return props.streaming ? `
if (event.type === "warmer") {
- return new Promise((resolve) => {
- setTimeout(() => {
- resolve({ serverId: "server-" + Math.random().toString(36).slice(2, 8) });
- }, event.delay);
- });
+ const response = await new Promise((resolve) => {
+ setTimeout(() => {
+ resolve({ serverId: "server-" + Math.random().toString(36).slice(2, 8) });
+ }, event.delay);
+ });
+
+ responseStream.write(JSON.stringify(response));
+ responseStream.end();
+ return;
+}` : `
+if (event.type === "warmer") {
+ return new Promise((resolve) => {
+ setTimeout(() => {
+ resolve({ serverId: "server-" + Math.random().toString(36).slice(2, 8) });
+ }, event.delay);
+ });
}`;
}
function getS3FileOptions(copy) {
Oh appreciate this!
Note: I cleaned up the patch a bit above and added a missed return
statement for the streaming response :)
Thanks @mateogianolio! Released in v2.39.9.
Btw. does this also fix the logging problem with logging?
Yes it does!