@nimbus-sh/worker 0.2.3 → 0.4.0
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/dist/_shared/session-router.d.ts +8 -0
- package/dist/_shared/session-router.d.ts.map +1 -1
- package/dist/_shared/session-router.js +8 -0
- package/dist/esbuild-wasm-bundle.generated.d.ts +1 -1
- package/dist/esbuild-wasm-bundle.generated.js +1 -1
- package/dist/facets/cirrus-real.js +1 -1
- package/dist/facets/manager.d.ts +43 -129
- package/dist/facets/manager.d.ts.map +1 -1
- package/dist/facets/manager.js +107 -318
- package/dist/facets/opencode-staging.d.ts +1 -1
- package/dist/facets/opencode-staging.d.ts.map +1 -1
- package/dist/facets/opencode-staging.js +3 -0
- package/dist/facets/real-vite-hmr.js +1 -1
- package/dist/facets/vite-dev-server.d.ts +4 -4
- package/dist/facets/vite-dev-server.js +5 -5
- package/dist/git/commands.d.ts +8 -0
- package/dist/git/commands.d.ts.map +1 -1
- package/dist/git/commands.js +41 -9
- package/dist/git/network-facet.d.ts +1 -1
- package/dist/git/network-facet.d.ts.map +1 -1
- package/dist/git/network-facet.js +39 -15
- package/dist/git-bundle.generated.d.ts +2 -2
- package/dist/git-bundle.generated.d.ts.map +1 -1
- package/dist/git-bundle.generated.js +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -1
- package/dist/loaders/child-process/spawn-facet.js +1 -1
- package/dist/loaders/child-process/spawn-pool.d.ts.map +1 -1
- package/dist/loaders/child-process/spawn-pool.js +2 -2
- package/dist/loaders/generated-workers.d.ts +2 -2
- package/dist/loaders/generated-workers.d.ts.map +1 -1
- package/dist/loaders/generated-workers.js +3 -3
- package/dist/loaders/npm-resolve-preamble.d.ts +3 -3
- package/dist/loaders/npm-resolve-preamble.js +3 -3
- package/dist/loaders/pre-bundle-preamble.d.ts +5 -5
- package/dist/loaders/pre-bundle-preamble.js +6 -6
- package/dist/loaders/process-host.d.ts +6 -107
- package/dist/loaders/process-host.d.ts.map +1 -1
- package/dist/loaders/process-host.js +6 -405
- package/dist/npm/install-batch-facet.d.ts +1 -1
- package/dist/npm/install-batch-facet.js +1 -1
- package/dist/npm/installer.d.ts +6 -6
- package/dist/npm/installer.d.ts.map +1 -1
- package/dist/npm/installer.js +28 -27
- package/dist/npm/pre-bundle-facet.d.ts +2 -2
- package/dist/npm/pre-bundle-facet.js +5 -5
- package/dist/npm/r2-cache.d.ts +1 -1
- package/dist/npm/resolve-facet.d.ts +1 -1
- package/dist/npm/resolve-facet.js +1 -1
- package/dist/npm/resolve-one-facet.d.ts +5 -5
- package/dist/npm/resolve-one-facet.js +5 -5
- package/dist/router/index.js +2 -2
- package/dist/router/remote-api.js +9 -1
- package/dist/runtime/bun-repl.d.ts +1 -1
- package/dist/runtime/bun-repl.js +3 -3
- package/dist/runtime/esbuild-wasm-bytes.js +1 -1
- package/dist/runtime/facet-loader-host.d.ts +5 -8
- package/dist/runtime/facet-loader-host.d.ts.map +1 -1
- package/dist/runtime/facet-loader-host.js +7 -11
- package/dist/runtime/node-repl.js +2 -2
- package/dist/runtime/node-shims-artifact.js +1 -1
- package/dist/runtime/node-shims.js +2 -1
- package/dist/runtime/opencode-artifact.js +1 -1
- package/dist/runtime/opentui-wasm-bytes.js +1 -1
- package/dist/runtime/python-repl.js +3 -3
- package/dist/runtime/ruby-repl.js +2 -2
- package/dist/runtime/ruby-resident.js +1 -1
- package/dist/runtime/sqlite-wasm-bytes.js +1 -1
- package/dist/session/diag.js +1 -1
- package/dist/session/hibernation.d.ts +20 -53
- package/dist/session/hibernation.d.ts.map +1 -1
- package/dist/session/hibernation.js +57 -194
- package/dist/session/init-phases.d.ts +2 -3
- package/dist/session/init-phases.d.ts.map +1 -1
- package/dist/session/init-phases.js +3 -2
- package/dist/session/init.d.ts.map +1 -1
- package/dist/session/init.js +8 -4
- package/dist/session/keys.d.ts +14 -37
- package/dist/session/keys.d.ts.map +1 -1
- package/dist/session/keys.js +18 -37
- package/dist/session/nimbus-session.d.ts +10 -15
- package/dist/session/nimbus-session.d.ts.map +1 -1
- package/dist/session/nimbus-session.js +28 -31
- package/dist/session/port-capability.d.ts +43 -0
- package/dist/session/port-capability.d.ts.map +1 -0
- package/dist/session/port-capability.js +49 -0
- package/dist/session/programmatic.d.ts +39 -5
- package/dist/session/programmatic.d.ts.map +1 -1
- package/dist/session/programmatic.js +150 -19
- package/dist/session/routes.d.ts +2 -0
- package/dist/session/routes.d.ts.map +1 -1
- package/dist/session/routes.js +96 -20
- package/dist/session/rpc.d.ts +36 -9
- package/dist/session/rpc.d.ts.map +1 -1
- package/dist/session/rpc.js +84 -24
- package/dist/session/start-real-vite.d.ts.map +1 -1
- package/dist/session/start-real-vite.js +3 -1
- package/dist/session/state-store.d.ts +3 -2
- package/dist/session/state-store.d.ts.map +1 -1
- package/dist/session/state-store.js +3 -2
- package/dist/session/supervisor-rpc.d.ts.map +1 -1
- package/dist/session/supervisor-rpc.js +7 -4
- package/dist/session/ws.d.ts +1 -3
- package/dist/session/ws.d.ts.map +1 -1
- package/dist/session/ws.js +4 -3
- package/dist/wrangler/nimbus-wrangler.js +1 -1
- package/package.json +4 -2
- package/scripts/bundle-esbuild-wasm.mjs +2 -2
- package/scripts/bundle-facet-workers.mjs +5 -7
- package/scripts/bundle-sqlite-wasm.mjs +1 -1
- package/dist/facets/inner-do-registry.d.ts +0 -41
- package/dist/facets/inner-do-registry.d.ts.map +0 -1
- package/dist/facets/inner-do-registry.js +0 -51
- package/dist/facets/launch-pacer.d.ts +0 -111
- package/dist/facets/launch-pacer.d.ts.map +0 -1
- package/dist/facets/launch-pacer.js +0 -130
- package/dist/loaders/fanout-pool.d.ts +0 -207
- package/dist/loaders/fanout-pool.d.ts.map +0 -1
- package/dist/loaders/fanout-pool.js +0 -363
- package/dist/loaders/loader-pool.d.ts +0 -294
- package/dist/loaders/loader-pool.d.ts.map +0 -1
- package/dist/loaders/loader-pool.js +0 -642
- package/dist/loaders/process-fabric.d.ts +0 -509
- package/dist/loaders/process-fabric.d.ts.map +0 -1
- package/dist/loaders/process-fabric.js +0 -360
- package/dist/loaders/vendor/errors.d.ts +0 -24
- package/dist/loaders/vendor/errors.d.ts.map +0 -1
- package/dist/loaders/vendor/errors.js +0 -46
- package/dist/loaders/vendor/serialize.d.ts +0 -3
- package/dist/loaders/vendor/serialize.d.ts.map +0 -1
- package/dist/loaders/vendor/serialize.js +0 -25
- package/dist/loaders/vendor/types.d.ts +0 -69
- package/dist/loaders/vendor/types.d.ts.map +0 -1
- package/dist/loaders/vendor/types.js +0 -4
- package/dist/loaders/workerd-facet-host.d.ts +0 -141
- package/dist/loaders/workerd-facet-host.d.ts.map +0 -1
- package/dist/loaders/workerd-facet-host.js +0 -284
- package/dist/session/bindings.d.ts +0 -209
- package/dist/session/bindings.d.ts.map +0 -1
- package/dist/session/bindings.js +0 -680
- package/dist/session/ctx-exports.d.ts +0 -16
- package/dist/session/ctx-exports.d.ts.map +0 -1
- package/dist/session/ctx-exports.js +0 -22
- package/dist/session/ws-hibernation-config.d.ts +0 -64
- package/dist/session/ws-hibernation-config.d.ts.map +0 -1
- package/dist/session/ws-hibernation-config.js +0 -89
|
@@ -18,11 +18,15 @@
|
|
|
18
18
|
* w9_proc_logs + w9_proc_exits.
|
|
19
19
|
* - scheduleHibFlush(host, ctx) — debounced setTimeout + best-effort
|
|
20
20
|
* setAlarm for post-hibernation drain.
|
|
21
|
-
* - dispatchAlarm(host) — alarm() handler body
|
|
22
|
-
*
|
|
23
|
-
* counter once per fresh isolate.
|
|
21
|
+
* - dispatchAlarm(host) — alarm() handler body: the fabric's generic
|
|
22
|
+
* reason dispatcher with this session's handlers registered.
|
|
24
23
|
* - flushOnClose(host) — synchronous flush on ws close.
|
|
25
24
|
*
|
|
25
|
+
* The timer multiplexer itself (reason map, schedule, the per-instance
|
|
26
|
+
* chain) is fabric machinery — `@nimbus-sh/fabric/timers.js`; this module
|
|
27
|
+
* registers the session's reasons ('w9-flush' | 'log-janitor' |
|
|
28
|
+
* 'resident-launch') on top of it.
|
|
29
|
+
*
|
|
26
30
|
* **`ctx` taken as a separate arg from `host`** because the parent
|
|
27
31
|
* `CloudflareDurableObject` class declares `ctx` as `protected`, which
|
|
28
32
|
* is nominal-typed in TS and cannot appear on a public interface
|
|
@@ -35,7 +39,8 @@
|
|
|
35
39
|
* wireProcessLogPersist again.
|
|
36
40
|
*/
|
|
37
41
|
import type { SessionProcessSupervisor } from '@nimbus-sh/core/runtime/session-process-supervisor.js';
|
|
38
|
-
import { type WsHibernationConfigResult } from '
|
|
42
|
+
import { type WsHibernationConfigResult } from '@nimbus-sh/fabric/ws-hibernation-config.js';
|
|
43
|
+
import { type TimerHost } from '@nimbus-sh/fabric/timers.js';
|
|
39
44
|
export type { WsHibernationConfigResult };
|
|
40
45
|
/**
|
|
41
46
|
* Minimal host shape. `_w9*` fields drop `private` on the class so
|
|
@@ -44,10 +49,8 @@ export type { WsHibernationConfigResult };
|
|
|
44
49
|
*
|
|
45
50
|
* `ctx` is NOT in this interface — passed as a separate arg.
|
|
46
51
|
*/
|
|
47
|
-
export interface HibHost {
|
|
52
|
+
export interface HibHost extends TimerHost {
|
|
48
53
|
processes: SessionProcessSupervisor;
|
|
49
|
-
_w9IsolateGen: number;
|
|
50
|
-
_w9IsolateGenPersisted: boolean;
|
|
51
54
|
_w9SchemaInit: boolean;
|
|
52
55
|
_w9PersistWired: boolean;
|
|
53
56
|
_w9FlushTimer: any;
|
|
@@ -55,8 +58,6 @@ export interface HibHost {
|
|
|
55
58
|
_w1JanitorArmed: boolean;
|
|
56
59
|
/** W1: destroyed-session tombstone — never re-arm alarms while set. */
|
|
57
60
|
_w1SessionDestroyed: boolean;
|
|
58
|
-
/** W1: serializes every alarm-map read-modify-write (see scheduleAlarm). */
|
|
59
|
-
_w1AlarmChain?: Promise<unknown>;
|
|
60
61
|
}
|
|
61
62
|
/**
|
|
62
63
|
* Run at DO ctor time. Returns the result for the class to assign to
|
|
@@ -104,66 +105,32 @@ export declare function ensureLogJanitor(host: HibHost, ctx: any): void;
|
|
|
104
105
|
/** W9: idempotent SQL schema bootstrap. */
|
|
105
106
|
export declare function ensureHibSchema(host: HibHost, ctx: any): void;
|
|
106
107
|
/**
|
|
107
|
-
* W1: canonical alarm-reason strings
|
|
108
|
-
*
|
|
109
|
-
*
|
|
110
|
-
*
|
|
108
|
+
* W1: this session's canonical alarm-reason strings, registered on the
|
|
109
|
+
* fabric's reason map. Forward-compat: the dispatcher silently drops unknown
|
|
110
|
+
* reasons so a rollback from a future deploy that added new reasons doesn't
|
|
111
|
+
* leave the alarm stuck.
|
|
111
112
|
*/
|
|
112
113
|
export type AlarmReason = 'w9-flush' | 'log-janitor' | 'resident-launch';
|
|
113
|
-
/**
|
|
114
|
-
* W1: schedule (or re-schedule) an alarm reason. Coordinated via a
|
|
115
|
-
* single map in DO storage so multiple subsystems (W9 debounced flush +
|
|
116
|
-
* W1 log-janitor sweep) don't clobber each other's `setAlarm()` calls.
|
|
117
|
-
*
|
|
118
|
-
* Semantics:
|
|
119
|
-
* - Reads the existing reasons map.
|
|
120
|
-
* - Sets `map[reason] = whenMs` IF `whenMs` is sooner than the
|
|
121
|
-
* currently-pending deadline for that reason (or no entry exists).
|
|
122
|
-
* Later-than-pending requests are silently ignored — the existing
|
|
123
|
-
* alarm will fire and re-arm anyway.
|
|
124
|
-
* - Writes the map back and calls `ctx.storage.setAlarm(min(deadlines))`.
|
|
125
|
-
*
|
|
126
|
-
* Cost: 1 storage read + 1 storage write + 1 setAlarm per call. setAlarm
|
|
127
|
-
* itself is billed as 1 row written per DO pricing. At W1's 60s
|
|
128
|
-
* cadence, this is ~$0.05/mo/session at scale — dwarfed by the
|
|
129
|
-
* hibernation duration savings.
|
|
130
|
-
*
|
|
131
|
-
* Fail-soft: any throw is swallowed with a warn. On older runtimes /
|
|
132
|
-
* wrangler-dev where setAlarm is unavailable, this is a no-op (the
|
|
133
|
-
* subsystem's in-isolate setTimeout fallback continues to work).
|
|
134
|
-
*/
|
|
135
|
-
export declare function scheduleAlarm(host: HibHost, ctx: any, reason: AlarmReason, whenMs: number): Promise<boolean>;
|
|
136
114
|
/**
|
|
137
115
|
* W9: ensure the alarm is set for the next flush window. Cheap to
|
|
138
116
|
* call repeatedly — we only schedule the in-isolate flush timer if
|
|
139
|
-
* it isn't already set. The persistent alarm goes through
|
|
117
|
+
* it isn't already set. The persistent alarm goes through timers.schedule
|
|
140
118
|
* so it coordinates with W1's log-janitor sweep.
|
|
141
119
|
*/
|
|
142
120
|
export declare function scheduleHibFlush(host: HibHost, ctx: any): void;
|
|
143
121
|
/**
|
|
144
|
-
* W1:
|
|
145
|
-
*
|
|
146
|
-
*
|
|
147
|
-
* For each pending reason whose deadline has passed, run its handler.
|
|
148
|
-
* Reasons supported today:
|
|
122
|
+
* W1: this session's alarm() handler body — the fabric's multi-reason
|
|
123
|
+
* dispatcher with this session's handlers registered:
|
|
149
124
|
* - `'w9-flush'` → processes.flushLogs()
|
|
125
|
+
* - `'resident-launch'` → pumpResidentLaunches()
|
|
150
126
|
* - `'log-janitor'` → processes.dropLogsOlderThan(orphanCheck); re-arm
|
|
151
|
-
* for next 60s cycle.
|
|
127
|
+
* for next 60s cycle while the session still has anything to sweep.
|
|
152
128
|
*
|
|
153
129
|
* `janitorOrphanCheck` is the orphan-pid predicate provided by the
|
|
154
130
|
* caller (typically `(pid) => !host.processes.get(pid)`). Decoupled
|
|
155
131
|
* so HibHost doesn't need to import ProcessTable.
|
|
156
|
-
*
|
|
157
|
-
* After running fireable reasons, re-arms `ctx.storage.setAlarm` at the
|
|
158
|
-
* earliest remaining deadline. If no reasons remain, deletes the map
|
|
159
|
-
* key and does NOT call setAlarm — the DO becomes hibernation-eligible
|
|
160
|
-
* after the 10s idle window.
|
|
161
|
-
*
|
|
162
|
-
* Forward/back-compat: unknown reasons silently dropped.
|
|
163
132
|
*/
|
|
164
|
-
export declare function dispatchAlarm(host: HibHost, ctx: any, janitorOrphanCheck?: (pid: number) => boolean, pumpResidentLaunches?: () => Promise<void
|
|
165
|
-
/** W9: increment + persist isolate-gen counter once per fresh isolate. */
|
|
166
|
-
export declare function maybeBumpIsolateGen(host: HibHost, ctx: any): Promise<void>;
|
|
133
|
+
export declare function dispatchAlarm(host: HibHost, ctx: any, janitorOrphanCheck?: (pid: number) => boolean, pumpResidentLaunches?: () => Promise<void>, alarmInfo?: AlarmInvocationInfo): Promise<void>;
|
|
167
134
|
/**
|
|
168
135
|
* W9: synchronous flush of the process-log ring on session close.
|
|
169
136
|
* Wraps `processes.flushLogs()` in a try/catch so a flush failure
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hibernation.d.ts","sourceRoot":"","sources":["../../src/session/hibernation.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"hibernation.d.ts","sourceRoot":"","sources":["../../src/session/hibernation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAGH,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,uDAAuD,CAAC;AACtG,OAAO,EAA0B,KAAK,yBAAyB,EAAE,MAAM,4CAA4C,CAAC;AACpH,OAAO,EAAU,KAAK,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAGrE,YAAY,EAAE,yBAAyB,EAAE,CAAC;AAE1C;;;;;;GAMG;AACH,MAAM,WAAW,OAAQ,SAAQ,SAAS;IACxC,SAAS,EAAE,wBAAwB,CAAC;IACpC,aAAa,EAAE,OAAO,CAAC;IACvB,eAAe,EAAE,OAAO,CAAC;IACzB,aAAa,EAAE,GAAG,CAAC;IACnB,4EAA4E;IAC5E,eAAe,EAAE,OAAO,CAAC;IACzB,uEAAuE;IACvE,mBAAmB,EAAE,OAAO,CAAC;CAC9B;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,GAAG,EAAE,GAAG,GAAG,yBAAyB,CAY9E;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,GAAG,IAAI,CA6GnE;AAED;;;;;;;;;;GAUG;AACH;;;;;;;;GAQG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,GAAG,IAAI,CAMrE;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,GAAG,IAAI,CAc9D;AAED,2CAA2C;AAC3C,wBAAgB,eAAe,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,GAAG,IAAI,CAqB7D;AAED;;;;;GAKG;AACH,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG,aAAa,GAAG,iBAAiB,CAAC;AAEzE;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,GAAG,IAAI,CAqB9D;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,OAAO,EACb,GAAG,EAAE,GAAG,EACR,kBAAkB,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,EAC7C,oBAAoB,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,EAC1C,SAAS,CAAC,EAAE,mBAAmB,GAC9B,OAAO,CAAC,IAAI,CAAC,CAuCf;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAMhD"}
|
|
@@ -18,11 +18,15 @@
|
|
|
18
18
|
* w9_proc_logs + w9_proc_exits.
|
|
19
19
|
* - scheduleHibFlush(host, ctx) — debounced setTimeout + best-effort
|
|
20
20
|
* setAlarm for post-hibernation drain.
|
|
21
|
-
* - dispatchAlarm(host) — alarm() handler body
|
|
22
|
-
*
|
|
23
|
-
* counter once per fresh isolate.
|
|
21
|
+
* - dispatchAlarm(host) — alarm() handler body: the fabric's generic
|
|
22
|
+
* reason dispatcher with this session's handlers registered.
|
|
24
23
|
* - flushOnClose(host) — synchronous flush on ws close.
|
|
25
24
|
*
|
|
25
|
+
* The timer multiplexer itself (reason map, schedule, the per-instance
|
|
26
|
+
* chain) is fabric machinery — `@nimbus-sh/fabric/timers.js`; this module
|
|
27
|
+
* registers the session's reasons ('w9-flush' | 'log-janitor' |
|
|
28
|
+
* 'resident-launch') on top of it.
|
|
29
|
+
*
|
|
26
30
|
* **`ctx` taken as a separate arg from `host`** because the parent
|
|
27
31
|
* `CloudflareDurableObject` class declares `ctx` as `protected`, which
|
|
28
32
|
* is nominal-typed in TS and cannot appear on a public interface
|
|
@@ -34,8 +38,9 @@
|
|
|
34
38
|
* responsible for setting `host._w9PersistWired = false` BEFORE calling
|
|
35
39
|
* wireProcessLogPersist again.
|
|
36
40
|
*/
|
|
37
|
-
import { configureWsHibernation } from '
|
|
38
|
-
import {
|
|
41
|
+
import { configureWsHibernation } from '@nimbus-sh/fabric/ws-hibernation-config.js';
|
|
42
|
+
import { timers } from '@nimbus-sh/fabric/timers.js';
|
|
43
|
+
import { SESSION_DESTROYED_KEY, W9_FLUSH_DEBOUNCE_MS } from './keys.js';
|
|
39
44
|
/**
|
|
40
45
|
* Run at DO ctor time. Returns the result for the class to assign to
|
|
41
46
|
* `_w9WsConfig`. Failures are non-fatal — older workerd builds may lack
|
|
@@ -211,11 +216,11 @@ export function ensureLogJanitor(host, ctx) {
|
|
|
211
216
|
if (host._w1SessionDestroyed)
|
|
212
217
|
return;
|
|
213
218
|
// Optimistic flag (dedupes same-tick appends), CONFIRMED by the schedule
|
|
214
|
-
// outcome:
|
|
219
|
+
// outcome: timers.schedule swallows storage errors, and a failure with the
|
|
215
220
|
// flag left set would mean no alarm AND nothing ever re-arming until the
|
|
216
221
|
// instance recycles.
|
|
217
222
|
host._w1JanitorArmed = true;
|
|
218
|
-
void
|
|
223
|
+
void timers(host, ctx).schedule('log-janitor', Date.now() + 60_000).then((ok) => {
|
|
219
224
|
if (!ok)
|
|
220
225
|
host._w1JanitorArmed = false;
|
|
221
226
|
});
|
|
@@ -241,63 +246,10 @@ export function ensureHibSchema(host, ctx) {
|
|
|
241
246
|
host._w9SchemaInit = false; // retry next time
|
|
242
247
|
}
|
|
243
248
|
}
|
|
244
|
-
/**
|
|
245
|
-
* W1: schedule (or re-schedule) an alarm reason. Coordinated via a
|
|
246
|
-
* single map in DO storage so multiple subsystems (W9 debounced flush +
|
|
247
|
-
* W1 log-janitor sweep) don't clobber each other's `setAlarm()` calls.
|
|
248
|
-
*
|
|
249
|
-
* Semantics:
|
|
250
|
-
* - Reads the existing reasons map.
|
|
251
|
-
* - Sets `map[reason] = whenMs` IF `whenMs` is sooner than the
|
|
252
|
-
* currently-pending deadline for that reason (or no entry exists).
|
|
253
|
-
* Later-than-pending requests are silently ignored — the existing
|
|
254
|
-
* alarm will fire and re-arm anyway.
|
|
255
|
-
* - Writes the map back and calls `ctx.storage.setAlarm(min(deadlines))`.
|
|
256
|
-
*
|
|
257
|
-
* Cost: 1 storage read + 1 storage write + 1 setAlarm per call. setAlarm
|
|
258
|
-
* itself is billed as 1 row written per DO pricing. At W1's 60s
|
|
259
|
-
* cadence, this is ~$0.05/mo/session at scale — dwarfed by the
|
|
260
|
-
* hibernation duration savings.
|
|
261
|
-
*
|
|
262
|
-
* Fail-soft: any throw is swallowed with a warn. On older runtimes /
|
|
263
|
-
* wrangler-dev where setAlarm is unavailable, this is a no-op (the
|
|
264
|
-
* subsystem's in-isolate setTimeout fallback continues to work).
|
|
265
|
-
*/
|
|
266
|
-
export function scheduleAlarm(host, ctx, reason, whenMs) {
|
|
267
|
-
// Serialize every read-modify-write of the reasons map through one
|
|
268
|
-
// per-instance chain: scheduleHibFlush and ensureLogJanitor fire
|
|
269
|
-
// back-to-back from the same log-activity hook, and two interleaved
|
|
270
|
-
// get→put cycles would silently drop whichever reason wrote first.
|
|
271
|
-
const run = async () => {
|
|
272
|
-
try {
|
|
273
|
-
const setAlarmFn = ctx?.storage?.setAlarm;
|
|
274
|
-
if (typeof setAlarmFn !== 'function')
|
|
275
|
-
return false;
|
|
276
|
-
const existing = (await ctx.storage.get(W1_NEXT_ALARM_REASONS_KEY));
|
|
277
|
-
const map = { ...(existing || {}) };
|
|
278
|
-
// Earliest-deadline-first: only update if new request is sooner or
|
|
279
|
-
// this reason has no pending entry.
|
|
280
|
-
if (!(reason in map) || whenMs < map[reason]) {
|
|
281
|
-
map[reason] = whenMs;
|
|
282
|
-
await ctx.storage.put(W1_NEXT_ALARM_REASONS_KEY, map);
|
|
283
|
-
}
|
|
284
|
-
const earliest = Math.min(...Object.values(map));
|
|
285
|
-
setAlarmFn.call(ctx.storage, earliest);
|
|
286
|
-
return true;
|
|
287
|
-
}
|
|
288
|
-
catch (e) {
|
|
289
|
-
console.warn('[nimbus/W1] scheduleAlarm threw:', e?.message);
|
|
290
|
-
return false;
|
|
291
|
-
}
|
|
292
|
-
};
|
|
293
|
-
const chained = (host._w1AlarmChain ?? Promise.resolve()).then(run, run);
|
|
294
|
-
host._w1AlarmChain = chained;
|
|
295
|
-
return chained;
|
|
296
|
-
}
|
|
297
249
|
/**
|
|
298
250
|
* W9: ensure the alarm is set for the next flush window. Cheap to
|
|
299
251
|
* call repeatedly — we only schedule the in-isolate flush timer if
|
|
300
|
-
* it isn't already set. The persistent alarm goes through
|
|
252
|
+
* it isn't already set. The persistent alarm goes through timers.schedule
|
|
301
253
|
* so it coordinates with W1's log-janitor sweep.
|
|
302
254
|
*/
|
|
303
255
|
export function scheduleHibFlush(host, ctx) {
|
|
@@ -319,154 +271,65 @@ export function scheduleHibFlush(host, ctx) {
|
|
|
319
271
|
}, W9_FLUSH_DEBOUNCE_MS);
|
|
320
272
|
// Persistent alarm: fires post-hibernation if the in-isolate timer
|
|
321
273
|
// didn't get a chance to run (DO evicted under memory pressure
|
|
322
|
-
// before the 250ms debounce expired). Coordinated via
|
|
274
|
+
// before the 250ms debounce expired). Coordinated via timers.schedule
|
|
323
275
|
// so W1's log-janitor doesn't clobber it (or vice-versa).
|
|
324
|
-
// Fire-and-forget —
|
|
325
|
-
void
|
|
276
|
+
// Fire-and-forget — timers.schedule is fail-soft.
|
|
277
|
+
void timers(host, ctx).schedule('w9-flush', Date.now() + W9_FLUSH_DEBOUNCE_MS * 4);
|
|
326
278
|
}
|
|
327
279
|
/**
|
|
328
|
-
* W1:
|
|
329
|
-
*
|
|
330
|
-
*
|
|
331
|
-
* For each pending reason whose deadline has passed, run its handler.
|
|
332
|
-
* Reasons supported today:
|
|
280
|
+
* W1: this session's alarm() handler body — the fabric's multi-reason
|
|
281
|
+
* dispatcher with this session's handlers registered:
|
|
333
282
|
* - `'w9-flush'` → processes.flushLogs()
|
|
283
|
+
* - `'resident-launch'` → pumpResidentLaunches()
|
|
334
284
|
* - `'log-janitor'` → processes.dropLogsOlderThan(orphanCheck); re-arm
|
|
335
|
-
* for next 60s cycle.
|
|
285
|
+
* for next 60s cycle while the session still has anything to sweep.
|
|
336
286
|
*
|
|
337
287
|
* `janitorOrphanCheck` is the orphan-pid predicate provided by the
|
|
338
288
|
* caller (typically `(pid) => !host.processes.get(pid)`). Decoupled
|
|
339
289
|
* so HibHost doesn't need to import ProcessTable.
|
|
340
|
-
*
|
|
341
|
-
* After running fireable reasons, re-arms `ctx.storage.setAlarm` at the
|
|
342
|
-
* earliest remaining deadline. If no reasons remain, deletes the map
|
|
343
|
-
* key and does NOT call setAlarm — the DO becomes hibernation-eligible
|
|
344
|
-
* after the 10s idle window.
|
|
345
|
-
*
|
|
346
|
-
* Forward/back-compat: unknown reasons silently dropped.
|
|
347
290
|
*/
|
|
348
|
-
export function dispatchAlarm(host, ctx, janitorOrphanCheck, pumpResidentLaunches) {
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
291
|
+
export function dispatchAlarm(host, ctx, janitorOrphanCheck, pumpResidentLaunches, alarmInfo) {
|
|
292
|
+
return timers(host, ctx).dispatch({
|
|
293
|
+
'w9-flush': () => {
|
|
294
|
+
host.processes.flushLogs();
|
|
295
|
+
},
|
|
296
|
+
'resident-launch': async () => {
|
|
297
|
+
// Awaited, not fired and forgotten: this invocation is the fresh
|
|
298
|
+
// turn the launch asked for, and it has to stay the one paying for
|
|
299
|
+
// the chunk it just released.
|
|
300
|
+
await pumpResidentLaunches?.();
|
|
301
|
+
},
|
|
302
|
+
'log-janitor': (now) => {
|
|
303
|
+
host.processes.dropLogsOlderThan(undefined, janitorOrphanCheck);
|
|
304
|
+
// Re-arm only while the session still has running processes or
|
|
305
|
+
// buffered logs to sweep. An idle, abandoned, or destroyed
|
|
306
|
+
// session must NOT keep an eternal 60s alarm loop alive: the
|
|
307
|
+
// janitor used to self-renew unconditionally (and the DO
|
|
308
|
+
// constructor re-armed it on every alarm-triggered boot), so
|
|
309
|
+
// every session ever created kept booting its DO every ~60s
|
|
310
|
+
// forever. The accumulated fleet of deleted probe sessions
|
|
311
|
+
// produced continuous DO-storage churn (measured ~24 zombie
|
|
312
|
+
// boots/s on 2026-07-13) that intermittently reset LIVE
|
|
313
|
+
// session DOs mid-run ("Internal error in Durable Object
|
|
314
|
+
// storage caused object to be reset"). The next log append
|
|
315
|
+
// re-arms the cycle via ensureLogJanitor.
|
|
316
|
+
if (host.processes.stats.running > 0 || host.processes.logStats.totalPids > 0) {
|
|
317
|
+
return { rearmAt: now + 60_000 };
|
|
318
|
+
}
|
|
319
|
+
host._w1JanitorArmed = false;
|
|
320
|
+
},
|
|
321
|
+
}, () => {
|
|
359
322
|
// Legacy path: pre-W1 deploys had no map. dispatchAlarm was called
|
|
360
323
|
// with no map and unconditionally ran the log flush. Preserve
|
|
361
324
|
// that on a missing map (one-time post-deploy, then the map is
|
|
362
|
-
// populated by the next scheduleHibFlush /
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
host.processes.flushLogs();
|
|
366
|
-
}
|
|
367
|
-
catch (e) {
|
|
368
|
-
console.warn('[nimbus/W9] legacy flush threw:', e?.message);
|
|
369
|
-
}
|
|
370
|
-
return;
|
|
371
|
-
}
|
|
372
|
-
const map = { ...existing };
|
|
373
|
-
// Snapshot fireable reasons BEFORE running any of them, so a
|
|
374
|
-
// handler that schedules itself for the next cycle doesn't get
|
|
375
|
-
// immediately re-fired in the same dispatch.
|
|
376
|
-
const fired = [];
|
|
377
|
-
for (const [reason, when] of Object.entries(map)) {
|
|
378
|
-
if (when <= now)
|
|
379
|
-
fired.push(reason);
|
|
380
|
-
}
|
|
381
|
-
for (const reason of fired) {
|
|
382
|
-
delete map[reason];
|
|
383
|
-
try {
|
|
384
|
-
if (reason === 'w9-flush') {
|
|
385
|
-
host.processes.flushLogs();
|
|
386
|
-
}
|
|
387
|
-
else if (reason === 'resident-launch') {
|
|
388
|
-
// Awaited, not fired and forgotten: this invocation is the fresh
|
|
389
|
-
// turn the launch asked for, and it has to stay the one paying for
|
|
390
|
-
// the chunk it just released.
|
|
391
|
-
await pumpResidentLaunches?.();
|
|
392
|
-
}
|
|
393
|
-
else if (reason === 'log-janitor') {
|
|
394
|
-
host.processes.dropLogsOlderThan(undefined, janitorOrphanCheck);
|
|
395
|
-
// Re-arm only while the session still has running processes or
|
|
396
|
-
// buffered logs to sweep. An idle, abandoned, or destroyed
|
|
397
|
-
// session must NOT keep an eternal 60s alarm loop alive: the
|
|
398
|
-
// janitor used to self-renew unconditionally (and the DO
|
|
399
|
-
// constructor re-armed it on every alarm-triggered boot), so
|
|
400
|
-
// every session ever created kept booting its DO every ~60s
|
|
401
|
-
// forever. The accumulated fleet of deleted probe sessions
|
|
402
|
-
// produced continuous DO-storage churn (measured ~24 zombie
|
|
403
|
-
// boots/s on 2026-07-13) that intermittently reset LIVE
|
|
404
|
-
// session DOs mid-run ("Internal error in Durable Object
|
|
405
|
-
// storage caused object to be reset"). The next log append
|
|
406
|
-
// re-arms the cycle via ensureLogJanitor.
|
|
407
|
-
if (host.processes.stats.running > 0 || host.processes.logStats.totalPids > 0) {
|
|
408
|
-
map['log-janitor'] = now + 60_000;
|
|
409
|
-
}
|
|
410
|
-
else {
|
|
411
|
-
host._w1JanitorArmed = false;
|
|
412
|
-
}
|
|
413
|
-
}
|
|
414
|
-
// Unknown reasons silently dropped (forward-compat).
|
|
415
|
-
}
|
|
416
|
-
catch (e) {
|
|
417
|
-
console.warn(`[nimbus/W1] dispatch ${reason} threw:`, e?.message);
|
|
418
|
-
}
|
|
419
|
-
}
|
|
420
|
-
// Re-arm or clear.
|
|
421
|
-
const setAlarmFn = ctx?.storage?.setAlarm;
|
|
422
|
-
if (Object.keys(map).length > 0) {
|
|
423
|
-
await ctx.storage.put(W1_NEXT_ALARM_REASONS_KEY, map);
|
|
424
|
-
const earliest = Math.min(...Object.values(map));
|
|
425
|
-
if (typeof setAlarmFn === 'function') {
|
|
426
|
-
setAlarmFn.call(ctx.storage, earliest);
|
|
427
|
-
}
|
|
325
|
+
// populated by the next scheduleHibFlush / timers.schedule call).
|
|
326
|
+
try {
|
|
327
|
+
host.processes.flushLogs();
|
|
428
328
|
}
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
await ctx.storage.delete(W1_NEXT_ALARM_REASONS_KEY);
|
|
432
|
-
}
|
|
433
|
-
catch { }
|
|
434
|
-
// No remaining reasons → no setAlarm call → DO becomes
|
|
435
|
-
// hibernation-eligible after the 10s idle window.
|
|
329
|
+
catch (e) {
|
|
330
|
+
console.warn('[nimbus/W9] legacy flush threw:', e?.message);
|
|
436
331
|
}
|
|
437
|
-
}
|
|
438
|
-
catch (e) {
|
|
439
|
-
console.warn('[nimbus/W1] dispatchAlarm threw:', e?.message);
|
|
440
|
-
}
|
|
441
|
-
}
|
|
442
|
-
/** W9: increment + persist isolate-gen counter once per fresh isolate. */
|
|
443
|
-
export async function maybeBumpIsolateGen(host, ctx) {
|
|
444
|
-
if (host._w9IsolateGenPersisted)
|
|
445
|
-
return;
|
|
446
|
-
host._w9IsolateGenPersisted = true;
|
|
447
|
-
try {
|
|
448
|
-
const prev = (await ctx.storage.get(W9_ISOLATE_GEN_KEY));
|
|
449
|
-
// Adopt the persisted truth first, and adopt the bump only after the
|
|
450
|
-
// put resolves. An unpersisted `next` would be re-read as `prev` by the
|
|
451
|
-
// NEXT boot and re-issued — two instances sharing one generation is
|
|
452
|
-
// exactly the pid-aliasing this counter exists to prevent. Running on
|
|
453
|
-
// the previous persisted generation is the lesser lapse, and the
|
|
454
|
-
// put-failure case is replica-only in practice (replicas never spawn).
|
|
455
|
-
//
|
|
456
|
-
// What holds the guarantee is the output gate, not this await: measured,
|
|
457
|
-
// the block body resolves in 0 ms even with a confirmed put, because
|
|
458
|
-
// `await storage.put()` returns before durability. The gate is what
|
|
459
|
-
// keeps a pid from generation N from escaping before N is durable, which
|
|
460
|
-
// is why marking this put `allowUnconfirmed` is not a free speedup — see
|
|
461
|
-
// scratchpad/coldstart-s1.md.
|
|
462
|
-
host._w9IsolateGen = typeof prev === 'number' ? prev : 0;
|
|
463
|
-
const next = host._w9IsolateGen + 1;
|
|
464
|
-
await ctx.storage.put(W9_ISOLATE_GEN_KEY, next);
|
|
465
|
-
host._w9IsolateGen = next;
|
|
466
|
-
}
|
|
467
|
-
catch (e) {
|
|
468
|
-
console.warn('[nimbus/W9] isolate-gen bump failed:', e?.message);
|
|
469
|
-
}
|
|
332
|
+
}, alarmInfo);
|
|
470
333
|
}
|
|
471
334
|
/**
|
|
472
335
|
* W9: synchronous flush of the process-log ring on session close.
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
* preserved — old probes still see it. New phase entries are
|
|
33
33
|
* additional ring entries, not replacements.
|
|
34
34
|
*/
|
|
35
|
-
import { type SessionState } from '@nimbus-sh/
|
|
35
|
+
import { type SessionState } from '@nimbus-sh/platform/oom-discriminator.js';
|
|
36
36
|
/**
|
|
37
37
|
* Set the current phase + record a transition. Fail-soft on the
|
|
38
38
|
* observability call; the phase update on `self` is direct and
|
|
@@ -40,7 +40,7 @@ import { type SessionState } from '@nimbus-sh/core/observability/oom-discriminat
|
|
|
40
40
|
*/
|
|
41
41
|
export declare function setPhase(self: {
|
|
42
42
|
_b4Phase: SessionState | null;
|
|
43
|
-
|
|
43
|
+
ctx?: unknown;
|
|
44
44
|
}, toState: SessionState, trigger: string): void;
|
|
45
45
|
/**
|
|
46
46
|
* [B'.5] Identify the original phase-based warm-rejoin case. The /ws
|
|
@@ -93,7 +93,6 @@ export declare function joinExistingSession(self: {
|
|
|
93
93
|
write(s: string): void;
|
|
94
94
|
};
|
|
95
95
|
_b4Phase: SessionState | null;
|
|
96
|
-
_w9IsolateGen?: number;
|
|
97
96
|
_b4WarmJoinCount: number;
|
|
98
97
|
}, ws: WebSocket, appendScrollback: (ctx: any, data: string, atMs: number) => void, loadScrollback: (ctx: any) => string): void;
|
|
99
98
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init-phases.d.ts","sourceRoot":"","sources":["../../src/session/init-phases.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,OAAO,EAAuB,KAAK,YAAY,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"init-phases.d.ts","sourceRoot":"","sources":["../../src/session/init-phases.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,OAAO,EAAuB,KAAK,YAAY,EAAE,MAAM,0CAA0C,CAAC;AAGlG;;;;GAIG;AACH,wBAAgB,QAAQ,CACtB,IAAI,EAAE;IAAE,QAAQ,EAAE,YAAY,GAAG,IAAI,CAAC;IAAC,GAAG,CAAC,EAAE,OAAO,CAAA;CAAE,EACtD,OAAO,EAAE,YAAY,EACrB,OAAO,EAAE,MAAM,GACd,IAAI,CAcN;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE;IACjC,QAAQ,EAAE,YAAY,GAAG,IAAI,CAAC;IAC9B,KAAK,EAAE,GAAG,CAAC;IAAC,QAAQ,EAAE,GAAG,CAAC;IAAC,MAAM,EAAE,GAAG,CAAC;CACxC,GAAG,OAAO,CAKV;AAED,KAAK,iBAAiB,GAAG,WAAW,GAAG,UAAU,GAAG,MAAM,CAAC;AAE3D;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE;IACtC,QAAQ,EAAE,YAAY,GAAG,IAAI,CAAC;IAC9B,KAAK,EAAE,OAAO,CAAC;IACf,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,OAAO,CAAC;CACjB,EAAE,OAAO,EAAE,SAAS,SAAS,EAAE,GAAG,iBAAiB,CAmBnD;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE;IACJ,GAAG,EAAE,GAAG,CAAC;IACT,QAAQ,EAAE;QAAE,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAAC;QAAC,KAAK,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC;IACpG,QAAQ,EAAE,YAAY,GAAG,IAAI,CAAC;IAC9B,gBAAgB,EAAE,MAAM,CAAC;CAC1B,EACD,EAAE,EAAE,SAAS,EACb,gBAAgB,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,EAChE,cAAc,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,MAAM,GACnC,IAAI,CAsCN"}
|
|
@@ -32,7 +32,8 @@
|
|
|
32
32
|
* preserved — old probes still see it. New phase entries are
|
|
33
33
|
* additional ring entries, not replacements.
|
|
34
34
|
*/
|
|
35
|
-
import { recordRecoveryEvent } from '@nimbus-sh/
|
|
35
|
+
import { recordRecoveryEvent } from '@nimbus-sh/platform/oom-discriminator.js';
|
|
36
|
+
import { generation } from '@nimbus-sh/fabric/generation.js';
|
|
36
37
|
/**
|
|
37
38
|
* Set the current phase + record a transition. Fail-soft on the
|
|
38
39
|
* observability call; the phase update on `self` is direct and
|
|
@@ -47,7 +48,7 @@ export function setPhase(self, toState, trigger) {
|
|
|
47
48
|
fromState,
|
|
48
49
|
toState,
|
|
49
50
|
trigger,
|
|
50
|
-
isolateGen: self.
|
|
51
|
+
isolateGen: generation(self.ctx),
|
|
51
52
|
dataLoss: false,
|
|
52
53
|
snapshotKeysRehydrated: 0,
|
|
53
54
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/session/init.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/session/init.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AA+EH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAErD;;;;;;;;GAQG;AACH,KAAK,QAAQ,GAAG,eAAe,GAAG;IAAE,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC;IAAC,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAA;CAAE,CAAC;AAa3E,wBAAsB,WAAW,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAosF9E"}
|
package/dist/session/init.js
CHANGED
|
@@ -68,14 +68,16 @@ import { listInstalledRuntimes, rehydrateInstalledRuntimes, registerRunnerFactor
|
|
|
68
68
|
// one-time Worker Startup Time paid on every fresh-isolate cold run.
|
|
69
69
|
import { hasSeededProject, SEED_PROJECT_DIR } from '@nimbus-sh/core/vfs/seed-project.js';
|
|
70
70
|
import { notifyTerminalEvent } from '../runtime/process-logs-api.js';
|
|
71
|
+
import { generation } from '@nimbus-sh/fabric/generation.js';
|
|
71
72
|
import { stripAnsi } from '@nimbus-sh/core/runtime/process-logs.js';
|
|
72
73
|
import { DEFAULT_MOUNT_POINTS, NODE_VERSION, } from '@nimbus-sh/core/constants.js';
|
|
73
74
|
import { ensureSessionStateSchema, loadShellState, stampHydratedAt, countSessionStateKeys, loadKernelMounts, persistKernelMounts, appendScrollback, loadScrollback, } from './state-store.js';
|
|
74
|
-
import { recordRecoveryEvent } from '@nimbus-sh/
|
|
75
|
+
import { recordRecoveryEvent } from '@nimbus-sh/platform/oom-discriminator.js';
|
|
75
76
|
import { sessionAiEnv } from './ai.js';
|
|
76
77
|
import { routeSessionLoopback } from './loopback.js';
|
|
77
78
|
import { setPhase } from './init-phases.js';
|
|
78
79
|
import { VITE_CONFIG_KEY } from './keys.js';
|
|
80
|
+
import { clearPortCapability } from './port-capability.js';
|
|
79
81
|
function resolveNpmPrefix(prefix, cwd) {
|
|
80
82
|
return prefix.startsWith('/')
|
|
81
83
|
? normalizeVfsPath(prefix)
|
|
@@ -165,7 +167,7 @@ export async function initSession(self, ws) {
|
|
|
165
167
|
+ 'running was lost with the old one — re-run it if it had not finished.\x1b[0m\r\n');
|
|
166
168
|
}
|
|
167
169
|
// A reset that killed a resident launch left its journal row behind
|
|
168
|
-
// (
|
|
170
|
+
// (fabric's FencedWork.recoverInterrupted). The alarm the dying
|
|
169
171
|
// instance was using for launch turns is NOT a trigger recovery can rely
|
|
170
172
|
// on — measured live, a launch killed early in its first chunks rolls the
|
|
171
173
|
// alarm-map put back with the rest of the dying turn, so the replacement
|
|
@@ -480,7 +482,7 @@ export async function initSession(self, ws) {
|
|
|
480
482
|
registerRunnerFactory('cpython-runner', (manifest, installRoot, binName, binKind) => async function pythonReplOrOneShot(ctx) {
|
|
481
483
|
const argv = ctx.args || [];
|
|
482
484
|
// No args at all → REPL session. Hand off to runPythonRepl
|
|
483
|
-
// which builds its own
|
|
485
|
+
// which builds its own IsolatePool (separate from the
|
|
484
486
|
// one-shot dispatch's pool) and drives a ReplSession.
|
|
485
487
|
if (argv.length === 0 && self.terminal) {
|
|
486
488
|
const { runPythonRepl } = await import('../runtime/python-repl.js');
|
|
@@ -1243,6 +1245,7 @@ export async function initSession(self, ws) {
|
|
|
1243
1245
|
try {
|
|
1244
1246
|
const previewStub = makeLongRunningPortStub(self.viteDevServer);
|
|
1245
1247
|
self.portRegistry.bindFacetStub(previewProcEntry.pid, previewStub);
|
|
1248
|
+
await clearPortCapability(self, previewPort);
|
|
1246
1249
|
self.portRegistry.register(previewPort, previewProcEntry.pid);
|
|
1247
1250
|
self._viteShimPid = previewProcEntry.pid;
|
|
1248
1251
|
self._viteShimPort = previewPort;
|
|
@@ -1457,6 +1460,7 @@ export async function initSession(self, ws) {
|
|
|
1457
1460
|
// facet uses (Express, Bun.serve, http.createServer().listen()).
|
|
1458
1461
|
const viteStub = makeLongRunningPortStub(self.viteDevServer);
|
|
1459
1462
|
self.portRegistry.bindFacetStub(viteProcEntry.pid, viteStub);
|
|
1463
|
+
await clearPortCapability(self, resolvedPort);
|
|
1460
1464
|
self.portRegistry.register(resolvedPort, viteProcEntry.pid);
|
|
1461
1465
|
// Track the wiring so `vite stop` and crash-handlers can tear it
|
|
1462
1466
|
// down without searching the registry.
|
|
@@ -2702,7 +2706,7 @@ export async function initSession(self, ws) {
|
|
|
2702
2706
|
fromState: fromState,
|
|
2703
2707
|
toState: 'hydrated',
|
|
2704
2708
|
trigger: 'init-session',
|
|
2705
|
-
isolateGen: self.
|
|
2709
|
+
isolateGen: generation(self.ctx),
|
|
2706
2710
|
dataLoss: false,
|
|
2707
2711
|
snapshotKeysRehydrated: snapshotKeys,
|
|
2708
2712
|
});
|
package/dist/session/keys.d.ts
CHANGED
|
@@ -17,9 +17,6 @@
|
|
|
17
17
|
* These keys persist DO state across deploys. Renaming any key is a
|
|
18
18
|
* storage migration — never do it without an explicit migration plan.
|
|
19
19
|
*/
|
|
20
|
-
/** W9: storage key for the isolate-generation counter (cold-start +
|
|
21
|
-
* post-hibernation wake; one increment per fresh isolate). */
|
|
22
|
-
export declare const W9_ISOLATE_GEN_KEY = "w9_isolate_gen";
|
|
23
20
|
/** W9: debounce window in ms before flushing pending process-log writes
|
|
24
21
|
* to SQL. Hot path (every append schedules a flush via this debounce). */
|
|
25
22
|
export declare const W9_FLUSH_DEBOUNCE_MS = 250;
|
|
@@ -34,25 +31,6 @@ export declare const SESSION_BASE_PATH_KEY = "session-base-path";
|
|
|
34
31
|
* hibernation so vite resumes serving after wake without re-running
|
|
35
32
|
* /api/start-vite. */
|
|
36
33
|
export declare const VITE_CONFIG_KEY = "vite-config";
|
|
37
|
-
/** W1: multi-reason alarm coordination map.
|
|
38
|
-
*
|
|
39
|
-
* JSON-serialised `Record<reason, deadlineMsEpoch>` where keys are
|
|
40
|
-
* canonical reason strings (e.g. 'w9-flush', 'log-janitor'). The
|
|
41
|
-
* alarm() dispatcher reads this on fire, dispatches every reason
|
|
42
|
-
* whose deadline has passed, and re-arms `ctx.storage.setAlarm` at
|
|
43
|
-
* the earliest remaining deadline.
|
|
44
|
-
*
|
|
45
|
-
* Why a map (not a single nextAlarmAt + reason): two subsystems
|
|
46
|
-
* (W9 debounced flush + W1 log-janitor sweep) can have distinct
|
|
47
|
-
* deadlines. Without the map, the later setAlarm() call would
|
|
48
|
-
* overwrite the earlier reason silently, breaking whichever
|
|
49
|
-
* subsystem expected its deadline.
|
|
50
|
-
*
|
|
51
|
-
* Forward-compat: dispatcher silently drops unknown reasons so a
|
|
52
|
-
* rollback from a future deploy that added new reasons doesn't
|
|
53
|
-
* leave the alarm stuck.
|
|
54
|
-
*/
|
|
55
|
-
export declare const W1_NEXT_ALARM_REASONS_KEY = "w1_next_alarm_reasons";
|
|
56
34
|
/**
|
|
57
35
|
* Destroyed-session tombstone. Written AFTER `storage.deleteAll()` in the
|
|
58
36
|
* destroy flow so a straggler facet RPC that wakes the dead DO cannot re-arm
|
|
@@ -60,24 +38,23 @@ export declare const W1_NEXT_ALARM_REASONS_KEY = "w1_next_alarm_reasons";
|
|
|
60
38
|
* metadata is the deliberate cost of keeping destroyed sessions inert.
|
|
61
39
|
*/
|
|
62
40
|
export declare const SESSION_DESTROYED_KEY = "session_destroyed";
|
|
63
|
-
/**
|
|
64
|
-
* Prefix for the resident-process journal: one row per resident this session
|
|
65
|
-
* owes the user, keyed by the pid it was built for.
|
|
66
|
-
*
|
|
67
|
-
* A resident holds its state in memory — the process table entry, the facet
|
|
68
|
-
* handle, the terminal — so an instance reset destroys it silently. The row
|
|
69
|
-
* is what a LATER instance reads to know a resident ended that way rather
|
|
70
|
-
* than on purpose: a pid at or below the reader's own pid base was allocated
|
|
71
|
-
* by a previous generation (see PID_GEN_STRIDE). Written (and synced) before
|
|
72
|
-
* the launch's first byte of work, rewritten as `running` when the launch
|
|
73
|
-
* settles, and released only when the PROCESS ends — because the resets this
|
|
74
|
-
* row survives strike after the launch as often as during it (measured live,
|
|
75
|
-
* staging 2026-08-13: every observed reset landed seconds AFTER settle).
|
|
76
|
-
*/
|
|
77
|
-
export declare const RESIDENT_LAUNCH_KEY_PREFIX = "resident-launch:";
|
|
78
41
|
/** Prefix for consumed single-use attach bootstrap token ids (`jti`).
|
|
79
42
|
* Written set-if-absent by `_rpcConsumeAttachBootstrap` on the attach
|
|
80
43
|
* exchange; an existing row means the bootstrap URL was replayed.
|
|
81
44
|
* Bounded: at most one row per `POST /new` bootstrap actually attached. */
|
|
82
45
|
export declare const ATTACH_BOOTSTRAP_JTI_KEY_PREFIX = "attach-bootstrap-jti:";
|
|
46
|
+
/**
|
|
47
|
+
* Prefix for a port's durable preview capability, keyed by port number. The
|
|
48
|
+
* registry mints the value in memory per registration; this is what lets a
|
|
49
|
+
* preview URL the embedder was already handed survive a rebuild. Owned by
|
|
50
|
+
* `session/port-capability.ts`, which is the only module that reads or writes
|
|
51
|
+
* these rows.
|
|
52
|
+
*/
|
|
53
|
+
export declare const PORT_CAPABILITY_KEY_PREFIX = "nimbus_preview_capability:";
|
|
54
|
+
/**
|
|
55
|
+
* Prefix for a named programmatic shell's durable cwd+env, keyed by shell id.
|
|
56
|
+
* One row per id the embedder has actually used; bounded by the embedder's own
|
|
57
|
+
* naming, the way a terminal tab is.
|
|
58
|
+
*/
|
|
59
|
+
export declare const SHELL_STATE_KEY_PREFIX = "nimbus_programmatic_shell:";
|
|
83
60
|
//# sourceMappingURL=keys.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"keys.d.ts","sourceRoot":"","sources":["../../src/session/keys.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;
|
|
1
|
+
{"version":3,"file":"keys.d.ts","sourceRoot":"","sources":["../../src/session/keys.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAOH;2EAC2E;AAC3E,eAAO,MAAM,oBAAoB,MAAM,CAAC;AAExC;;yDAEyD;AACzD,eAAO,MAAM,mBAAmB,mBAAmB,CAAC;AAEpD;0DAC0D;AAC1D,eAAO,MAAM,qBAAqB,sBAAsB,CAAC;AAEzD;;uBAEuB;AACvB,eAAO,MAAM,eAAe,gBAAgB,CAAC;AAE7C;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,sBAAsB,CAAC;AAEzD;;;4EAG4E;AAC5E,eAAO,MAAM,+BAA+B,0BAA0B,CAAC;AAEvE;;;;;;GAMG;AACH,eAAO,MAAM,0BAA0B,+BAA+B,CAAC;AAEvE;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,+BAA+B,CAAC"}
|