@nimbus-sh/worker 0.1.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/README.md +219 -0
- package/dist/_shared/bytes.d.ts +18 -0
- package/dist/_shared/bytes.d.ts.map +1 -0
- package/dist/_shared/bytes.js +17 -0
- package/dist/_shared/cache-stats.d.ts +146 -0
- package/dist/_shared/cache-stats.d.ts.map +1 -0
- package/dist/_shared/cache-stats.js +162 -0
- package/dist/_shared/exports-resolver.d.ts +76 -0
- package/dist/_shared/exports-resolver.d.ts.map +1 -0
- package/dist/_shared/exports-resolver.js +284 -0
- package/dist/_shared/install-phase.d.ts +47 -0
- package/dist/_shared/install-phase.d.ts.map +1 -0
- package/dist/_shared/install-phase.js +1 -0
- package/dist/_shared/real-node-imports.d.ts +38 -0
- package/dist/_shared/real-node-imports.d.ts.map +1 -0
- package/dist/_shared/real-node-imports.js +46 -0
- package/dist/_shared/retry.d.ts +93 -0
- package/dist/_shared/retry.d.ts.map +1 -0
- package/dist/_shared/retry.js +161 -0
- package/dist/_shared/session-id.d.ts +39 -0
- package/dist/_shared/session-id.d.ts.map +1 -0
- package/dist/_shared/session-id.js +127 -0
- package/dist/_shared/session-router.d.ts +104 -0
- package/dist/_shared/session-router.d.ts.map +1 -0
- package/dist/_shared/session-router.js +165 -0
- package/dist/_shared/w7-frame.d.ts +93 -0
- package/dist/_shared/w7-frame.d.ts.map +1 -0
- package/dist/_shared/w7-frame.js +402 -0
- package/dist/auth/index.d.ts +16 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +15 -0
- package/dist/auth/middleware.d.ts +85 -0
- package/dist/auth/middleware.d.ts.map +1 -0
- package/dist/auth/middleware.js +150 -0
- package/dist/auth/token.d.ts +96 -0
- package/dist/auth/token.d.ts.map +1 -0
- package/dist/auth/token.js +226 -0
- package/dist/auth/types.d.ts +141 -0
- package/dist/auth/types.d.ts.map +1 -0
- package/dist/auth/types.js +114 -0
- package/dist/bindings/d1.d.ts +102 -0
- package/dist/bindings/d1.d.ts.map +1 -0
- package/dist/bindings/d1.js +549 -0
- package/dist/bindings/kv.d.ts +82 -0
- package/dist/bindings/kv.d.ts.map +1 -0
- package/dist/bindings/kv.js +290 -0
- package/dist/bindings/r2.d.ts +137 -0
- package/dist/bindings/r2.d.ts.map +1 -0
- package/dist/bindings/r2.js +379 -0
- package/dist/cirrus-npm-cjs.generated.d.ts +17 -0
- package/dist/cirrus-npm-cjs.generated.d.ts.map +1 -0
- package/dist/cirrus-npm-cjs.generated.js +41 -0
- package/dist/cirrus-plugin-react.generated.d.ts +34 -0
- package/dist/cirrus-plugin-react.generated.d.ts.map +1 -0
- package/dist/cirrus-plugin-react.generated.js +33 -0
- package/dist/constants.d.ts +34 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +116 -0
- package/dist/esbuild-wasm-bundle.generated.d.ts +41 -0
- package/dist/esbuild-wasm-bundle.generated.d.ts.map +1 -0
- package/dist/esbuild-wasm-bundle.generated.js +40 -0
- package/dist/facets/cirrus-real.d.ts +147 -0
- package/dist/facets/cirrus-real.d.ts.map +1 -0
- package/dist/facets/cirrus-real.js +981 -0
- package/dist/facets/inner-do-registry.d.ts +41 -0
- package/dist/facets/inner-do-registry.d.ts.map +1 -0
- package/dist/facets/inner-do-registry.js +51 -0
- package/dist/facets/manager.d.ts +314 -0
- package/dist/facets/manager.d.ts.map +1 -0
- package/dist/facets/manager.js +2681 -0
- package/dist/facets/process.d.ts +318 -0
- package/dist/facets/process.d.ts.map +1 -0
- package/dist/facets/process.js +567 -0
- package/dist/facets/real-vite-fs-shim.d.ts +151 -0
- package/dist/facets/real-vite-fs-shim.d.ts.map +1 -0
- package/dist/facets/real-vite-fs-shim.js +1279 -0
- package/dist/facets/real-vite-hmr.d.ts +142 -0
- package/dist/facets/real-vite-hmr.d.ts.map +1 -0
- package/dist/facets/real-vite-hmr.js +476 -0
- package/dist/facets/vite-dev-server.d.ts +293 -0
- package/dist/facets/vite-dev-server.d.ts.map +1 -0
- package/dist/facets/vite-dev-server.js +2580 -0
- package/dist/facets/wasm-swap-registry.d.ts +261 -0
- package/dist/facets/wasm-swap-registry.d.ts.map +1 -0
- package/dist/facets/wasm-swap-registry.js +551 -0
- package/dist/facets/ws-terminal.d.ts +107 -0
- package/dist/facets/ws-terminal.d.ts.map +1 -0
- package/dist/facets/ws-terminal.js +207 -0
- package/dist/git/commands.d.ts +13 -0
- package/dist/git/commands.d.ts.map +1 -0
- package/dist/git/commands.js +633 -0
- package/dist/git/network-facet.d.ts +61 -0
- package/dist/git/network-facet.d.ts.map +1 -0
- package/dist/git/network-facet.js +700 -0
- package/dist/git-bundle.generated.d.ts +16 -0
- package/dist/git-bundle.generated.d.ts.map +1 -0
- package/dist/git-bundle.generated.js +15 -0
- package/dist/index.d.ts +41 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +73 -0
- package/dist/loaders/child-process/spawn-facet.d.ts +90 -0
- package/dist/loaders/child-process/spawn-facet.d.ts.map +1 -0
- package/dist/loaders/child-process/spawn-facet.js +103 -0
- package/dist/loaders/child-process/spawn-pool.d.ts +110 -0
- package/dist/loaders/child-process/spawn-pool.d.ts.map +1 -0
- package/dist/loaders/child-process/spawn-pool.js +161 -0
- package/dist/loaders/fanout-pool.d.ts +195 -0
- package/dist/loaders/fanout-pool.d.ts.map +1 -0
- package/dist/loaders/fanout-pool.js +326 -0
- package/dist/loaders/generated-workers.d.ts +26 -0
- package/dist/loaders/generated-workers.d.ts.map +1 -0
- package/dist/loaders/generated-workers.js +25 -0
- package/dist/loaders/index.d.ts +15 -0
- package/dist/loaders/index.d.ts.map +1 -0
- package/dist/loaders/index.js +13 -0
- package/dist/loaders/loader-pool.d.ts +273 -0
- package/dist/loaders/loader-pool.d.ts.map +1 -0
- package/dist/loaders/loader-pool.js +624 -0
- package/dist/loaders/npm-resolve-preamble.d.ts +34 -0
- package/dist/loaders/npm-resolve-preamble.d.ts.map +1 -0
- package/dist/loaders/npm-resolve-preamble.js +237 -0
- package/dist/loaders/pre-bundle-preamble.d.ts +41 -0
- package/dist/loaders/pre-bundle-preamble.d.ts.map +1 -0
- package/dist/loaders/pre-bundle-preamble.js +114 -0
- package/dist/loaders/vendor/codegen.d.ts +24 -0
- package/dist/loaders/vendor/codegen.d.ts.map +1 -0
- package/dist/loaders/vendor/codegen.js +44 -0
- package/dist/loaders/vendor/errors.d.ts +24 -0
- package/dist/loaders/vendor/errors.d.ts.map +1 -0
- package/dist/loaders/vendor/errors.js +46 -0
- package/dist/loaders/vendor/index.d.ts +16 -0
- package/dist/loaders/vendor/index.d.ts.map +1 -0
- package/dist/loaders/vendor/index.js +11 -0
- package/dist/loaders/vendor/pool.d.ts +88 -0
- package/dist/loaders/vendor/pool.d.ts.map +1 -0
- package/dist/loaders/vendor/pool.js +353 -0
- package/dist/loaders/vendor/primitives.d.ts +11 -0
- package/dist/loaders/vendor/primitives.d.ts.map +1 -0
- package/dist/loaders/vendor/primitives.js +33 -0
- package/dist/loaders/vendor/serialize.d.ts +3 -0
- package/dist/loaders/vendor/serialize.d.ts.map +1 -0
- package/dist/loaders/vendor/serialize.js +25 -0
- package/dist/loaders/vendor/types.d.ts +60 -0
- package/dist/loaders/vendor/types.d.ts.map +1 -0
- package/dist/loaders/vendor/types.js +4 -0
- package/dist/npm/cache.d.ts +136 -0
- package/dist/npm/cache.d.ts.map +1 -0
- package/dist/npm/cache.js +429 -0
- package/dist/npm/install-batch-facet.d.ts +129 -0
- package/dist/npm/install-batch-facet.d.ts.map +1 -0
- package/dist/npm/install-batch-facet.js +598 -0
- package/dist/npm/install-facet.d.ts +29 -0
- package/dist/npm/install-facet.d.ts.map +1 -0
- package/dist/npm/install-facet.js +9 -0
- package/dist/npm/installer.d.ts +239 -0
- package/dist/npm/installer.d.ts.map +1 -0
- package/dist/npm/installer.js +2022 -0
- package/dist/npm/npx-install.d.ts +74 -0
- package/dist/npm/npx-install.d.ts.map +1 -0
- package/dist/npm/npx-install.js +302 -0
- package/dist/npm/pre-bundle-facet.d.ts +168 -0
- package/dist/npm/pre-bundle-facet.d.ts.map +1 -0
- package/dist/npm/pre-bundle-facet.js +653 -0
- package/dist/npm/r2-cache.d.ts +286 -0
- package/dist/npm/r2-cache.d.ts.map +1 -0
- package/dist/npm/r2-cache.js +506 -0
- package/dist/npm/resolve-facet.d.ts +202 -0
- package/dist/npm/resolve-facet.d.ts.map +1 -0
- package/dist/npm/resolve-facet.js +833 -0
- package/dist/npm/resolve-one-facet.d.ts +204 -0
- package/dist/npm/resolve-one-facet.d.ts.map +1 -0
- package/dist/npm/resolve-one-facet.js +437 -0
- package/dist/npm/resolver.d.ts +109 -0
- package/dist/npm/resolver.d.ts.map +1 -0
- package/dist/npm/resolver.js +899 -0
- package/dist/npm/tarball-stream.d.ts +85 -0
- package/dist/npm/tarball-stream.d.ts.map +1 -0
- package/dist/npm/tarball-stream.js +205 -0
- package/dist/npm/tarball.d.ts +51 -0
- package/dist/npm/tarball.d.ts.map +1 -0
- package/dist/npm/tarball.js +185 -0
- package/dist/observability/diag-counters.d.ts +292 -0
- package/dist/observability/diag-counters.d.ts.map +1 -0
- package/dist/observability/diag-counters.js +302 -0
- package/dist/observability/heap-estimate.d.ts +166 -0
- package/dist/observability/heap-estimate.d.ts.map +1 -0
- package/dist/observability/heap-estimate.js +192 -0
- package/dist/observability/heavy-alloc-coord.d.ts +95 -0
- package/dist/observability/heavy-alloc-coord.d.ts.map +1 -0
- package/dist/observability/heavy-alloc-coord.js +149 -0
- package/dist/observability/oom-classify.d.ts +56 -0
- package/dist/observability/oom-classify.d.ts.map +1 -0
- package/dist/observability/oom-classify.js +118 -0
- package/dist/observability/oom-discriminator.d.ts +192 -0
- package/dist/observability/oom-discriminator.d.ts.map +1 -0
- package/dist/observability/oom-discriminator.js +233 -0
- package/dist/real-vite-bundle.generated.d.ts +46 -0
- package/dist/real-vite-bundle.generated.d.ts.map +1 -0
- package/dist/real-vite-bundle.generated.js +53 -0
- package/dist/replica/routing.d.ts +171 -0
- package/dist/replica/routing.d.ts.map +1 -0
- package/dist/replica/routing.js +288 -0
- package/dist/replica/suspension.d.ts +36 -0
- package/dist/replica/suspension.d.ts.map +1 -0
- package/dist/replica/suspension.js +49 -0
- package/dist/router/index.d.ts +156 -0
- package/dist/router/index.d.ts.map +1 -0
- package/dist/router/index.js +220 -0
- package/dist/runtime/assets-loader.d.ts +71 -0
- package/dist/runtime/assets-loader.d.ts.map +1 -0
- package/dist/runtime/assets-loader.js +128 -0
- package/dist/runtime/barrel-detect.d.ts +46 -0
- package/dist/runtime/barrel-detect.d.ts.map +1 -0
- package/dist/runtime/barrel-detect.js +73 -0
- package/dist/runtime/barrel-synthesizer.d.ts +181 -0
- package/dist/runtime/barrel-synthesizer.d.ts.map +1 -0
- package/dist/runtime/barrel-synthesizer.js +541 -0
- package/dist/runtime/bun-repl.d.ts +46 -0
- package/dist/runtime/bun-repl.d.ts.map +1 -0
- package/dist/runtime/bun-repl.js +326 -0
- package/dist/runtime/bun-runner.d.ts +66 -0
- package/dist/runtime/bun-runner.d.ts.map +1 -0
- package/dist/runtime/bun-runner.js +219 -0
- package/dist/runtime/clang-runner.d.ts +38 -0
- package/dist/runtime/clang-runner.d.ts.map +1 -0
- package/dist/runtime/clang-runner.js +1033 -0
- package/dist/runtime/comment-strip.d.ts +37 -0
- package/dist/runtime/comment-strip.d.ts.map +1 -0
- package/dist/runtime/comment-strip.js +74 -0
- package/dist/runtime/esbuild-service.d.ts +201 -0
- package/dist/runtime/esbuild-service.d.ts.map +1 -0
- package/dist/runtime/esbuild-service.js +1444 -0
- package/dist/runtime/esbuild-wasm-bytes.d.ts +87 -0
- package/dist/runtime/esbuild-wasm-bytes.d.ts.map +1 -0
- package/dist/runtime/esbuild-wasm-bytes.js +131 -0
- package/dist/runtime/framework-detect.d.ts +71 -0
- package/dist/runtime/framework-detect.d.ts.map +1 -0
- package/dist/runtime/framework-detect.js +178 -0
- package/dist/runtime/long-running-handle.d.ts +133 -0
- package/dist/runtime/long-running-handle.d.ts.map +1 -0
- package/dist/runtime/long-running-handle.js +192 -0
- package/dist/runtime/node-repl.d.ts +36 -0
- package/dist/runtime/node-repl.d.ts.map +1 -0
- package/dist/runtime/node-repl.js +293 -0
- package/dist/runtime/node-runner.d.ts +111 -0
- package/dist/runtime/node-runner.d.ts.map +1 -0
- package/dist/runtime/node-runner.js +194 -0
- package/dist/runtime/node-shims.d.ts +24 -0
- package/dist/runtime/node-shims.d.ts.map +1 -0
- package/dist/runtime/node-shims.js +3019 -0
- package/dist/runtime/package-manager.d.ts +118 -0
- package/dist/runtime/package-manager.d.ts.map +1 -0
- package/dist/runtime/package-manager.js +420 -0
- package/dist/runtime/port-registry.d.ts +80 -0
- package/dist/runtime/port-registry.d.ts.map +1 -0
- package/dist/runtime/port-registry.js +166 -0
- package/dist/runtime/process-logs-api.d.ts +102 -0
- package/dist/runtime/process-logs-api.d.ts.map +1 -0
- package/dist/runtime/process-logs-api.js +253 -0
- package/dist/runtime/process-logs.d.ts +311 -0
- package/dist/runtime/process-logs.d.ts.map +1 -0
- package/dist/runtime/process-logs.js +656 -0
- package/dist/runtime/process-table.d.ts +65 -0
- package/dist/runtime/process-table.d.ts.map +1 -0
- package/dist/runtime/process-table.js +107 -0
- package/dist/runtime/project-detect.d.ts +21 -0
- package/dist/runtime/project-detect.d.ts.map +1 -0
- package/dist/runtime/project-detect.js +46 -0
- package/dist/runtime/python-repl.d.ts +66 -0
- package/dist/runtime/python-repl.d.ts.map +1 -0
- package/dist/runtime/python-repl.js +563 -0
- package/dist/runtime/python-runner.d.ts +50 -0
- package/dist/runtime/python-runner.d.ts.map +1 -0
- package/dist/runtime/python-runner.js +870 -0
- package/dist/runtime/repl-session.d.ts +160 -0
- package/dist/runtime/repl-session.d.ts.map +1 -0
- package/dist/runtime/repl-session.js +393 -0
- package/dist/runtime/require-resolver.d.ts +52 -0
- package/dist/runtime/require-resolver.d.ts.map +1 -0
- package/dist/runtime/require-resolver.js +690 -0
- package/dist/runtime/router-basename.d.ts +36 -0
- package/dist/runtime/router-basename.d.ts.map +1 -0
- package/dist/runtime/router-basename.js +310 -0
- package/dist/runtime/ruby-repl.d.ts +43 -0
- package/dist/runtime/ruby-repl.d.ts.map +1 -0
- package/dist/runtime/ruby-repl.js +229 -0
- package/dist/runtime/ruby-runner.d.ts +62 -0
- package/dist/runtime/ruby-runner.d.ts.map +1 -0
- package/dist/runtime/ruby-runner.js +737 -0
- package/dist/runtime/runtime-catalog.d.ts +99 -0
- package/dist/runtime/runtime-catalog.d.ts.map +1 -0
- package/dist/runtime/runtime-catalog.js +183 -0
- package/dist/runtime/runtime-registry.d.ts +136 -0
- package/dist/runtime/runtime-registry.d.ts.map +1 -0
- package/dist/runtime/runtime-registry.js +318 -0
- package/dist/runtime/streams.d.ts +13 -0
- package/dist/runtime/streams.d.ts.map +1 -0
- package/dist/runtime/streams.js +402 -0
- package/dist/runtime/wasi-instance.d.ts +190 -0
- package/dist/runtime/wasi-instance.d.ts.map +1 -0
- package/dist/runtime/wasi-instance.js +2044 -0
- package/dist/runtime/wasm-runner.d.ts +117 -0
- package/dist/runtime/wasm-runner.d.ts.map +1 -0
- package/dist/runtime/wasm-runner.js +705 -0
- package/dist/session/bindings.d.ts +168 -0
- package/dist/session/bindings.d.ts.map +1 -0
- package/dist/session/bindings.js +524 -0
- package/dist/session/ctx-exports.d.ts +16 -0
- package/dist/session/ctx-exports.d.ts.map +1 -0
- package/dist/session/ctx-exports.js +22 -0
- package/dist/session/diag.d.ts +62 -0
- package/dist/session/diag.d.ts.map +1 -0
- package/dist/session/diag.js +118 -0
- package/dist/session/fs-watch.d.ts +132 -0
- package/dist/session/fs-watch.d.ts.map +1 -0
- package/dist/session/fs-watch.js +255 -0
- package/dist/session/helpers.d.ts +150 -0
- package/dist/session/helpers.d.ts.map +1 -0
- package/dist/session/helpers.js +472 -0
- package/dist/session/hibernation.d.ts +145 -0
- package/dist/session/hibernation.d.ts.map +1 -0
- package/dist/session/hibernation.js +385 -0
- package/dist/session/init-phases.d.ts +87 -0
- package/dist/session/init-phases.d.ts.map +1 -0
- package/dist/session/init-phases.js +137 -0
- package/dist/session/init.d.ts +46 -0
- package/dist/session/init.d.ts.map +1 -0
- package/dist/session/init.js +3579 -0
- package/dist/session/keys.d.ts +56 -0
- package/dist/session/keys.d.ts.map +1 -0
- package/dist/session/keys.js +55 -0
- package/dist/session/nimbus-session.d.ts +434 -0
- package/dist/session/nimbus-session.d.ts.map +1 -0
- package/dist/session/nimbus-session.js +1084 -0
- package/dist/session/programmatic.d.ts +105 -0
- package/dist/session/programmatic.d.ts.map +1 -0
- package/dist/session/programmatic.js +326 -0
- package/dist/session/replica-routes.d.ts +68 -0
- package/dist/session/replica-routes.d.ts.map +1 -0
- package/dist/session/replica-routes.js +77 -0
- package/dist/session/routes.d.ts +29 -0
- package/dist/session/routes.d.ts.map +1 -0
- package/dist/session/routes.js +1331 -0
- package/dist/session/rpc.d.ts +323 -0
- package/dist/session/rpc.d.ts.map +1 -0
- package/dist/session/rpc.js +808 -0
- package/dist/session/state-store.d.ts +210 -0
- package/dist/session/state-store.d.ts.map +1 -0
- package/dist/session/state-store.js +459 -0
- package/dist/session/supervisor-rpc.d.ts +269 -0
- package/dist/session/supervisor-rpc.d.ts.map +1 -0
- package/dist/session/supervisor-rpc.js +437 -0
- package/dist/session/ws-hibernation-config.d.ts +64 -0
- package/dist/session/ws-hibernation-config.d.ts.map +1 -0
- package/dist/session/ws-hibernation-config.js +89 -0
- package/dist/session/ws.d.ts +95 -0
- package/dist/session/ws.d.ts.map +1 -0
- package/dist/session/ws.js +395 -0
- package/dist/shell/features.d.ts +410 -0
- package/dist/shell/features.d.ts.map +1 -0
- package/dist/shell/features.js +1885 -0
- package/dist/shell/unix-commands.d.ts +15 -0
- package/dist/shell/unix-commands.d.ts.map +1 -0
- package/dist/shell/unix-commands.js +3703 -0
- package/dist/stubs/lifo-ui.d.ts +10 -0
- package/dist/stubs/lifo-ui.d.ts.map +1 -0
- package/dist/stubs/lifo-ui.js +1 -0
- package/dist/tailwind-play.generated.d.ts +19 -0
- package/dist/tailwind-play.generated.d.ts.map +1 -0
- package/dist/tailwind-play.generated.js +18 -0
- package/dist/vfs/dev-provider.d.ts +64 -0
- package/dist/vfs/dev-provider.d.ts.map +1 -0
- package/dist/vfs/dev-provider.js +191 -0
- package/dist/vfs/events.d.ts +51 -0
- package/dist/vfs/events.d.ts.map +1 -0
- package/dist/vfs/events.js +127 -0
- package/dist/vfs/path.d.ts +30 -0
- package/dist/vfs/path.d.ts.map +1 -0
- package/dist/vfs/path.js +41 -0
- package/dist/vfs/seed-project.d.ts +62 -0
- package/dist/vfs/seed-project.d.ts.map +1 -0
- package/dist/vfs/seed-project.js +1045 -0
- package/dist/vfs/sqlite-vfs.d.ts +435 -0
- package/dist/vfs/sqlite-vfs.d.ts.map +1 -0
- package/dist/vfs/sqlite-vfs.js +1670 -0
- package/dist/vfs/symlink-registry.d.ts +64 -0
- package/dist/vfs/symlink-registry.d.ts.map +1 -0
- package/dist/vfs/symlink-registry.js +137 -0
- package/dist/wrangler/nimbus-wrangler.d.ts +157 -0
- package/dist/wrangler/nimbus-wrangler.d.ts.map +1 -0
- package/dist/wrangler/nimbus-wrangler.js +931 -0
- package/package.json +77 -0
- package/public/_assets/cirrus-plugin-react.bundle.js +70740 -0
- package/public/_assets/esbuild-0.24.2.wasm +0 -0
- package/public/_assets/real-vite-bundle.js +101478 -0
- package/public/_assets/rollup.wasm +0 -0
- package/public/favicon.svg +8 -0
- package/public/index.html +565 -0
- package/public/s/index.html +2379 -0
- package/scripts/bundle-esbuild-wasm.mjs +244 -0
- package/scripts/bundle-facet-workers.mjs +137 -0
- package/scripts/bundle-git.mjs +118 -0
- package/scripts/bundle-npm-cjs.mjs +363 -0
- package/scripts/bundle-plugin-react.mjs +480 -0
- package/scripts/bundle-real-vite.mjs +959 -0
- package/scripts/bundle-runtime.mjs +600 -0
- package/scripts/bundle-tailwind-play.mjs +130 -0
- package/scripts/patch-lifo-ui.mjs +131 -0
|
@@ -0,0 +1,385 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* session/hibernation.ts — W9 hibernation persistence + alarm dispatch.
|
|
3
|
+
*
|
|
4
|
+
* Workerd hibernates Durable Objects between requests to free memory.
|
|
5
|
+
* On wake, the new isolate must rebuild its in-memory state from
|
|
6
|
+
* SQL — but it also needs to know "is this the same lifecycle as
|
|
7
|
+
* before, or did workerd recycle me?" That distinction matters for
|
|
8
|
+
* recovery (warmJoin vs cold init) and is captured by isolateGen,
|
|
9
|
+
* a counter persisted across hibernations.
|
|
10
|
+
*
|
|
11
|
+
* Surfaces:
|
|
12
|
+
* - wireHibernationOnConstruct(ctx) — runs configureWsHibernation in
|
|
13
|
+
* the DO ctor; graceful-degrades on throw.
|
|
14
|
+
* - wireProcessLogPersist(host, ctx) — installs the SQL-backed
|
|
15
|
+
* PersistAdapter on host.processLogs; patches append/markExit to
|
|
16
|
+
* schedule debounced flushes.
|
|
17
|
+
* - ensureHibSchema(host, ctx) — idempotent CREATE TABLE for
|
|
18
|
+
* w9_proc_logs + w9_proc_exits.
|
|
19
|
+
* - scheduleHibFlush(host, ctx) — debounced setTimeout + best-effort
|
|
20
|
+
* setAlarm for post-hibernation drain.
|
|
21
|
+
* - dispatchAlarm(host) — alarm() handler body.
|
|
22
|
+
* - maybeBumpIsolateGen(host, ctx) — increment + persist isolate-gen
|
|
23
|
+
* counter once per fresh isolate.
|
|
24
|
+
* - flushOnClose(host) — synchronous flush on ws close.
|
|
25
|
+
*
|
|
26
|
+
* **`ctx` taken as a separate arg from `host`** because the parent
|
|
27
|
+
* `CloudflareDurableObject` class declares `ctx` as `protected`, which
|
|
28
|
+
* is nominal-typed in TS and cannot appear on a public interface
|
|
29
|
+
* (DEFECT-D1 found at S3; documented in session-refactor-build-progress.md).
|
|
30
|
+
*
|
|
31
|
+
* Per plan §VI.7 F.2 invariant: `_w9PersistWired` must be reset
|
|
32
|
+
* between `processLogs` replacement and re-wire on
|
|
33
|
+
* `/api/_test/hib/simulate`. The class-side handler is responsible for
|
|
34
|
+
* setting `host._w9PersistWired = false` BEFORE calling
|
|
35
|
+
* wireProcessLogPersist again.
|
|
36
|
+
*/
|
|
37
|
+
import { configureWsHibernation } from './ws-hibernation-config.js';
|
|
38
|
+
import { W9_ISOLATE_GEN_KEY, W9_FLUSH_DEBOUNCE_MS, W1_NEXT_ALARM_REASONS_KEY } from './keys.js';
|
|
39
|
+
/**
|
|
40
|
+
* Run at DO ctor time. Returns the result for the class to assign to
|
|
41
|
+
* `_w9WsConfig`. Failures are non-fatal — older workerd builds may lack
|
|
42
|
+
* the API; the result lands in /api/_diag/memory.hib for verification.
|
|
43
|
+
*/
|
|
44
|
+
export function wireHibernationOnConstruct(ctx) {
|
|
45
|
+
try {
|
|
46
|
+
return configureWsHibernation(ctx);
|
|
47
|
+
}
|
|
48
|
+
catch (e) {
|
|
49
|
+
console.warn('[nimbus/W9] configureWsHibernation threw:', e?.message);
|
|
50
|
+
return {
|
|
51
|
+
autoResponseConfigured: false,
|
|
52
|
+
timeoutSetMs: null,
|
|
53
|
+
autoResponseError: e?.message,
|
|
54
|
+
timeoutError: e?.message,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* W9: install the SQL-backed PersistAdapter on host.processLogs.
|
|
60
|
+
*
|
|
61
|
+
* NOTE: any future alarm-driven subsystem MUST coordinate via a single
|
|
62
|
+
* `alarm()` dispatcher (e.g., a `nextAlarmReason` storage key checked
|
|
63
|
+
* inside the dispatcher). Today W9 is the only consumer; the dispatcher
|
|
64
|
+
* lives in `dispatchAlarm()` below, invoked from the class's `alarm()`
|
|
65
|
+
* handler.
|
|
66
|
+
*
|
|
67
|
+
* Idempotent: gated by host._w9PersistWired. Caller MUST reset that
|
|
68
|
+
* flag to false before re-invoking after a host.processLogs replacement
|
|
69
|
+
* (per /api/_test/hib/simulate flow; plan §VI.7 F.2 invariant).
|
|
70
|
+
*/
|
|
71
|
+
export function wireProcessLogPersist(host, ctx) {
|
|
72
|
+
if (host._w9PersistWired)
|
|
73
|
+
return;
|
|
74
|
+
host._w9PersistWired = true;
|
|
75
|
+
const adapter = {
|
|
76
|
+
load(pid) {
|
|
77
|
+
try {
|
|
78
|
+
ensureHibSchema(host, ctx);
|
|
79
|
+
const sql = ctx.storage.sql;
|
|
80
|
+
const chunkRows = [...sql.exec('SELECT pid, seq, ts, stream, data, binary FROM w9_proc_logs WHERE pid = ? ORDER BY seq ASC', pid)];
|
|
81
|
+
const exitRows = [...sql.exec('SELECT code, at, reason FROM w9_proc_exits WHERE pid = ?', pid)];
|
|
82
|
+
const chunks = chunkRows.map((r) => ({
|
|
83
|
+
ts: Number(r.ts),
|
|
84
|
+
stream: r.stream === 'stderr' ? 'stderr' : 'stdout',
|
|
85
|
+
data: String(r.data),
|
|
86
|
+
binary: !!r.binary,
|
|
87
|
+
...(r.seq !== undefined ? { seq: Number(r.seq) } : {}),
|
|
88
|
+
}));
|
|
89
|
+
const exit = exitRows.length > 0
|
|
90
|
+
? {
|
|
91
|
+
code: Number(exitRows[0].code),
|
|
92
|
+
at: Number(exitRows[0].at),
|
|
93
|
+
reason: exitRows[0].reason ?? undefined,
|
|
94
|
+
}
|
|
95
|
+
: null;
|
|
96
|
+
return { chunks, exit };
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
persistChunks(pid, rows) {
|
|
103
|
+
if (rows.length === 0)
|
|
104
|
+
return;
|
|
105
|
+
try {
|
|
106
|
+
ensureHibSchema(host, ctx);
|
|
107
|
+
const sql = ctx.storage.sql;
|
|
108
|
+
// Use a single transactionSync wrapping the per-row INSERTs so
|
|
109
|
+
// a partial write either fully lands or fully rolls back. Real
|
|
110
|
+
// multi-row VALUES (?,?,?), (?,?,?), … is faster but requires
|
|
111
|
+
// dynamic-arity SQL building — clarity wins here; flushes
|
|
112
|
+
// happen at most once per debounce window so the volume is low.
|
|
113
|
+
ctx.storage.transactionSync(() => {
|
|
114
|
+
for (const r of rows) {
|
|
115
|
+
const c = r.chunk;
|
|
116
|
+
sql.exec('INSERT OR REPLACE INTO w9_proc_logs (pid, seq, ts, stream, data, binary) VALUES (?, ?, ?, ?, ?, ?)', pid, r.seq, c.ts, c.stream, c.data, c.binary ? 1 : 0);
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
catch (e) {
|
|
121
|
+
console.warn('[nimbus/W9] persistChunks failed:', e?.message);
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
persistExit(pid, info) {
|
|
125
|
+
try {
|
|
126
|
+
ensureHibSchema(host, ctx);
|
|
127
|
+
const sql = ctx.storage.sql;
|
|
128
|
+
sql.exec('INSERT OR REPLACE INTO w9_proc_exits (pid, code, at, reason) VALUES (?, ?, ?, ?)', pid, info.code, info.at, info.reason ?? null);
|
|
129
|
+
}
|
|
130
|
+
catch (e) {
|
|
131
|
+
console.warn('[nimbus/W9] persistExit failed:', e?.message);
|
|
132
|
+
}
|
|
133
|
+
},
|
|
134
|
+
dropPid(pid) {
|
|
135
|
+
try {
|
|
136
|
+
ensureHibSchema(host, ctx);
|
|
137
|
+
const sql = ctx.storage.sql;
|
|
138
|
+
ctx.storage.transactionSync(() => {
|
|
139
|
+
sql.exec('DELETE FROM w9_proc_logs WHERE pid = ?', pid);
|
|
140
|
+
sql.exec('DELETE FROM w9_proc_exits WHERE pid = ?', pid);
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
catch (e) {
|
|
144
|
+
console.warn('[nimbus/W9] dropPid failed:', e?.message);
|
|
145
|
+
}
|
|
146
|
+
},
|
|
147
|
+
pruneBeforeSeq(pid, seq) {
|
|
148
|
+
try {
|
|
149
|
+
ensureHibSchema(host, ctx);
|
|
150
|
+
const sql = ctx.storage.sql;
|
|
151
|
+
sql.exec('DELETE FROM w9_proc_logs WHERE pid = ? AND seq < ?', pid, seq);
|
|
152
|
+
}
|
|
153
|
+
catch (e) {
|
|
154
|
+
console.warn('[nimbus/W9] pruneBeforeSeq failed:', e?.message);
|
|
155
|
+
}
|
|
156
|
+
},
|
|
157
|
+
};
|
|
158
|
+
host.processLogs.setPersist(adapter);
|
|
159
|
+
// Wrap append/markExit on the store to schedule a debounced flush.
|
|
160
|
+
// We patch via method override rather than monkey-patching because
|
|
161
|
+
// the store doesn't (and shouldn't) know about timers — flush
|
|
162
|
+
// scheduling is the host's responsibility.
|
|
163
|
+
const origAppend = host.processLogs.append.bind(host.processLogs);
|
|
164
|
+
const origMarkExit = host.processLogs.markExit.bind(host.processLogs);
|
|
165
|
+
host.processLogs.append = (pid, stream, data) => {
|
|
166
|
+
origAppend(pid, stream, data);
|
|
167
|
+
scheduleHibFlush(host, ctx);
|
|
168
|
+
};
|
|
169
|
+
host.processLogs.markExit = (pid, code, reason) => {
|
|
170
|
+
origMarkExit(pid, code, reason);
|
|
171
|
+
// Exit-on-process-end is a strong "flush soon" signal — if the
|
|
172
|
+
// process crashed we want the dump persisted before the actor
|
|
173
|
+
// can hibernate. Schedule but don't bypass debounce, so a fast
|
|
174
|
+
// exit-after-spawn doesn't double-fire.
|
|
175
|
+
scheduleHibFlush(host, ctx);
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
/** W9: idempotent SQL schema bootstrap. */
|
|
179
|
+
export function ensureHibSchema(host, ctx) {
|
|
180
|
+
if (host._w9SchemaInit)
|
|
181
|
+
return;
|
|
182
|
+
host._w9SchemaInit = true;
|
|
183
|
+
try {
|
|
184
|
+
const sql = ctx.storage.sql;
|
|
185
|
+
sql.exec('CREATE TABLE IF NOT EXISTS w9_proc_logs (' +
|
|
186
|
+
'pid INTEGER NOT NULL, seq INTEGER NOT NULL, ts INTEGER NOT NULL, ' +
|
|
187
|
+
'stream TEXT NOT NULL, data TEXT NOT NULL, binary INTEGER NOT NULL, ' +
|
|
188
|
+
'PRIMARY KEY (pid, seq))');
|
|
189
|
+
sql.exec('CREATE INDEX IF NOT EXISTS w9_proc_logs_ts ON w9_proc_logs(ts)');
|
|
190
|
+
sql.exec('CREATE TABLE IF NOT EXISTS w9_proc_exits (' +
|
|
191
|
+
'pid INTEGER PRIMARY KEY, code INTEGER NOT NULL, at INTEGER NOT NULL, ' +
|
|
192
|
+
'reason TEXT)');
|
|
193
|
+
}
|
|
194
|
+
catch (e) {
|
|
195
|
+
console.warn('[nimbus/W9] schema init failed:', e?.message);
|
|
196
|
+
host._w9SchemaInit = false; // retry next time
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* W1: schedule (or re-schedule) an alarm reason. Coordinated via a
|
|
201
|
+
* single map in DO storage so multiple subsystems (W9 debounced flush +
|
|
202
|
+
* W1 log-janitor sweep) don't clobber each other's `setAlarm()` calls.
|
|
203
|
+
*
|
|
204
|
+
* Semantics:
|
|
205
|
+
* - Reads the existing reasons map.
|
|
206
|
+
* - Sets `map[reason] = whenMs` IF `whenMs` is sooner than the
|
|
207
|
+
* currently-pending deadline for that reason (or no entry exists).
|
|
208
|
+
* Later-than-pending requests are silently ignored — the existing
|
|
209
|
+
* alarm will fire and re-arm anyway.
|
|
210
|
+
* - Writes the map back and calls `ctx.storage.setAlarm(min(deadlines))`.
|
|
211
|
+
*
|
|
212
|
+
* Cost: 1 storage read + 1 storage write + 1 setAlarm per call. setAlarm
|
|
213
|
+
* itself is billed as 1 row written per DO pricing. At W1's 60s
|
|
214
|
+
* cadence, this is ~$0.05/mo/session at scale — dwarfed by the
|
|
215
|
+
* hibernation duration savings.
|
|
216
|
+
*
|
|
217
|
+
* Fail-soft: any throw is swallowed with a warn. On older runtimes /
|
|
218
|
+
* wrangler-dev where setAlarm is unavailable, this is a no-op (the
|
|
219
|
+
* subsystem's in-isolate setTimeout fallback continues to work).
|
|
220
|
+
*/
|
|
221
|
+
export async function scheduleAlarm(ctx, reason, whenMs) {
|
|
222
|
+
try {
|
|
223
|
+
const setAlarmFn = ctx?.storage?.setAlarm;
|
|
224
|
+
if (typeof setAlarmFn !== 'function')
|
|
225
|
+
return;
|
|
226
|
+
const existing = (await ctx.storage.get(W1_NEXT_ALARM_REASONS_KEY));
|
|
227
|
+
const map = { ...(existing || {}) };
|
|
228
|
+
// Earliest-deadline-first: only update if new request is sooner or
|
|
229
|
+
// this reason has no pending entry.
|
|
230
|
+
if (!(reason in map) || whenMs < map[reason]) {
|
|
231
|
+
map[reason] = whenMs;
|
|
232
|
+
await ctx.storage.put(W1_NEXT_ALARM_REASONS_KEY, map);
|
|
233
|
+
}
|
|
234
|
+
const earliest = Math.min(...Object.values(map));
|
|
235
|
+
setAlarmFn.call(ctx.storage, earliest);
|
|
236
|
+
}
|
|
237
|
+
catch (e) {
|
|
238
|
+
console.warn('[nimbus/W1] scheduleAlarm threw:', e?.message);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* W9: ensure the alarm is set for the next flush window. Cheap to
|
|
243
|
+
* call repeatedly — we only schedule the in-isolate flush timer if
|
|
244
|
+
* it isn't already set. The persistent alarm goes through scheduleAlarm
|
|
245
|
+
* so it coordinates with W1's log-janitor sweep.
|
|
246
|
+
*/
|
|
247
|
+
export function scheduleHibFlush(host, ctx) {
|
|
248
|
+
if (host._w9FlushTimer)
|
|
249
|
+
return;
|
|
250
|
+
// Local timer for fast in-isolate flush. SHORT-LIVED (250 ms); the
|
|
251
|
+
// callback nulls itself so this timer does not persistently prevent
|
|
252
|
+
// hibernation — once it fires, the DO is timer-free again.
|
|
253
|
+
// Per CF docs, transient setTimeout during an active request is the
|
|
254
|
+
// expected pattern; what blocks hibernation is a RECURRING timer.
|
|
255
|
+
host._w9FlushTimer = setTimeout(() => {
|
|
256
|
+
host._w9FlushTimer = null;
|
|
257
|
+
try {
|
|
258
|
+
host.processLogs.flush();
|
|
259
|
+
}
|
|
260
|
+
catch (e) {
|
|
261
|
+
console.warn('[nimbus/W9] flush threw:', e?.message);
|
|
262
|
+
}
|
|
263
|
+
}, W9_FLUSH_DEBOUNCE_MS);
|
|
264
|
+
// Persistent alarm: fires post-hibernation if the in-isolate timer
|
|
265
|
+
// didn't get a chance to run (DO evicted under memory pressure
|
|
266
|
+
// before the 250ms debounce expired). Coordinated via scheduleAlarm
|
|
267
|
+
// so W1's log-janitor doesn't clobber it (or vice-versa).
|
|
268
|
+
// Fire-and-forget — scheduleAlarm is fail-soft.
|
|
269
|
+
void scheduleAlarm(ctx, 'w9-flush', Date.now() + W9_FLUSH_DEBOUNCE_MS * 4);
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* W1: multi-reason alarm dispatcher. Called from the DO's `alarm()`
|
|
273
|
+
* handler.
|
|
274
|
+
*
|
|
275
|
+
* For each pending reason whose deadline has passed, run its handler.
|
|
276
|
+
* Reasons supported today:
|
|
277
|
+
* - `'w9-flush'` → processLogs.flush()
|
|
278
|
+
* - `'log-janitor'` → processLogs.dropOlderThan(orphanCheck); re-arm
|
|
279
|
+
* for next 60s cycle.
|
|
280
|
+
*
|
|
281
|
+
* `janitorOrphanCheck` is the orphan-pid predicate provided by the
|
|
282
|
+
* caller (typically `(pid) => !host.processTable.get(pid)`). Decoupled
|
|
283
|
+
* so HibHost doesn't need to import ProcessTable.
|
|
284
|
+
*
|
|
285
|
+
* After running fireable reasons, re-arms `ctx.storage.setAlarm` at the
|
|
286
|
+
* earliest remaining deadline. If no reasons remain, deletes the map
|
|
287
|
+
* key and does NOT call setAlarm — the DO becomes hibernation-eligible
|
|
288
|
+
* after the 10s idle window.
|
|
289
|
+
*
|
|
290
|
+
* Forward/back-compat: unknown reasons silently dropped.
|
|
291
|
+
*/
|
|
292
|
+
export async function dispatchAlarm(host, ctx, janitorOrphanCheck) {
|
|
293
|
+
try {
|
|
294
|
+
const now = Date.now();
|
|
295
|
+
const existing = (await ctx?.storage?.get?.(W1_NEXT_ALARM_REASONS_KEY));
|
|
296
|
+
// Legacy path: pre-W1 deploys had no map. dispatchAlarm was called
|
|
297
|
+
// with no map and unconditionally ran processLogs.flush(). Preserve
|
|
298
|
+
// that on a missing map (one-time post-deploy, then the map is
|
|
299
|
+
// populated by the next scheduleHibFlush / scheduleAlarm call).
|
|
300
|
+
if (!existing || Object.keys(existing).length === 0) {
|
|
301
|
+
try {
|
|
302
|
+
host.processLogs.flush();
|
|
303
|
+
}
|
|
304
|
+
catch (e) {
|
|
305
|
+
console.warn('[nimbus/W9] legacy flush threw:', e?.message);
|
|
306
|
+
}
|
|
307
|
+
return;
|
|
308
|
+
}
|
|
309
|
+
const map = { ...existing };
|
|
310
|
+
// Snapshot fireable reasons BEFORE running any of them, so a
|
|
311
|
+
// handler that schedules itself for the next cycle doesn't get
|
|
312
|
+
// immediately re-fired in the same dispatch.
|
|
313
|
+
const fired = [];
|
|
314
|
+
for (const [reason, when] of Object.entries(map)) {
|
|
315
|
+
if (when <= now)
|
|
316
|
+
fired.push(reason);
|
|
317
|
+
}
|
|
318
|
+
for (const reason of fired) {
|
|
319
|
+
delete map[reason];
|
|
320
|
+
try {
|
|
321
|
+
if (reason === 'w9-flush') {
|
|
322
|
+
host.processLogs.flush();
|
|
323
|
+
}
|
|
324
|
+
else if (reason === 'log-janitor') {
|
|
325
|
+
host.processLogs.dropOlderThan(undefined, janitorOrphanCheck);
|
|
326
|
+
// Self-renew: schedule next sweep 60s out.
|
|
327
|
+
map['log-janitor'] = now + 60_000;
|
|
328
|
+
}
|
|
329
|
+
// Unknown reasons silently dropped (forward-compat).
|
|
330
|
+
}
|
|
331
|
+
catch (e) {
|
|
332
|
+
console.warn(`[nimbus/W1] dispatch ${reason} threw:`, e?.message);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
// Re-arm or clear.
|
|
336
|
+
const setAlarmFn = ctx?.storage?.setAlarm;
|
|
337
|
+
if (Object.keys(map).length > 0) {
|
|
338
|
+
await ctx.storage.put(W1_NEXT_ALARM_REASONS_KEY, map);
|
|
339
|
+
const earliest = Math.min(...Object.values(map));
|
|
340
|
+
if (typeof setAlarmFn === 'function') {
|
|
341
|
+
setAlarmFn.call(ctx.storage, earliest);
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
else {
|
|
345
|
+
try {
|
|
346
|
+
await ctx.storage.delete(W1_NEXT_ALARM_REASONS_KEY);
|
|
347
|
+
}
|
|
348
|
+
catch { }
|
|
349
|
+
// No remaining reasons → no setAlarm call → DO becomes
|
|
350
|
+
// hibernation-eligible after the 10s idle window.
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
catch (e) {
|
|
354
|
+
console.warn('[nimbus/W1] dispatchAlarm threw:', e?.message);
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
/** W9: increment + persist isolate-gen counter once per fresh isolate. */
|
|
358
|
+
export async function maybeBumpIsolateGen(host, ctx) {
|
|
359
|
+
if (host._w9IsolateGenPersisted)
|
|
360
|
+
return;
|
|
361
|
+
host._w9IsolateGenPersisted = true;
|
|
362
|
+
try {
|
|
363
|
+
const prev = (await ctx.storage.get(W9_ISOLATE_GEN_KEY));
|
|
364
|
+
const next = (typeof prev === 'number' ? prev : 0) + 1;
|
|
365
|
+
host._w9IsolateGen = next;
|
|
366
|
+
await ctx.storage.put(W9_ISOLATE_GEN_KEY, next);
|
|
367
|
+
}
|
|
368
|
+
catch (e) {
|
|
369
|
+
console.warn('[nimbus/W9] isolate-gen bump failed:', e?.message);
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
/**
|
|
373
|
+
* W9: synchronous flush of the process-log ring on session close.
|
|
374
|
+
* Wraps `processLogs.flush()` in a try/catch so a flush failure
|
|
375
|
+
* doesn't take down the close handler. Cheap when there's nothing
|
|
376
|
+
* dirty (idempotent inside the store).
|
|
377
|
+
*/
|
|
378
|
+
export function flushOnClose(host) {
|
|
379
|
+
try {
|
|
380
|
+
host.processLogs.flush();
|
|
381
|
+
}
|
|
382
|
+
catch (e) {
|
|
383
|
+
console.warn('[nimbus/W9] flush-on-close failed:', e?.message);
|
|
384
|
+
}
|
|
385
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* src/session/init-phases.ts — B'.4 R/B/W/O state machine for initSession.
|
|
3
|
+
*
|
|
4
|
+
* Track B' goal: make the implicit phases of initSession explicit and
|
|
5
|
+
* observable. Each phase boundary calls `setPhase(self, phase, trigger)`
|
|
6
|
+
* which:
|
|
7
|
+
* 1. Updates `self._b4Phase` so /api/_diag/session.phase reflects it.
|
|
8
|
+
* 2. Records a recovery_event entry capturing the transition. The
|
|
9
|
+
* ring is bounded to 50 events and is the C'.2 surface — phase
|
|
10
|
+
* transitions are SUPPLEMENTAL to the existing high-level
|
|
11
|
+
* cold/hydrated/active/drained markers, not a replacement.
|
|
12
|
+
*
|
|
13
|
+
* The phases:
|
|
14
|
+
* - rehydrate: Phase R — loading persisted values from DO SQLite
|
|
15
|
+
* (cwd, env, mounts, scrollback). Pure SQL reads;
|
|
16
|
+
* sets up locals consumed by later phases.
|
|
17
|
+
* - build: Phase B — constructing Kernel + Shell + registry +
|
|
18
|
+
* installing 60+ commands + wiring SqliteVFSProvider
|
|
19
|
+
* mounts. Most CPU-intensive phase.
|
|
20
|
+
* - wire: Phase W — attaching the WebSocketTerminal to the
|
|
21
|
+
* Shell, replaying persisted scrollback into the WS.
|
|
22
|
+
* This is the phase B'.5 will be able to re-run on
|
|
23
|
+
* an already-built session ("join existing").
|
|
24
|
+
* - online: Phase O — cold-start UI: MOTD, starter-app hint,
|
|
25
|
+
* framework-detect line. ONLY runs on cold start
|
|
26
|
+
* (when persisted.hasPersistedState=false). On warm
|
|
27
|
+
* re-init this phase is skipped and initSession ends
|
|
28
|
+
* with the 'hydrated' marker instead of 'online'.
|
|
29
|
+
*
|
|
30
|
+
* The legacy single recordRecoveryEvent({fromState, toState:
|
|
31
|
+
* 'hydrated', trigger:'init-session'}) call at end of initSession is
|
|
32
|
+
* preserved — old probes still see it. New phase entries are
|
|
33
|
+
* additional ring entries, not replacements.
|
|
34
|
+
*/
|
|
35
|
+
import { type SessionState } from '../observability/oom-discriminator.js';
|
|
36
|
+
/**
|
|
37
|
+
* Set the current phase + record a transition. Fail-soft on the
|
|
38
|
+
* observability call; the phase update on `self` is direct and
|
|
39
|
+
* cheap.
|
|
40
|
+
*/
|
|
41
|
+
export declare function setPhase(self: {
|
|
42
|
+
_b4Phase: SessionState | null;
|
|
43
|
+
_w9IsolateGen?: number;
|
|
44
|
+
}, toState: SessionState, trigger: string): void;
|
|
45
|
+
/**
|
|
46
|
+
* [B'.5] Determine whether the next /ws upgrade should run the warm-
|
|
47
|
+
* rejoin path (Phase R + Phase W only) or the full cold-init path
|
|
48
|
+
* (R + B + W + O + hydrated).
|
|
49
|
+
*
|
|
50
|
+
* Conditions for warm rejoin:
|
|
51
|
+
* 1. Phase = 'drained' (a wsClose / wsError fired since last init).
|
|
52
|
+
* 2. Kernel + Shell + Terminal are still alive in-memory (the
|
|
53
|
+
* [B'.5] change to wsClose stopped nulling them).
|
|
54
|
+
* 3. Same isolate (no DO eviction since the close).
|
|
55
|
+
*
|
|
56
|
+
* If ANY condition fails, the full cold-init path is the safe choice.
|
|
57
|
+
*/
|
|
58
|
+
export declare function isWarmRejoin(self: {
|
|
59
|
+
_b4Phase: SessionState | null;
|
|
60
|
+
shell: any;
|
|
61
|
+
terminal: any;
|
|
62
|
+
kernel: any;
|
|
63
|
+
}): boolean;
|
|
64
|
+
/**
|
|
65
|
+
* [B'.5] Run the warm-rejoin path. Skips Phase B (kernel + shell are
|
|
66
|
+
* already built and alive in-memory). Phase R loads any state that
|
|
67
|
+
* may have changed since drained (none today — Phase R is no-op on
|
|
68
|
+
* warm rejoin); Phase W swaps the WebSocketTerminal's underlying ws
|
|
69
|
+
* to the new socket and replays scrollback so the user sees their
|
|
70
|
+
* pre-close terminal contents above the live prompt.
|
|
71
|
+
*
|
|
72
|
+
* The `self` argument is intentionally minimal — only the fields
|
|
73
|
+
* this function actually touches. The full SessionInternal isn't
|
|
74
|
+
* needed here; init-phases.ts shouldn't grow a circular dep on
|
|
75
|
+
* nimbus-session-internal.
|
|
76
|
+
*/
|
|
77
|
+
export declare function joinExistingSession(self: {
|
|
78
|
+
ctx: any;
|
|
79
|
+
terminal: {
|
|
80
|
+
attach(ws: WebSocket, onFlush?: (data: string) => void): void;
|
|
81
|
+
write(s: string): void;
|
|
82
|
+
};
|
|
83
|
+
_b4Phase: SessionState | null;
|
|
84
|
+
_w9IsolateGen?: number;
|
|
85
|
+
_b4WarmJoinCount: number;
|
|
86
|
+
}, ws: WebSocket, appendScrollback: (ctx: any, data: string, atMs: number) => void, loadScrollback: (ctx: any) => string): void;
|
|
87
|
+
//# sourceMappingURL=init-phases.d.ts.map
|
|
@@ -0,0 +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,uCAAuC,CAAC;AAE/F;;;;GAIG;AACH,wBAAgB,QAAQ,CACtB,IAAI,EAAE;IAAE,QAAQ,EAAE,YAAY,GAAG,IAAI,CAAC;IAAC,aAAa,CAAC,EAAE,MAAM,CAAA;CAAE,EAC/D,OAAO,EAAE,YAAY,EACrB,OAAO,EAAE,MAAM,GACd,IAAI,CAcN;AAED;;;;;;;;;;;;GAYG;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;;;;;;;;;;;;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,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,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"}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* src/session/init-phases.ts — B'.4 R/B/W/O state machine for initSession.
|
|
3
|
+
*
|
|
4
|
+
* Track B' goal: make the implicit phases of initSession explicit and
|
|
5
|
+
* observable. Each phase boundary calls `setPhase(self, phase, trigger)`
|
|
6
|
+
* which:
|
|
7
|
+
* 1. Updates `self._b4Phase` so /api/_diag/session.phase reflects it.
|
|
8
|
+
* 2. Records a recovery_event entry capturing the transition. The
|
|
9
|
+
* ring is bounded to 50 events and is the C'.2 surface — phase
|
|
10
|
+
* transitions are SUPPLEMENTAL to the existing high-level
|
|
11
|
+
* cold/hydrated/active/drained markers, not a replacement.
|
|
12
|
+
*
|
|
13
|
+
* The phases:
|
|
14
|
+
* - rehydrate: Phase R — loading persisted values from DO SQLite
|
|
15
|
+
* (cwd, env, mounts, scrollback). Pure SQL reads;
|
|
16
|
+
* sets up locals consumed by later phases.
|
|
17
|
+
* - build: Phase B — constructing Kernel + Shell + registry +
|
|
18
|
+
* installing 60+ commands + wiring SqliteVFSProvider
|
|
19
|
+
* mounts. Most CPU-intensive phase.
|
|
20
|
+
* - wire: Phase W — attaching the WebSocketTerminal to the
|
|
21
|
+
* Shell, replaying persisted scrollback into the WS.
|
|
22
|
+
* This is the phase B'.5 will be able to re-run on
|
|
23
|
+
* an already-built session ("join existing").
|
|
24
|
+
* - online: Phase O — cold-start UI: MOTD, starter-app hint,
|
|
25
|
+
* framework-detect line. ONLY runs on cold start
|
|
26
|
+
* (when persisted.hasPersistedState=false). On warm
|
|
27
|
+
* re-init this phase is skipped and initSession ends
|
|
28
|
+
* with the 'hydrated' marker instead of 'online'.
|
|
29
|
+
*
|
|
30
|
+
* The legacy single recordRecoveryEvent({fromState, toState:
|
|
31
|
+
* 'hydrated', trigger:'init-session'}) call at end of initSession is
|
|
32
|
+
* preserved — old probes still see it. New phase entries are
|
|
33
|
+
* additional ring entries, not replacements.
|
|
34
|
+
*/
|
|
35
|
+
import { recordRecoveryEvent } from '../observability/oom-discriminator.js';
|
|
36
|
+
/**
|
|
37
|
+
* Set the current phase + record a transition. Fail-soft on the
|
|
38
|
+
* observability call; the phase update on `self` is direct and
|
|
39
|
+
* cheap.
|
|
40
|
+
*/
|
|
41
|
+
export function setPhase(self, toState, trigger) {
|
|
42
|
+
const fromState = self._b4Phase ?? 'cold';
|
|
43
|
+
self._b4Phase = toState;
|
|
44
|
+
try {
|
|
45
|
+
recordRecoveryEvent({
|
|
46
|
+
at: Date.now(),
|
|
47
|
+
fromState,
|
|
48
|
+
toState,
|
|
49
|
+
trigger,
|
|
50
|
+
isolateGen: self._w9IsolateGen ?? 0,
|
|
51
|
+
dataLoss: false,
|
|
52
|
+
snapshotKeysRehydrated: 0,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
catch { /* observability is non-critical */ }
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* [B'.5] Determine whether the next /ws upgrade should run the warm-
|
|
59
|
+
* rejoin path (Phase R + Phase W only) or the full cold-init path
|
|
60
|
+
* (R + B + W + O + hydrated).
|
|
61
|
+
*
|
|
62
|
+
* Conditions for warm rejoin:
|
|
63
|
+
* 1. Phase = 'drained' (a wsClose / wsError fired since last init).
|
|
64
|
+
* 2. Kernel + Shell + Terminal are still alive in-memory (the
|
|
65
|
+
* [B'.5] change to wsClose stopped nulling them).
|
|
66
|
+
* 3. Same isolate (no DO eviction since the close).
|
|
67
|
+
*
|
|
68
|
+
* If ANY condition fails, the full cold-init path is the safe choice.
|
|
69
|
+
*/
|
|
70
|
+
export function isWarmRejoin(self) {
|
|
71
|
+
return self._b4Phase === 'drained'
|
|
72
|
+
&& self.shell != null
|
|
73
|
+
&& self.terminal != null
|
|
74
|
+
&& self.kernel != null;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* [B'.5] Run the warm-rejoin path. Skips Phase B (kernel + shell are
|
|
78
|
+
* already built and alive in-memory). Phase R loads any state that
|
|
79
|
+
* may have changed since drained (none today — Phase R is no-op on
|
|
80
|
+
* warm rejoin); Phase W swaps the WebSocketTerminal's underlying ws
|
|
81
|
+
* to the new socket and replays scrollback so the user sees their
|
|
82
|
+
* pre-close terminal contents above the live prompt.
|
|
83
|
+
*
|
|
84
|
+
* The `self` argument is intentionally minimal — only the fields
|
|
85
|
+
* this function actually touches. The full SessionInternal isn't
|
|
86
|
+
* needed here; init-phases.ts shouldn't grow a circular dep on
|
|
87
|
+
* nimbus-session-internal.
|
|
88
|
+
*/
|
|
89
|
+
export function joinExistingSession(self, ws, appendScrollback, loadScrollback) {
|
|
90
|
+
// Phase R — pure SQL reads. No-op on warm rejoin (live state is
|
|
91
|
+
// already correct in self.shell / self.terminal). Recorded in the
|
|
92
|
+
// ring for symmetry with cold init.
|
|
93
|
+
setPhase(self, 'rehydrate', 'warm-rejoin');
|
|
94
|
+
// Phase W — re-attach the existing WebSocketTerminal to the new
|
|
95
|
+
// ws and replay persisted scrollback. The Shell's reference to
|
|
96
|
+
// the same WebSocketTerminal instance is preserved (we mutate
|
|
97
|
+
// its internal ws ref via attach()).
|
|
98
|
+
setPhase(self, 'wire', 'warm-rejoin');
|
|
99
|
+
self.terminal.attach(ws, (frame) => {
|
|
100
|
+
try {
|
|
101
|
+
appendScrollback(self.ctx, frame, Date.now());
|
|
102
|
+
}
|
|
103
|
+
catch (e) {
|
|
104
|
+
try {
|
|
105
|
+
console.warn("[B'.3] appendScrollback failed:", e?.message || e);
|
|
106
|
+
}
|
|
107
|
+
catch { }
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
// Replay scrollback to the new ws so the user sees the prior
|
|
111
|
+
// session's terminal contents. Same shape as cold-init's replay
|
|
112
|
+
// when persisted state exists.
|
|
113
|
+
try {
|
|
114
|
+
const replay = loadScrollback(self.ctx);
|
|
115
|
+
if (replay.length > 0)
|
|
116
|
+
self.terminal.write(replay);
|
|
117
|
+
}
|
|
118
|
+
catch (e) {
|
|
119
|
+
try {
|
|
120
|
+
console.warn("[B'.3] scrollback replay failed:", e?.message || e);
|
|
121
|
+
}
|
|
122
|
+
catch { }
|
|
123
|
+
}
|
|
124
|
+
// Phase O is SKIPPED on warm rejoin (just like warm path of
|
|
125
|
+
// initSession). The original cold-start banner is in the replay.
|
|
126
|
+
// Settle to 'hydrated' as the terminal phase via setPhase so the
|
|
127
|
+
// ring records the wire→hydrated transition for forensics.
|
|
128
|
+
setPhase(self, 'hydrated', 'warm-rejoin');
|
|
129
|
+
// Bump the warm-join counter; surfaced via /api/_diag/session.
|
|
130
|
+
self._b4WarmJoinCount += 1;
|
|
131
|
+
// ws.send({type:'ready'}) — the client expects this to know the
|
|
132
|
+
// shell is live. Same as initSession's last line.
|
|
133
|
+
try {
|
|
134
|
+
ws.send(JSON.stringify({ type: 'ready' }));
|
|
135
|
+
}
|
|
136
|
+
catch { }
|
|
137
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* session/init.ts — initSession boot + shell-command registrations.
|
|
3
|
+
*
|
|
4
|
+
* Why this is one big function and not a class:
|
|
5
|
+
* initSession runs once per /ws upgrade and walks the session
|
|
6
|
+
* through Phase R (rehydrate from SQL), Phase B (build kernel +
|
|
7
|
+
* shell + register commands), Phase W (attach terminal), and
|
|
8
|
+
* (cold-only) Phase O (MOTD + framework hint). The phases share
|
|
9
|
+
* lots of locals (vfs, kernel, registry, shell) and ordering
|
|
10
|
+
* matters strictly — there's no interesting reuse boundary that a
|
|
11
|
+
* class decomposition would expose.
|
|
12
|
+
*
|
|
13
|
+
* The function is intentionally written so that a reader sees:
|
|
14
|
+
* 1. setPhase('rehydrate') ...
|
|
15
|
+
* 2. setPhase('build') ... (~95% of the LOC)
|
|
16
|
+
* 3. setPhase('online') if (cold)
|
|
17
|
+
* 4. self._b4Phase = 'hydrated'
|
|
18
|
+
*
|
|
19
|
+
* Extracted from src/nimbus-session.ts during the SESSION-REFACTOR
|
|
20
|
+
* (audit/sections/SESSION-REFACTOR-PLAN.md §B.3.8 + S6) so the DO
|
|
21
|
+
* class itself stays small. Imports `self: InitHost` (a narrow view
|
|
22
|
+
* of SessionInternal + readonly ctx/env) which gives the compiler
|
|
23
|
+
* enough type info without the surface area of the full DO class.
|
|
24
|
+
*
|
|
25
|
+
* Imports and class delegators on NimbusSession preserve back-compat:
|
|
26
|
+
* - acceptShellWebSocket → self.initSession(ws) (S7 will extract).
|
|
27
|
+
* - The class still has `initSession(ws)` as a delegator method.
|
|
28
|
+
*/
|
|
29
|
+
import type { SessionInternal } from './internal.js';
|
|
30
|
+
/**
|
|
31
|
+
* `initSession` reads `this.ctx` and `this.env` extensively (~14 sites).
|
|
32
|
+
* Both are `protected` on the parent `CloudflareDurableObject` class
|
|
33
|
+
* (DEFECT-D1, see audit/sessions/session-refactor-build-progress.md).
|
|
34
|
+
* The pragmatic shape for THIS module: extend SessionInternal with
|
|
35
|
+
* `ctx`/`env` as `any` and have the class delegator cast `this as
|
|
36
|
+
* unknown as InitHost`. Other sibling modules (-rpc, -ws, -hib,
|
|
37
|
+
* -replica) DO take ctx as a separate explicit arg per D1 — initSession
|
|
38
|
+
* can't because the body has too many call sites to thread through.
|
|
39
|
+
*/
|
|
40
|
+
type InitHost = SessionInternal & {
|
|
41
|
+
readonly ctx: any;
|
|
42
|
+
readonly env: any;
|
|
43
|
+
};
|
|
44
|
+
export declare function initSession(self: InitHost, ws: WebSocket): void;
|
|
45
|
+
export {};
|
|
46
|
+
//# sourceMappingURL=init.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/session/init.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AA8DH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAErD;;;;;;;;;GASG;AACH,KAAK,QAAQ,GAAG,eAAe,GAAG;IAAE,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC;IAAC,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAA;CAAE,CAAC;AAG3E,wBAAgB,WAAW,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,SAAS,GAAG,IAAI,CAk8G/D"}
|