@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.
Files changed (45) hide show
  1. package/cli/commands/dev.js +10 -6
  2. package/constructs/AstroSite.d.ts +1 -1
  3. package/constructs/EdgeFunction.d.ts +1 -1
  4. package/constructs/EdgeFunction.js +8 -6
  5. package/constructs/Function.d.ts +3 -2
  6. package/constructs/Function.js +2 -1
  7. package/constructs/Job.d.ts +2 -2
  8. package/constructs/Job.js +4 -2
  9. package/constructs/NextjsSite.d.ts +1 -1
  10. package/constructs/NextjsSite.js +2 -2
  11. package/constructs/RemixSite.d.ts +1 -1
  12. package/constructs/SolidStartSite.d.ts +1 -1
  13. package/constructs/SsrFunction.d.ts +2 -2
  14. package/constructs/SsrFunction.js +7 -5
  15. package/constructs/SsrSite.d.ts +2 -2
  16. package/constructs/SsrSite.js +1 -1
  17. package/constructs/Stack.d.ts +1 -1
  18. package/constructs/Stack.js +1 -1
  19. package/constructs/SvelteKitSite.d.ts +1 -1
  20. package/constructs/deprecated/NextjsSite.d.ts +3 -3
  21. package/constructs/deprecated/NextjsSite.js +4 -1
  22. package/constructs/deprecated/cross-region-helper.js +3 -3
  23. package/iot.js +55 -0
  24. package/package.json +3 -3
  25. package/runtime/handlers/node.js +24 -2
  26. package/runtime/handlers.d.ts +4 -0
  27. package/runtime/memory-logging.d.ts +26 -0
  28. package/runtime/memory-logging.js +112 -0
  29. package/runtime/mono-build-config.d.ts +6 -3
  30. package/runtime/mono-build-config.js +34 -10
  31. package/runtime/server.js +35 -44
  32. package/runtime/stdout-attribution.d.ts +18 -0
  33. package/runtime/stdout-attribution.js +43 -0
  34. package/runtime/worker-config.d.ts +19 -0
  35. package/runtime/worker-config.js +26 -0
  36. package/runtime/worker-pool-logging.d.ts +2 -2
  37. package/runtime/worker-pool-logging.js +5 -5
  38. package/runtime/worker-pool.d.ts +77 -0
  39. package/runtime/worker-pool.js +162 -0
  40. package/runtime/workers.d.ts +33 -11
  41. package/runtime/workers.js +405 -513
  42. package/support/nodejs-runtime/index.mjs +214 -100
  43. package/watcher.js +2 -0
  44. package/LICENSE +0 -21
  45. package/README.md +0 -43
@@ -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
- // Trigger warmup by invoking Lambda functions with warmup payloads
405
- // This creates workers through the real request flow
406
- import("../../runtime/workers.js").then(async (mod) => {
407
- const workers = await mod.useRuntimeWorkers();
408
- await workers.triggerWarmup(30);
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: "nodejs18.x",
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 === "nodejs22.x"
349
- ? Runtime.NODEJS_22_X.name
350
- : runtime === "nodejs20.x"
351
- ? Runtime.NODEJS_20_X.name
352
- : Runtime.NODEJS_18_X.name,
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,
@@ -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 "nodejs22.x"
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;
@@ -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 || "nodejs22.x";
93
+ props.runtime = props.runtime || "nodejs24.x";
93
94
  if (props.runtime === "go1.x")
94
95
  useWarning().add("go.deprecated");
95
96
  // Set defaults
@@ -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 "nodejs18.x"
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 ?? "nodejs18.x"]);
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" : "nodejs18.x";
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;
@@ -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 ?? "nodejs18.x",
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: "nodejs18.x",
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 === "nodejs22.x"
111
- ? Runtime.NODEJS_22_X
112
- : runtime === "nodejs20.x"
113
- ? Runtime.NODEJS_20_X
114
- : Runtime.NODEJS_18_X,
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()
@@ -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;
@@ -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: "nodejs18.x",
637
+ runtime: "nodejs24.x",
638
638
  handler: "index.handler",
639
639
  timeout: 10,
640
640
  memorySize: 128,
@@ -47,7 +47,7 @@ export declare class Stack extends CDKStack {
47
47
  * ```js
48
48
  * stack.setDefaultFunctionProps({
49
49
  * srcPath: "backend",
50
- * runtime: "nodejs18.x",
50
+ * runtime: "nodejs24.x",
51
51
  * });
52
52
  * ```
53
53
  */
@@ -68,7 +68,7 @@ export class Stack extends CDKStack {
68
68
  * ```js
69
69
  * stack.setDefaultFunctionProps({
70
70
  * srcPath: "backend",
71
- * runtime: "nodejs18.x",
71
+ * runtime: "nodejs24.x",
72
72
  * });
73
73
  * ```
74
74
  */
@@ -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 "nodejs18.x"
77
+ * @default "nodejs24.x"
78
78
  * @example
79
79
  * ```js
80
80
  * new Function(stack, "Function", {
81
81
  * path: "path/to/site",
82
- * runtime: "nodejs18.x",
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.NODEJS_18_X;
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.NODEJS_20_X,
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.NODEJS_20_X,
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.NODEJS_20_X,
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.6-ig.8",
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": "44.5.0",
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.201.0",
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",
@@ -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
- execArgv: ["--enable-source-maps"],
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("exit", () => workers.exited(input.workerID));
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) => {
@@ -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 {};