@intelligems/sst 2.49.6-ig.8 → 2.49.8-ig.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cli/commands/dev.js +10 -6
- package/constructs/AstroSite.d.ts +1 -1
- package/constructs/EdgeFunction.d.ts +1 -1
- package/constructs/EdgeFunction.js +8 -6
- package/constructs/Function.d.ts +3 -2
- package/constructs/Function.js +2 -1
- package/constructs/Job.d.ts +2 -2
- package/constructs/Job.js +4 -2
- package/constructs/NextjsSite.d.ts +1 -1
- package/constructs/NextjsSite.js +2 -2
- package/constructs/RemixSite.d.ts +1 -1
- package/constructs/SolidStartSite.d.ts +1 -1
- package/constructs/SsrFunction.d.ts +2 -2
- package/constructs/SsrFunction.js +7 -5
- package/constructs/SsrSite.d.ts +2 -2
- package/constructs/SsrSite.js +1 -1
- package/constructs/Stack.d.ts +1 -1
- package/constructs/Stack.js +1 -1
- package/constructs/SvelteKitSite.d.ts +1 -1
- package/constructs/deprecated/NextjsSite.d.ts +3 -3
- package/constructs/deprecated/NextjsSite.js +4 -1
- package/constructs/deprecated/cross-region-helper.js +3 -3
- package/iot.js +55 -0
- package/package.json +3 -3
- package/runtime/handlers/node.js +24 -2
- package/runtime/handlers.d.ts +4 -0
- package/runtime/memory-logging.d.ts +26 -0
- package/runtime/memory-logging.js +112 -0
- package/runtime/mono-build-config.d.ts +6 -3
- package/runtime/mono-build-config.js +34 -10
- package/runtime/server.js +35 -44
- package/runtime/stdout-attribution.d.ts +18 -0
- package/runtime/stdout-attribution.js +43 -0
- package/runtime/worker-config.d.ts +19 -0
- package/runtime/worker-config.js +26 -0
- package/runtime/worker-pool-logging.d.ts +2 -2
- package/runtime/worker-pool-logging.js +5 -5
- package/runtime/worker-pool.d.ts +77 -0
- package/runtime/worker-pool.js +162 -0
- package/runtime/workers.d.ts +33 -11
- package/runtime/workers.js +405 -513
- package/support/nodejs-runtime/index.mjs +214 -100
- package/watcher.js +2 -0
- package/LICENSE +0 -21
- package/README.md +0 -43
package/cli/commands/dev.js
CHANGED
|
@@ -401,12 +401,16 @@ export const dev = (program) => program.command(["dev", "start"], "Work on your
|
|
|
401
401
|
import("./plugins/warmer.js").then((mod) => mod.useRDSWarmer()),
|
|
402
402
|
useFunctionLogger(),
|
|
403
403
|
]);
|
|
404
|
-
//
|
|
405
|
-
//
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
404
|
+
// Warm the pool through the real request flow. SST_WARMUP_COUNT=0
|
|
405
|
+
// turns this off; the count is capped at the pool size so warmup can
|
|
406
|
+
// never hold more isolates than steady state would.
|
|
407
|
+
const { WARMUP_COUNT } = await import("../../runtime/worker-config.js");
|
|
408
|
+
if (WARMUP_COUNT > 0) {
|
|
409
|
+
import("../../runtime/workers.js").then(async (mod) => {
|
|
410
|
+
const workers = await mod.useRuntimeWorkers();
|
|
411
|
+
await workers.triggerWarmup(WARMUP_COUNT);
|
|
412
|
+
});
|
|
413
|
+
}
|
|
410
414
|
}
|
|
411
415
|
catch (e) {
|
|
412
416
|
await exitWithError(e);
|
|
@@ -43,7 +43,7 @@ export declare class AstroSite extends SsrSite {
|
|
|
43
43
|
data: {
|
|
44
44
|
mode: "placeholder" | "deployed";
|
|
45
45
|
path: string;
|
|
46
|
-
runtime: "nodejs16.x" | "nodejs18.x" | "nodejs20.x" | "nodejs22.x";
|
|
46
|
+
runtime: "nodejs16.x" | "nodejs18.x" | "nodejs20.x" | "nodejs22.x" | "nodejs24.x";
|
|
47
47
|
customDomainUrl: string | undefined;
|
|
48
48
|
url: string | undefined;
|
|
49
49
|
edge: boolean | undefined;
|
|
@@ -9,7 +9,7 @@ import { Permissions } from "./util/permission.js";
|
|
|
9
9
|
export interface EdgeFunctionProps {
|
|
10
10
|
bundle?: string;
|
|
11
11
|
handler: string;
|
|
12
|
-
runtime?: "nodejs16.x" | "nodejs18.x" | "nodejs20.x" | "nodejs22.x";
|
|
12
|
+
runtime?: "nodejs16.x" | "nodejs18.x" | "nodejs20.x" | "nodejs22.x" | "nodejs24.x";
|
|
13
13
|
timeout?: number | Duration;
|
|
14
14
|
memorySize?: number | Size;
|
|
15
15
|
permissions?: Permissions;
|
|
@@ -43,7 +43,7 @@ export class EdgeFunction extends Construct {
|
|
|
43
43
|
// them.
|
|
44
44
|
this.scope = props.scopeOverride || this;
|
|
45
45
|
this.props = {
|
|
46
|
-
runtime: "
|
|
46
|
+
runtime: "nodejs24.x",
|
|
47
47
|
timeout: 10,
|
|
48
48
|
memorySize: 1024,
|
|
49
49
|
...props,
|
|
@@ -345,11 +345,13 @@ export class EdgeFunction extends Construct {
|
|
|
345
345
|
S3Bucket: assetBucket,
|
|
346
346
|
S3Key: assetKey,
|
|
347
347
|
},
|
|
348
|
-
Runtime: runtime === "
|
|
349
|
-
? Runtime.
|
|
350
|
-
: runtime === "
|
|
351
|
-
? Runtime.
|
|
352
|
-
:
|
|
348
|
+
Runtime: runtime === "nodejs24.x"
|
|
349
|
+
? Runtime.NODEJS_24_X.name
|
|
350
|
+
: runtime === "nodejs22.x"
|
|
351
|
+
? Runtime.NODEJS_22_X.name
|
|
352
|
+
: runtime === "nodejs20.x"
|
|
353
|
+
? Runtime.NODEJS_20_X.name
|
|
354
|
+
: Runtime.NODEJS_18_X.name,
|
|
353
355
|
MemorySize: typeof memorySize === "string"
|
|
354
356
|
? toCdkSize(memorySize).toMebibytes()
|
|
355
357
|
: memorySize,
|
package/constructs/Function.d.ts
CHANGED
|
@@ -18,6 +18,7 @@ declare const supportedRuntimes: {
|
|
|
18
18
|
"nodejs18.x": CDKRuntime;
|
|
19
19
|
"nodejs20.x": CDKRuntime;
|
|
20
20
|
"nodejs22.x": CDKRuntime;
|
|
21
|
+
"nodejs24.x": CDKRuntime;
|
|
21
22
|
"python3.7": CDKRuntime;
|
|
22
23
|
"python3.8": CDKRuntime;
|
|
23
24
|
"python3.9": CDKRuntime;
|
|
@@ -150,7 +151,7 @@ export interface FunctionProps extends Omit<FunctionOptions, "functionName" | "m
|
|
|
150
151
|
handler?: string;
|
|
151
152
|
/**
|
|
152
153
|
* The runtime environment for the function.
|
|
153
|
-
* @default "
|
|
154
|
+
* @default "nodejs24.x"
|
|
154
155
|
* @example
|
|
155
156
|
* ```js
|
|
156
157
|
* new Function(stack, "Function", {
|
|
@@ -799,7 +800,7 @@ export declare class Function extends CDKFunction implements SSTConstruct {
|
|
|
799
800
|
type: "Function";
|
|
800
801
|
data: {
|
|
801
802
|
arn: string;
|
|
802
|
-
runtime: "container" | "rust" | "nodejs16.x" | "nodejs18.x" | "nodejs20.x" | "nodejs22.x" | "python3.7" | "python3.8" | "python3.9" | "python3.10" | "python3.11" | "python3.12" | "python3.13" | "dotnetcore3.1" | "dotnet6" | "dotnet8" | "java8" | "java11" | "java17" | "java21" | "go1.x" | "go" | undefined;
|
|
803
|
+
runtime: "container" | "rust" | "nodejs16.x" | "nodejs18.x" | "nodejs20.x" | "nodejs22.x" | "nodejs24.x" | "python3.7" | "python3.8" | "python3.9" | "python3.10" | "python3.11" | "python3.12" | "python3.13" | "dotnetcore3.1" | "dotnet6" | "dotnet8" | "java8" | "java11" | "java17" | "java21" | "go1.x" | "go" | undefined;
|
|
803
804
|
handler: string | undefined;
|
|
804
805
|
missingSourcemap: boolean | undefined;
|
|
805
806
|
localId: string;
|
package/constructs/Function.js
CHANGED
|
@@ -37,6 +37,7 @@ const supportedRuntimes = {
|
|
|
37
37
|
"nodejs18.x": CDKRuntime.NODEJS_18_X,
|
|
38
38
|
"nodejs20.x": CDKRuntime.NODEJS_20_X,
|
|
39
39
|
"nodejs22.x": CDKRuntime.NODEJS_22_X,
|
|
40
|
+
"nodejs24.x": CDKRuntime.NODEJS_24_X,
|
|
40
41
|
"python3.7": CDKRuntime.PYTHON_3_7,
|
|
41
42
|
"python3.8": CDKRuntime.PYTHON_3_8,
|
|
42
43
|
"python3.9": CDKRuntime.PYTHON_3_9,
|
|
@@ -89,7 +90,7 @@ export class Function extends CDKFunction {
|
|
|
89
90
|
.forEach((per) => {
|
|
90
91
|
props = Function.mergeProps(per, props);
|
|
91
92
|
});
|
|
92
|
-
props.runtime = props.runtime || "
|
|
93
|
+
props.runtime = props.runtime || "nodejs24.x";
|
|
93
94
|
if (props.runtime === "go1.x")
|
|
94
95
|
useWarning().add("go.deprecated");
|
|
95
96
|
// Set defaults
|
package/constructs/Job.d.ts
CHANGED
|
@@ -100,7 +100,7 @@ export interface JobProps {
|
|
|
100
100
|
architecture?: "x86_64" | "arm_64";
|
|
101
101
|
/**
|
|
102
102
|
* The runtime environment for the job.
|
|
103
|
-
* @default "
|
|
103
|
+
* @default "nodejs24.x"
|
|
104
104
|
* @example
|
|
105
105
|
* ```js
|
|
106
106
|
* new Job(stack, "MyJob", {
|
|
@@ -109,7 +109,7 @@ export interface JobProps {
|
|
|
109
109
|
* })
|
|
110
110
|
*```
|
|
111
111
|
*/
|
|
112
|
-
runtime?: "nodejs" | "nodejs16.x" | "nodejs18.x" | "nodejs20.x" | "nodejs22.x" | "container";
|
|
112
|
+
runtime?: "nodejs" | "nodejs16.x" | "nodejs18.x" | "nodejs20.x" | "nodejs22.x" | "nodejs24.x" | "container";
|
|
113
113
|
/**
|
|
114
114
|
* For "nodejs" runtime, point to the entry point and handler function.
|
|
115
115
|
* Of the format: `/path/to/file.function`.
|
package/constructs/Job.js
CHANGED
|
@@ -285,6 +285,7 @@ export class Job extends Construct {
|
|
|
285
285
|
"nodejs18.x": "amazon/aws-lambda-nodejs:18.2023.12.14.13",
|
|
286
286
|
"nodejs20.x": "amazon/aws-lambda-nodejs:20.2023.12.14.13",
|
|
287
287
|
"nodejs22.x": "amazon/aws-lambda-nodejs:22.2024.11.22.14",
|
|
288
|
+
"nodejs24.x": "amazon/aws-lambda-nodejs:24.2025.12.21.13",
|
|
288
289
|
},
|
|
289
290
|
x86_64: {
|
|
290
291
|
nodejs: "amazon/aws-lambda-nodejs:16",
|
|
@@ -292,11 +293,12 @@ export class Job extends Construct {
|
|
|
292
293
|
"nodejs18.x": "amazon/aws-lambda-nodejs:18",
|
|
293
294
|
"nodejs20.x": "amazon/aws-lambda-nodejs:20",
|
|
294
295
|
"nodejs22.x": "amazon/aws-lambda-nodejs:22",
|
|
296
|
+
"nodejs24.x": "amazon/aws-lambda-nodejs:24",
|
|
295
297
|
},
|
|
296
298
|
};
|
|
297
299
|
const image = LinuxBuildImage.fromDockerRegistry(
|
|
298
300
|
// ARM images can be found here https://hub.docker.com/r/amazon/aws-lambda-nodejs
|
|
299
|
-
dockerImageMap[architecture ?? "x86_64"][runtime ?? "
|
|
301
|
+
dockerImageMap[architecture ?? "x86_64"][runtime ?? "nodejs24.x"]);
|
|
300
302
|
project.environment = {
|
|
301
303
|
...project.environment,
|
|
302
304
|
type: architecture === "arm_64" ? "ARM_CONTAINER" : "LINUX_CONTAINER",
|
|
@@ -415,6 +417,6 @@ export class Job extends Construct {
|
|
|
415
417
|
}
|
|
416
418
|
convertJobRuntimeToFunctionRuntime() {
|
|
417
419
|
const { runtime } = this.props;
|
|
418
|
-
return runtime === "container" ? "container" : "
|
|
420
|
+
return runtime === "container" ? "container" : "nodejs24.x";
|
|
419
421
|
}
|
|
420
422
|
}
|
|
@@ -163,7 +163,7 @@ export declare class NextjsSite extends SsrSite {
|
|
|
163
163
|
data: {
|
|
164
164
|
mode: "placeholder" | "deployed";
|
|
165
165
|
path: string;
|
|
166
|
-
runtime: "nodejs16.x" | "nodejs18.x" | "nodejs20.x" | "nodejs22.x";
|
|
166
|
+
runtime: "nodejs16.x" | "nodejs18.x" | "nodejs20.x" | "nodejs22.x" | "nodejs24.x";
|
|
167
167
|
customDomainUrl: string | undefined;
|
|
168
168
|
url: string | undefined;
|
|
169
169
|
edge: boolean | undefined;
|
package/constructs/NextjsSite.js
CHANGED
|
@@ -78,7 +78,7 @@ export class NextjsSite extends SsrSite {
|
|
|
78
78
|
...baseServerConfig,
|
|
79
79
|
handler: fn.handler,
|
|
80
80
|
bundle: path.join(sitePath, fn.bundle),
|
|
81
|
-
runtime: this.props.runtime ?? "
|
|
81
|
+
runtime: this.props.runtime ?? "nodejs24.x",
|
|
82
82
|
architecture: Architecture.ARM_64,
|
|
83
83
|
memorySize: this.props.memorySize ?? 1536,
|
|
84
84
|
environment: {
|
|
@@ -107,7 +107,7 @@ export class NextjsSite extends SsrSite {
|
|
|
107
107
|
function: {
|
|
108
108
|
handler: fn.handler,
|
|
109
109
|
bundle: path.join(sitePath, fn.bundle),
|
|
110
|
-
runtime: "
|
|
110
|
+
runtime: "nodejs24.x",
|
|
111
111
|
memorySize: 1024,
|
|
112
112
|
environment: {
|
|
113
113
|
...environment,
|
|
@@ -101,7 +101,7 @@ export declare class RemixSite extends SsrSite {
|
|
|
101
101
|
data: {
|
|
102
102
|
mode: "placeholder" | "deployed";
|
|
103
103
|
path: string;
|
|
104
|
-
runtime: "nodejs16.x" | "nodejs18.x" | "nodejs20.x" | "nodejs22.x";
|
|
104
|
+
runtime: "nodejs16.x" | "nodejs18.x" | "nodejs20.x" | "nodejs22.x" | "nodejs24.x";
|
|
105
105
|
customDomainUrl: string | undefined;
|
|
106
106
|
url: string | undefined;
|
|
107
107
|
edge: boolean | undefined;
|
|
@@ -80,7 +80,7 @@ export declare class SolidStartSite extends SsrSite {
|
|
|
80
80
|
data: {
|
|
81
81
|
mode: "placeholder" | "deployed";
|
|
82
82
|
path: string;
|
|
83
|
-
runtime: "nodejs16.x" | "nodejs18.x" | "nodejs20.x" | "nodejs22.x";
|
|
83
|
+
runtime: "nodejs16.x" | "nodejs18.x" | "nodejs20.x" | "nodejs22.x" | "nodejs24.x";
|
|
84
84
|
customDomainUrl: string | undefined;
|
|
85
85
|
url: string | undefined;
|
|
86
86
|
edge: boolean | undefined;
|
|
@@ -11,7 +11,7 @@ import { Duration } from "./util/duration.js";
|
|
|
11
11
|
export interface SsrFunctionProps extends Omit<FunctionOptions, "memorySize" | "timeout" | "runtime"> {
|
|
12
12
|
bundle?: string;
|
|
13
13
|
handler: string;
|
|
14
|
-
runtime?: "nodejs16.x" | "nodejs18.x" | "nodejs20.x" | "nodejs22.x";
|
|
14
|
+
runtime?: "nodejs16.x" | "nodejs18.x" | "nodejs20.x" | "nodejs22.x" | "nodejs24.x";
|
|
15
15
|
timeout?: number | Duration;
|
|
16
16
|
memorySize?: number | Size;
|
|
17
17
|
permissions?: Permissions;
|
|
@@ -58,7 +58,7 @@ export declare class SsrFunction extends Construct implements SSTConstruct {
|
|
|
58
58
|
type: "Function";
|
|
59
59
|
data: {
|
|
60
60
|
arn: string;
|
|
61
|
-
runtime: "nodejs16.x" | "nodejs18.x" | "nodejs20.x" | "nodejs22.x" | undefined;
|
|
61
|
+
runtime: "nodejs16.x" | "nodejs18.x" | "nodejs20.x" | "nodejs22.x" | "nodejs24.x" | undefined;
|
|
62
62
|
handler: string;
|
|
63
63
|
missingSourcemap: boolean | undefined;
|
|
64
64
|
localId: string;
|
|
@@ -107,11 +107,13 @@ export class SsrFunction extends Construct {
|
|
|
107
107
|
handler: handler.split(path.sep).join(path.posix.sep),
|
|
108
108
|
logRetention: logRetention ?? RetentionDays.THREE_DAYS,
|
|
109
109
|
code: Code.fromBucket(Bucket.fromBucketName(this, "IServerFunctionBucket", assetBucket), assetKey),
|
|
110
|
-
runtime: runtime === "
|
|
111
|
-
? Runtime.
|
|
112
|
-
: runtime === "
|
|
113
|
-
? Runtime.
|
|
114
|
-
:
|
|
110
|
+
runtime: runtime === "nodejs24.x"
|
|
111
|
+
? Runtime.NODEJS_24_X
|
|
112
|
+
: runtime === "nodejs22.x"
|
|
113
|
+
? Runtime.NODEJS_22_X
|
|
114
|
+
: runtime === "nodejs20.x"
|
|
115
|
+
? Runtime.NODEJS_20_X
|
|
116
|
+
: Runtime.NODEJS_18_X,
|
|
115
117
|
architecture,
|
|
116
118
|
memorySize: typeof memorySize === "string"
|
|
117
119
|
? toCdkSize(memorySize).toMebibytes()
|
package/constructs/SsrSite.d.ts
CHANGED
|
@@ -139,7 +139,7 @@ export interface SsrSiteProps {
|
|
|
139
139
|
* runtime: "nodejs20.x",
|
|
140
140
|
* ```
|
|
141
141
|
*/
|
|
142
|
-
runtime?: "nodejs16.x" | "nodejs18.x" | "nodejs20.x" | "nodejs22.x";
|
|
142
|
+
runtime?: "nodejs16.x" | "nodejs18.x" | "nodejs20.x" | "nodejs22.x" | "nodejs24.x";
|
|
143
143
|
/**
|
|
144
144
|
* Used to configure nodejs function properties
|
|
145
145
|
*/
|
|
@@ -465,7 +465,7 @@ export declare abstract class SsrSite extends Construct implements SSTConstruct
|
|
|
465
465
|
data: {
|
|
466
466
|
mode: "placeholder" | "deployed";
|
|
467
467
|
path: string;
|
|
468
|
-
runtime: "nodejs16.x" | "nodejs18.x" | "nodejs20.x" | "nodejs22.x";
|
|
468
|
+
runtime: "nodejs16.x" | "nodejs18.x" | "nodejs20.x" | "nodejs22.x" | "nodejs24.x";
|
|
469
469
|
customDomainUrl: string | undefined;
|
|
470
470
|
url: string | undefined;
|
|
471
471
|
edge: boolean | undefined;
|
package/constructs/SsrSite.js
CHANGED
|
@@ -634,7 +634,7 @@ function handler(event) {
|
|
|
634
634
|
singletonUrlSigner ??
|
|
635
635
|
new EdgeFunction(self, "ServerUrlSigningFunction", {
|
|
636
636
|
bundle: path.join(__dirname, "../support/signing-function"),
|
|
637
|
-
runtime: "
|
|
637
|
+
runtime: "nodejs24.x",
|
|
638
638
|
handler: "index.handler",
|
|
639
639
|
timeout: 10,
|
|
640
640
|
memorySize: 128,
|
package/constructs/Stack.d.ts
CHANGED
package/constructs/Stack.js
CHANGED
|
@@ -121,7 +121,7 @@ export declare class SvelteKitSite extends SsrSite {
|
|
|
121
121
|
data: {
|
|
122
122
|
mode: "placeholder" | "deployed";
|
|
123
123
|
path: string;
|
|
124
|
-
runtime: "nodejs16.x" | "nodejs18.x" | "nodejs20.x" | "nodejs22.x";
|
|
124
|
+
runtime: "nodejs16.x" | "nodejs18.x" | "nodejs20.x" | "nodejs22.x" | "nodejs24.x";
|
|
125
125
|
customDomainUrl: string | undefined;
|
|
126
126
|
url: string | undefined;
|
|
127
127
|
edge: boolean | undefined;
|
|
@@ -74,16 +74,16 @@ export interface NextjsSiteProps {
|
|
|
74
74
|
permissions?: Permissions;
|
|
75
75
|
/**
|
|
76
76
|
* The runtime environment.
|
|
77
|
-
* @default "
|
|
77
|
+
* @default "nodejs24.x"
|
|
78
78
|
* @example
|
|
79
79
|
* ```js
|
|
80
80
|
* new Function(stack, "Function", {
|
|
81
81
|
* path: "path/to/site",
|
|
82
|
-
* runtime: "
|
|
82
|
+
* runtime: "nodejs24.x",
|
|
83
83
|
* })
|
|
84
84
|
*```
|
|
85
85
|
*/
|
|
86
|
-
runtime?: "nodejs16.x" | "nodejs18.x" | "nodejs20.x" | "nodejs22.x";
|
|
86
|
+
runtime?: "nodejs16.x" | "nodejs18.x" | "nodejs20.x" | "nodejs22.x" | "nodejs24.x";
|
|
87
87
|
};
|
|
88
88
|
};
|
|
89
89
|
/**
|
|
@@ -1039,13 +1039,16 @@ export class NextjsSite extends Construct {
|
|
|
1039
1039
|
return replaceValues;
|
|
1040
1040
|
}
|
|
1041
1041
|
normalizeRuntime(runtime) {
|
|
1042
|
+
if (runtime === "nodejs24.x") {
|
|
1043
|
+
return lambda.Runtime.NODEJS_24_X;
|
|
1044
|
+
}
|
|
1042
1045
|
if (runtime === "nodejs22.x") {
|
|
1043
1046
|
return lambda.Runtime.NODEJS_22_X;
|
|
1044
1047
|
}
|
|
1045
1048
|
if (runtime === "nodejs20.x") {
|
|
1046
1049
|
return lambda.Runtime.NODEJS_20_X;
|
|
1047
1050
|
}
|
|
1048
|
-
return lambda.Runtime.
|
|
1051
|
+
return lambda.Runtime.NODEJS_24_X;
|
|
1049
1052
|
}
|
|
1050
1053
|
}
|
|
1051
1054
|
export const useSites = createAppContext(() => {
|
|
@@ -18,7 +18,7 @@ export function getOrCreateBucket(scope) {
|
|
|
18
18
|
const provider = new lambda.Function(stack, providerId, {
|
|
19
19
|
code: lambda.Code.fromAsset(path.join(__dirname, "../../support/edge-function")),
|
|
20
20
|
handler: "s3-bucket.handler",
|
|
21
|
-
runtime: lambda.Runtime.
|
|
21
|
+
runtime: lambda.Runtime.NODEJS_22_X,
|
|
22
22
|
timeout: Duration.minutes(15),
|
|
23
23
|
memorySize: 1024,
|
|
24
24
|
initialPolicy: [
|
|
@@ -50,7 +50,7 @@ export function createFunction(scope, name, role, bucketName, functionParams) {
|
|
|
50
50
|
provider = new lambda.Function(stack, providerId, {
|
|
51
51
|
code: lambda.Code.fromAsset(path.join(__dirname, "../../support/edge-function")),
|
|
52
52
|
handler: "edge-lambda.handler",
|
|
53
|
-
runtime: lambda.Runtime.
|
|
53
|
+
runtime: lambda.Runtime.NODEJS_22_X,
|
|
54
54
|
timeout: Duration.minutes(15),
|
|
55
55
|
memorySize: 1024,
|
|
56
56
|
initialPolicy: [
|
|
@@ -88,7 +88,7 @@ export function createVersion(scope, name, functionArn) {
|
|
|
88
88
|
provider = new lambda.Function(stack, providerId, {
|
|
89
89
|
code: lambda.Code.fromAsset(path.join(__dirname, "../../support/edge-function")),
|
|
90
90
|
handler: "edge-lambda-version.handler",
|
|
91
|
-
runtime: lambda.Runtime.
|
|
91
|
+
runtime: lambda.Runtime.NODEJS_22_X,
|
|
92
92
|
timeout: Duration.minutes(15),
|
|
93
93
|
memorySize: 1024,
|
|
94
94
|
initialPolicy: [
|
package/iot.js
CHANGED
|
@@ -22,6 +22,59 @@ import { useBus } from "./bus.js";
|
|
|
22
22
|
import { useProject } from "./project.js";
|
|
23
23
|
import { useBootstrap } from "./bootstrap.js";
|
|
24
24
|
import { PutObjectCommand, S3Client } from "@aws-sdk/client-s3";
|
|
25
|
+
/**
|
|
26
|
+
* Re-sign the next reconnect with credentials that are still alive.
|
|
27
|
+
*
|
|
28
|
+
* The device is built with resolved credential *values*, because
|
|
29
|
+
* `aws-iot-device-sdk` takes strings rather than a provider. It keeps them in
|
|
30
|
+
* closure variables and re-signs the WebSocket URL from those on every
|
|
31
|
+
* reconnect, and nothing ever writes to them again except this call. So once
|
|
32
|
+
* the session expires, every retry presents a dead `sessionToken`, AWS IoT
|
|
33
|
+
* rejects the upgrade, and the socket closes again — forever.
|
|
34
|
+
*
|
|
35
|
+
* Measured on one machine: the connection dropped routinely five times in the
|
|
36
|
+
* first fifteen minutes and recovered each time; an hour later the credentials
|
|
37
|
+
* expired, and the next drop began **93 consecutive failed reconnects over five
|
|
38
|
+
* hours**, none of which emitted an `error` event. Nothing in the CLI said
|
|
39
|
+
* anything, and every request through the Live Lambda bridge 504'd.
|
|
40
|
+
*
|
|
41
|
+
* Every other AWS call in the process is unaffected, because `useAWSClient`
|
|
42
|
+
* passes the *provider* and the SDK calls it per request. This is the one path
|
|
43
|
+
* that holds values, so it is the one path that needs telling.
|
|
44
|
+
*
|
|
45
|
+
* **Why `close` and not `reconnect`.** The signing is synchronous and this
|
|
46
|
+
* refresh is not, so the two race. `emit("reconnect")` runs its handlers and
|
|
47
|
+
* returns — it does not await them — and `_setupStream()` signs on the next
|
|
48
|
+
* line, from whatever the variables hold at that instant. A refresh started
|
|
49
|
+
* there always loses. `close` fires one backoff interval earlier (the SDK
|
|
50
|
+
* manages its own, from `baseReconnectTimeMs` of 1s up to 128s, ignoring the
|
|
51
|
+
* `reconnectPeriod` passed in), which is ample for the resolve to land before
|
|
52
|
+
* the next attempt signs.
|
|
53
|
+
*
|
|
54
|
+
* So this wins the race by margin, not by construction. Two things bound it:
|
|
55
|
+
* `close` fires on **every** failed reconnect, not once per outage, so the
|
|
56
|
+
* values can never be more than one backoff interval stale; and the retry loop
|
|
57
|
+
* is unconditional. Making it airtight would mean keeping the stored
|
|
58
|
+
* credentials warm so the synchronous path can never read a stale one — a
|
|
59
|
+
* timer, which is machinery duplicating what the memoized provider already
|
|
60
|
+
* does. Measured recovery is five seconds, so that is not worth it yet.
|
|
61
|
+
*
|
|
62
|
+
* The provider only reaches the network within five minutes of expiry, so this
|
|
63
|
+
* is an in-memory read on most drops and one real refresh per session.
|
|
64
|
+
*/
|
|
65
|
+
async function refreshWebSocketCredentials(device, label) {
|
|
66
|
+
try {
|
|
67
|
+
const fresh = await useAWSCredentials();
|
|
68
|
+
// The typings mark `expiration` as required, but the implementation only
|
|
69
|
+
// assigns the three credential strings and never reads it — so this passes
|
|
70
|
+
// what the provider gave rather than inventing a date to satisfy a
|
|
71
|
+
// parameter nothing uses.
|
|
72
|
+
device.updateWebSocketCredentials(fresh.accessKeyId, fresh.secretAccessKey, fresh.sessionToken, fresh.expiration);
|
|
73
|
+
}
|
|
74
|
+
catch (err) {
|
|
75
|
+
Logger.debug(`${label} credential refresh failed`, err);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
25
78
|
export const useIOT = lazy(async () => {
|
|
26
79
|
const bus = useBus();
|
|
27
80
|
const endpoint = await useIOTEndpoint();
|
|
@@ -116,6 +169,7 @@ export const useIOT = lazy(async () => {
|
|
|
116
169
|
});
|
|
117
170
|
device.on("close", () => {
|
|
118
171
|
Logger.debug("IoT closed");
|
|
172
|
+
void refreshWebSocketCredentials(device, "IoT");
|
|
119
173
|
});
|
|
120
174
|
device.on("reconnect", () => {
|
|
121
175
|
Logger.debug("IoT reconnecting...");
|
|
@@ -241,6 +295,7 @@ export const useIOTControl = lazy(async () => {
|
|
|
241
295
|
});
|
|
242
296
|
device.on("close", () => {
|
|
243
297
|
Logger.debug("IoT control closed");
|
|
298
|
+
void refreshWebSocketCredentials(device, "IoT control");
|
|
244
299
|
});
|
|
245
300
|
device.on("reconnect", () => {
|
|
246
301
|
Logger.debug("IoT control reconnecting...");
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"sideEffects": false,
|
|
3
3
|
"name": "@intelligems/sst",
|
|
4
|
-
"version": "2.49.
|
|
4
|
+
"version": "2.49.8-ig.1",
|
|
5
5
|
"bin": {
|
|
6
6
|
"sst": "cli/sst.js"
|
|
7
7
|
},
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"homepage": "https://sst.dev",
|
|
33
33
|
"dependencies": {
|
|
34
34
|
"@aws-cdk/aws-lambda-python-alpha": "2.201.0-alpha.0",
|
|
35
|
-
"@aws-cdk/cloud-assembly-schema": "
|
|
35
|
+
"@aws-cdk/cloud-assembly-schema": "48.0.0",
|
|
36
36
|
"@aws-cdk/cloudformation-diff": "2.182.0",
|
|
37
37
|
"@aws-cdk/cx-api": "2.201.0",
|
|
38
38
|
"@aws-cdk/toolkit-lib": "1.1.1",
|
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
"@smithy/signature-v4": "2.0.16",
|
|
61
61
|
"@trpc/server": "9.18.0",
|
|
62
62
|
"adm-zip": "0.5.14",
|
|
63
|
-
"aws-cdk-lib": "2.
|
|
63
|
+
"aws-cdk-lib": "2.224.0",
|
|
64
64
|
"aws-iot-device-sdk": "^2.2.13",
|
|
65
65
|
"aws-sdk": "^2.1501.0",
|
|
66
66
|
"builtin-modules": "3.2.0",
|
package/runtime/handlers/node.js
CHANGED
|
@@ -12,6 +12,8 @@ import { Colors } from "../../cli/colors.js";
|
|
|
12
12
|
import { Logger } from "../../logger.js";
|
|
13
13
|
import { findAbove } from "../../util/fs.js";
|
|
14
14
|
import { useMonoBuildConfig } from "../mono-build-config.js";
|
|
15
|
+
import { SOURCE_MAPS, WORKER_MAX_HEAP_MB } from "../worker-config.js";
|
|
16
|
+
import { forgetWorkerMemory, recordWorkerMemory } from "../memory-logging.js";
|
|
15
17
|
export const useNodeHandler = () => {
|
|
16
18
|
const rebuildCache = {};
|
|
17
19
|
process.on("exit", () => {
|
|
@@ -40,7 +42,13 @@ export const useNodeHandler = () => {
|
|
|
40
42
|
...input.environment,
|
|
41
43
|
IS_LOCAL: "true",
|
|
42
44
|
},
|
|
43
|
-
|
|
45
|
+
// Source maps cost memory in every isolate; opt in with SST_SOURCE_MAPS=true
|
|
46
|
+
execArgv: SOURCE_MAPS ? ["--enable-source-maps"] : [],
|
|
47
|
+
// Cap each isolate so a leaking handler kills its own worker
|
|
48
|
+
// instead of growing the whole dev process until the machine stalls
|
|
49
|
+
resourceLimits: WORKER_MAX_HEAP_MB > 0
|
|
50
|
+
? { maxOldGenerationSizeMb: WORKER_MAX_HEAP_MB }
|
|
51
|
+
: undefined,
|
|
44
52
|
workerData: input,
|
|
45
53
|
stderr: true,
|
|
46
54
|
stdin: true,
|
|
@@ -52,11 +60,25 @@ export const useNodeHandler = () => {
|
|
|
52
60
|
worker.stderr.on("data", (data) => {
|
|
53
61
|
workers.stdout(input.workerID, data.toString());
|
|
54
62
|
});
|
|
55
|
-
worker.on("
|
|
63
|
+
worker.on("message", (msg) => {
|
|
64
|
+
if (msg && msg.type === "sst.memory") {
|
|
65
|
+
recordWorkerMemory(input.workerID, msg.report);
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
worker.on("error", (err) => {
|
|
69
|
+
Logger.debug("Worker error", input.workerID, err);
|
|
70
|
+
});
|
|
71
|
+
worker.on("exit", () => {
|
|
72
|
+
threads.delete(input.workerID);
|
|
73
|
+
forgetWorkerMemory(input.workerID);
|
|
74
|
+
workers.exited(input.workerID);
|
|
75
|
+
});
|
|
56
76
|
threads.set(input.workerID, worker);
|
|
57
77
|
},
|
|
58
78
|
stopWorker: async (workerID) => {
|
|
59
79
|
const worker = threads.get(workerID);
|
|
80
|
+
threads.delete(workerID);
|
|
81
|
+
forgetWorkerMemory(workerID);
|
|
60
82
|
await worker?.terminate();
|
|
61
83
|
},
|
|
62
84
|
build: async (input) => {
|
package/runtime/handlers.d.ts
CHANGED
|
@@ -30,6 +30,10 @@ export interface StartWorkerInput {
|
|
|
30
30
|
runtime: string;
|
|
31
31
|
/** Whether this worker is using mono build mode */
|
|
32
32
|
isMonoBuild?: boolean;
|
|
33
|
+
/** Invocations this worker may run at once (Node only; others run one). */
|
|
34
|
+
concurrency?: number;
|
|
35
|
+
/** Ask the worker to report its memory usage to the parent. */
|
|
36
|
+
debugMemory?: boolean;
|
|
33
37
|
}
|
|
34
38
|
interface ShouldBuildInput {
|
|
35
39
|
file: string;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export interface WorkerMemoryReport {
|
|
2
|
+
rss: number;
|
|
3
|
+
heapUsed: number;
|
|
4
|
+
heapTotal: number;
|
|
5
|
+
external: number;
|
|
6
|
+
/** "loaded" right after the bundle import, "response" after an invocation. */
|
|
7
|
+
phase: "loaded" | "response";
|
|
8
|
+
loadMs?: number;
|
|
9
|
+
}
|
|
10
|
+
interface WorkerStatsProvider {
|
|
11
|
+
(): {
|
|
12
|
+
workers: number;
|
|
13
|
+
inFlight: number;
|
|
14
|
+
queued: number;
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
export declare const isMemoryTrackingEnabled: () => boolean;
|
|
18
|
+
/** Called by the Node handler whenever a worker posts a memory report. */
|
|
19
|
+
export declare function recordWorkerMemory(workerID: string, report: WorkerMemoryReport): void;
|
|
20
|
+
/** Called by the Node handler when a worker goes away. */
|
|
21
|
+
export declare function forgetWorkerMemory(workerID: string): void;
|
|
22
|
+
/** Start periodic sampling. No-op unless SST_DEBUG_MEMORY=true. */
|
|
23
|
+
export declare function startMemorySampling(stats: WorkerStatsProvider): void;
|
|
24
|
+
/** Peak line for the pool session summary. Empty when tracking is off. */
|
|
25
|
+
export declare function memorySummary(): string;
|
|
26
|
+
export {};
|