@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
@@ -0,0 +1,162 @@
1
+ /**
2
+ * Bookkeeping for pooled dev workers.
3
+ *
4
+ * A pool key groups workers that can serve the same invocations: one key per
5
+ * function normally, one shared key for every Node function in mono-build
6
+ * mode. Each worker may hold up to `maxConcurrency` invocations at once, and a
7
+ * key never holds more than `maxWorkers` live (non-stale) workers, so the
8
+ * memory a key can consume is bounded by `maxWorkers` isolates.
9
+ *
10
+ * This module decides *which* worker serves a request and when a worker is
11
+ * retired. It never starts or stops threads itself: `onTerminate` is the hook
12
+ * the owner uses to actually stop the worker.
13
+ */
14
+ export class WorkerPool {
15
+ opts;
16
+ pools = new Map();
17
+ byID = new Map();
18
+ constructor(opts) {
19
+ this.opts = opts;
20
+ }
21
+ add(worker) {
22
+ let pool = this.pools.get(worker.poolKey);
23
+ if (!pool) {
24
+ pool = [];
25
+ this.pools.set(worker.poolKey, pool);
26
+ }
27
+ pool.push(worker);
28
+ this.byID.set(worker.id, worker);
29
+ }
30
+ get(id) {
31
+ return this.byID.get(id);
32
+ }
33
+ workersFor(poolKey) {
34
+ return this.pools.get(poolKey) ?? [];
35
+ }
36
+ all() {
37
+ return [...this.byID.values()];
38
+ }
39
+ /** Live workers count toward the cap; stale ones are on their way out. */
40
+ liveCount(poolKey) {
41
+ return this.workersFor(poolKey).filter((w) => !w.stale).length;
42
+ }
43
+ canCreate(poolKey) {
44
+ return this.liveCount(poolKey) < this.opts.maxWorkers;
45
+ }
46
+ /**
47
+ * Least-loaded live worker with spare capacity, or undefined. Workers whose
48
+ * bundle is older than `currentMtime` are retired on the way: idle ones now,
49
+ * busy ones once they drain.
50
+ */
51
+ pick(poolKey, currentMtime) {
52
+ const pool = this.pools.get(poolKey);
53
+ if (!pool || pool.length === 0)
54
+ return undefined;
55
+ for (const worker of [...pool]) {
56
+ if (currentMtime &&
57
+ worker.bundleMtime &&
58
+ currentMtime > worker.bundleMtime &&
59
+ !worker.stale) {
60
+ this.retire(worker, "stale_mtime");
61
+ }
62
+ }
63
+ let best;
64
+ for (const worker of pool) {
65
+ if (worker.stale)
66
+ continue;
67
+ if (worker.inFlight >= worker.maxConcurrency)
68
+ continue;
69
+ if (!best || worker.inFlight < best.inFlight)
70
+ best = worker;
71
+ }
72
+ return best;
73
+ }
74
+ /** Hand an invocation to a worker. */
75
+ checkout(worker, functionID) {
76
+ if (worker.idleTimer) {
77
+ clearTimeout(worker.idleTimer);
78
+ worker.idleTimer = undefined;
79
+ }
80
+ worker.inFlight += 1;
81
+ worker.functionID = functionID;
82
+ }
83
+ /**
84
+ * An invocation finished. Returns what became of the worker: it is gone
85
+ * (stale and drained), idle (timer armed), or still busy.
86
+ */
87
+ checkin(worker) {
88
+ if (worker.inFlight > 0)
89
+ worker.inFlight -= 1;
90
+ if (worker.inFlight > 0)
91
+ return "busy";
92
+ if (worker.stale) {
93
+ this.remove(worker);
94
+ this.opts.onTerminate(worker, "stale");
95
+ return "terminated";
96
+ }
97
+ worker.idleTimer = setTimeout(() => {
98
+ worker.idleTimer = undefined;
99
+ if (worker.inFlight > 0)
100
+ return;
101
+ if (!this.byID.has(worker.id))
102
+ return;
103
+ this.remove(worker);
104
+ this.opts.onTerminate(worker, "idle_timeout");
105
+ }, this.opts.idleTimeoutMs);
106
+ return "idle";
107
+ }
108
+ /**
109
+ * The code behind `poolKey` changed. Idle workers go now; busy ones are
110
+ * marked stale and go when they drain. Returns the ids of workers that
111
+ * were only marked.
112
+ */
113
+ invalidate(poolKey, reason) {
114
+ const marked = [];
115
+ for (const worker of [...this.workersFor(poolKey)]) {
116
+ if (worker.inFlight === 0) {
117
+ this.remove(worker);
118
+ this.opts.onTerminate(worker, reason);
119
+ }
120
+ else {
121
+ worker.stale = true;
122
+ marked.push(worker.id);
123
+ }
124
+ }
125
+ return marked;
126
+ }
127
+ /** Forget a worker that exited on its own (crash, OOM, self-timeout). */
128
+ remove(worker) {
129
+ if (worker.idleTimer) {
130
+ clearTimeout(worker.idleTimer);
131
+ worker.idleTimer = undefined;
132
+ }
133
+ this.byID.delete(worker.id);
134
+ const pool = this.pools.get(worker.poolKey);
135
+ if (!pool)
136
+ return;
137
+ const idx = pool.indexOf(worker);
138
+ if (idx >= 0)
139
+ pool.splice(idx, 1);
140
+ if (pool.length === 0)
141
+ this.pools.delete(worker.poolKey);
142
+ }
143
+ stats() {
144
+ let idle = 0;
145
+ let inFlight = 0;
146
+ for (const worker of this.byID.values()) {
147
+ if (worker.inFlight === 0)
148
+ idle += 1;
149
+ inFlight += worker.inFlight;
150
+ }
151
+ return { workers: this.byID.size, idle, inFlight };
152
+ }
153
+ retire(worker, reason) {
154
+ if (worker.inFlight === 0) {
155
+ this.remove(worker);
156
+ this.opts.onTerminate(worker, reason);
157
+ }
158
+ else {
159
+ worker.stale = true;
160
+ }
161
+ }
162
+ }
@@ -1,3 +1,4 @@
1
+ import { EventPayload } from "../bus.js";
1
2
  declare module "../bus.js" {
2
3
  interface Events {
3
4
  "worker.started": {
@@ -11,6 +12,8 @@ declare module "../bus.js" {
11
12
  "worker.exited": {
12
13
  workerID: string;
13
14
  functionID: string;
15
+ /** Set for pooled workers: the id the runtime server keys on. */
16
+ pooledWorkerID?: string;
14
17
  };
15
18
  "worker.stdout": {
16
19
  workerID: string;
@@ -39,27 +42,45 @@ declare module "../bus.js" {
39
42
  };
40
43
  }
41
44
  }
45
+ interface Worker {
46
+ workerID: string;
47
+ functionID: string;
48
+ }
42
49
  export declare const useRuntimeWorkers: () => Promise<{
43
- fromID(workerID: string): {
44
- workerID: string;
45
- functionID: string;
46
- };
50
+ fromID(workerID: string): Worker;
47
51
  getCurrentRequestID(workerID: string): string | undefined;
52
+ /**
53
+ * Who a response belongs to. Pooled workers may hold several requests,
54
+ * so the request id decides; non-pooled workers are their own AWS worker.
55
+ */
56
+ resolveRequest(workerID: string, requestID?: string): {
57
+ awsWorkerID: string;
58
+ functionID: string;
59
+ } | undefined;
48
60
  stdout(workerID: string, message: string): void;
49
61
  exited(workerID: string): void;
50
- onResponse(pooledWorkerID: string): void;
51
- getAwsWorkerID(pooledWorkerID: string): string | undefined;
62
+ onResponse(pooledWorkerID: string, requestID?: string): void;
52
63
  isPooled(workerID: string): boolean;
53
- subscribe: <Type extends "worker.started" | "worker.stopped" | "worker.exited" | "worker.stdout" | "worker.reused">(type: Type, cb: (payload: import("../bus.js").EventPayload<Type>) => void) => {
64
+ stats: () => {
65
+ workers: number;
66
+ inFlight: number;
67
+ queued: number;
68
+ };
69
+ subscribe: <Type extends "worker.started" | "worker.stopped" | "worker.exited" | "worker.stdout" | "worker.reused">(type: Type, cb: (payload: EventPayload<Type>) => void) => {
54
70
  type: keyof import("../bus.js").Events;
55
71
  cb: (payload: any) => void;
56
72
  };
57
73
  /**
58
- * Trigger warmup by invoking Lambda functions with warmup payloads.
59
- * This sends real requests through the IoT bridge, which naturally creates workers.
60
- * @param count Number of workers to warm up (default: 15)
74
+ * Warm the pool by invoking a Node function with warm pings.
75
+ *
76
+ * Each ping is marked as a fan-out *child* (`__WARMER_INVOCATION__ > 1`)
77
+ * so the app's lambda-warmer preloads its handlers and returns instead of
78
+ * fanning out to `concurrency` more Lambdas, which is what turned the old
79
+ * 30 pings into ~900 worker creations. The count is capped at the pool
80
+ * size, and pings go through the normal pool path, so warmup can never
81
+ * hold more isolates than steady state.
61
82
  */
62
- triggerWarmup(count?: number): Promise<{
83
+ triggerWarmup(count: number): Promise<{
63
84
  warmed: number;
64
85
  elapsed?: undefined;
65
86
  } | {
@@ -67,3 +88,4 @@ export declare const useRuntimeWorkers: () => Promise<{
67
88
  elapsed: number;
68
89
  }>;
69
90
  }>;
91
+ export {};