@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,195 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* fanout-pool.ts — two-tier fan-out primitive.
|
|
3
|
+
*
|
|
4
|
+
* Background
|
|
5
|
+
* ──────────
|
|
6
|
+
* The supervisor DO sits behind a V8 invariant: at most **4 concurrent
|
|
7
|
+
* env.LOADER.get(...).getEntrypoint().fetch(...)** calls per DO method
|
|
8
|
+
* invocation (3 from a Worker handler context). Beyond that, additional
|
|
9
|
+
* dispatches serialize against the cap and produce
|
|
10
|
+
* `Too many concurrent dynamic workers` errors. See
|
|
11
|
+
* `audit/sections/FANOUT-AUDIT.md` and
|
|
12
|
+
* `docs/research/poc-multi-backend-findings.md` for the measurement
|
|
13
|
+
* data.
|
|
14
|
+
*
|
|
15
|
+
* The existing `NimbusLoaderPool` (src/loaders/loader-pool.ts) defaults
|
|
16
|
+
* `concurrency = 4` precisely because of this cap. Every wide fan-out
|
|
17
|
+
* site in `src/npm/installer.ts` (resolver, install-batch, pre-bundle)
|
|
18
|
+
* was forced into a `concurrency: 1` outer pool with an internal
|
|
19
|
+
* limiter inside ONE facet — see the explicit comment at
|
|
20
|
+
* installer.ts:654 ("collapses what was 4 concurrent dynamic workers
|
|
21
|
+
* (pool.map slots) into 1").
|
|
22
|
+
*
|
|
23
|
+
* Two validated topologies (POC findings)
|
|
24
|
+
* ───────────────────────────────────────
|
|
25
|
+
* POC C in-DO fan-out 1 coordinator DO + N≤4 loaders 4.03× at N=4
|
|
26
|
+
* POC B DO Pool + 1 Loader/DO N peer DOs × 1 loader each 7.75× at N=8, flat to N=32
|
|
27
|
+
*
|
|
28
|
+
* `NimbusFanoutPool` exposes ONE `submitMany` API that routes
|
|
29
|
+
* automatically:
|
|
30
|
+
* width < IN_DO_THRESHOLD → POC C (uses existing NimbusLoaderPool)
|
|
31
|
+
* width >= IN_DO_THRESHOLD → POC B (peer NimbusSession DOs)
|
|
32
|
+
*
|
|
33
|
+
* IN_DO_THRESHOLD is 5 — exactly above the V8 cap so we never use the
|
|
34
|
+
* in-DO path beyond the safe ceiling, and the peer-DO path takes over
|
|
35
|
+
* cleanly for the wider workloads.
|
|
36
|
+
*
|
|
37
|
+
* Stable-id router
|
|
38
|
+
* ────────────────
|
|
39
|
+
* Each task carries a `key` (string). The router maps
|
|
40
|
+
* `key → siblingId = peerNamespace(coordDoIdShort, hash(key) mod N)`.
|
|
41
|
+
* Same key → same peer DO across runs. Tests can predict which peer
|
|
42
|
+
* handles which task, and warm peer isolates are reusable across
|
|
43
|
+
* back-to-back fan-outs that share keys.
|
|
44
|
+
*
|
|
45
|
+
* Hard-fail policy
|
|
46
|
+
* ────────────────
|
|
47
|
+
* Anti-requirement: NO fallback. If `env.LOADER` is missing, throw
|
|
48
|
+
* (existing NimbusLoaderPool already does). If
|
|
49
|
+
* `env.NIMBUS_SESSION` is missing AND a peer-DO route is needed,
|
|
50
|
+
* throw. Callers MUST get a deterministic error rather than silently
|
|
51
|
+
* collapsing back to width-1. The supervisor error handler logs and
|
|
52
|
+
* the install fails loudly — same posture every other facet binding
|
|
53
|
+
* has.
|
|
54
|
+
*
|
|
55
|
+
* Backpressure
|
|
56
|
+
* ────────────
|
|
57
|
+
* Hard cap: `MAX_PEER_FANOUT = 32` (POC B's flat zone). If
|
|
58
|
+
* `tasks.length > 32`, the surplus is queued and dispatched in
|
|
59
|
+
* subsequent rounds after the first 32 settle. This keeps the
|
|
60
|
+
* per-request peer-DO count bounded.
|
|
61
|
+
*/
|
|
62
|
+
/**
|
|
63
|
+
* Threshold at which we switch from in-DO POC C → peer-DO POC B.
|
|
64
|
+
*
|
|
65
|
+
* Set to **5** so the in-DO path stays below the V8 4-loaders-per-method
|
|
66
|
+
* cap by construction. width < 5 → POC C; width >= 5 → POC B.
|
|
67
|
+
*/
|
|
68
|
+
export declare const IN_DO_THRESHOLD = 5;
|
|
69
|
+
/**
|
|
70
|
+
* Hard cap on concurrent peer DOs per single submitMany call. POC B
|
|
71
|
+
* measured flat throughput from N=8 to N=32; we use the ceiling so
|
|
72
|
+
* pathological 500-pkg installs still parallelise as wide as the
|
|
73
|
+
* topology supports.
|
|
74
|
+
*/
|
|
75
|
+
export declare const MAX_PEER_FANOUT = 32;
|
|
76
|
+
/** Argument shape for `submitMany`. */
|
|
77
|
+
export interface FanoutTask<A> {
|
|
78
|
+
/**
|
|
79
|
+
* Routing key for the stable-id router. Same key → same peer DO
|
|
80
|
+
* (when on the peer-DO path). Tests use this to predict placement.
|
|
81
|
+
*/
|
|
82
|
+
key: string;
|
|
83
|
+
/** Argument passed to the user fn. */
|
|
84
|
+
args: A;
|
|
85
|
+
}
|
|
86
|
+
/** Options handed to NimbusFanoutPool's constructor. */
|
|
87
|
+
export interface NimbusFanoutPoolOptions {
|
|
88
|
+
/**
|
|
89
|
+
* Tag prepended to peer-DO ids and in-DO loader ids for debugging
|
|
90
|
+
* (e.g. "npm-install-batch"). Affects neither isolate identity (in-DO
|
|
91
|
+
* path uses the existing NimbusLoaderPool's tag-fold) nor peer-DO
|
|
92
|
+
* deterministic placement (peer ids fold tag + key).
|
|
93
|
+
*/
|
|
94
|
+
tag: string;
|
|
95
|
+
/**
|
|
96
|
+
* Per-task timeout in ms. Default 60_000. Forwarded to the in-DO
|
|
97
|
+
* NimbusLoaderPool's submit calls and to the peer-DO RPC's own
|
|
98
|
+
* NimbusLoaderPool.
|
|
99
|
+
*/
|
|
100
|
+
timeoutMs?: number;
|
|
101
|
+
/**
|
|
102
|
+
* Preamble bundled into every facet (in-DO and inside each peer
|
|
103
|
+
* DO). Same semantics as NimbusLoaderPool's preamble option.
|
|
104
|
+
*/
|
|
105
|
+
preamble?: string;
|
|
106
|
+
/**
|
|
107
|
+
* Wasm modules forwarded to every facet. Same semantics as
|
|
108
|
+
* NimbusLoaderPool's wasmModules option.
|
|
109
|
+
*/
|
|
110
|
+
wasmModules?: Record<string, ArrayBuffer>;
|
|
111
|
+
/**
|
|
112
|
+
* Extra bindings forwarded to every facet. Same semantics as
|
|
113
|
+
* NimbusLoaderPool's extraBindings option.
|
|
114
|
+
*/
|
|
115
|
+
extraBindings?: Record<string, unknown>;
|
|
116
|
+
/**
|
|
117
|
+
* If set, skip the supervisor-RPC binding injection (mirrors
|
|
118
|
+
* NimbusLoaderPool's omitSupervisor flag).
|
|
119
|
+
*/
|
|
120
|
+
omitSupervisor?: boolean;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Two-tier fan-out pool. Constructed by the supervisor DO; routes
|
|
124
|
+
* each `submitMany` call automatically based on width.
|
|
125
|
+
*
|
|
126
|
+
* Lifetime: cheap to construct (no async init). Multiple submitMany
|
|
127
|
+
* calls share NO state — each is dispatched fresh. The class
|
|
128
|
+
* exists primarily as a clean API surface; per-call dispatch state
|
|
129
|
+
* lives only inside submitMany's promise.
|
|
130
|
+
*/
|
|
131
|
+
export declare class NimbusFanoutPool {
|
|
132
|
+
private readonly env;
|
|
133
|
+
private readonly ctx;
|
|
134
|
+
private readonly opts;
|
|
135
|
+
private readonly coordDoId;
|
|
136
|
+
private readonly coordDoIdShort;
|
|
137
|
+
constructor(env: any, ctx: DurableObjectState, opts: NimbusFanoutPoolOptions);
|
|
138
|
+
/**
|
|
139
|
+
* Dispatch `tasks` across the appropriate topology and return
|
|
140
|
+
* results in input order.
|
|
141
|
+
*
|
|
142
|
+
* Routing:
|
|
143
|
+
* tasks.length < 5 → POC C in-DO via NimbusLoaderPool (concurrency = tasks.length, capped at 4)
|
|
144
|
+
* tasks.length >= 5 → POC B peer-DO via env.NIMBUS_SESSION sibling DOs (deterministic stable-id router)
|
|
145
|
+
*
|
|
146
|
+
* Backpressure: if `tasks.length > MAX_PEER_FANOUT (32)`, tasks
|
|
147
|
+
* are sharded modulo `MAX_PEER_FANOUT` and each shard's bucket
|
|
148
|
+
* runs serially inside its assigned peer DO via the in-peer
|
|
149
|
+
* NimbusLoaderPool's concurrency (capped at 4 there too). A
|
|
150
|
+
* single submitMany call returns when ALL tasks complete (or any
|
|
151
|
+
* throws).
|
|
152
|
+
*
|
|
153
|
+
* `fn` is the user function executed per task. It runs INSIDE a
|
|
154
|
+
* Worker Loader isolate (in the in-DO path) or inside a peer DO's
|
|
155
|
+
* Worker Loader isolate (in the peer-DO path); same trust posture
|
|
156
|
+
* as NimbusLoaderPool.submit. The function is serialized via
|
|
157
|
+
* the vendored serializeFunction (same as NimbusLoaderPool#prepare).
|
|
158
|
+
*/
|
|
159
|
+
submitMany<A, R>(tasks: FanoutTask<A>[], fn: (item: A, env: any) => R | Promise<R>): Promise<R[]>;
|
|
160
|
+
/**
|
|
161
|
+
* Diagnostic: report which topology a given task count would use.
|
|
162
|
+
* Used by tests to assert routing without exercising the full
|
|
163
|
+
* dispatch path.
|
|
164
|
+
*/
|
|
165
|
+
topologyFor(taskCount: number): 'in-do' | 'peer-do' | 'empty';
|
|
166
|
+
/**
|
|
167
|
+
* Compute the deterministic peer-DO id for a given task key, given
|
|
168
|
+
* the peer count. Exposed so tests can assert routing predictions
|
|
169
|
+
* BEFORE running the dispatch.
|
|
170
|
+
*
|
|
171
|
+
* Shape: `nbf:${tag}:${coordDoIdShort}:${shard}` where
|
|
172
|
+
* `shard = hash(key) mod peerCount`. The hash is hashSource()
|
|
173
|
+
* (FNV-1a over a single-string input — adequate for routing; not
|
|
174
|
+
* cryptographic). Peer count is `min(tasks.length, MAX_PEER_FANOUT)`.
|
|
175
|
+
*/
|
|
176
|
+
peerSiblingId(key: string, peerCount: number): string;
|
|
177
|
+
private _dispatchInDo;
|
|
178
|
+
private _dispatchPeerDo;
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Stable hash → shard. Uses a fresh djb2 over the key (NOT
|
|
182
|
+
* hashSource) and modulos by peerCount.
|
|
183
|
+
*
|
|
184
|
+
* Why not reuse hashSource: hashSource returns a base-36 string,
|
|
185
|
+
* NOT hex — its alphabet is `[0-9a-z]`. parseInt(str, 16) on a
|
|
186
|
+
* base-36 string aborts at the first non-hex char (any of g-z),
|
|
187
|
+
* which produces extremely poor distribution: keys with the same
|
|
188
|
+
* leading-hex-prefix collide regardless of their suffix. (Seen in
|
|
189
|
+
* the wild: `task-0 .. task-7` all collided onto shard 4.)
|
|
190
|
+
*
|
|
191
|
+
* Deterministic: same key + same peerCount → same shard, every run.
|
|
192
|
+
* Tests use this to predict placement.
|
|
193
|
+
*/
|
|
194
|
+
export declare function hashKeyToShard(key: string, peerCount: number): number;
|
|
195
|
+
//# sourceMappingURL=fanout-pool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fanout-pool.d.ts","sourceRoot":"","sources":["../../src/loaders/fanout-pool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4DG;AAMH;;;;;GAKG;AACH,eAAO,MAAM,eAAe,IAAI,CAAC;AAEjC;;;;;GAKG;AACH,eAAO,MAAM,eAAe,KAAK,CAAC;AAElC,uCAAuC;AACvC,MAAM,WAAW,UAAU,CAAC,CAAC;IAC3B;;;OAGG;IACH,GAAG,EAAE,MAAM,CAAC;IACZ,sCAAsC;IACtC,IAAI,EAAE,CAAC,CAAC;CACT;AAED,wDAAwD;AACxD,MAAM,WAAW,uBAAuB;IACtC;;;;;OAKG;IACH,GAAG,EAAE,MAAM,CAAC;IACZ;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAC1C;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACxC;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED;;;;;;;;GAQG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAM;IAC1B,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAqB;IACzC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAA0B;IAC/C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;gBAE5B,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,kBAAkB,EAAE,IAAI,EAAE,uBAAuB;IAiB5E;;;;;;;;;;;;;;;;;;;;OAoBG;IACG,UAAU,CAAC,CAAC,EAAE,CAAC,EACnB,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,EAAE,EACtB,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,KAAK,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GACxC,OAAO,CAAC,CAAC,EAAE,CAAC;IASf;;;;OAIG;IACH,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,GAAG,OAAO;IAK7D;;;;;;;;;OASG;IACH,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM;YAOvC,aAAa;YAmCb,eAAe;CAwH9B;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAUrE"}
|
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* fanout-pool.ts — two-tier fan-out primitive.
|
|
3
|
+
*
|
|
4
|
+
* Background
|
|
5
|
+
* ──────────
|
|
6
|
+
* The supervisor DO sits behind a V8 invariant: at most **4 concurrent
|
|
7
|
+
* env.LOADER.get(...).getEntrypoint().fetch(...)** calls per DO method
|
|
8
|
+
* invocation (3 from a Worker handler context). Beyond that, additional
|
|
9
|
+
* dispatches serialize against the cap and produce
|
|
10
|
+
* `Too many concurrent dynamic workers` errors. See
|
|
11
|
+
* `audit/sections/FANOUT-AUDIT.md` and
|
|
12
|
+
* `docs/research/poc-multi-backend-findings.md` for the measurement
|
|
13
|
+
* data.
|
|
14
|
+
*
|
|
15
|
+
* The existing `NimbusLoaderPool` (src/loaders/loader-pool.ts) defaults
|
|
16
|
+
* `concurrency = 4` precisely because of this cap. Every wide fan-out
|
|
17
|
+
* site in `src/npm/installer.ts` (resolver, install-batch, pre-bundle)
|
|
18
|
+
* was forced into a `concurrency: 1` outer pool with an internal
|
|
19
|
+
* limiter inside ONE facet — see the explicit comment at
|
|
20
|
+
* installer.ts:654 ("collapses what was 4 concurrent dynamic workers
|
|
21
|
+
* (pool.map slots) into 1").
|
|
22
|
+
*
|
|
23
|
+
* Two validated topologies (POC findings)
|
|
24
|
+
* ───────────────────────────────────────
|
|
25
|
+
* POC C in-DO fan-out 1 coordinator DO + N≤4 loaders 4.03× at N=4
|
|
26
|
+
* POC B DO Pool + 1 Loader/DO N peer DOs × 1 loader each 7.75× at N=8, flat to N=32
|
|
27
|
+
*
|
|
28
|
+
* `NimbusFanoutPool` exposes ONE `submitMany` API that routes
|
|
29
|
+
* automatically:
|
|
30
|
+
* width < IN_DO_THRESHOLD → POC C (uses existing NimbusLoaderPool)
|
|
31
|
+
* width >= IN_DO_THRESHOLD → POC B (peer NimbusSession DOs)
|
|
32
|
+
*
|
|
33
|
+
* IN_DO_THRESHOLD is 5 — exactly above the V8 cap so we never use the
|
|
34
|
+
* in-DO path beyond the safe ceiling, and the peer-DO path takes over
|
|
35
|
+
* cleanly for the wider workloads.
|
|
36
|
+
*
|
|
37
|
+
* Stable-id router
|
|
38
|
+
* ────────────────
|
|
39
|
+
* Each task carries a `key` (string). The router maps
|
|
40
|
+
* `key → siblingId = peerNamespace(coordDoIdShort, hash(key) mod N)`.
|
|
41
|
+
* Same key → same peer DO across runs. Tests can predict which peer
|
|
42
|
+
* handles which task, and warm peer isolates are reusable across
|
|
43
|
+
* back-to-back fan-outs that share keys.
|
|
44
|
+
*
|
|
45
|
+
* Hard-fail policy
|
|
46
|
+
* ────────────────
|
|
47
|
+
* Anti-requirement: NO fallback. If `env.LOADER` is missing, throw
|
|
48
|
+
* (existing NimbusLoaderPool already does). If
|
|
49
|
+
* `env.NIMBUS_SESSION` is missing AND a peer-DO route is needed,
|
|
50
|
+
* throw. Callers MUST get a deterministic error rather than silently
|
|
51
|
+
* collapsing back to width-1. The supervisor error handler logs and
|
|
52
|
+
* the install fails loudly — same posture every other facet binding
|
|
53
|
+
* has.
|
|
54
|
+
*
|
|
55
|
+
* Backpressure
|
|
56
|
+
* ────────────
|
|
57
|
+
* Hard cap: `MAX_PEER_FANOUT = 32` (POC B's flat zone). If
|
|
58
|
+
* `tasks.length > 32`, the surplus is queued and dispatched in
|
|
59
|
+
* subsequent rounds after the first 32 settle. This keeps the
|
|
60
|
+
* per-request peer-DO count bounded.
|
|
61
|
+
*/
|
|
62
|
+
import { serializeFunction } from './vendor/serialize.js';
|
|
63
|
+
import { BindingError } from './vendor/errors.js';
|
|
64
|
+
import { NimbusLoaderPool } from './loader-pool.js';
|
|
65
|
+
/**
|
|
66
|
+
* Threshold at which we switch from in-DO POC C → peer-DO POC B.
|
|
67
|
+
*
|
|
68
|
+
* Set to **5** so the in-DO path stays below the V8 4-loaders-per-method
|
|
69
|
+
* cap by construction. width < 5 → POC C; width >= 5 → POC B.
|
|
70
|
+
*/
|
|
71
|
+
export const IN_DO_THRESHOLD = 5;
|
|
72
|
+
/**
|
|
73
|
+
* Hard cap on concurrent peer DOs per single submitMany call. POC B
|
|
74
|
+
* measured flat throughput from N=8 to N=32; we use the ceiling so
|
|
75
|
+
* pathological 500-pkg installs still parallelise as wide as the
|
|
76
|
+
* topology supports.
|
|
77
|
+
*/
|
|
78
|
+
export const MAX_PEER_FANOUT = 32;
|
|
79
|
+
/**
|
|
80
|
+
* Two-tier fan-out pool. Constructed by the supervisor DO; routes
|
|
81
|
+
* each `submitMany` call automatically based on width.
|
|
82
|
+
*
|
|
83
|
+
* Lifetime: cheap to construct (no async init). Multiple submitMany
|
|
84
|
+
* calls share NO state — each is dispatched fresh. The class
|
|
85
|
+
* exists primarily as a clean API surface; per-call dispatch state
|
|
86
|
+
* lives only inside submitMany's promise.
|
|
87
|
+
*/
|
|
88
|
+
export class NimbusFanoutPool {
|
|
89
|
+
env;
|
|
90
|
+
ctx;
|
|
91
|
+
opts;
|
|
92
|
+
coordDoId;
|
|
93
|
+
coordDoIdShort;
|
|
94
|
+
constructor(env, ctx, opts) {
|
|
95
|
+
// Hard-fail on missing LOADER. NimbusLoaderPool also enforces this,
|
|
96
|
+
// but we check up front so the diagnostic points at the fanout-pool
|
|
97
|
+
// construction site rather than the deferred loader-pool one.
|
|
98
|
+
if (!env?.LOADER || typeof env.LOADER.get !== 'function') {
|
|
99
|
+
throw new BindingError('NimbusFanoutPool: env.LOADER binding missing or invalid. ' +
|
|
100
|
+
'Add a [[worker_loaders]] entry to wrangler.jsonc.');
|
|
101
|
+
}
|
|
102
|
+
this.env = env;
|
|
103
|
+
this.ctx = ctx;
|
|
104
|
+
this.opts = opts;
|
|
105
|
+
this.coordDoId = ctx.id.toString();
|
|
106
|
+
this.coordDoIdShort = this.coordDoId.slice(0, 12);
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Dispatch `tasks` across the appropriate topology and return
|
|
110
|
+
* results in input order.
|
|
111
|
+
*
|
|
112
|
+
* Routing:
|
|
113
|
+
* tasks.length < 5 → POC C in-DO via NimbusLoaderPool (concurrency = tasks.length, capped at 4)
|
|
114
|
+
* tasks.length >= 5 → POC B peer-DO via env.NIMBUS_SESSION sibling DOs (deterministic stable-id router)
|
|
115
|
+
*
|
|
116
|
+
* Backpressure: if `tasks.length > MAX_PEER_FANOUT (32)`, tasks
|
|
117
|
+
* are sharded modulo `MAX_PEER_FANOUT` and each shard's bucket
|
|
118
|
+
* runs serially inside its assigned peer DO via the in-peer
|
|
119
|
+
* NimbusLoaderPool's concurrency (capped at 4 there too). A
|
|
120
|
+
* single submitMany call returns when ALL tasks complete (or any
|
|
121
|
+
* throws).
|
|
122
|
+
*
|
|
123
|
+
* `fn` is the user function executed per task. It runs INSIDE a
|
|
124
|
+
* Worker Loader isolate (in the in-DO path) or inside a peer DO's
|
|
125
|
+
* Worker Loader isolate (in the peer-DO path); same trust posture
|
|
126
|
+
* as NimbusLoaderPool.submit. The function is serialized via
|
|
127
|
+
* the vendored serializeFunction (same as NimbusLoaderPool#prepare).
|
|
128
|
+
*/
|
|
129
|
+
async submitMany(tasks, fn) {
|
|
130
|
+
if (tasks.length === 0)
|
|
131
|
+
return [];
|
|
132
|
+
if (tasks.length < IN_DO_THRESHOLD) {
|
|
133
|
+
return this._dispatchInDo(tasks, fn);
|
|
134
|
+
}
|
|
135
|
+
return this._dispatchPeerDo(tasks, fn);
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Diagnostic: report which topology a given task count would use.
|
|
139
|
+
* Used by tests to assert routing without exercising the full
|
|
140
|
+
* dispatch path.
|
|
141
|
+
*/
|
|
142
|
+
topologyFor(taskCount) {
|
|
143
|
+
if (taskCount === 0)
|
|
144
|
+
return 'empty';
|
|
145
|
+
return taskCount < IN_DO_THRESHOLD ? 'in-do' : 'peer-do';
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Compute the deterministic peer-DO id for a given task key, given
|
|
149
|
+
* the peer count. Exposed so tests can assert routing predictions
|
|
150
|
+
* BEFORE running the dispatch.
|
|
151
|
+
*
|
|
152
|
+
* Shape: `nbf:${tag}:${coordDoIdShort}:${shard}` where
|
|
153
|
+
* `shard = hash(key) mod peerCount`. The hash is hashSource()
|
|
154
|
+
* (FNV-1a over a single-string input — adequate for routing; not
|
|
155
|
+
* cryptographic). Peer count is `min(tasks.length, MAX_PEER_FANOUT)`.
|
|
156
|
+
*/
|
|
157
|
+
peerSiblingId(key, peerCount) {
|
|
158
|
+
const shard = hashKeyToShard(key, peerCount);
|
|
159
|
+
return `nbf:${this.opts.tag}:${this.coordDoIdShort}:${shard}`;
|
|
160
|
+
}
|
|
161
|
+
// ── Private: in-DO dispatch (POC C) ──────────────────────────────
|
|
162
|
+
async _dispatchInDo(tasks, fn) {
|
|
163
|
+
// Use the existing NimbusLoaderPool. Concurrency = task count
|
|
164
|
+
// (capped at 4 by constructor — tasks.length is already < 5
|
|
165
|
+
// here, so the cap won't bite). Each task = one pool.submit;
|
|
166
|
+
// pool.map runs them with stable-slot reuse.
|
|
167
|
+
const concurrency = Math.min(tasks.length, IN_DO_THRESHOLD - 1);
|
|
168
|
+
const pool = new NimbusLoaderPool(this.env, this.ctx, {
|
|
169
|
+
concurrency,
|
|
170
|
+
timeoutMs: this.opts.timeoutMs,
|
|
171
|
+
tag: this.opts.tag,
|
|
172
|
+
preamble: this.opts.preamble,
|
|
173
|
+
wasmModules: this.opts.wasmModules,
|
|
174
|
+
extraBindings: this.opts.extraBindings,
|
|
175
|
+
omitSupervisor: this.opts.omitSupervisor,
|
|
176
|
+
});
|
|
177
|
+
try {
|
|
178
|
+
// pool.map runs the function over `items` with concurrency-bounded
|
|
179
|
+
// slot reuse. Each slot is one warm loader isolate; we get exactly
|
|
180
|
+
// `concurrency` loader isolates total — well under the 4-cap.
|
|
181
|
+
const items = tasks.map((t) => t.args);
|
|
182
|
+
const results = await pool.map(fn, items);
|
|
183
|
+
// pool.map returns Array<R | null> (null on per-item failure with
|
|
184
|
+
// onError='null'/'skip'). Default onError='throw' rejects on
|
|
185
|
+
// first failure, so successful settle here implies all R values.
|
|
186
|
+
return results;
|
|
187
|
+
}
|
|
188
|
+
finally {
|
|
189
|
+
try {
|
|
190
|
+
pool.dispose();
|
|
191
|
+
}
|
|
192
|
+
catch { /* best-effort */ }
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
// ── Private: peer-DO dispatch (POC B) ────────────────────────────
|
|
196
|
+
async _dispatchPeerDo(tasks, fn) {
|
|
197
|
+
const ns = this.env?.NIMBUS_SESSION;
|
|
198
|
+
if (!ns || typeof ns.idFromName !== 'function' || typeof ns.get !== 'function') {
|
|
199
|
+
throw new BindingError('NimbusFanoutPool: env.NIMBUS_SESSION binding missing or invalid. ' +
|
|
200
|
+
'The peer-DO topology requires it. ' +
|
|
201
|
+
'Add the binding via durable_objects.bindings in wrangler.jsonc.');
|
|
202
|
+
}
|
|
203
|
+
// Serialize the user function ONCE here on the supervisor side.
|
|
204
|
+
// Each peer DO receives the same fnSource string; warm peer
|
|
205
|
+
// loader isolates (keyed on fnHash) reuse across calls with
|
|
206
|
+
// identical fns.
|
|
207
|
+
const fnSource = serializeFunction(fn);
|
|
208
|
+
// Cap peer count at MAX_PEER_FANOUT. Tasks beyond N=32 are
|
|
209
|
+
// bucketed into existing shards — each shard's peer DO then
|
|
210
|
+
// runs its bucket through its in-DO NimbusLoaderPool.map
|
|
211
|
+
// (concurrency capped at 4 there).
|
|
212
|
+
const peerCount = Math.min(tasks.length, MAX_PEER_FANOUT);
|
|
213
|
+
// Group tasks by deterministic shard. Same key → same shard, so
|
|
214
|
+
// tests can predict which peer handles which task.
|
|
215
|
+
const shards = new Map();
|
|
216
|
+
for (const t of tasks) {
|
|
217
|
+
const shard = hashKeyToShard(t.key, peerCount);
|
|
218
|
+
let bucket = shards.get(shard);
|
|
219
|
+
if (!bucket) {
|
|
220
|
+
bucket = [];
|
|
221
|
+
shards.set(shard, bucket);
|
|
222
|
+
}
|
|
223
|
+
bucket.push(t);
|
|
224
|
+
}
|
|
225
|
+
// Dispatch each shard to its peer DO. Build a map from
|
|
226
|
+
// task → its place in the original tasks array so we can
|
|
227
|
+
// reassemble results in input order.
|
|
228
|
+
const taskIndex = new Map();
|
|
229
|
+
tasks.forEach((t, i) => taskIndex.set(t, i));
|
|
230
|
+
const results = new Array(tasks.length);
|
|
231
|
+
// Build one async dispatcher per shard (closure capturing siblingName,
|
|
232
|
+
// bucket). NOT eagerly-started — wrapped in a thunk so we can stagger
|
|
233
|
+
// dispatch via Promise chains without forcing all shards to start
|
|
234
|
+
// simultaneously.
|
|
235
|
+
const dispatchers = [];
|
|
236
|
+
for (const [shard, bucket] of shards) {
|
|
237
|
+
const siblingName = `nbf:${this.opts.tag}:${this.coordDoIdShort}:${shard}`;
|
|
238
|
+
const id = ns.idFromName(siblingName);
|
|
239
|
+
const stub = ns.get(id);
|
|
240
|
+
dispatchers.push(async () => {
|
|
241
|
+
// Each peer DO RPC call uses ONE LOADER worker on its side.
|
|
242
|
+
// Supervisor → peer DO is a stub.fetch / RPC method call,
|
|
243
|
+
// NOT an env.LOADER.get(); that's the cap-sidestep that
|
|
244
|
+
// makes POC B work.
|
|
245
|
+
const peerArgs = bucket.map((t) => t.args);
|
|
246
|
+
const rpcResp = await stub._rpcFanoutExecute(fnSource, peerArgs, {
|
|
247
|
+
tag: this.opts.tag,
|
|
248
|
+
timeoutMs: this.opts.timeoutMs,
|
|
249
|
+
preamble: this.opts.preamble,
|
|
250
|
+
wasmModules: this.opts.wasmModules,
|
|
251
|
+
extraBindings: this.opts.extraBindings,
|
|
252
|
+
omitSupervisor: this.opts.omitSupervisor,
|
|
253
|
+
// INSTALL-HONESTY: forward the COORDINATOR's full doId so
|
|
254
|
+
// the peer's NimbusLoaderPool can mint a SUPERVISOR
|
|
255
|
+
// binding that routes back HERE (the user's session DO),
|
|
256
|
+
// not to the peer DO itself. Without this, peer DOs'
|
|
257
|
+
// env.SUPERVISOR.writeBatch / writeBatchStream / stdout /
|
|
258
|
+
// ... write into the peer's own VFS — invisible to the
|
|
259
|
+
// user. See INSTALL-HONESTY-retro.md.
|
|
260
|
+
coordinatorDoId: this.coordDoId,
|
|
261
|
+
});
|
|
262
|
+
const peerResults = (rpcResp?.results ?? []);
|
|
263
|
+
if (peerResults.length !== bucket.length) {
|
|
264
|
+
throw new Error(`peer DO returned ${peerResults.length} results for ${bucket.length} tasks ` +
|
|
265
|
+
`(siblingName=${siblingName})`);
|
|
266
|
+
}
|
|
267
|
+
// Place each result back into its original input slot.
|
|
268
|
+
for (let i = 0; i < bucket.length; i++) {
|
|
269
|
+
const origIdx = taskIndex.get(bucket[i]);
|
|
270
|
+
results[origIdx] = peerResults[i];
|
|
271
|
+
}
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
// [P0a wave-4d STAGGERED FAN-OUT]
|
|
275
|
+
// Dispatching all N shards via a single Promise.all triggered N
|
|
276
|
+
// simultaneous peer-DO cold-starts. Under concurrent-session load
|
|
277
|
+
// (N sessions × M shards each), the workerd DO scheduler queue
|
|
278
|
+
// overflows → workerd cancels some shards with "Durable Object
|
|
279
|
+
// is overloaded" → batch-fanout aborts. Verified prod 15d3bfda:
|
|
280
|
+
// 17-33% session failure rate at N=12 concurrent.
|
|
281
|
+
//
|
|
282
|
+
// Wave-4d fix: chunk dispatch into PHASES. Each phase fires
|
|
283
|
+
// FANOUT_PHASE_SIZE shards via Promise.all and AWAITS phase
|
|
284
|
+
// completion before the next phase starts. Reduces simultaneous
|
|
285
|
+
// peer-DO cold-starts from N to FANOUT_PHASE_SIZE per session.
|
|
286
|
+
//
|
|
287
|
+
// FANOUT_PHASE_SIZE = 4: empirically the breakpoint where workerd
|
|
288
|
+
// schedules without queue overflow at N=12 concurrent (4 × 12 = 48
|
|
289
|
+
// simultaneous DO cold-starts, vs 8 × 12 = 96 for single-phase).
|
|
290
|
+
//
|
|
291
|
+
// NOT a sleep/setTimeout — pure Promise-chain serialization. Phase 2
|
|
292
|
+
// dispatchers START immediately when Phase 1 completes; no idle gap.
|
|
293
|
+
const FANOUT_PHASE_SIZE = 4;
|
|
294
|
+
for (let i = 0; i < dispatchers.length; i += FANOUT_PHASE_SIZE) {
|
|
295
|
+
const phase = dispatchers.slice(i, i + FANOUT_PHASE_SIZE);
|
|
296
|
+
await Promise.all(phase.map((d) => d()));
|
|
297
|
+
}
|
|
298
|
+
return results;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Stable hash → shard. Uses a fresh djb2 over the key (NOT
|
|
303
|
+
* hashSource) and modulos by peerCount.
|
|
304
|
+
*
|
|
305
|
+
* Why not reuse hashSource: hashSource returns a base-36 string,
|
|
306
|
+
* NOT hex — its alphabet is `[0-9a-z]`. parseInt(str, 16) on a
|
|
307
|
+
* base-36 string aborts at the first non-hex char (any of g-z),
|
|
308
|
+
* which produces extremely poor distribution: keys with the same
|
|
309
|
+
* leading-hex-prefix collide regardless of their suffix. (Seen in
|
|
310
|
+
* the wild: `task-0 .. task-7` all collided onto shard 4.)
|
|
311
|
+
*
|
|
312
|
+
* Deterministic: same key + same peerCount → same shard, every run.
|
|
313
|
+
* Tests use this to predict placement.
|
|
314
|
+
*/
|
|
315
|
+
export function hashKeyToShard(key, peerCount) {
|
|
316
|
+
if (peerCount <= 1)
|
|
317
|
+
return 0;
|
|
318
|
+
// djb2, returning an unsigned 32-bit integer — full 2^32 range,
|
|
319
|
+
// no string-format conversion gotchas. peerCount <= MAX_PEER_FANOUT
|
|
320
|
+
// (32) << 2^32, so the modulo distributes uniformly for any input.
|
|
321
|
+
let h = 5381;
|
|
322
|
+
for (let i = 0; i < key.length; i++) {
|
|
323
|
+
h = ((h << 5) + h + key.charCodeAt(i)) | 0;
|
|
324
|
+
}
|
|
325
|
+
return (h >>> 0) % peerCount;
|
|
326
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* generated-workers.ts — AUTO-GENERATED. DO NOT EDIT.
|
|
3
|
+
*
|
|
4
|
+
* Produced by scripts/bundle-facet-workers.mjs from:
|
|
5
|
+
* - src/npm/tarball-stream.ts (streaming tar primitives)
|
|
6
|
+
* - src/_shared/w7-frame.ts (W7 streaming bulk-write encoder)
|
|
7
|
+
*
|
|
8
|
+
* Consumed by src/loaders/loader-pool.ts callers via the `preamble`
|
|
9
|
+
* option. The preamble is injected at the top of every generated
|
|
10
|
+
* worker module so user functions can reference the exported
|
|
11
|
+
* helpers by name.
|
|
12
|
+
*
|
|
13
|
+
* Tar-stream symbols: parseTarHeader, streamTarEntries,
|
|
14
|
+
* readableStreamToAsyncIterable, MAX_FILE_BYTES.
|
|
15
|
+
* W7-frame symbols: encodeWriteBatchStream, decodeWriteBatchStream,
|
|
16
|
+
* W7_MAGIC, W7_TRAILER.
|
|
17
|
+
*
|
|
18
|
+
* Generated at: 2026-06-02T20:52:06.510Z
|
|
19
|
+
* Tar size: 3.84 KiB
|
|
20
|
+
* W7 size: 7.77 KiB
|
|
21
|
+
*/
|
|
22
|
+
export declare const TAR_STREAM_PREAMBLE: string;
|
|
23
|
+
export declare const TAR_STREAM_PREAMBLE_SIZE: number;
|
|
24
|
+
export declare const W7_FRAME_PREAMBLE: string;
|
|
25
|
+
export declare const W7_FRAME_PREAMBLE_SIZE: number;
|
|
26
|
+
//# sourceMappingURL=generated-workers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generated-workers.d.ts","sourceRoot":"","sources":["../../src/loaders/generated-workers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,eAAO,MAAM,mBAAmB,EAAE,MAAygI,CAAC;AAE5iI,eAAO,MAAM,wBAAwB,EAAE,MAAa,CAAC;AAErD,eAAO,MAAM,iBAAiB,EAAE,MAA+iQ,CAAC;AAEhlQ,eAAO,MAAM,sBAAsB,EAAE,MAAa,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* generated-workers.ts — AUTO-GENERATED. DO NOT EDIT.
|
|
3
|
+
*
|
|
4
|
+
* Produced by scripts/bundle-facet-workers.mjs from:
|
|
5
|
+
* - src/npm/tarball-stream.ts (streaming tar primitives)
|
|
6
|
+
* - src/_shared/w7-frame.ts (W7 streaming bulk-write encoder)
|
|
7
|
+
*
|
|
8
|
+
* Consumed by src/loaders/loader-pool.ts callers via the `preamble`
|
|
9
|
+
* option. The preamble is injected at the top of every generated
|
|
10
|
+
* worker module so user functions can reference the exported
|
|
11
|
+
* helpers by name.
|
|
12
|
+
*
|
|
13
|
+
* Tar-stream symbols: parseTarHeader, streamTarEntries,
|
|
14
|
+
* readableStreamToAsyncIterable, MAX_FILE_BYTES.
|
|
15
|
+
* W7-frame symbols: encodeWriteBatchStream, decodeWriteBatchStream,
|
|
16
|
+
* W7_MAGIC, W7_TRAILER.
|
|
17
|
+
*
|
|
18
|
+
* Generated at: 2026-06-02T20:52:06.510Z
|
|
19
|
+
* Tar size: 3.84 KiB
|
|
20
|
+
* W7 size: 7.77 KiB
|
|
21
|
+
*/
|
|
22
|
+
export const TAR_STREAM_PREAMBLE = "// src/npm/tarball-stream.ts\nvar MAX_FILE_BYTES = 2e7;\nfunction parseTarHeader(block) {\n if (block[0] === 0) return null;\n let name = \"\";\n for (let i = 0; i < 100 && block[i] !== 0; i++) {\n name += String.fromCharCode(block[i]);\n }\n let prefix = \"\";\n for (let i = 345; i < 500 && block[i] !== 0; i++) {\n prefix += String.fromCharCode(block[i]);\n }\n if (prefix) name = prefix + \"/\" + name;\n name = name.replace(/^package\\//, \"\");\n let sizeStr = \"\";\n for (let i = 124; i < 136 && block[i] !== 0; i++) {\n sizeStr += String.fromCharCode(block[i]);\n }\n const size = parseInt(sizeStr.trim(), 8) || 0;\n const typeFlag = block[156];\n return { name, size, typeFlag };\n}\nasync function* readableStreamToAsyncIterable(rs) {\n const reader = rs.getReader();\n try {\n while (true) {\n const { value, done } = await reader.read();\n if (done) return;\n if (value && value.length > 0) yield value;\n }\n } finally {\n try {\n reader.releaseLock();\n } catch {\n }\n }\n}\nasync function* streamTarEntries(source, onSkip) {\n let carry = new Uint8Array(0);\n let state = { kind: \"header\" };\n function concat(a, b) {\n if (a.length === 0) return b;\n if (b.length === 0) return a;\n const out = new Uint8Array(a.length + b.length);\n out.set(a, 0);\n out.set(b, a.length);\n return out;\n }\n for await (const chunkRaw of source) {\n let buf = concat(carry, chunkRaw);\n let cursor = 0;\n while (true) {\n if (state.kind === \"header\") {\n if (buf.length - cursor < 512) break;\n const header = buf.subarray(cursor, cursor + 512);\n const parsed = parseTarHeader(header);\n cursor += 512;\n if (!parsed) return;\n const { name, size, typeFlag } = parsed;\n const pad = size === 0 ? 0 : (512 - size % 512) % 512;\n const isRegularFile = typeFlag === 48 || typeFlag === 0;\n if (size === 0) {\n if (isRegularFile && name) {\n yield { name, data: new Uint8Array(0) };\n }\n state = { kind: \"header\" };\n continue;\n }\n if (!isRegularFile || !name || size > MAX_FILE_BYTES) {\n if (onSkip) {\n const reason = !isRegularFile ? \"non-regular\" : !name ? \"no-name\" : \"too-large\";\n try {\n onSkip(name, size, reason);\n } catch {\n }\n }\n state = { kind: \"skip\", remaining: size + pad };\n continue;\n }\n state = {\n kind: \"file\",\n name,\n remaining: size,\n fileBuf: new Uint8Array(size),\n fileOffset: 0,\n pad,\n skip: false\n };\n continue;\n }\n if (state.kind === \"file\") {\n const avail2 = buf.length - cursor;\n if (avail2 === 0) break;\n if (state.remaining > 0) {\n const take2 = Math.min(state.remaining, avail2);\n state.fileBuf.set(buf.subarray(cursor, cursor + take2), state.fileOffset);\n state.fileOffset += take2;\n state.remaining -= take2;\n cursor += take2;\n if (state.remaining > 0) break;\n }\n if (state.pad > 0) {\n const avail22 = buf.length - cursor;\n if (avail22 === 0) break;\n const take2 = Math.min(state.pad, avail22);\n state.pad -= take2;\n cursor += take2;\n if (state.pad > 0) break;\n }\n yield { name: state.name, data: state.fileBuf };\n state = { kind: \"header\" };\n continue;\n }\n const avail = buf.length - cursor;\n if (avail === 0) break;\n const take = Math.min(state.remaining, avail);\n cursor += take;\n state.remaining -= take;\n if (state.remaining > 0) break;\n state = { kind: \"header\" };\n }\n if (cursor >= buf.length) {\n carry = new Uint8Array(0);\n } else if (cursor === 0) {\n carry = buf;\n } else {\n carry = buf.slice(cursor);\n }\n }\n}";
|
|
23
|
+
export const TAR_STREAM_PREAMBLE_SIZE = 3932;
|
|
24
|
+
export const W7_FRAME_PREAMBLE = "// src/_shared/w7-frame.ts\nvar W7_MAGIC = new Uint8Array([78, 87, 55, 1]);\nvar W7_TRAILER = new Uint8Array([78, 69, 78, 68]);\nvar ENCODER_QUEUE_HWM = 256 * 1024;\nvar ENCODER_EMIT_CAP = 64 * 1024;\nvar _peakInFlight = 0;\nvar _currentInFlight = 0;\nfunction _peakInFlightBytes() {\n return _peakInFlight;\n}\nfunction _resetPeakInFlightBytes() {\n _peakInFlight = 0;\n _currentInFlight = 0;\n}\nfunction _trackInFlightAdd(n) {\n _currentInFlight += n;\n if (_currentInFlight > _peakInFlight) _peakInFlight = _currentInFlight;\n}\nfunction _trackInFlightSub(n) {\n _currentInFlight -= n;\n if (_currentInFlight < 0) _currentInFlight = 0;\n}\nfunction encodeWriteBatchStream(payload) {\n const inodes = payload.inodes ?? [];\n const chunks = payload.chunks ?? [];\n const deletePaths = payload.deletePaths;\n let phase = 0;\n let chunkIdx = 0;\n const enc = new TextEncoder();\n const headerBytes = enc.encode(JSON.stringify({\n inodes,\n deletePaths,\n chunkCount: chunks.length\n }));\n const source = {\n type: \"bytes\",\n pull(controller) {\n try {\n if (phase === 0) {\n enqueue(controller, W7_MAGIC.slice());\n phase = 1;\n return;\n }\n if (phase === 1) {\n const hdr = new Uint8Array(4 + headerBytes.length);\n writeU32LE(hdr, 0, headerBytes.length);\n hdr.set(headerBytes, 4);\n enqueue(controller, hdr);\n phase = 2;\n return;\n }\n if (phase === 2) {\n if (chunkIdx >= chunks.length) {\n phase = 3;\n } else {\n const c = chunks[chunkIdx++];\n const pathBytes = enc.encode(c.path);\n const data = c.data instanceof Uint8Array ? c.data : new Uint8Array(c.data);\n const headerSize = 4 + pathBytes.length + 4 + 4;\n const headerOut = new Uint8Array(headerSize);\n let o = 0;\n writeU32LE(headerOut, o, pathBytes.length);\n o += 4;\n headerOut.set(pathBytes, o);\n o += pathBytes.length;\n writeU32LE(headerOut, o, c.chunkId);\n o += 4;\n writeU32LE(headerOut, o, data.length);\n o += 4;\n enqueue(controller, headerOut);\n if (data.length === 0) return;\n if (data.length <= ENCODER_EMIT_CAP) {\n enqueue(controller, data);\n } else {\n for (let i = 0; i < data.length; i += ENCODER_EMIT_CAP) {\n enqueue(controller, data.subarray(i, Math.min(i + ENCODER_EMIT_CAP, data.length)));\n }\n }\n return;\n }\n }\n if (phase === 3) {\n enqueue(controller, W7_TRAILER.slice());\n phase = 4;\n controller.close();\n return;\n }\n controller.close();\n } catch (e) {\n controller.error(e);\n }\n },\n cancel() {\n phase = 4;\n chunkIdx = chunks.length;\n }\n };\n return new ReadableStream(source, {\n // Byte streams (`type: 'bytes'`) MUST use the default byte-counted\n // strategy: highWaterMark is in bytes, size is implicit. Custom\n // `size` callbacks are forbidden — they throw at construction.\n highWaterMark: ENCODER_QUEUE_HWM\n });\n function enqueue(controller, bytes) {\n _trackInFlightAdd(bytes.byteLength);\n controller.enqueue(bytes);\n queueMicrotask(() => _trackInFlightSub(bytes.byteLength));\n }\n}\nasync function decodeWriteBatchStream(stream) {\n const reader = stream.getReader();\n const buf = new ByteBuffer(reader);\n const magic = await buf.readExact(4, \"magic\");\n if (!bytesEqual(magic, W7_MAGIC)) {\n try {\n reader.releaseLock();\n } catch {\n }\n throw new Error(`w7-frame: bad magic, expected NW7\\\\x01, got ${Array.from(magic).map((b) => b.toString(16)).join(\" \")}`);\n }\n const hdrLenBytes = await buf.readExact(4, \"header-length\");\n const hdrLen = readU32LE(hdrLenBytes, 0);\n if (hdrLen < 0 || hdrLen > 64 * 1024 * 1024) {\n throw new Error(`w7-frame: implausible header length ${hdrLen}`);\n }\n const hdrJson = await buf.readExact(hdrLen, \"header-json\");\n let header;\n try {\n header = JSON.parse(new TextDecoder().decode(hdrJson));\n } catch (e) {\n throw new Error(`w7-frame: header JSON parse failed: ${e?.message || e}`);\n }\n if (!header || !Array.isArray(header.inodes) || typeof header.chunkCount !== \"number\") {\n throw new Error(\"w7-frame: header missing required fields (inodes / chunkCount)\");\n }\n const chunkIter = {\n [Symbol.asyncIterator]() {\n let idx = 0;\n let exhausted = false;\n return {\n async next() {\n if (exhausted) return { value: void 0, done: true };\n if (idx >= header.chunkCount) {\n const trailer = await buf.readExact(4, \"trailer\");\n if (!bytesEqual(trailer, W7_TRAILER)) {\n throw new Error(\n `w7-frame: bad trailer, expected NEND, got ${Array.from(trailer).map((b) => String.fromCharCode(b)).join(\"\")}`\n );\n }\n try {\n reader.releaseLock();\n } catch {\n }\n exhausted = true;\n return { value: void 0, done: true };\n }\n const pathLenBytes = await buf.readExact(4, \"chunk-path-length\");\n const pathLen = readU32LE(pathLenBytes, 0);\n if (pathLen < 0 || pathLen > 64 * 1024) {\n throw new Error(`w7-frame: implausible path length ${pathLen} at chunk ${idx}`);\n }\n const pathBytes = await buf.readExact(pathLen, \"chunk-path\");\n const path = new TextDecoder().decode(pathBytes);\n const chunkIdBytes = await buf.readExact(4, \"chunk-id\");\n const chunkId = readU32LE(chunkIdBytes, 0);\n const dataLenBytes = await buf.readExact(4, \"chunk-data-length\");\n const dataLen = readU32LE(dataLenBytes, 0);\n if (dataLen < 0 || dataLen > 64 * 1024 * 1024) {\n throw new Error(`w7-frame: implausible data length ${dataLen} at chunk ${idx}`);\n }\n const data = await buf.readExact(dataLen, \"chunk-data\");\n idx++;\n return { value: { path, chunkId, data }, done: false };\n },\n async return() {\n exhausted = true;\n try {\n reader.releaseLock();\n } catch {\n }\n return { value: void 0, done: true };\n }\n };\n }\n };\n return {\n inodes: header.inodes,\n deletePaths: header.deletePaths,\n chunkIter\n };\n}\nfunction writeU32LE(out, off, n) {\n out[off] = n & 255;\n out[off + 1] = n >>> 8 & 255;\n out[off + 2] = n >>> 16 & 255;\n out[off + 3] = n >>> 24 & 255;\n}\nfunction readU32LE(buf, off) {\n return (buf[off] | buf[off + 1] << 8 | buf[off + 2] << 16 | buf[off + 3] << 24) >>> 0;\n}\nfunction bytesEqual(a, b) {\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i++) if (a[i] !== b[i]) return false;\n return true;\n}\nvar ByteBuffer = class {\n constructor(reader) {\n this.reader = reader;\n }\n chunks = [];\n avail = 0;\n done = false;\n async readExact(n, label) {\n if (n === 0) return new Uint8Array(0);\n while (this.avail < n) {\n if (this.done) {\n throw new Error(\n `w7-frame: stream ended ${this.avail} bytes into expected ${n}-byte ${label}`\n );\n }\n const { value, done } = await this.reader.read();\n if (done) {\n this.done = true;\n } else if (value && value.length > 0) {\n this.chunks.push(value);\n this.avail += value.length;\n }\n }\n const out = new Uint8Array(n);\n let copied = 0;\n while (copied < n) {\n const head = this.chunks[0];\n const take = Math.min(head.length, n - copied);\n out.set(head.subarray(0, take), copied);\n copied += take;\n if (take === head.length) {\n this.chunks.shift();\n } else {\n this.chunks[0] = head.subarray(take);\n }\n }\n this.avail -= n;\n return out;\n }\n};";
|
|
25
|
+
export const W7_FRAME_PREAMBLE_SIZE = 7954;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parallel dispatch utilities for Nimbus.
|
|
3
|
+
*
|
|
4
|
+
* Only the Nimbus-scoped pool is re-exported. The vendored
|
|
5
|
+
* cloudflare-parallel surface is intentionally NOT exposed here — callers
|
|
6
|
+
* must use the wrapper so they inherit stable-slot isolate reuse, Nimbus
|
|
7
|
+
* compat flags, and SupervisorRPC autoinjection.
|
|
8
|
+
*
|
|
9
|
+
* See src/loaders/loader-pool.ts for the pool implementation and
|
|
10
|
+
* src/loaders/vendor/ for the upstream cloudflare-parallel library.
|
|
11
|
+
*/
|
|
12
|
+
export { NimbusLoaderPool } from './loader-pool.js';
|
|
13
|
+
export type { NimbusLoaderPoolOptions, NimbusLoaderCallOptions, NimbusLoaderMapOptions, } from './loader-pool.js';
|
|
14
|
+
export { BindingError, ExecutionError, RetryExhaustedError, TimeoutError, } from './loader-pool.js';
|
|
15
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/loaders/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,YAAY,EACV,uBAAuB,EACvB,uBAAuB,EACvB,sBAAsB,GACvB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,YAAY,EACZ,cAAc,EACd,mBAAmB,EACnB,YAAY,GACb,MAAM,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parallel dispatch utilities for Nimbus.
|
|
3
|
+
*
|
|
4
|
+
* Only the Nimbus-scoped pool is re-exported. The vendored
|
|
5
|
+
* cloudflare-parallel surface is intentionally NOT exposed here — callers
|
|
6
|
+
* must use the wrapper so they inherit stable-slot isolate reuse, Nimbus
|
|
7
|
+
* compat flags, and SupervisorRPC autoinjection.
|
|
8
|
+
*
|
|
9
|
+
* See src/loaders/loader-pool.ts for the pool implementation and
|
|
10
|
+
* src/loaders/vendor/ for the upstream cloudflare-parallel library.
|
|
11
|
+
*/
|
|
12
|
+
export { NimbusLoaderPool } from './loader-pool.js';
|
|
13
|
+
export { BindingError, ExecutionError, RetryExhaustedError, TimeoutError, } from './loader-pool.js';
|