@rocicorp/zero 1.10.0-canary.21 → 1.10.0-canary.23
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/out/analyze-query/src/bin-analyze.js +1 -1
- package/out/analyze-query/src/bin-analyze.js.map +1 -1
- package/out/replicache/src/dag/gc.d.ts.map +1 -1
- package/out/replicache/src/dag/gc.js +2 -1
- package/out/replicache/src/dag/gc.js.map +1 -1
- package/out/replicache/src/dag/invalid-ref-count-error.d.ts +12 -0
- package/out/replicache/src/dag/invalid-ref-count-error.d.ts.map +1 -0
- package/out/replicache/src/dag/invalid-ref-count-error.js +19 -0
- package/out/replicache/src/dag/invalid-ref-count-error.js.map +1 -0
- package/out/replicache/src/dag/store-impl.d.ts +12 -2
- package/out/replicache/src/dag/store-impl.d.ts.map +1 -1
- package/out/replicache/src/dag/store-impl.js +22 -8
- package/out/replicache/src/dag/store-impl.js.map +1 -1
- package/out/replicache/src/kv/expo-sqlite/store.d.ts.map +1 -1
- package/out/replicache/src/kv/expo-sqlite/store.js +1 -1
- package/out/replicache/src/kv/expo-sqlite/store.js.map +1 -1
- package/out/replicache/src/kv/idb-store-with-mem-fallback.d.ts +15 -5
- package/out/replicache/src/kv/idb-store-with-mem-fallback.d.ts.map +1 -1
- package/out/replicache/src/kv/idb-store-with-mem-fallback.js +25 -25
- package/out/replicache/src/kv/idb-store-with-mem-fallback.js.map +1 -1
- package/out/replicache/src/kv/idb-store.d.ts +9 -0
- package/out/replicache/src/kv/idb-store.d.ts.map +1 -1
- package/out/replicache/src/kv/idb-store.js +14 -2
- package/out/replicache/src/kv/idb-store.js.map +1 -1
- package/out/replicache/src/kv/mem-store.d.ts +1 -0
- package/out/replicache/src/kv/mem-store.d.ts.map +1 -1
- package/out/replicache/src/kv/mem-store.js +3 -0
- package/out/replicache/src/kv/mem-store.js.map +1 -1
- package/out/replicache/src/kv/op-sqlite/store.d.ts.map +1 -1
- package/out/replicache/src/kv/op-sqlite/store.js +1 -1
- package/out/replicache/src/kv/op-sqlite/store.js.map +1 -1
- package/out/replicache/src/kv/sqlite-store.d.ts +2 -1
- package/out/replicache/src/kv/sqlite-store.d.ts.map +1 -1
- package/out/replicache/src/kv/sqlite-store.js +6 -1
- package/out/replicache/src/kv/sqlite-store.js.map +1 -1
- package/out/replicache/src/kv/store.d.ts +6 -0
- package/out/replicache/src/kv/store.d.ts.map +1 -1
- package/out/replicache/src/persist/collect-idb-databases.d.ts +10 -5
- package/out/replicache/src/persist/collect-idb-databases.d.ts.map +1 -1
- package/out/replicache/src/persist/collect-idb-databases.js +16 -9
- package/out/replicache/src/persist/collect-idb-databases.js.map +1 -1
- package/out/replicache/src/replicache-impl.d.ts +14 -3
- package/out/replicache/src/replicache-impl.d.ts.map +1 -1
- package/out/replicache/src/replicache-impl.js +104 -9
- package/out/replicache/src/replicache-impl.js.map +1 -1
- package/out/shared/src/arrays.js +1 -15
- package/out/shared/src/arrays.js.map +1 -1
- package/out/shared/src/hash.d.ts +1 -0
- package/out/shared/src/hash.d.ts.map +1 -1
- package/out/shared/src/hash.js +10 -28
- package/out/shared/src/hash.js.map +1 -1
- package/out/shared/src/iterables.d.ts +2 -0
- package/out/shared/src/iterables.d.ts.map +1 -1
- package/out/shared/src/iterables.js +18 -1
- package/out/shared/src/iterables.js.map +1 -1
- package/out/shared/src/json.d.ts.map +1 -1
- package/out/shared/src/json.js +2 -2
- package/out/shared/src/json.js.map +1 -1
- package/out/shared/src/ring-buffer.d.ts +8 -0
- package/out/shared/src/ring-buffer.d.ts.map +1 -1
- package/out/shared/src/ring-buffer.js +22 -1
- package/out/shared/src/ring-buffer.js.map +1 -1
- package/out/shared/src/xxhash32.d.ts +36 -0
- package/out/shared/src/xxhash32.d.ts.map +1 -0
- package/out/shared/src/xxhash32.js +51 -0
- package/out/shared/src/xxhash32.js.map +1 -0
- package/out/z2s/src/compiler.js +1 -1
- package/out/zero/package.js +1 -1
- package/out/zero/package.js.map +1 -1
- package/out/zero-cache/src/auth/read-authorizer.js +1 -1
- package/out/zero-cache/src/config/zero-config.d.ts +8 -0
- package/out/zero-cache/src/config/zero-config.d.ts.map +1 -1
- package/out/zero-cache/src/config/zero-config.js +28 -1
- package/out/zero-cache/src/config/zero-config.js.map +1 -1
- package/out/zero-cache/src/custom-queries/transform-query.js +1 -1
- package/out/zero-cache/src/server/change-streamer.d.ts.map +1 -1
- package/out/zero-cache/src/server/change-streamer.js +11 -3
- package/out/zero-cache/src/server/change-streamer.js.map +1 -1
- package/out/zero-cache/src/server/inspector-delegate.d.ts +18 -2
- package/out/zero-cache/src/server/inspector-delegate.d.ts.map +1 -1
- package/out/zero-cache/src/server/inspector-delegate.js +23 -9
- package/out/zero-cache/src/server/inspector-delegate.js.map +1 -1
- package/out/zero-cache/src/server/main.d.ts.map +1 -1
- package/out/zero-cache/src/server/main.js +8 -1
- package/out/zero-cache/src/server/main.js.map +1 -1
- package/out/zero-cache/src/server/mutator.js +2 -0
- package/out/zero-cache/src/server/mutator.js.map +1 -1
- package/out/zero-cache/src/server/reaper.d.ts.map +1 -1
- package/out/zero-cache/src/server/reaper.js +2 -0
- package/out/zero-cache/src/server/reaper.js.map +1 -1
- package/out/zero-cache/src/server/replicator.d.ts.map +1 -1
- package/out/zero-cache/src/server/replicator.js +2 -0
- package/out/zero-cache/src/server/replicator.js.map +1 -1
- package/out/zero-cache/src/server/runner/zero-dispatcher.d.ts.map +1 -1
- package/out/zero-cache/src/server/runner/zero-dispatcher.js +3 -0
- package/out/zero-cache/src/server/runner/zero-dispatcher.js.map +1 -1
- package/out/zero-cache/src/server/syncer.d.ts.map +1 -1
- package/out/zero-cache/src/server/syncer.js +2 -0
- package/out/zero-cache/src/server/syncer.js.map +1 -1
- package/out/zero-cache/src/services/analyze.d.ts.map +1 -1
- package/out/zero-cache/src/services/analyze.js +3 -2
- package/out/zero-cache/src/services/analyze.js.map +1 -1
- package/out/zero-cache/src/services/change-source/common/backfill-manager.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/common/backfill-manager.js +14 -1
- package/out/zero-cache/src/services/change-source/common/backfill-manager.js.map +1 -1
- package/out/zero-cache/src/services/change-source/common/change-stream-multiplexer.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/common/change-stream-multiplexer.js +15 -3
- package/out/zero-cache/src/services/change-source/common/change-stream-multiplexer.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/initial-sync.js +1 -1
- package/out/zero-cache/src/services/change-streamer/change-streamer-http.d.ts +3 -0
- package/out/zero-cache/src/services/change-streamer/change-streamer-http.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/change-streamer-http.js +3 -1
- package/out/zero-cache/src/services/change-streamer/change-streamer-http.js.map +1 -1
- package/out/zero-cache/src/services/mutagen/mutagen.d.ts +5 -0
- package/out/zero-cache/src/services/mutagen/mutagen.d.ts.map +1 -1
- package/out/zero-cache/src/services/mutagen/mutagen.js +7 -1
- package/out/zero-cache/src/services/mutagen/mutagen.js.map +1 -1
- package/out/zero-cache/src/services/mutagen/pusher.js +3 -2
- package/out/zero-cache/src/services/mutagen/pusher.js.map +1 -1
- package/out/zero-cache/src/services/profz.d.ts +7 -0
- package/out/zero-cache/src/services/profz.d.ts.map +1 -0
- package/out/zero-cache/src/services/profz.js +103 -0
- package/out/zero-cache/src/services/profz.js.map +1 -0
- package/out/zero-cache/src/services/run-ast.d.ts +12 -0
- package/out/zero-cache/src/services/run-ast.d.ts.map +1 -1
- package/out/zero-cache/src/services/run-ast.js +27 -15
- package/out/zero-cache/src/services/run-ast.js.map +1 -1
- package/out/zero-cache/src/services/runner.d.ts.map +1 -1
- package/out/zero-cache/src/services/runner.js +1 -1
- package/out/zero-cache/src/services/runner.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/cvr.d.ts +45 -0
- package/out/zero-cache/src/services/view-syncer/cvr.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/cvr.js +133 -1
- package/out/zero-cache/src/services/view-syncer/cvr.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/drain-coordinator.d.ts +14 -1
- package/out/zero-cache/src/services/view-syncer/drain-coordinator.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/drain-coordinator.js +30 -4
- package/out/zero-cache/src/services/view-syncer/drain-coordinator.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/hydration-budget.d.ts +33 -0
- package/out/zero-cache/src/services/view-syncer/hydration-budget.d.ts.map +1 -0
- package/out/zero-cache/src/services/view-syncer/hydration-budget.js +62 -0
- package/out/zero-cache/src/services/view-syncer/hydration-budget.js.map +1 -0
- package/out/zero-cache/src/services/view-syncer/hydration-circuit-breaker.d.ts +51 -0
- package/out/zero-cache/src/services/view-syncer/hydration-circuit-breaker.d.ts.map +1 -0
- package/out/zero-cache/src/services/view-syncer/hydration-circuit-breaker.js +78 -0
- package/out/zero-cache/src/services/view-syncer/hydration-circuit-breaker.js.map +1 -0
- package/out/zero-cache/src/services/view-syncer/inspect-handler.d.ts +1 -1
- package/out/zero-cache/src/services/view-syncer/inspect-handler.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/inspect-handler.js +2 -2
- package/out/zero-cache/src/services/view-syncer/inspect-handler.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts +2 -1
- package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/pipeline-driver.js +33 -18
- package/out/zero-cache/src/services/view-syncer/pipeline-driver.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/query-covering.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/query-covering.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/snapshotter.d.ts +4 -1
- package/out/zero-cache/src/services/view-syncer/snapshotter.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/snapshotter.js +9 -3
- package/out/zero-cache/src/services/view-syncer/snapshotter.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts +11 -1
- package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/view-syncer.js +470 -90
- package/out/zero-cache/src/services/view-syncer/view-syncer.js.map +1 -1
- package/out/zero-cache/src/types/processes.d.ts +32 -0
- package/out/zero-cache/src/types/processes.d.ts.map +1 -1
- package/out/zero-cache/src/types/processes.js +43 -4
- package/out/zero-cache/src/types/processes.js.map +1 -1
- package/out/zero-cache/src/types/profiler.d.ts +12 -0
- package/out/zero-cache/src/types/profiler.d.ts.map +1 -1
- package/out/zero-cache/src/types/profiler.js +46 -1
- package/out/zero-cache/src/types/profiler.js.map +1 -1
- package/out/zero-cache/src/workers/syncer-ws-message-handler.d.ts.map +1 -1
- package/out/zero-cache/src/workers/syncer-ws-message-handler.js +21 -16
- package/out/zero-cache/src/workers/syncer-ws-message-handler.js.map +1 -1
- package/out/zero-cache/src/workers/syncer.d.ts.map +1 -1
- package/out/zero-cache/src/workers/syncer.js +10 -1
- package/out/zero-cache/src/workers/syncer.js.map +1 -1
- package/out/zero-client/src/client/connection-manager.d.ts +20 -0
- package/out/zero-client/src/client/connection-manager.d.ts.map +1 -1
- package/out/zero-client/src/client/connection-manager.js +32 -14
- package/out/zero-client/src/client/connection-manager.js.map +1 -1
- package/out/zero-client/src/client/connection-status-enum.d.ts +2 -0
- package/out/zero-client/src/client/connection-status-enum.d.ts.map +1 -1
- package/out/zero-client/src/client/connection-status-enum.js +3 -1
- package/out/zero-client/src/client/connection-status-enum.js.map +1 -1
- package/out/zero-client/src/client/connection.d.ts +6 -0
- package/out/zero-client/src/client/connection.d.ts.map +1 -1
- package/out/zero-client/src/client/connection.js +2 -1
- package/out/zero-client/src/client/connection.js.map +1 -1
- package/out/zero-client/src/client/context.d.ts +22 -12
- package/out/zero-client/src/client/context.d.ts.map +1 -1
- package/out/zero-client/src/client/context.js +92 -25
- package/out/zero-client/src/client/context.js.map +1 -1
- package/out/zero-client/src/client/custom.js +2 -2
- package/out/zero-client/src/client/custom.js.map +1 -1
- package/out/zero-client/src/client/error.js +1 -1
- package/out/zero-client/src/client/ivm-branch.d.ts.map +1 -1
- package/out/zero-client/src/client/ivm-branch.js +20 -3
- package/out/zero-client/src/client/ivm-branch.js.map +1 -1
- package/out/zero-client/src/client/mutator-proxy.d.ts.map +1 -1
- package/out/zero-client/src/client/mutator-proxy.js +2 -1
- package/out/zero-client/src/client/mutator-proxy.js.map +1 -1
- package/out/zero-client/src/client/options.d.ts +3 -0
- package/out/zero-client/src/client/options.d.ts.map +1 -1
- package/out/zero-client/src/client/options.js.map +1 -1
- package/out/zero-client/src/client/query-manager.d.ts +2 -0
- package/out/zero-client/src/client/query-manager.d.ts.map +1 -1
- package/out/zero-client/src/client/query-manager.js +48 -9
- package/out/zero-client/src/client/query-manager.js.map +1 -1
- package/out/zero-client/src/client/version.js +1 -1
- package/out/zero-client/src/client/zero-rep.d.ts.map +1 -1
- package/out/zero-client/src/client/zero-rep.js +1 -1
- package/out/zero-client/src/client/zero-rep.js.map +1 -1
- package/out/zero-client/src/client/zero.d.ts +18 -3
- package/out/zero-client/src/client/zero.d.ts.map +1 -1
- package/out/zero-client/src/client/zero.js +61 -14
- package/out/zero-client/src/client/zero.js.map +1 -1
- package/out/zero-client/src/types/query-result.d.ts +2 -0
- package/out/zero-client/src/types/query-result.d.ts.map +1 -1
- package/out/zero-protocol/src/ast.d.ts +64 -1
- package/out/zero-protocol/src/ast.d.ts.map +1 -1
- package/out/zero-protocol/src/ast.js +223 -51
- package/out/zero-protocol/src/ast.js.map +1 -1
- package/out/zero-protocol/src/error.d.ts +1 -1
- package/out/zero-protocol/src/query-hash-visitor.d.ts +81 -0
- package/out/zero-protocol/src/query-hash-visitor.d.ts.map +1 -0
- package/out/zero-protocol/src/query-hash-visitor.js +324 -0
- package/out/zero-protocol/src/query-hash-visitor.js.map +1 -0
- package/out/zero-protocol/src/query-hash.d.ts +7 -2
- package/out/zero-protocol/src/query-hash.d.ts.map +1 -1
- package/out/zero-protocol/src/query-hash.js +12 -9
- package/out/zero-protocol/src/query-hash.js.map +1 -1
- package/out/zero-react/src/use-query.d.ts +5 -4
- package/out/zero-react/src/use-query.d.ts.map +1 -1
- package/out/zero-react/src/use-query.js +86 -9
- package/out/zero-react/src/use-query.js.map +1 -1
- package/out/zero-solid/src/solid-view.d.ts +17 -0
- package/out/zero-solid/src/solid-view.d.ts.map +1 -1
- package/out/zero-solid/src/solid-view.js +39 -1
- package/out/zero-solid/src/solid-view.js.map +1 -1
- package/out/zero-solid/src/use-query.js +5 -3
- package/out/zero-solid/src/use-query.js.map +1 -1
- package/out/zql/src/builder/debug-delegate.d.ts +6 -1
- package/out/zql/src/builder/debug-delegate.d.ts.map +1 -1
- package/out/zql/src/builder/debug-delegate.js +14 -2
- package/out/zql/src/builder/debug-delegate.js.map +1 -1
- package/out/zql/src/ivm/array-view.d.ts +29 -0
- package/out/zql/src/ivm/array-view.d.ts.map +1 -1
- package/out/zql/src/ivm/array-view.js +58 -9
- package/out/zql/src/ivm/array-view.js.map +1 -1
- package/out/zql/src/ivm/cap.d.ts.map +1 -1
- package/out/zql/src/ivm/cap.js +5 -3
- package/out/zql/src/ivm/cap.js.map +1 -1
- package/out/zql/src/ivm/deferred-input.d.ts.map +1 -1
- package/out/zql/src/ivm/deferred-input.js +3 -2
- package/out/zql/src/ivm/deferred-input.js.map +1 -1
- package/out/zql/src/ivm/exists.d.ts +1 -1
- package/out/zql/src/ivm/exists.d.ts.map +1 -1
- package/out/zql/src/ivm/exists.js +1 -1
- package/out/zql/src/ivm/exists.js.map +1 -1
- package/out/zql/src/ivm/fan-in.d.ts +2 -2
- package/out/zql/src/ivm/fan-in.d.ts.map +1 -1
- package/out/zql/src/ivm/fan-in.js +6 -5
- package/out/zql/src/ivm/fan-in.js.map +1 -1
- package/out/zql/src/ivm/fan-out.d.ts +2 -2
- package/out/zql/src/ivm/fan-out.d.ts.map +1 -1
- package/out/zql/src/ivm/fan-out.js.map +1 -1
- package/out/zql/src/ivm/filter-operators.d.ts +4 -4
- package/out/zql/src/ivm/filter-operators.d.ts.map +1 -1
- package/out/zql/src/ivm/filter-operators.js +10 -8
- package/out/zql/src/ivm/filter-operators.js.map +1 -1
- package/out/zql/src/ivm/filter.d.ts +2 -2
- package/out/zql/src/ivm/filter.d.ts.map +1 -1
- package/out/zql/src/ivm/filter.js +7 -4
- package/out/zql/src/ivm/filter.js.map +1 -1
- package/out/zql/src/ivm/flipped-join.js +2 -2
- package/out/zql/src/ivm/flipped-join.js.map +1 -1
- package/out/zql/src/ivm/maybe-split-and-push-edit-change.d.ts +1 -1
- package/out/zql/src/ivm/maybe-split-and-push-edit-change.d.ts.map +1 -1
- package/out/zql/src/ivm/maybe-split-and-push-edit-change.js +6 -4
- package/out/zql/src/ivm/maybe-split-and-push-edit-change.js.map +1 -1
- package/out/zql/src/ivm/memory-source.d.ts +15 -3
- package/out/zql/src/ivm/memory-source.d.ts.map +1 -1
- package/out/zql/src/ivm/memory-source.js +35 -9
- package/out/zql/src/ivm/memory-source.js.map +1 -1
- package/out/zql/src/ivm/take.d.ts.map +1 -1
- package/out/zql/src/ivm/take.js +3 -4
- package/out/zql/src/ivm/take.js.map +1 -1
- package/out/zql/src/ivm/union-fan-in.d.ts.map +1 -1
- package/out/zql/src/ivm/union-fan-in.js +9 -7
- package/out/zql/src/ivm/union-fan-in.js.map +1 -1
- package/out/zql/src/ivm/view-apply-change.d.ts.map +1 -1
- package/out/zql/src/ivm/view-apply-change.js +3 -3
- package/out/zql/src/ivm/view-apply-change.js.map +1 -1
- package/out/zql/src/ivm/view.d.ts +15 -0
- package/out/zql/src/ivm/view.d.ts.map +1 -1
- package/out/zql/src/mutate/mutator-registry.d.ts.map +1 -1
- package/out/zql/src/mutate/mutator-registry.js +2 -2
- package/out/zql/src/mutate/mutator-registry.js.map +1 -1
- package/out/zql/src/query/query-delegate-base.d.ts +4 -2
- package/out/zql/src/query/query-delegate-base.d.ts.map +1 -1
- package/out/zql/src/query/query-delegate-base.js +69 -36
- package/out/zql/src/query/query-delegate-base.js.map +1 -1
- package/out/zql/src/query/query-delegate.d.ts +33 -6
- package/out/zql/src/query/query-delegate.d.ts.map +1 -1
- package/out/zql/src/query/query-impl.d.ts +25 -14
- package/out/zql/src/query/query-impl.d.ts.map +1 -1
- package/out/zql/src/query/query-impl.js +414 -94
- package/out/zql/src/query/query-impl.js.map +1 -1
- package/out/zql/src/query/query-internals.d.ts +21 -11
- package/out/zql/src/query/query-internals.d.ts.map +1 -1
- package/out/zql/src/query/query-internals.js.map +1 -1
- package/out/zql/src/query/query-transitions.d.ts +171 -0
- package/out/zql/src/query/query-transitions.d.ts.map +1 -0
- package/out/zql/src/query/query-transitions.js +207 -0
- package/out/zql/src/query/query-transitions.js.map +1 -0
- package/out/zql/src/query/query.d.ts +11 -2
- package/out/zql/src/query/query.d.ts.map +1 -1
- package/out/zql/src/query/runnable-query-impl.d.ts +3 -2
- package/out/zql/src/query/runnable-query-impl.d.ts.map +1 -1
- package/out/zql/src/query/runnable-query-impl.js +23 -2
- package/out/zql/src/query/runnable-query-impl.js.map +1 -1
- package/out/zql/src/query/typed-view.d.ts +1 -1
- package/out/zql/src/query/typed-view.d.ts.map +1 -1
- package/out/zqlite/src/db.d.ts +9 -1
- package/out/zqlite/src/db.d.ts.map +1 -1
- package/out/zqlite/src/db.js +8 -2
- package/out/zqlite/src/db.js.map +1 -1
- package/out/zqlite/src/table-source.d.ts +1 -0
- package/out/zqlite/src/table-source.d.ts.map +1 -1
- package/out/zqlite/src/table-source.js +10 -5
- package/out/zqlite/src/table-source.js.map +1 -1
- package/package.json +1 -1
|
@@ -16,8 +16,32 @@ export declare const MESSAGE_TYPES: {
|
|
|
16
16
|
readonly notify: "notify";
|
|
17
17
|
readonly ready: "ready";
|
|
18
18
|
readonly backupWatermarkUpdate: "backupWatermakUpdate";
|
|
19
|
+
readonly profile: "profile";
|
|
20
|
+
readonly profileResponse: "profileResponse";
|
|
19
21
|
};
|
|
22
|
+
export type ProfileRequest = {
|
|
23
|
+
readonly id: string;
|
|
24
|
+
readonly durationMs: number;
|
|
25
|
+
readonly worker?: string | undefined;
|
|
26
|
+
readonly workerIndex?: number | undefined;
|
|
27
|
+
};
|
|
28
|
+
export type ProfileResponse = {
|
|
29
|
+
readonly id: string;
|
|
30
|
+
readonly name: string;
|
|
31
|
+
readonly profile?: unknown | undefined;
|
|
32
|
+
readonly error?: string | undefined;
|
|
33
|
+
};
|
|
34
|
+
export type ProfileMessage = ['profile', ProfileRequest];
|
|
35
|
+
export type ProfileResponseMessage = ['profileResponse', ProfileResponse];
|
|
20
36
|
export type Message<Payload> = [keyof typeof MESSAGE_TYPES, Payload];
|
|
37
|
+
/**
|
|
38
|
+
* Subscribes the `handler` to messages of the given `type` and returns a
|
|
39
|
+
* function that unsubscribes it. Use this (rather than
|
|
40
|
+
* {@link Receiver.onMessageType()}) for handlers scoped to a request or
|
|
41
|
+
* operation rather than to the lifetime of the {@link Worker}; the
|
|
42
|
+
* `'message'` listener is otherwise retained by the Worker forever.
|
|
43
|
+
*/
|
|
44
|
+
export declare function subscribeToMessageType<M extends Message<unknown>>(e: EventEmitter, type: M[0], handler: (msg: M[1], sendHandle?: SendHandle) => void): () => void;
|
|
21
45
|
export interface Sender {
|
|
22
46
|
send<M extends Message<unknown>>(message: M, sendHandle?: SendHandle, callback?: (error: Error | null) => void): boolean;
|
|
23
47
|
kill(signal?: NodeJS.Signals): void;
|
|
@@ -86,4 +110,12 @@ export declare function forkChildWorker(moduleUrl: URL, env?: NodeJS.ProcessEnv,
|
|
|
86
110
|
* in a single process.
|
|
87
111
|
*/
|
|
88
112
|
export declare function inProcChannel(): [Worker, Worker];
|
|
113
|
+
/**
|
|
114
|
+
* Creates a {@link Worker} facade that broadcasts `send()` to all provided
|
|
115
|
+
* workers and aggregates their `'message'` events into one stream.
|
|
116
|
+
*
|
|
117
|
+
* This is useful for code that expects a single Worker for IPC (e.g.
|
|
118
|
+
* `handleProfzRequest`) but needs to reach multiple child workers.
|
|
119
|
+
*/
|
|
120
|
+
export declare function broadcastWorker(workers: Worker[]): Worker;
|
|
89
121
|
//# sourceMappingURL=processes.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"processes.d.ts","sourceRoot":"","sources":["../../../../../zero-cache/src/types/processes.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,UAAU,EAEhB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,YAAY,MAAM,aAAa,CAAC;AAIvC;;;;;;;;GAQG;AACH,eAAO,MAAM,aAAa
|
|
1
|
+
{"version":3,"file":"processes.d.ts","sourceRoot":"","sources":["../../../../../zero-cache/src/types/processes.ts"],"names":[],"mappings":"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"}
|
|
@@ -7,11 +7,26 @@ function getMessage(type, data) {
|
|
|
7
7
|
if (Array.isArray(data) && data.length === 2 && data[0] === type) return data[1];
|
|
8
8
|
return null;
|
|
9
9
|
}
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
/**
|
|
11
|
+
* Subscribes the `handler` to messages of the given `type` and returns a
|
|
12
|
+
* function that unsubscribes it. Use this (rather than
|
|
13
|
+
* {@link Receiver.onMessageType()}) for handlers scoped to a request or
|
|
14
|
+
* operation rather than to the lifetime of the {@link Worker}; the
|
|
15
|
+
* `'message'` listener is otherwise retained by the Worker forever.
|
|
16
|
+
*/
|
|
17
|
+
function subscribeToMessageType(e, type, handler) {
|
|
18
|
+
const listener = (data, sendHandle) => {
|
|
12
19
|
const msg = getMessage(type, data);
|
|
13
20
|
if (msg) handler(msg, sendHandle);
|
|
14
|
-
}
|
|
21
|
+
};
|
|
22
|
+
e.on("message", listener);
|
|
23
|
+
return () => {
|
|
24
|
+
e.off("message", listener);
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
function onMessageType(e, type, handler) {
|
|
28
|
+
subscribeToMessageType(e, type, handler);
|
|
29
|
+
return e;
|
|
15
30
|
}
|
|
16
31
|
function onceMessageType(e, type, handler) {
|
|
17
32
|
const listener = (data, sendHandle) => {
|
|
@@ -112,7 +127,31 @@ function inProcChannel() {
|
|
|
112
127
|
pid
|
|
113
128
|
}))];
|
|
114
129
|
}
|
|
130
|
+
/**
|
|
131
|
+
* Creates a {@link Worker} facade that broadcasts `send()` to all provided
|
|
132
|
+
* workers and aggregates their `'message'` events into one stream.
|
|
133
|
+
*
|
|
134
|
+
* This is useful for code that expects a single Worker for IPC (e.g.
|
|
135
|
+
* `handleProfzRequest`) but needs to reach multiple child workers.
|
|
136
|
+
*/
|
|
137
|
+
function broadcastWorker(workers) {
|
|
138
|
+
const emitter = new EventEmitter();
|
|
139
|
+
for (const w of workers) w.on("message", (message, sendHandle) => emitter.emit("message", message, sendHandle));
|
|
140
|
+
const send = (message, sendHandle, callback) => {
|
|
141
|
+
for (const w of workers) w.send(message, sendHandle);
|
|
142
|
+
if (callback) callback(null);
|
|
143
|
+
return true;
|
|
144
|
+
};
|
|
145
|
+
const kill = (signal = "SIGTERM") => {
|
|
146
|
+
for (const w of workers) w.kill(signal);
|
|
147
|
+
};
|
|
148
|
+
return wrap(Object.assign(emitter, {
|
|
149
|
+
send,
|
|
150
|
+
kill,
|
|
151
|
+
pid
|
|
152
|
+
}));
|
|
153
|
+
}
|
|
115
154
|
//#endregion
|
|
116
|
-
export { childWorker, parentWorker, singleProcessMode };
|
|
155
|
+
export { broadcastWorker, childWorker, parentWorker, singleProcessMode, subscribeToMessageType };
|
|
117
156
|
|
|
118
157
|
//# sourceMappingURL=processes.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"processes.js","names":[],"sources":["../../../../../zero-cache/src/types/processes.ts"],"sourcesContent":["import {\n type ChildProcess,\n fork,\n type SendHandle,\n type Serializable,\n} from 'node:child_process';\nimport EventEmitter from 'node:events';\nimport {platform} from 'node:os';\nimport {pid} from 'node:process';\n\n/**\n * Central registry of message type names, which are used to identify\n * the payload in {@link Message} objects sent between processes. The\n * payloads themselves are implementation specific and defined in each\n * component; only the type name is reserved here to avoid collisions.\n *\n * Receiving logic can call {@link getMessage()} with the name of\n * the message of interest to filter messages to those of interest.\n */\nexport const MESSAGE_TYPES = {\n handoff: 'handoff',\n status: 'status',\n subscribe: 'subscribe',\n notify: 'notify',\n ready: 'ready',\n backupWatermarkUpdate: 'backupWatermakUpdate',\n} as const;\n\nexport type Message<Payload> = [keyof typeof MESSAGE_TYPES, Payload];\n\nfunction getMessage<M extends Message<unknown>>(\n type: M[0],\n data: unknown,\n): M[1] | null {\n if (Array.isArray(data) && data.length === 2 && data[0] === type) {\n return data[1] as M[1];\n }\n return null;\n}\n\nfunction onMessageType<M extends Message<unknown>>(\n e: EventEmitter,\n type: M[0],\n handler: (msg: M[1], sendHandle?: SendHandle) => void,\n) {\n return e.on('message', (data, sendHandle) => {\n const msg = getMessage(type, data);\n if (msg) {\n handler(msg, sendHandle);\n }\n });\n}\n\nfunction onceMessageType<M extends Message<unknown>>(\n e: EventEmitter,\n type: M[0],\n handler: (msg: M[1], sendHandle?: SendHandle) => void,\n) {\n const listener = (data: unknown, sendHandle: SendHandle) => {\n const msg = getMessage(type, data);\n if (msg) {\n e.off('message', listener);\n handler(msg, sendHandle);\n }\n };\n return e.on('message', listener);\n}\n\nexport interface Sender {\n send<M extends Message<unknown>>(\n message: M,\n sendHandle?: SendHandle,\n callback?: (error: Error | null) => void,\n ): boolean;\n\n kill(signal?: NodeJS.Signals): void;\n}\n\nexport interface Subprocess extends Sender, EventEmitter {\n pid?: number | undefined;\n}\n\nexport interface Receiver extends EventEmitter {\n /**\n * The receiving side of {@link Sender.send()} that is a wrapper around\n * {@link on}('message', ...) that invokes the `handler` for messages of\n * the specified `type`.\n */\n onMessageType<M extends Message<unknown>>(\n type: M[0],\n handler: (msg: M[1], sendHandle?: SendHandle) => void,\n ): this;\n\n /**\n * The receiving side of {@link Sender.send()} that behaves like\n * {@link once}('message', ...) that invokes the `handler` for the next\n * message of the specified `type` and then unsubscribes.\n */\n onceMessageType<M extends Message<unknown>>(\n type: M[0],\n handler: (msg: M[1], sendHandle?: SendHandle) => void,\n ): this;\n}\n\nexport interface Worker extends Subprocess, Receiver {}\n\n/**\n * Adds the {@link Receiver.onMessageType()} and {@link Receiver.onceMessageType()}\n * methods to convert the given `EventEmitter` to a `Receiver`.\n */\nfunction wrap<P extends EventEmitter>(proc: P): P & Receiver {\n return new Proxy(proc, {\n get(target: P, prop: string | symbol, receiver: unknown) {\n switch (prop) {\n case 'onMessageType':\n return (\n type: keyof typeof MESSAGE_TYPES,\n handler: (msg: unknown, sendHandle?: SendHandle) => void,\n ) => {\n onMessageType(target, type, handler);\n return receiver; // this\n };\n case 'onceMessageType':\n return (\n type: keyof typeof MESSAGE_TYPES,\n handler: (msg: unknown, sendHandle?: SendHandle) => void,\n ) => {\n onceMessageType(target, type, handler);\n return receiver; // this\n };\n }\n return Reflect.get(target, prop, receiver);\n },\n }) as P & Receiver;\n}\n\ntype Proc = Pick<ChildProcess, 'send' | 'kill' | 'pid'> & EventEmitter;\n\n/**\n * The parentWorker for forked processes, or `null` if the process was not forked.\n * (Analogous to the `parentPort: MessagePort | null` of the `\"workers\"` library).\n */\nexport const parentWorker: Worker | null = process.send\n ? wrap(process as Proc)\n : null;\n\nconst SINGLE_PROCESS = 'SINGLE_PROCESS';\nlet singleProcessOverride = false;\nexport function singleProcessMode(): boolean {\n return singleProcessOverride || (process.env[SINGLE_PROCESS] ?? '0') !== '0';\n}\n\nexport function setSingleProcessMode(enabled: boolean = true): void {\n singleProcessOverride = enabled;\n}\n\n/**\n * Determines whether a module loaded as a worker process entry point should\n * start its worker.\n *\n * Most workers are launched via {@link childWorker}, which in single-process\n * mode runs them in-process (no real fork) by invoking their exported\n * `runWorker` directly; those entry points must therefore *not* self-start in\n * single-process mode, or they would run twice.\n *\n * A worker launched via {@link forkChildWorker}, however, is *always* a real\n * forked OS process — even in single-process mode — and it inherits the\n * parent's `SINGLE_PROCESS` env. So {@link singleProcessMode} alone would\n * wrongly suppress its startup, leaving the parent to spin re-forking a child\n * that immediately exits. Such a forked child has a non-null\n * {@link parentWorker} (`process.send` is defined), which is the signal to\n * start regardless. A standalone direct launch (no parent, not single-process)\n * also starts.\n *\n * @param parent The entry point's {@link parentWorker} (non-null iff forked).\n * @param isSingleProcessMode The result of {@link singleProcessMode}.\n */\nexport function shouldStartWorker(\n parent: Worker | null,\n isSingleProcessMode: boolean,\n): boolean {\n return parent !== null || !isSingleProcessMode;\n}\n\n/**\n *\n * @param modulePath Path to the module file, relative to zero-cache/src/, or an absolute file:// URL\n */\nexport function childWorker(\n moduleUrl: URL,\n env?: NodeJS.ProcessEnv,\n ...args: string[]\n): Worker {\n args = workerArgs(args);\n\n if (singleProcessMode()) {\n const [parent, child] = inProcChannel();\n import(moduleUrl.href)\n .then(async ({default: runWorker}) => {\n try {\n await runWorker(parent, env ?? process.env, ...args);\n child.emit('close', 0);\n return;\n } catch (err) {\n child.emit('error', err);\n child.emit('close', -1);\n }\n })\n .catch(err => child.emit('error', err));\n return child;\n }\n return forkChildWorkerWithArgs(moduleUrl, env, args);\n}\n\nexport function forkChildWorker(\n moduleUrl: URL,\n env?: NodeJS.ProcessEnv,\n ...args: string[]\n): Worker {\n return forkChildWorkerWithArgs(moduleUrl, env, workerArgs(args));\n}\n\nfunction workerArgs(args: string[]): string[] {\n return [...args, ...process.argv.slice(2)];\n}\n\nfunction forkChildWorkerWithArgs(\n moduleUrl: URL,\n env: NodeJS.ProcessEnv | undefined,\n args: string[],\n): Worker {\n const child = fork(moduleUrl, args, {\n // For production / non-windows, set `detached` to `true` so that SIGINT is\n // not automatically propagated and graceful shutdown happens as intended.\n // For Win32, detached: true causes all subprocesses to open in separate\n // terminals and breaks inter-process kill signals, so set it to false.\n detached: platform() !== 'win32',\n serialization: 'advanced', // use structured clone for IPC\n env,\n });\n return wrap(child);\n}\n\n/**\n * Creates two connected `Worker` instances such that messages sent to one\n * via the {@link Worker.send()} method are received by the other's\n * `on('message', ...)` handler.\n *\n * This is analogous to the two `MessagePort`s of a `MessageChannel`, and\n * is useful for executing code written for inter-process communication\n * in a single process.\n */\nexport function inProcChannel(): [Worker, Worker] {\n const worker1 = new EventEmitter();\n const worker2 = new EventEmitter();\n\n const sendTo =\n (dest: EventEmitter) =>\n (\n message: Serializable,\n sendHandle?: SendHandle,\n callback?: (error: Error | null) => void,\n ) => {\n dest.emit('message', message, sendHandle);\n if (callback) {\n callback(null);\n }\n return true;\n };\n\n const kill =\n (dest: EventEmitter) =>\n (signal: NodeJS.Signals = 'SIGTERM') =>\n dest.emit(signal, signal);\n\n return [\n wrap(\n Object.assign(worker1, {send: sendTo(worker2), kill: kill(worker2), pid}),\n ),\n wrap(\n Object.assign(worker2, {send: sendTo(worker1), kill: kill(worker1), pid}),\n ),\n ];\n}\n"],"mappings":";;;;;AA8BA,SAAS,WACP,MACA,MACa;CACb,IAAI,MAAM,QAAQ,IAAI,KAAK,KAAK,WAAW,KAAK,KAAK,OAAO,MAC1D,OAAO,KAAK;CAEd,OAAO;AACT;AAEA,SAAS,cACP,GACA,MACA,SACA;CACA,OAAO,EAAE,GAAG,YAAY,MAAM,eAAe;EAC3C,MAAM,MAAM,WAAW,MAAM,IAAI;EACjC,IAAI,KACF,QAAQ,KAAK,UAAU;CAE3B,CAAC;AACH;AAEA,SAAS,gBACP,GACA,MACA,SACA;CACA,MAAM,YAAY,MAAe,eAA2B;EAC1D,MAAM,MAAM,WAAW,MAAM,IAAI;EACjC,IAAI,KAAK;GACP,EAAE,IAAI,WAAW,QAAQ;GACzB,QAAQ,KAAK,UAAU;EACzB;CACF;CACA,OAAO,EAAE,GAAG,WAAW,QAAQ;AACjC;;;;;AA4CA,SAAS,KAA6B,MAAuB;CAC3D,OAAO,IAAI,MAAM,MAAM,EACrB,IAAI,QAAW,MAAuB,UAAmB;EACvD,QAAQ,MAAR;GACE,KAAK,iBACH,QACE,MACA,YACG;IACH,cAAc,QAAQ,MAAM,OAAO;IACnC,OAAO;GACT;GACF,KAAK,mBACH,QACE,MACA,YACG;IACH,gBAAgB,QAAQ,MAAM,OAAO;IACrC,OAAO;GACT;EACJ;EACA,OAAO,QAAQ,IAAI,QAAQ,MAAM,QAAQ;CAC3C,EACF,CAAC;AACH;;;;;AAQA,IAAa,eAA8B,QAAQ,OAC/C,KAAK,OAAe,IACpB;AAEJ,IAAM,iBAAiB;AACvB,IAAI,wBAAwB;AAC5B,SAAgB,oBAA6B;CAC3C,OAAO,0BAA0B,QAAQ,IAAI,mBAAmB,SAAS;AAC3E;;;;;AAsCA,SAAgB,YACd,WACA,KACA,GAAG,MACK;CACR,OAAO,WAAW,IAAI;CAEtB,IAAI,kBAAkB,GAAG;EACvB,MAAM,CAAC,QAAQ,SAAS,cAAc;EACtC,OAAO,UAAU,MACd,KAAK,OAAO,EAAC,SAAS,gBAAe;GACpC,IAAI;IACF,MAAM,UAAU,QAAQ,OAAO,QAAQ,KAAK,GAAG,IAAI;IACnD,MAAM,KAAK,SAAS,CAAC;IACrB;GACF,SAAS,KAAK;IACZ,MAAM,KAAK,SAAS,GAAG;IACvB,MAAM,KAAK,SAAS,EAAE;GACxB;EACF,CAAC,EACA,OAAM,QAAO,MAAM,KAAK,SAAS,GAAG,CAAC;EACxC,OAAO;CACT;CACA,OAAO,wBAAwB,WAAW,KAAK,IAAI;AACrD;AAUA,SAAS,WAAW,MAA0B;CAC5C,OAAO,CAAC,GAAG,MAAM,GAAG,QAAQ,KAAK,MAAM,CAAC,CAAC;AAC3C;AAEA,SAAS,wBACP,WACA,KACA,MACQ;CAUR,OAAO,KATO,KAAK,WAAW,MAAM;EAKlC,UAAU,SAAS,MAAM;EACzB,eAAe;EACf;CACF,CACY,CAAK;AACnB;;;;;;;;;;AAWA,SAAgB,gBAAkC;CAChD,MAAM,UAAU,IAAI,aAAa;CACjC,MAAM,UAAU,IAAI,aAAa;CAEjC,MAAM,UACH,UAEC,SACA,YACA,aACG;EACH,KAAK,KAAK,WAAW,SAAS,UAAU;EACxC,IAAI,UACF,SAAS,IAAI;EAEf,OAAO;CACT;CAEF,MAAM,QACH,UACA,SAAyB,cACxB,KAAK,KAAK,QAAQ,MAAM;CAE5B,OAAO,CACL,KACE,OAAO,OAAO,SAAS;EAAC,MAAM,OAAO,OAAO;EAAG,MAAM,KAAK,OAAO;EAAG;CAAG,CAAC,CAC1E,GACA,KACE,OAAO,OAAO,SAAS;EAAC,MAAM,OAAO,OAAO;EAAG,MAAM,KAAK,OAAO;EAAG;CAAG,CAAC,CAC1E,CACF;AACF"}
|
|
1
|
+
{"version":3,"file":"processes.js","names":[],"sources":["../../../../../zero-cache/src/types/processes.ts"],"sourcesContent":["import {\n type ChildProcess,\n fork,\n type SendHandle,\n type Serializable,\n} from 'node:child_process';\nimport EventEmitter from 'node:events';\nimport {platform} from 'node:os';\nimport {pid} from 'node:process';\n\n/**\n * Central registry of message type names, which are used to identify\n * the payload in {@link Message} objects sent between processes. The\n * payloads themselves are implementation specific and defined in each\n * component; only the type name is reserved here to avoid collisions.\n *\n * Receiving logic can call {@link getMessage()} with the name of\n * the message of interest to filter messages to those of interest.\n */\nexport const MESSAGE_TYPES = {\n handoff: 'handoff',\n status: 'status',\n subscribe: 'subscribe',\n notify: 'notify',\n ready: 'ready',\n backupWatermarkUpdate: 'backupWatermakUpdate',\n profile: 'profile',\n profileResponse: 'profileResponse',\n} as const;\n\nexport type ProfileRequest = {\n readonly id: string;\n readonly durationMs: number;\n readonly worker?: string | undefined;\n readonly workerIndex?: number | undefined;\n};\n\nexport type ProfileResponse = {\n readonly id: string;\n readonly name: string;\n readonly profile?: unknown | undefined;\n readonly error?: string | undefined;\n};\n\nexport type ProfileMessage = ['profile', ProfileRequest];\nexport type ProfileResponseMessage = ['profileResponse', ProfileResponse];\n\nexport type Message<Payload> = [keyof typeof MESSAGE_TYPES, Payload];\n\nfunction getMessage<M extends Message<unknown>>(\n type: M[0],\n data: unknown,\n): M[1] | null {\n if (Array.isArray(data) && data.length === 2 && data[0] === type) {\n return data[1] as M[1];\n }\n return null;\n}\n\n/**\n * Subscribes the `handler` to messages of the given `type` and returns a\n * function that unsubscribes it. Use this (rather than\n * {@link Receiver.onMessageType()}) for handlers scoped to a request or\n * operation rather than to the lifetime of the {@link Worker}; the\n * `'message'` listener is otherwise retained by the Worker forever.\n */\nexport function subscribeToMessageType<M extends Message<unknown>>(\n e: EventEmitter,\n type: M[0],\n handler: (msg: M[1], sendHandle?: SendHandle) => void,\n): () => void {\n const listener = (data: unknown, sendHandle?: SendHandle) => {\n const msg = getMessage(type, data);\n if (msg) {\n handler(msg, sendHandle);\n }\n };\n e.on('message', listener);\n return () => {\n e.off('message', listener);\n };\n}\n\nfunction onMessageType<M extends Message<unknown>>(\n e: EventEmitter,\n type: M[0],\n handler: (msg: M[1], sendHandle?: SendHandle) => void,\n) {\n subscribeToMessageType(e, type, handler);\n return e;\n}\n\nfunction onceMessageType<M extends Message<unknown>>(\n e: EventEmitter,\n type: M[0],\n handler: (msg: M[1], sendHandle?: SendHandle) => void,\n) {\n const listener = (data: unknown, sendHandle: SendHandle) => {\n const msg = getMessage(type, data);\n if (msg) {\n e.off('message', listener);\n handler(msg, sendHandle);\n }\n };\n return e.on('message', listener);\n}\n\nexport interface Sender {\n send<M extends Message<unknown>>(\n message: M,\n sendHandle?: SendHandle,\n callback?: (error: Error | null) => void,\n ): boolean;\n\n kill(signal?: NodeJS.Signals): void;\n}\n\nexport interface Subprocess extends Sender, EventEmitter {\n pid?: number | undefined;\n}\n\nexport interface Receiver extends EventEmitter {\n /**\n * The receiving side of {@link Sender.send()} that is a wrapper around\n * {@link on}('message', ...) that invokes the `handler` for messages of\n * the specified `type`.\n */\n onMessageType<M extends Message<unknown>>(\n type: M[0],\n handler: (msg: M[1], sendHandle?: SendHandle) => void,\n ): this;\n\n /**\n * The receiving side of {@link Sender.send()} that behaves like\n * {@link once}('message', ...) that invokes the `handler` for the next\n * message of the specified `type` and then unsubscribes.\n */\n onceMessageType<M extends Message<unknown>>(\n type: M[0],\n handler: (msg: M[1], sendHandle?: SendHandle) => void,\n ): this;\n}\n\nexport interface Worker extends Subprocess, Receiver {}\n\n/**\n * Adds the {@link Receiver.onMessageType()} and {@link Receiver.onceMessageType()}\n * methods to convert the given `EventEmitter` to a `Receiver`.\n */\nfunction wrap<P extends EventEmitter>(proc: P): P & Receiver {\n return new Proxy(proc, {\n get(target: P, prop: string | symbol, receiver: unknown) {\n switch (prop) {\n case 'onMessageType':\n return (\n type: keyof typeof MESSAGE_TYPES,\n handler: (msg: unknown, sendHandle?: SendHandle) => void,\n ) => {\n onMessageType(target, type, handler);\n return receiver; // this\n };\n case 'onceMessageType':\n return (\n type: keyof typeof MESSAGE_TYPES,\n handler: (msg: unknown, sendHandle?: SendHandle) => void,\n ) => {\n onceMessageType(target, type, handler);\n return receiver; // this\n };\n }\n return Reflect.get(target, prop, receiver);\n },\n }) as P & Receiver;\n}\n\ntype Proc = Pick<ChildProcess, 'send' | 'kill' | 'pid'> & EventEmitter;\n\n/**\n * The parentWorker for forked processes, or `null` if the process was not forked.\n * (Analogous to the `parentPort: MessagePort | null` of the `\"workers\"` library).\n */\nexport const parentWorker: Worker | null = process.send\n ? wrap(process as Proc)\n : null;\n\nconst SINGLE_PROCESS = 'SINGLE_PROCESS';\nlet singleProcessOverride = false;\nexport function singleProcessMode(): boolean {\n return singleProcessOverride || (process.env[SINGLE_PROCESS] ?? '0') !== '0';\n}\n\nexport function setSingleProcessMode(enabled: boolean = true): void {\n singleProcessOverride = enabled;\n}\n\n/**\n * Determines whether a module loaded as a worker process entry point should\n * start its worker.\n *\n * Most workers are launched via {@link childWorker}, which in single-process\n * mode runs them in-process (no real fork) by invoking their exported\n * `runWorker` directly; those entry points must therefore *not* self-start in\n * single-process mode, or they would run twice.\n *\n * A worker launched via {@link forkChildWorker}, however, is *always* a real\n * forked OS process — even in single-process mode — and it inherits the\n * parent's `SINGLE_PROCESS` env. So {@link singleProcessMode} alone would\n * wrongly suppress its startup, leaving the parent to spin re-forking a child\n * that immediately exits. Such a forked child has a non-null\n * {@link parentWorker} (`process.send` is defined), which is the signal to\n * start regardless. A standalone direct launch (no parent, not single-process)\n * also starts.\n *\n * @param parent The entry point's {@link parentWorker} (non-null iff forked).\n * @param isSingleProcessMode The result of {@link singleProcessMode}.\n */\nexport function shouldStartWorker(\n parent: Worker | null,\n isSingleProcessMode: boolean,\n): boolean {\n return parent !== null || !isSingleProcessMode;\n}\n\n/**\n *\n * @param modulePath Path to the module file, relative to zero-cache/src/, or an absolute file:// URL\n */\nexport function childWorker(\n moduleUrl: URL,\n env?: NodeJS.ProcessEnv,\n ...args: string[]\n): Worker {\n args = workerArgs(args);\n\n if (singleProcessMode()) {\n const [parent, child] = inProcChannel();\n import(moduleUrl.href)\n .then(async ({default: runWorker}) => {\n try {\n await runWorker(parent, env ?? process.env, ...args);\n child.emit('close', 0);\n return;\n } catch (err) {\n child.emit('error', err);\n child.emit('close', -1);\n }\n })\n .catch(err => child.emit('error', err));\n return child;\n }\n return forkChildWorkerWithArgs(moduleUrl, env, args);\n}\n\nexport function forkChildWorker(\n moduleUrl: URL,\n env?: NodeJS.ProcessEnv,\n ...args: string[]\n): Worker {\n return forkChildWorkerWithArgs(moduleUrl, env, workerArgs(args));\n}\n\nfunction workerArgs(args: string[]): string[] {\n return [...args, ...process.argv.slice(2)];\n}\n\nfunction forkChildWorkerWithArgs(\n moduleUrl: URL,\n env: NodeJS.ProcessEnv | undefined,\n args: string[],\n): Worker {\n const child = fork(moduleUrl, args, {\n // For production / non-windows, set `detached` to `true` so that SIGINT is\n // not automatically propagated and graceful shutdown happens as intended.\n // For Win32, detached: true causes all subprocesses to open in separate\n // terminals and breaks inter-process kill signals, so set it to false.\n detached: platform() !== 'win32',\n serialization: 'advanced', // use structured clone for IPC\n env,\n });\n return wrap(child);\n}\n\n/**\n * Creates two connected `Worker` instances such that messages sent to one\n * via the {@link Worker.send()} method are received by the other's\n * `on('message', ...)` handler.\n *\n * This is analogous to the two `MessagePort`s of a `MessageChannel`, and\n * is useful for executing code written for inter-process communication\n * in a single process.\n */\nexport function inProcChannel(): [Worker, Worker] {\n const worker1 = new EventEmitter();\n const worker2 = new EventEmitter();\n\n const sendTo =\n (dest: EventEmitter) =>\n (\n message: Serializable,\n sendHandle?: SendHandle,\n callback?: (error: Error | null) => void,\n ) => {\n dest.emit('message', message, sendHandle);\n if (callback) {\n callback(null);\n }\n return true;\n };\n\n const kill =\n (dest: EventEmitter) =>\n (signal: NodeJS.Signals = 'SIGTERM') =>\n dest.emit(signal, signal);\n\n return [\n wrap(\n Object.assign(worker1, {send: sendTo(worker2), kill: kill(worker2), pid}),\n ),\n wrap(\n Object.assign(worker2, {send: sendTo(worker1), kill: kill(worker1), pid}),\n ),\n ];\n}\n\n/**\n * Creates a {@link Worker} facade that broadcasts `send()` to all provided\n * workers and aggregates their `'message'` events into one stream.\n *\n * This is useful for code that expects a single Worker for IPC (e.g.\n * `handleProfzRequest`) but needs to reach multiple child workers.\n */\nexport function broadcastWorker(workers: Worker[]): Worker {\n const emitter = new EventEmitter();\n\n for (const w of workers) {\n w.on('message', (message: Serializable, sendHandle?: SendHandle) =>\n emitter.emit('message', message, sendHandle),\n );\n }\n\n const send = <M extends Message<unknown>>(\n message: M,\n sendHandle?: SendHandle,\n callback?: (error: Error | null) => void,\n ) => {\n for (const w of workers) {\n w.send(message, sendHandle);\n }\n if (callback) {\n callback(null);\n }\n return true;\n };\n\n const kill = (signal: NodeJS.Signals = 'SIGTERM') => {\n for (const w of workers) {\n w.kill(signal);\n }\n };\n\n return wrap(Object.assign(emitter, {send, kill, pid}));\n}\n"],"mappings":"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"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { LogContext } from '@rocicorp/logger';
|
|
2
|
+
import type { Worker } from './processes.ts';
|
|
2
3
|
/**
|
|
3
4
|
* Convenience wrapper around a `node:inspector` {@link Session} for
|
|
4
5
|
* optionally taking cpu profiles.
|
|
@@ -8,6 +9,17 @@ export declare class CpuProfiler {
|
|
|
8
9
|
static connect(): Promise<CpuProfiler>;
|
|
9
10
|
private constructor();
|
|
10
11
|
start(): Promise<void>;
|
|
12
|
+
/**
|
|
13
|
+
* Captures a CPU profile for the specified duration (in milliseconds)
|
|
14
|
+
* and returns the V8 profile object.
|
|
15
|
+
*/
|
|
16
|
+
static profile(durationMs: number): Promise<unknown>;
|
|
17
|
+
stop(): Promise<unknown>;
|
|
11
18
|
stopAndDispose(lc: LogContext, filename: string): Promise<void>;
|
|
12
19
|
}
|
|
20
|
+
/**
|
|
21
|
+
* Registers an IPC handler on `parent` to capture a CPU profile when
|
|
22
|
+
* requested, sending back the resulting V8 profile.
|
|
23
|
+
*/
|
|
24
|
+
export declare function installProfileHandler(parent: Worker | null, workerName: string, workerIndex?: number | undefined): void;
|
|
13
25
|
//# sourceMappingURL=profiler.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"profiler.d.ts","sourceRoot":"","sources":["../../../../../zero-cache/src/types/profiler.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"profiler.d.ts","sourceRoot":"","sources":["../../../../../zero-cache/src/types/profiler.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AACjD,OAAO,KAAK,EAAiB,MAAM,EAAC,MAAM,gBAAgB,CAAC;AAE3D;;;GAGG;AACH,qBAAa,WAAW;;WACT,OAAO;IASpB,OAAO;IAID,KAAK;IAIX;;;OAGG;WACU,OAAO,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAOpD,IAAI,IAAI,OAAO,CAAC,OAAO,CAAC;IAOxB,cAAc,CAAC,EAAE,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM;CAOtD;AAID;;;GAGG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,MAAM,GAAG,IAAI,EACrB,UAAU,EAAE,MAAM,EAClB,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,GAC/B,IAAI,CA6BN"}
|
|
@@ -21,6 +21,22 @@ var CpuProfiler = class CpuProfiler {
|
|
|
21
21
|
async start() {
|
|
22
22
|
await this.#session.post("Profiler.start");
|
|
23
23
|
}
|
|
24
|
+
/**
|
|
25
|
+
* Captures a CPU profile for the specified duration (in milliseconds)
|
|
26
|
+
* and returns the V8 profile object.
|
|
27
|
+
*/
|
|
28
|
+
static async profile(durationMs) {
|
|
29
|
+
const profiler = await CpuProfiler.connect();
|
|
30
|
+
await profiler.start();
|
|
31
|
+
await new Promise((resolve) => setTimeout(resolve, durationMs));
|
|
32
|
+
return await profiler.stop();
|
|
33
|
+
}
|
|
34
|
+
async stop() {
|
|
35
|
+
const { profile } = await this.#session.post("Profiler.stop");
|
|
36
|
+
await this.#session.post("Profiler.disable");
|
|
37
|
+
this.#session.disconnect();
|
|
38
|
+
return profile;
|
|
39
|
+
}
|
|
24
40
|
async stopAndDispose(lc, filename) {
|
|
25
41
|
const { profile } = await this.#session.post("Profiler.stop");
|
|
26
42
|
const path = join(tmpdir(), `${filename}.cpuprofile`);
|
|
@@ -29,7 +45,36 @@ var CpuProfiler = class CpuProfiler {
|
|
|
29
45
|
this.#session.disconnect();
|
|
30
46
|
}
|
|
31
47
|
};
|
|
48
|
+
var WORKER_INDEX_SUFFIX = /-\d+$/;
|
|
49
|
+
/**
|
|
50
|
+
* Registers an IPC handler on `parent` to capture a CPU profile when
|
|
51
|
+
* requested, sending back the resulting V8 profile.
|
|
52
|
+
*/
|
|
53
|
+
function installProfileHandler(parent, workerName, workerIndex) {
|
|
54
|
+
if (!parent) return;
|
|
55
|
+
parent.onMessageType("profile", async (req) => {
|
|
56
|
+
if (req.worker !== void 0) {
|
|
57
|
+
const baseName = workerName.replace(WORKER_INDEX_SUFFIX, "");
|
|
58
|
+
if (!(req.worker === workerName || req.worker === baseName)) return;
|
|
59
|
+
if (req.workerIndex !== void 0 && workerIndex !== void 0 && req.workerIndex !== workerIndex) return;
|
|
60
|
+
}
|
|
61
|
+
try {
|
|
62
|
+
const profile = await CpuProfiler.profile(req.durationMs);
|
|
63
|
+
parent.send(["profileResponse", {
|
|
64
|
+
id: req.id,
|
|
65
|
+
name: workerName,
|
|
66
|
+
profile
|
|
67
|
+
}]);
|
|
68
|
+
} catch (err) {
|
|
69
|
+
parent.send(["profileResponse", {
|
|
70
|
+
id: req.id,
|
|
71
|
+
name: workerName,
|
|
72
|
+
error: String(err)
|
|
73
|
+
}]);
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
}
|
|
32
77
|
//#endregion
|
|
33
|
-
export { CpuProfiler };
|
|
78
|
+
export { CpuProfiler, installProfileHandler };
|
|
34
79
|
|
|
35
80
|
//# sourceMappingURL=profiler.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"profiler.js","names":["#session"],"sources":["../../../../../zero-cache/src/types/profiler.ts"],"sourcesContent":["import {writeFile} from 'node:fs/promises';\nimport {Session} from 'node:inspector/promises';\nimport {tmpdir} from 'node:os';\nimport {join} from 'node:path';\nimport type {LogContext} from '@rocicorp/logger';\n\n/**\n * Convenience wrapper around a `node:inspector` {@link Session} for\n * optionally taking cpu profiles.\n */\nexport class CpuProfiler {\n static async connect() {\n const session = new Session();\n session.connect();\n await session.post('Profiler.enable');\n return new CpuProfiler(session);\n }\n\n readonly #session;\n\n private constructor(session: Session) {\n this.#session = session;\n }\n\n async start() {\n await this.#session.post('Profiler.start');\n }\n\n async stopAndDispose(lc: LogContext, filename: string) {\n const {profile} = await this.#session.post('Profiler.stop');\n const path = join(tmpdir(), `${filename}.cpuprofile`);\n await writeFile(path, JSON.stringify(profile));\n lc.info?.(`wrote cpu profile to ${path}`);\n this.#session.disconnect();\n }\n}\n"],"mappings":";;;;;;;;;
|
|
1
|
+
{"version":3,"file":"profiler.js","names":["#session"],"sources":["../../../../../zero-cache/src/types/profiler.ts"],"sourcesContent":["import {writeFile} from 'node:fs/promises';\nimport {Session} from 'node:inspector/promises';\nimport {tmpdir} from 'node:os';\nimport {join} from 'node:path';\nimport type {LogContext} from '@rocicorp/logger';\nimport type {ProfileMessage, Worker} from './processes.ts';\n\n/**\n * Convenience wrapper around a `node:inspector` {@link Session} for\n * optionally taking cpu profiles.\n */\nexport class CpuProfiler {\n static async connect() {\n const session = new Session();\n session.connect();\n await session.post('Profiler.enable');\n return new CpuProfiler(session);\n }\n\n readonly #session;\n\n private constructor(session: Session) {\n this.#session = session;\n }\n\n async start() {\n await this.#session.post('Profiler.start');\n }\n\n /**\n * Captures a CPU profile for the specified duration (in milliseconds)\n * and returns the V8 profile object.\n */\n static async profile(durationMs: number): Promise<unknown> {\n const profiler = await CpuProfiler.connect();\n await profiler.start();\n await new Promise(resolve => setTimeout(resolve, durationMs));\n return await profiler.stop();\n }\n\n async stop(): Promise<unknown> {\n const {profile} = await this.#session.post('Profiler.stop');\n await this.#session.post('Profiler.disable');\n this.#session.disconnect();\n return profile;\n }\n\n async stopAndDispose(lc: LogContext, filename: string) {\n const {profile} = await this.#session.post('Profiler.stop');\n const path = join(tmpdir(), `${filename}.cpuprofile`);\n await writeFile(path, JSON.stringify(profile));\n lc.info?.(`wrote cpu profile to ${path}`);\n this.#session.disconnect();\n }\n}\n\nconst WORKER_INDEX_SUFFIX = /-\\d+$/;\n\n/**\n * Registers an IPC handler on `parent` to capture a CPU profile when\n * requested, sending back the resulting V8 profile.\n */\nexport function installProfileHandler(\n parent: Worker | null,\n workerName: string,\n workerIndex?: number | undefined,\n): void {\n if (!parent) {\n return;\n }\n parent.onMessageType<ProfileMessage>('profile', async req => {\n if (req.worker !== undefined) {\n const baseName = workerName.replace(WORKER_INDEX_SUFFIX, '');\n const matchesName = req.worker === workerName || req.worker === baseName;\n if (!matchesName) {\n return;\n }\n if (\n req.workerIndex !== undefined &&\n workerIndex !== undefined &&\n req.workerIndex !== workerIndex\n ) {\n return;\n }\n }\n try {\n const profile = await CpuProfiler.profile(req.durationMs);\n parent.send(['profileResponse', {id: req.id, name: workerName, profile}]);\n } catch (err) {\n parent.send([\n 'profileResponse',\n {id: req.id, name: workerName, error: String(err)},\n ]);\n }\n });\n}\n"],"mappings":";;;;;;;;;AAWA,IAAa,cAAb,MAAa,YAAY;CACvB,aAAa,UAAU;EACrB,MAAM,UAAU,IAAI,QAAQ;EAC5B,QAAQ,QAAQ;EAChB,MAAM,QAAQ,KAAK,iBAAiB;EACpC,OAAO,IAAI,YAAY,OAAO;CAChC;CAEA;CAEA,YAAoB,SAAkB;EACpC,KAAKA,WAAW;CAClB;CAEA,MAAM,QAAQ;EACZ,MAAM,KAAKA,SAAS,KAAK,gBAAgB;CAC3C;;;;;CAMA,aAAa,QAAQ,YAAsC;EACzD,MAAM,WAAW,MAAM,YAAY,QAAQ;EAC3C,MAAM,SAAS,MAAM;EACrB,MAAM,IAAI,SAAQ,YAAW,WAAW,SAAS,UAAU,CAAC;EAC5D,OAAO,MAAM,SAAS,KAAK;CAC7B;CAEA,MAAM,OAAyB;EAC7B,MAAM,EAAC,YAAW,MAAM,KAAKA,SAAS,KAAK,eAAe;EAC1D,MAAM,KAAKA,SAAS,KAAK,kBAAkB;EAC3C,KAAKA,SAAS,WAAW;EACzB,OAAO;CACT;CAEA,MAAM,eAAe,IAAgB,UAAkB;EACrD,MAAM,EAAC,YAAW,MAAM,KAAKA,SAAS,KAAK,eAAe;EAC1D,MAAM,OAAO,KAAK,OAAO,GAAG,GAAG,SAAS,YAAY;EACpD,MAAM,UAAU,MAAM,KAAK,UAAU,OAAO,CAAC;EAC7C,GAAG,OAAO,wBAAwB,MAAM;EACxC,KAAKA,SAAS,WAAW;CAC3B;AACF;AAEA,IAAM,sBAAsB;;;;;AAM5B,SAAgB,sBACd,QACA,YACA,aACM;CACN,IAAI,CAAC,QACH;CAEF,OAAO,cAA8B,WAAW,OAAM,QAAO;EAC3D,IAAI,IAAI,WAAW,KAAA,GAAW;GAC5B,MAAM,WAAW,WAAW,QAAQ,qBAAqB,EAAE;GAE3D,IAAI,EADgB,IAAI,WAAW,cAAc,IAAI,WAAW,WAE9D;GAEF,IACE,IAAI,gBAAgB,KAAA,KACpB,gBAAgB,KAAA,KAChB,IAAI,gBAAgB,aAEpB;EAEJ;EACA,IAAI;GACF,MAAM,UAAU,MAAM,YAAY,QAAQ,IAAI,UAAU;GACxD,OAAO,KAAK,CAAC,mBAAmB;IAAC,IAAI,IAAI;IAAI,MAAM;IAAY;GAAO,CAAC,CAAC;EAC1E,SAAS,KAAK;GACZ,OAAO,KAAK,CACV,mBACA;IAAC,IAAI,IAAI;IAAI,MAAM;IAAY,OAAO,OAAO,GAAG;GAAC,CACnD,CAAC;EACH;CACF,CAAC;AACH"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"syncer-ws-message-handler.d.ts","sourceRoot":"","sources":["../../../../../zero-cache/src/workers/syncer-ws-message-handler.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AAOjD,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,kCAAkC,CAAC;AAC/D,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,gCAAgC,CAAC;AAC5D,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,+BAA+B,CAAC;AAC1D,OAAO,EACL,KAAK,wBAAwB,EAE9B,MAAM,uDAAuD,CAAC;AAC/D,OAAO,EAAC,KAAK,UAAU,EAAC,MAAM,wCAAwC,CAAC;AACvE,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,qBAAqB,CAAC;AACvD,OAAO,KAAK,EAAC,aAAa,EAAE,cAAc,EAAC,MAAM,iBAAiB,CAAC;AAiBnE,qBAAa,sBAAuB,YAAW,cAAc;;gBAWzD,EAAE,EAAE,UAAU,EACd,aAAa,EAAE,aAAa,EAC5B,kBAAkB,EAAE,wBAAwB,EAC5C,UAAU,EAAE,UAAU,EACtB,OAAO,EAAE,OAAO,GAAG,SAAS,EAC5B,MAAM,EAAE,MAAM,GAAG,SAAS;IAoBtB,aAAa,CAAC,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"syncer-ws-message-handler.d.ts","sourceRoot":"","sources":["../../../../../zero-cache/src/workers/syncer-ws-message-handler.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AAOjD,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,kCAAkC,CAAC;AAC/D,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,gCAAgC,CAAC;AAC5D,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,+BAA+B,CAAC;AAC1D,OAAO,EACL,KAAK,wBAAwB,EAE9B,MAAM,uDAAuD,CAAC;AAC/D,OAAO,EAAC,KAAK,UAAU,EAAC,MAAM,wCAAwC,CAAC;AACvE,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,qBAAqB,CAAC;AACvD,OAAO,KAAK,EAAC,aAAa,EAAE,cAAc,EAAC,MAAM,iBAAiB,CAAC;AAiBnE,qBAAa,sBAAuB,YAAW,cAAc;;gBAWzD,EAAE,EAAE,UAAU,EACd,aAAa,EAAE,aAAa,EAC5B,kBAAkB,EAAE,wBAAwB,EAC5C,UAAU,EAAE,UAAU,EACtB,OAAO,EAAE,OAAO,GAAG,SAAS,EAC5B,MAAM,EAAE,MAAM,GAAG,SAAS;IAoBtB,aAAa,CAAC,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;CA8N7D"}
|
|
@@ -86,22 +86,27 @@ var SyncerWsMessageHandler = class {
|
|
|
86
86
|
}];
|
|
87
87
|
const auth = this.#connContextManager.mustGetConnectionContext(this.#connectionSelector).auth;
|
|
88
88
|
assert(auth?.type !== "opaque", "Only JWT auth is supported for CRUD mutations");
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
const
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
errors
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
89
|
+
mutagen.ref();
|
|
90
|
+
try {
|
|
91
|
+
return [await this.#mutationLock.withLock(async () => {
|
|
92
|
+
const errors = [];
|
|
93
|
+
for (const mutation of mutations) {
|
|
94
|
+
const maybeError = await mutagen.processMutation(mutation, auth?.decoded, this.#pusher !== void 0);
|
|
95
|
+
if (maybeError !== void 0) errors.push({
|
|
96
|
+
kind: maybeError[0],
|
|
97
|
+
message: maybeError[1],
|
|
98
|
+
origin: ZeroCache
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
if (errors.length > 0) return {
|
|
102
|
+
type: "transient",
|
|
103
|
+
errors
|
|
104
|
+
};
|
|
105
|
+
return { type: "ok" };
|
|
106
|
+
})];
|
|
107
|
+
} finally {
|
|
108
|
+
mutagen.unref();
|
|
109
|
+
}
|
|
105
110
|
}));
|
|
106
111
|
case "changeDesiredQueries":
|
|
107
112
|
await withTraceparent(msg[1].traceparent, () => startAsyncSpan(tracer, "connection.changeDesiredQueries", () => viewSyncer.changeDesiredQueries(this.#connectionSelector, msg)));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"syncer-ws-message-handler.js","names":["#viewSyncer","#mutagen","#mutationLock","#lc","#clientGroupID","#connectionSelector","#connContextManager","#pusher"],"sources":["../../../../../zero-cache/src/workers/syncer-ws-message-handler.ts"],"sourcesContent":["import {ROOT_CONTEXT, context, propagation, trace} from '@opentelemetry/api';\nimport {Lock} from '@rocicorp/lock';\nimport type {LogContext} from '@rocicorp/logger';\nimport {startAsyncSpan, startSpan} from '../../../otel/src/span.ts';\nimport {version} from '../../../otel/src/version.ts';\nimport {assert, unreachable} from '../../../shared/src/asserts.ts';\nimport {ErrorKind} from '../../../zero-protocol/src/error-kind.ts';\nimport {ErrorOrigin} from '../../../zero-protocol/src/error-origin.ts';\nimport type {ErrorBody} from '../../../zero-protocol/src/error.ts';\nimport type {Upstream} from '../../../zero-protocol/src/up.ts';\nimport type {Mutagen} from '../services/mutagen/mutagen.ts';\nimport type {Pusher} from '../services/mutagen/pusher.ts';\nimport {\n type ConnectionContextManager,\n type ConnectionSelector,\n} from '../services/view-syncer/connection-context-manager.ts';\nimport {type ViewSyncer} from '../services/view-syncer/view-syncer.ts';\nimport type {ConnectParams} from './connect-params.ts';\nimport type {HandlerResult, MessageHandler} from './connection.ts';\n\nconst tracer = trace.getTracer('syncer-ws-server', version);\n\n/**\n * Wraps a function in an OTEL context extracted from a W3C traceparent header.\n * This enables distributed tracing from the client through zero-cache to\n * the user's API server.\n */\nfunction withTraceparent<T>(traceparent: string | undefined, fn: () => T): T {\n if (!traceparent) {\n return fn();\n }\n const extracted = propagation.extract(ROOT_CONTEXT, {traceparent});\n return context.with(extracted, fn);\n}\n\nexport class SyncerWsMessageHandler implements MessageHandler {\n readonly #viewSyncer: ViewSyncer;\n readonly #mutagen: Mutagen | undefined;\n readonly #mutationLock: Lock;\n readonly #lc: LogContext;\n readonly #clientGroupID: string;\n readonly #connectionSelector: ConnectionSelector;\n readonly #connContextManager: ConnectionContextManager;\n readonly #pusher: Pusher | undefined;\n\n constructor(\n lc: LogContext,\n connectParams: ConnectParams,\n connContextManager: ConnectionContextManager,\n viewSyncer: ViewSyncer,\n mutagen: Mutagen | undefined,\n pusher: Pusher | undefined,\n ) {\n const {clientGroupID, clientID, wsID} = connectParams;\n this.#viewSyncer = viewSyncer;\n this.#mutagen = mutagen;\n this.#connContextManager = connContextManager;\n this.#mutationLock = new Lock();\n this.#lc = lc\n .withContext('connection')\n .withContext('clientID', clientID)\n .withContext('clientGroupID', clientGroupID)\n .withContext('wsID', wsID);\n this.#clientGroupID = clientGroupID;\n this.#pusher = pusher;\n this.#connectionSelector = {\n clientID,\n wsID,\n };\n }\n\n async handleMessage(msg: Upstream): Promise<HandlerResult[]> {\n const lc = this.#lc;\n const msgType = msg[0];\n const viewSyncer = this.#viewSyncer;\n switch (msgType) {\n case 'ping':\n lc.error?.('Ping is not supported at this layer by Zero');\n break;\n case 'pull':\n lc.error?.('Pull is not supported by Zero');\n break;\n case 'push': {\n return withTraceparent(msg[1].traceparent, () =>\n startAsyncSpan<HandlerResult[]>(\n tracer,\n 'connection.push',\n async () => {\n const {clientGroupID, mutations} = msg[1];\n if (clientGroupID !== this.#clientGroupID) {\n return [\n {\n type: 'fatal',\n error: {\n kind: ErrorKind.InvalidPush,\n message:\n `clientGroupID in mutation \"${clientGroupID}\" does not match ` +\n `clientGroupID of connection \"${this.#clientGroupID}`,\n origin: ErrorOrigin.ZeroCache,\n },\n } satisfies HandlerResult,\n ];\n }\n\n if (mutations.length === 0) {\n return [\n {\n type: 'ok',\n },\n ];\n }\n\n // The client only ever sends 1 mutation per push.\n // #pusher will throw if it sees a CRUD mutation.\n // #mutagen will throw if it see a custom mutation.\n if (mutations[0].type === 'custom') {\n if (!this.#pusher) {\n return [\n {\n type: 'fatal',\n error: {\n kind: ErrorKind.InvalidPush,\n message:\n 'A ZERO_MUTATE_URL must be set in order to process custom mutations.',\n origin: ErrorOrigin.ZeroCache,\n },\n } satisfies HandlerResult,\n ];\n }\n return [\n this.#pusher.enqueuePush(this.#connectionSelector, msg[1]),\n ];\n }\n\n const mutagen = this.#mutagen;\n if (!mutagen) {\n return [\n {\n type: 'fatal',\n error: {\n kind: ErrorKind.InvalidPush,\n message: `Support for legacy CRUD mutations is disabled`,\n origin: ErrorOrigin.ZeroCache,\n },\n } satisfies HandlerResult,\n ];\n }\n\n const auth = this.#connContextManager.mustGetConnectionContext(\n this.#connectionSelector,\n ).auth;\n assert(\n auth?.type !== 'opaque',\n 'Only JWT auth is supported for CRUD mutations',\n );\n\n // Hold a connection-level lock while processing mutations so that:\n // 1. Mutations are processed in the order in which they are received and\n // 2. A single view syncer connection cannot hog multiple upstream connections.\n const ret = await this.#mutationLock.withLock(async () => {\n const errors: ErrorBody[] = [];\n for (const mutation of mutations) {\n const maybeError = await mutagen.processMutation(\n mutation,\n auth?.decoded,\n this.#pusher !== undefined,\n );\n if (maybeError !== undefined) {\n errors.push({\n kind: maybeError[0],\n message: maybeError[1],\n origin: ErrorOrigin.ZeroCache,\n });\n }\n }\n if (errors.length > 0) {\n return {type: 'transient', errors} satisfies HandlerResult;\n }\n return {type: 'ok'} satisfies HandlerResult;\n });\n return [ret];\n },\n ),\n );\n }\n case 'changeDesiredQueries':\n await withTraceparent(msg[1].traceparent, () =>\n startAsyncSpan(tracer, 'connection.changeDesiredQueries', () =>\n viewSyncer.changeDesiredQueries(this.#connectionSelector, msg),\n ),\n );\n break;\n case 'updateAuth':\n await startAsyncSpan(tracer, 'connection.updateAuth', async () => {\n const initialConnCtx =\n this.#connContextManager.mustGetConnectionContext(\n this.#connectionSelector,\n );\n const updatedConnCtx = await this.#connContextManager.updateAuth(\n this.#connectionSelector,\n msg[1],\n );\n const authRevisionChanged =\n updatedConnCtx.revision !== initialConnCtx.revision;\n\n await viewSyncer.updateAuth(\n this.#connectionSelector,\n msg,\n authRevisionChanged,\n );\n });\n break;\n case 'deleteClients': {\n const deletedClientIDs = await startAsyncSpan(\n tracer,\n 'connection.deleteClients',\n () => viewSyncer.deleteClients(this.#connectionSelector, msg),\n );\n if (this.#pusher && deletedClientIDs.length > 0) {\n await this.#pusher.deleteClientMutations(\n this.#connectionSelector,\n deletedClientIDs,\n );\n }\n break;\n }\n case 'initConnection': {\n this.#connContextManager.initConnection(\n this.#connectionSelector,\n msg[1],\n );\n return withTraceparent(msg[1].traceparent, () => {\n const ret: HandlerResult[] = [\n {\n type: 'stream',\n source: 'viewSyncer',\n stream: startSpan(tracer, 'connection.initConnection', () =>\n viewSyncer.initConnection(this.#connectionSelector, msg),\n ),\n },\n ];\n\n // Given we support both CRUD and Custom mutators,\n // we do not initialize the `pusher` unless the user has opted\n // into custom mutations. We detect that by checking\n // if the pushURL has been set.\n if (this.#pusher) {\n ret.push({\n type: 'stream',\n source: 'pusher',\n stream: this.#pusher.initConnection(this.#connectionSelector),\n });\n }\n\n return ret;\n });\n }\n case 'closeConnection':\n // This message is deprecated and no longer used.\n break;\n\n case 'inspect':\n await startAsyncSpan(tracer, 'connection.inspect', () =>\n viewSyncer.inspect(this.#connectionSelector, msg),\n );\n break;\n\n case 'ackMutationResponses':\n if (this.#pusher) {\n await this.#pusher.ackMutationResponses(\n this.#connectionSelector,\n msg[1],\n );\n }\n break;\n\n default:\n unreachable(msgType);\n }\n\n return [{type: 'ok'}];\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"syncer-ws-message-handler.js","names":["#viewSyncer","#mutagen","#mutationLock","#lc","#clientGroupID","#connectionSelector","#connContextManager","#pusher"],"sources":["../../../../../zero-cache/src/workers/syncer-ws-message-handler.ts"],"sourcesContent":["import {ROOT_CONTEXT, context, propagation, trace} from '@opentelemetry/api';\nimport {Lock} from '@rocicorp/lock';\nimport type {LogContext} from '@rocicorp/logger';\nimport {startAsyncSpan, startSpan} from '../../../otel/src/span.ts';\nimport {version} from '../../../otel/src/version.ts';\nimport {assert, unreachable} from '../../../shared/src/asserts.ts';\nimport {ErrorKind} from '../../../zero-protocol/src/error-kind.ts';\nimport {ErrorOrigin} from '../../../zero-protocol/src/error-origin.ts';\nimport type {ErrorBody} from '../../../zero-protocol/src/error.ts';\nimport type {Upstream} from '../../../zero-protocol/src/up.ts';\nimport type {Mutagen} from '../services/mutagen/mutagen.ts';\nimport type {Pusher} from '../services/mutagen/pusher.ts';\nimport {\n type ConnectionContextManager,\n type ConnectionSelector,\n} from '../services/view-syncer/connection-context-manager.ts';\nimport {type ViewSyncer} from '../services/view-syncer/view-syncer.ts';\nimport type {ConnectParams} from './connect-params.ts';\nimport type {HandlerResult, MessageHandler} from './connection.ts';\n\nconst tracer = trace.getTracer('syncer-ws-server', version);\n\n/**\n * Wraps a function in an OTEL context extracted from a W3C traceparent header.\n * This enables distributed tracing from the client through zero-cache to\n * the user's API server.\n */\nfunction withTraceparent<T>(traceparent: string | undefined, fn: () => T): T {\n if (!traceparent) {\n return fn();\n }\n const extracted = propagation.extract(ROOT_CONTEXT, {traceparent});\n return context.with(extracted, fn);\n}\n\nexport class SyncerWsMessageHandler implements MessageHandler {\n readonly #viewSyncer: ViewSyncer;\n readonly #mutagen: Mutagen | undefined;\n readonly #mutationLock: Lock;\n readonly #lc: LogContext;\n readonly #clientGroupID: string;\n readonly #connectionSelector: ConnectionSelector;\n readonly #connContextManager: ConnectionContextManager;\n readonly #pusher: Pusher | undefined;\n\n constructor(\n lc: LogContext,\n connectParams: ConnectParams,\n connContextManager: ConnectionContextManager,\n viewSyncer: ViewSyncer,\n mutagen: Mutagen | undefined,\n pusher: Pusher | undefined,\n ) {\n const {clientGroupID, clientID, wsID} = connectParams;\n this.#viewSyncer = viewSyncer;\n this.#mutagen = mutagen;\n this.#connContextManager = connContextManager;\n this.#mutationLock = new Lock();\n this.#lc = lc\n .withContext('connection')\n .withContext('clientID', clientID)\n .withContext('clientGroupID', clientGroupID)\n .withContext('wsID', wsID);\n this.#clientGroupID = clientGroupID;\n this.#pusher = pusher;\n this.#connectionSelector = {\n clientID,\n wsID,\n };\n }\n\n async handleMessage(msg: Upstream): Promise<HandlerResult[]> {\n const lc = this.#lc;\n const msgType = msg[0];\n const viewSyncer = this.#viewSyncer;\n switch (msgType) {\n case 'ping':\n lc.error?.('Ping is not supported at this layer by Zero');\n break;\n case 'pull':\n lc.error?.('Pull is not supported by Zero');\n break;\n case 'push': {\n return withTraceparent(msg[1].traceparent, () =>\n startAsyncSpan<HandlerResult[]>(\n tracer,\n 'connection.push',\n async () => {\n const {clientGroupID, mutations} = msg[1];\n if (clientGroupID !== this.#clientGroupID) {\n return [\n {\n type: 'fatal',\n error: {\n kind: ErrorKind.InvalidPush,\n message:\n `clientGroupID in mutation \"${clientGroupID}\" does not match ` +\n `clientGroupID of connection \"${this.#clientGroupID}`,\n origin: ErrorOrigin.ZeroCache,\n },\n } satisfies HandlerResult,\n ];\n }\n\n if (mutations.length === 0) {\n return [\n {\n type: 'ok',\n },\n ];\n }\n\n // The client only ever sends 1 mutation per push.\n // #pusher will throw if it sees a CRUD mutation.\n // #mutagen will throw if it see a custom mutation.\n if (mutations[0].type === 'custom') {\n if (!this.#pusher) {\n return [\n {\n type: 'fatal',\n error: {\n kind: ErrorKind.InvalidPush,\n message:\n 'A ZERO_MUTATE_URL must be set in order to process custom mutations.',\n origin: ErrorOrigin.ZeroCache,\n },\n } satisfies HandlerResult,\n ];\n }\n return [\n this.#pusher.enqueuePush(this.#connectionSelector, msg[1]),\n ];\n }\n\n const mutagen = this.#mutagen;\n if (!mutagen) {\n return [\n {\n type: 'fatal',\n error: {\n kind: ErrorKind.InvalidPush,\n message: `Support for legacy CRUD mutations is disabled`,\n origin: ErrorOrigin.ZeroCache,\n },\n } satisfies HandlerResult,\n ];\n }\n\n const auth = this.#connContextManager.mustGetConnectionContext(\n this.#connectionSelector,\n ).auth;\n assert(\n auth?.type !== 'opaque',\n 'Only JWT auth is supported for CRUD mutations',\n );\n\n // Hold a ref on the mutagen for the duration of the push so that\n // the connection closing mid-push does not stop the service\n // (closing its replica handle) between two of its mutations.\n // (The connection holds a ref while open, and messages are not\n // dispatched after it has closed, so the service is running\n // here.)\n mutagen.ref();\n try {\n // Hold a connection-level lock while processing mutations so that:\n // 1. Mutations are processed in the order in which they are received and\n // 2. A single view syncer connection cannot hog multiple upstream connections.\n const ret = await this.#mutationLock.withLock(async () => {\n const errors: ErrorBody[] = [];\n for (const mutation of mutations) {\n const maybeError = await mutagen.processMutation(\n mutation,\n auth?.decoded,\n this.#pusher !== undefined,\n );\n if (maybeError !== undefined) {\n errors.push({\n kind: maybeError[0],\n message: maybeError[1],\n origin: ErrorOrigin.ZeroCache,\n });\n }\n }\n if (errors.length > 0) {\n return {type: 'transient', errors} satisfies HandlerResult;\n }\n return {type: 'ok'} satisfies HandlerResult;\n });\n return [ret];\n } finally {\n mutagen.unref();\n }\n },\n ),\n );\n }\n case 'changeDesiredQueries':\n await withTraceparent(msg[1].traceparent, () =>\n startAsyncSpan(tracer, 'connection.changeDesiredQueries', () =>\n viewSyncer.changeDesiredQueries(this.#connectionSelector, msg),\n ),\n );\n break;\n case 'updateAuth':\n await startAsyncSpan(tracer, 'connection.updateAuth', async () => {\n const initialConnCtx =\n this.#connContextManager.mustGetConnectionContext(\n this.#connectionSelector,\n );\n const updatedConnCtx = await this.#connContextManager.updateAuth(\n this.#connectionSelector,\n msg[1],\n );\n const authRevisionChanged =\n updatedConnCtx.revision !== initialConnCtx.revision;\n\n await viewSyncer.updateAuth(\n this.#connectionSelector,\n msg,\n authRevisionChanged,\n );\n });\n break;\n case 'deleteClients': {\n const deletedClientIDs = await startAsyncSpan(\n tracer,\n 'connection.deleteClients',\n () => viewSyncer.deleteClients(this.#connectionSelector, msg),\n );\n if (this.#pusher && deletedClientIDs.length > 0) {\n await this.#pusher.deleteClientMutations(\n this.#connectionSelector,\n deletedClientIDs,\n );\n }\n break;\n }\n case 'initConnection': {\n this.#connContextManager.initConnection(\n this.#connectionSelector,\n msg[1],\n );\n return withTraceparent(msg[1].traceparent, () => {\n const ret: HandlerResult[] = [\n {\n type: 'stream',\n source: 'viewSyncer',\n stream: startSpan(tracer, 'connection.initConnection', () =>\n viewSyncer.initConnection(this.#connectionSelector, msg),\n ),\n },\n ];\n\n // Given we support both CRUD and Custom mutators,\n // we do not initialize the `pusher` unless the user has opted\n // into custom mutations. We detect that by checking\n // if the pushURL has been set.\n if (this.#pusher) {\n ret.push({\n type: 'stream',\n source: 'pusher',\n stream: this.#pusher.initConnection(this.#connectionSelector),\n });\n }\n\n return ret;\n });\n }\n case 'closeConnection':\n // This message is deprecated and no longer used.\n break;\n\n case 'inspect':\n await startAsyncSpan(tracer, 'connection.inspect', () =>\n viewSyncer.inspect(this.#connectionSelector, msg),\n );\n break;\n\n case 'ackMutationResponses':\n if (this.#pusher) {\n await this.#pusher.ackMutationResponses(\n this.#connectionSelector,\n msg[1],\n );\n }\n break;\n\n default:\n unreachable(msgType);\n }\n\n return [{type: 'ok'}];\n }\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"syncer.d.ts","sourceRoot":"","sources":["../../../../../zero-cache/src/workers/syncer.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"syncer.d.ts","sourceRoot":"","sources":["../../../../../zero-cache/src/workers/syncer.ts"],"names":[],"mappings":"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"}
|
|
@@ -14,7 +14,7 @@ import { DrainCoordinator } from "../services/view-syncer/drain-coordinator.js";
|
|
|
14
14
|
import { Connection, sendError } from "./connection.js";
|
|
15
15
|
import { SyncerWsMessageHandler } from "./syncer-ws-message-handler.js";
|
|
16
16
|
import { resolver } from "@rocicorp/resolver";
|
|
17
|
-
import { WebSocketServer } from "ws";
|
|
17
|
+
import { WebSocket, WebSocketServer } from "ws";
|
|
18
18
|
import { pid } from "node:process";
|
|
19
19
|
//#region ../zero-cache/src/workers/syncer.ts
|
|
20
20
|
function computePipelineDedupStats(viewSyncers) {
|
|
@@ -341,6 +341,15 @@ var Syncer = class {
|
|
|
341
341
|
recordConnectionFailure("internal");
|
|
342
342
|
throw e;
|
|
343
343
|
}
|
|
344
|
+
if (ws.readyState !== WebSocket.OPEN) {
|
|
345
|
+
this.#lc.debug?.("websocket closed while resolving auth", {
|
|
346
|
+
clientGroupID,
|
|
347
|
+
clientID,
|
|
348
|
+
readyState: ws.readyState
|
|
349
|
+
});
|
|
350
|
+
recordConnectionFailure("closed_during_auth");
|
|
351
|
+
return;
|
|
352
|
+
}
|
|
344
353
|
const viewSyncer = this.#viewSyncers.getService(clientGroupID);
|
|
345
354
|
const connContextManager = viewSyncer.connContextManager;
|
|
346
355
|
const group = connContextManager.getGroupState();
|