@dxos/client-services 0.10.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/chunk-client-services-layer.mjs +11425 -0
- package/dist/lib/chunk-client-services-layer.mjs.map +1 -0
- package/dist/lib/chunk-decorate.mjs +9 -0
- package/dist/lib/index.mjs +731 -0
- package/dist/lib/index.mjs.map +1 -0
- package/dist/lib/packlets/diagnostics/browser-diagnostics-broadcast.mjs +72 -0
- package/dist/lib/packlets/diagnostics/browser-diagnostics-broadcast.mjs.map +1 -0
- package/dist/lib/packlets/diagnostics/diagnostics-broadcast.mjs +14 -0
- package/dist/lib/packlets/diagnostics/diagnostics-broadcast.mjs.map +1 -0
- package/dist/lib/packlets/locks/browser.mjs +105 -0
- package/dist/lib/packlets/locks/browser.mjs.map +1 -0
- package/dist/lib/packlets/locks/node.mjs +53 -0
- package/dist/lib/packlets/locks/node.mjs.map +1 -0
- package/dist/lib/testing.mjs +570 -0
- package/dist/lib/testing.mjs.map +1 -0
- package/dist/types/src/index.d.ts +2 -0
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/packlets/agents/edge-agent-manager.d.ts +21 -4
- package/dist/types/src/packlets/agents/edge-agent-manager.d.ts.map +1 -1
- package/dist/types/src/packlets/agents/edge-agent-service.d.ts +8 -7
- package/dist/types/src/packlets/agents/edge-agent-service.d.ts.map +1 -1
- package/dist/types/src/packlets/devices/devices-service.d.ts +7 -5
- package/dist/types/src/packlets/devices/devices-service.d.ts.map +1 -1
- package/dist/types/src/packlets/devtools/devtools.d.ts +30 -29
- package/dist/types/src/packlets/devtools/devtools.d.ts.map +1 -1
- package/dist/types/src/packlets/devtools/feeds.d.ts +1 -1
- package/dist/types/src/packlets/devtools/feeds.d.ts.map +1 -1
- package/dist/types/src/packlets/devtools/network.d.ts +2 -1
- package/dist/types/src/packlets/devtools/network.d.ts.map +1 -1
- package/dist/types/src/packlets/devtools/spaces.d.ts.map +1 -1
- package/dist/types/src/packlets/diagnostics/diagnostics-broadcast.d.ts +2 -2
- package/dist/types/src/packlets/diagnostics/diagnostics-broadcast.d.ts.map +1 -1
- package/dist/types/src/packlets/diagnostics/diagnostics-collector.d.ts.map +1 -1
- package/dist/types/src/packlets/diagnostics/diagnostics.d.ts +1 -8
- package/dist/types/src/packlets/diagnostics/diagnostics.d.ts.map +1 -1
- package/dist/types/src/packlets/identity/authenticator.d.ts +1 -1
- package/dist/types/src/packlets/identity/authenticator.d.ts.map +1 -1
- package/dist/types/src/packlets/identity/contacts-service.d.ts +9 -6
- package/dist/types/src/packlets/identity/contacts-service.d.ts.map +1 -1
- package/dist/types/src/packlets/identity/identity-manager.d.ts +32 -3
- package/dist/types/src/packlets/identity/identity-manager.d.ts.map +1 -1
- package/dist/types/src/packlets/identity/identity-recovery-manager.d.ts +23 -4
- package/dist/types/src/packlets/identity/identity-recovery-manager.d.ts.map +1 -1
- package/dist/types/src/packlets/identity/identity-service.d.ts +15 -20
- package/dist/types/src/packlets/identity/identity-service.d.ts.map +1 -1
- package/dist/types/src/packlets/identity/identity.d.ts +2 -2
- package/dist/types/src/packlets/identity/identity.d.ts.map +1 -1
- package/dist/types/src/packlets/invitations/edge-invitation-handler.d.ts.map +1 -1
- package/dist/types/src/packlets/invitations/invitations-handler.d.ts +17 -0
- package/dist/types/src/packlets/invitations/invitations-handler.d.ts.map +1 -1
- package/dist/types/src/packlets/invitations/invitations-manager.d.ts +25 -4
- package/dist/types/src/packlets/invitations/invitations-manager.d.ts.map +1 -1
- package/dist/types/src/packlets/invitations/invitations-service.d.ts +11 -11
- package/dist/types/src/packlets/invitations/invitations-service.d.ts.map +1 -1
- package/dist/types/src/packlets/logging/logging-service.d.ts +14 -12
- package/dist/types/src/packlets/logging/logging-service.d.ts.map +1 -1
- package/dist/types/src/packlets/metadata/index.d.ts +3 -0
- package/dist/types/src/packlets/metadata/index.d.ts.map +1 -0
- package/dist/types/src/packlets/metadata/metadata-store.d.ts +107 -0
- package/dist/types/src/packlets/metadata/metadata-store.d.ts.map +1 -0
- package/dist/types/src/packlets/metadata/metadata-store.test.d.ts +2 -0
- package/dist/types/src/packlets/metadata/metadata-store.test.d.ts.map +1 -0
- package/dist/types/src/packlets/metadata/sqlite-metadata-store.d.ts +65 -0
- package/dist/types/src/packlets/metadata/sqlite-metadata-store.d.ts.map +1 -0
- package/dist/types/src/packlets/network/network-service.d.ts +15 -14
- package/dist/types/src/packlets/network/network-service.d.ts.map +1 -1
- package/dist/types/src/packlets/pipeline/codec.d.ts +11 -0
- package/dist/types/src/packlets/pipeline/codec.d.ts.map +1 -0
- package/dist/types/src/packlets/pipeline/feeds.d.ts +7 -0
- package/dist/types/src/packlets/pipeline/feeds.d.ts.map +1 -0
- package/dist/types/src/packlets/pipeline/index.d.ts +5 -0
- package/dist/types/src/packlets/pipeline/index.d.ts.map +1 -0
- package/dist/types/src/packlets/pipeline/message-selector.d.ts +11 -0
- package/dist/types/src/packlets/pipeline/message-selector.d.ts.map +1 -0
- package/dist/types/src/packlets/pipeline/pipeline-stress.test.d.ts +2 -0
- package/dist/types/src/packlets/pipeline/pipeline-stress.test.d.ts.map +1 -0
- package/dist/types/src/packlets/pipeline/pipeline.d.ts +131 -0
- package/dist/types/src/packlets/pipeline/pipeline.d.ts.map +1 -0
- package/dist/types/src/packlets/pipeline/pipeline.test.d.ts +2 -0
- package/dist/types/src/packlets/pipeline/pipeline.test.d.ts.map +1 -0
- package/dist/types/src/packlets/pipeline/testing/index.d.ts +2 -0
- package/dist/types/src/packlets/pipeline/testing/index.d.ts.map +1 -0
- package/dist/types/src/packlets/pipeline/testing/test-feed-builder.d.ts +9 -0
- package/dist/types/src/packlets/pipeline/testing/test-feed-builder.d.ts.map +1 -0
- package/dist/types/src/packlets/pipeline/timeframe-clock.d.ts +31 -0
- package/dist/types/src/packlets/pipeline/timeframe-clock.d.ts.map +1 -0
- package/dist/types/src/packlets/services/client-services-layer.d.ts +21 -0
- package/dist/types/src/packlets/services/client-services-layer.d.ts.map +1 -0
- package/dist/types/src/packlets/services/cross-device-space-synchronizer.d.ts +28 -0
- package/dist/types/src/packlets/services/cross-device-space-synchronizer.d.ts.map +1 -0
- package/dist/types/src/packlets/services/effect-rpc.test.d.ts +2 -0
- package/dist/types/src/packlets/services/effect-rpc.test.d.ts.map +1 -0
- package/dist/types/src/packlets/services/feed-syncer.d.ts +22 -2
- package/dist/types/src/packlets/services/feed-syncer.d.ts.map +1 -1
- package/dist/types/src/packlets/services/index.d.ts +2 -2
- package/dist/types/src/packlets/services/index.d.ts.map +1 -1
- package/dist/types/src/packlets/services/platform.d.ts.map +1 -1
- package/dist/types/src/packlets/services/service-context.d.ts +38 -57
- package/dist/types/src/packlets/services/service-context.d.ts.map +1 -1
- package/dist/types/src/packlets/services/service-host.d.ts +82 -31
- package/dist/types/src/packlets/services/service-host.d.ts.map +1 -1
- package/dist/types/src/packlets/services/sqlite-storage.d.ts +29 -0
- package/dist/types/src/packlets/services/sqlite-storage.d.ts.map +1 -1
- package/dist/types/src/packlets/services/sqlite-storage.test.d.ts +2 -0
- package/dist/types/src/packlets/services/sqlite-storage.test.d.ts.map +1 -0
- package/dist/types/src/packlets/space/admission-discovery-extension.d.ts +30 -0
- package/dist/types/src/packlets/space/admission-discovery-extension.d.ts.map +1 -0
- package/dist/types/src/packlets/space/auth.d.ts +24 -0
- package/dist/types/src/packlets/space/auth.d.ts.map +1 -0
- package/dist/types/src/packlets/space/control-pipeline.d.ts +46 -0
- package/dist/types/src/packlets/space/control-pipeline.d.ts.map +1 -0
- package/dist/types/src/packlets/space/control-pipeline.test.d.ts +2 -0
- package/dist/types/src/packlets/space/control-pipeline.test.d.ts.map +1 -0
- package/dist/types/src/packlets/space/index.d.ts +6 -0
- package/dist/types/src/packlets/space/index.d.ts.map +1 -0
- package/dist/types/src/packlets/space/replication.browser.test.d.ts +2 -0
- package/dist/types/src/packlets/space/replication.browser.test.d.ts.map +1 -0
- package/dist/types/src/packlets/space/space-manager.browser.test.d.ts +2 -0
- package/dist/types/src/packlets/space/space-manager.browser.test.d.ts.map +1 -0
- package/dist/types/src/packlets/space/space-manager.d.ts +72 -0
- package/dist/types/src/packlets/space/space-manager.d.ts.map +1 -0
- package/dist/types/src/packlets/space/space-protocol.browser.test.d.ts +2 -0
- package/dist/types/src/packlets/space/space-protocol.browser.test.d.ts.map +1 -0
- package/dist/types/src/packlets/space/space-protocol.d.ts +99 -0
- package/dist/types/src/packlets/space/space-protocol.d.ts.map +1 -0
- package/dist/types/src/packlets/space/space-protocol.test.d.ts +2 -0
- package/dist/types/src/packlets/space/space-protocol.test.d.ts.map +1 -0
- package/dist/types/src/packlets/space/space.d.ts +65 -0
- package/dist/types/src/packlets/space/space.d.ts.map +1 -0
- package/dist/types/src/packlets/space/space.test.d.ts +2 -0
- package/dist/types/src/packlets/space/space.test.d.ts.map +1 -0
- package/dist/types/src/packlets/space/testing/change-metadata.d.ts +8 -0
- package/dist/types/src/packlets/space/testing/change-metadata.d.ts.map +1 -0
- package/dist/types/src/packlets/space/testing/index.d.ts +4 -0
- package/dist/types/src/packlets/space/testing/index.d.ts.map +1 -0
- package/dist/types/src/packlets/space/testing/test-agent-builder.d.ts +62 -0
- package/dist/types/src/packlets/space/testing/test-agent-builder.d.ts.map +1 -0
- package/dist/types/src/packlets/space-export/serialized-space-reader.d.ts +1 -1
- package/dist/types/src/packlets/space-export/serialized-space-reader.d.ts.map +1 -1
- package/dist/types/src/packlets/space-export/serialized-space-writer.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/data-space-manager.d.ts +40 -7
- package/dist/types/src/packlets/spaces/data-space-manager.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/data-space.d.ts +3 -1
- package/dist/types/src/packlets/spaces/data-space.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/genesis.d.ts +1 -1
- package/dist/types/src/packlets/spaces/genesis.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/spaces-service.d.ts +25 -23
- package/dist/types/src/packlets/spaces/spaces-service.d.ts.map +1 -1
- package/dist/types/src/packlets/storage/level.d.ts.map +1 -1
- package/dist/types/src/packlets/system/system-service.d.ts +18 -18
- package/dist/types/src/packlets/system/system-service.d.ts.map +1 -1
- package/dist/types/src/packlets/testing/invitation-utils.d.ts +1 -1
- package/dist/types/src/packlets/testing/invitation-utils.d.ts.map +1 -1
- package/dist/types/src/packlets/testing/test-builder.d.ts +7 -6
- package/dist/types/src/packlets/testing/test-builder.d.ts.map +1 -1
- package/dist/types/src/packlets/worker/worker-runtime.d.ts +41 -58
- package/dist/types/src/packlets/worker/worker-runtime.d.ts.map +1 -1
- package/dist/types/src/packlets/worker/worker-session.d.ts +21 -8
- package/dist/types/src/packlets/worker/worker-session.d.ts.map +1 -1
- package/dist/types/src/testing/index.d.ts +1 -0
- package/dist/types/src/testing/index.d.ts.map +1 -1
- package/dist/types/src/version.d.ts +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +52 -48
- package/src/index.ts +2 -0
- package/src/packlets/agents/edge-agent-manager.ts +56 -15
- package/src/packlets/agents/edge-agent-service.ts +25 -15
- package/src/packlets/devices/devices-service.test.ts +20 -19
- package/src/packlets/devices/devices-service.ts +17 -17
- package/src/packlets/devtools/devtools.ts +133 -75
- package/src/packlets/devtools/feeds.ts +2 -1
- package/src/packlets/devtools/network.ts +42 -12
- package/src/packlets/devtools/spaces.ts +1 -1
- package/src/packlets/diagnostics/diagnostics-broadcast.ts +4 -2
- package/src/packlets/diagnostics/diagnostics-collector.ts +5 -18
- package/src/packlets/diagnostics/diagnostics.ts +0 -11
- package/src/packlets/identity/authenticator.ts +2 -1
- package/src/packlets/identity/contacts-service.ts +46 -37
- package/src/packlets/identity/identity-manager.test.ts +3 -1
- package/src/packlets/identity/identity-manager.ts +73 -5
- package/src/packlets/identity/identity-recovery-manager.ts +56 -7
- package/src/packlets/identity/identity-service.test.ts +27 -18
- package/src/packlets/identity/identity-service.ts +114 -71
- package/src/packlets/identity/identity.test.ts +4 -9
- package/src/packlets/identity/identity.ts +1 -2
- package/src/packlets/invitations/edge-invitation-handler.ts +0 -1
- package/src/packlets/invitations/invitations-handler.ts +39 -3
- package/src/packlets/invitations/invitations-manager.ts +52 -4
- package/src/packlets/invitations/invitations-service.ts +54 -28
- package/src/packlets/logging/logging-service.ts +41 -29
- package/src/packlets/logging/logging.test.ts +28 -15
- package/src/packlets/metadata/index.ts +6 -0
- package/src/packlets/metadata/metadata-store.test.ts +49 -0
- package/src/packlets/metadata/metadata-store.ts +446 -0
- package/src/packlets/metadata/sqlite-metadata-store.ts +409 -0
- package/src/packlets/network/network-service.test.ts +19 -12
- package/src/packlets/network/network-service.ts +96 -29
- package/src/packlets/pipeline/codec.ts +18 -0
- package/src/packlets/pipeline/feeds.ts +22 -0
- package/src/packlets/pipeline/index.ts +8 -0
- package/src/packlets/pipeline/message-selector.ts +35 -0
- package/src/packlets/pipeline/pipeline-stress.test.ts +230 -0
- package/src/packlets/pipeline/pipeline.test.ts +140 -0
- package/src/packlets/pipeline/pipeline.ts +439 -0
- package/src/packlets/pipeline/testing/index.ts +5 -0
- package/src/packlets/pipeline/testing/test-feed-builder.ts +19 -0
- package/src/packlets/pipeline/timeframe-clock.ts +81 -0
- package/src/packlets/services/client-services-layer.ts +186 -0
- package/src/packlets/services/cross-device-space-synchronizer.ts +132 -0
- package/src/packlets/services/effect-rpc.test.ts +314 -0
- package/src/packlets/services/feed-syncer.ts +57 -3
- package/src/packlets/services/index.ts +2 -2
- package/src/packlets/services/platform.ts +0 -6
- package/src/packlets/services/service-context.ts +219 -522
- package/src/packlets/services/service-host.test.ts +34 -11
- package/src/packlets/services/service-host.ts +693 -213
- package/src/packlets/services/spec.md +106 -0
- package/src/packlets/services/sqlite-storage.test.ts +48 -0
- package/src/packlets/services/sqlite-storage.ts +117 -20
- package/src/packlets/space/admission-discovery-extension.ts +91 -0
- package/src/packlets/space/auth.ts +92 -0
- package/src/packlets/space/control-pipeline.test.ts +165 -0
- package/src/packlets/space/control-pipeline.ts +229 -0
- package/src/packlets/space/index.ts +9 -0
- package/src/packlets/space/replication.browser.test.ts +58 -0
- package/src/packlets/space/space-manager.browser.test.ts +40 -0
- package/src/packlets/space/space-manager.ts +224 -0
- package/src/packlets/space/space-protocol.browser.test.ts +129 -0
- package/src/packlets/space/space-protocol.test.ts +158 -0
- package/src/packlets/space/space-protocol.ts +308 -0
- package/src/packlets/space/space.test.ts +181 -0
- package/src/packlets/space/space.ts +196 -0
- package/src/packlets/space/testing/change-metadata.ts +27 -0
- package/src/packlets/space/testing/index.ts +7 -0
- package/src/packlets/space/testing/test-agent-builder.ts +252 -0
- package/src/packlets/space-export/serialized-space-reader.ts +3 -1
- package/src/packlets/space-export/serialized-space-writer.ts +53 -30
- package/src/packlets/space-export/space-archive.test.ts +30 -0
- package/src/packlets/spaces/data-space-manager.test.ts +1 -1
- package/src/packlets/spaces/data-space-manager.ts +148 -33
- package/src/packlets/spaces/data-space.ts +29 -18
- package/src/packlets/spaces/edge-feed-replicator.test.ts +1 -1
- package/src/packlets/spaces/genesis.ts +1 -1
- package/src/packlets/spaces/spaces-service.test.ts +35 -22
- package/src/packlets/spaces/spaces-service.ts +259 -180
- package/src/packlets/storage/level.ts +3 -1
- package/src/packlets/system/system-service.test.ts +31 -13
- package/src/packlets/system/system-service.ts +65 -37
- package/src/packlets/testing/invitation-utils.ts +3 -3
- package/src/packlets/testing/test-builder.ts +35 -20
- package/src/packlets/worker/worker-runtime.ts +222 -260
- package/src/packlets/worker/worker-session.ts +108 -91
- package/src/testing/index.ts +1 -0
- package/src/version.ts +1 -1
- package/dist/lib/browser/chunk-QCWEHHJW.mjs +0 -24
- package/dist/lib/browser/chunk-QCWEHHJW.mjs.map +0 -7
- package/dist/lib/browser/chunk-XJRPB3GA.mjs +0 -22
- package/dist/lib/browser/chunk-XJRPB3GA.mjs.map +0 -7
- package/dist/lib/browser/chunk-XU5R2BMF.mjs +0 -8837
- package/dist/lib/browser/chunk-XU5R2BMF.mjs.map +0 -7
- package/dist/lib/browser/index.mjs +0 -876
- package/dist/lib/browser/index.mjs.map +0 -7
- package/dist/lib/browser/meta.json +0 -1
- package/dist/lib/browser/packlets/diagnostics/browser-diagnostics-broadcast.mjs +0 -88
- package/dist/lib/browser/packlets/diagnostics/browser-diagnostics-broadcast.mjs.map +0 -7
- package/dist/lib/browser/packlets/diagnostics/diagnostics-broadcast.mjs +0 -11
- package/dist/lib/browser/packlets/diagnostics/diagnostics-broadcast.mjs.map +0 -7
- package/dist/lib/browser/packlets/locks/browser.mjs +0 -86
- package/dist/lib/browser/packlets/locks/browser.mjs.map +0 -7
- package/dist/lib/browser/packlets/locks/node.mjs +0 -48
- package/dist/lib/browser/packlets/locks/node.mjs.map +0 -7
- package/dist/lib/browser/testing/index.mjs +0 -436
- package/dist/lib/browser/testing/index.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-2DT3MZRL.mjs +0 -22
- package/dist/lib/node-esm/chunk-2DT3MZRL.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-2SZHAWBN.mjs +0 -24
- package/dist/lib/node-esm/chunk-2SZHAWBN.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-H5YTUD35.mjs +0 -8837
- package/dist/lib/node-esm/chunk-H5YTUD35.mjs.map +0 -7
- package/dist/lib/node-esm/index.mjs +0 -876
- package/dist/lib/node-esm/index.mjs.map +0 -7
- package/dist/lib/node-esm/meta.json +0 -1
- package/dist/lib/node-esm/packlets/diagnostics/browser-diagnostics-broadcast.mjs +0 -88
- package/dist/lib/node-esm/packlets/diagnostics/browser-diagnostics-broadcast.mjs.map +0 -7
- package/dist/lib/node-esm/packlets/diagnostics/diagnostics-broadcast.mjs +0 -11
- package/dist/lib/node-esm/packlets/diagnostics/diagnostics-broadcast.mjs.map +0 -7
- package/dist/lib/node-esm/packlets/locks/browser.mjs +0 -86
- package/dist/lib/node-esm/packlets/locks/browser.mjs.map +0 -7
- package/dist/lib/node-esm/packlets/locks/node.mjs +0 -48
- package/dist/lib/node-esm/packlets/locks/node.mjs.map +0 -7
- package/dist/lib/node-esm/testing/index.mjs +0 -436
- package/dist/lib/node-esm/testing/index.mjs.map +0 -7
- package/dist/types/src/packlets/services/client-rpc-server.d.ts +0 -24
- package/dist/types/src/packlets/services/client-rpc-server.d.ts.map +0 -1
- package/dist/types/src/packlets/services/service-registry.d.ts +0 -15
- package/dist/types/src/packlets/services/service-registry.d.ts.map +0 -1
- package/dist/types/src/packlets/services/service-registry.test.d.ts +0 -2
- package/dist/types/src/packlets/services/service-registry.test.d.ts.map +0 -1
- package/dist/types/src/testing/setup.d.ts +0 -3
- package/dist/types/src/testing/setup.d.ts.map +0 -1
- package/src/packlets/services/client-rpc-server.ts +0 -111
- package/src/packlets/services/service-registry.test.ts +0 -78
- package/src/packlets/services/service-registry.ts +0 -36
- package/src/testing/setup.ts +0 -11
|
@@ -3,25 +3,26 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
import * as Reactivity from '@effect/experimental/Reactivity';
|
|
6
|
+
import type * as RpcClient from '@effect/rpc/RpcClient';
|
|
7
|
+
import type * as RpcServer from '@effect/rpc/RpcServer';
|
|
6
8
|
import type * as SqlClient from '@effect/sql/SqlClient';
|
|
9
|
+
import * as Context_ from 'effect/Context';
|
|
7
10
|
import * as Effect from 'effect/Effect';
|
|
11
|
+
import * as Exit from 'effect/Exit';
|
|
8
12
|
import * as Layer from 'effect/Layer';
|
|
9
13
|
import * as ManagedRuntime from 'effect/ManagedRuntime';
|
|
14
|
+
import * as Scope from 'effect/Scope';
|
|
10
15
|
|
|
11
16
|
import { Trigger } from '@dxos/async';
|
|
12
|
-
import { DEFAULT_WORKER_BROADCAST_CHANNEL } from '@dxos/client-protocol';
|
|
13
17
|
import { type Config } from '@dxos/config';
|
|
14
18
|
import { Context } from '@dxos/context';
|
|
19
|
+
import { EffectEx } from '@dxos/effect';
|
|
15
20
|
import { invariant } from '@dxos/invariant';
|
|
16
21
|
import { log } from '@dxos/log';
|
|
17
|
-
import {
|
|
18
|
-
MemorySignalManager,
|
|
19
|
-
MemorySignalManagerContext,
|
|
20
|
-
WebsocketSignalManager,
|
|
21
|
-
setIdentityTags,
|
|
22
|
-
} from '@dxos/messaging';
|
|
22
|
+
import { MemorySignalManager, MemorySignalManagerContext, setIdentityTags } from '@dxos/messaging';
|
|
23
23
|
import { RtcTransportProxyFactory } from '@dxos/network-manager';
|
|
24
|
-
import {
|
|
24
|
+
import { makeInProcessClient } from '@dxos/protocols';
|
|
25
|
+
import { DevicesService, IdentityService } from '@dxos/protocols/rpc';
|
|
25
26
|
import * as SqlExport from '@dxos/sql-sqlite/SqlExport';
|
|
26
27
|
import * as SqliteClient from '@dxos/sql-sqlite/SqliteClient';
|
|
27
28
|
import * as SqlTransaction from '@dxos/sql-sqlite/SqlTransaction';
|
|
@@ -30,16 +31,17 @@ import { type MaybePromise } from '@dxos/util';
|
|
|
30
31
|
import { ClientServicesHost } from '../services';
|
|
31
32
|
import { WorkerSession } from './worker-session';
|
|
32
33
|
|
|
33
|
-
//
|
|
34
|
+
// Session transports are effect-rpc protocol layers handed over by the worker framework: appProtocol
|
|
35
|
+
// serves the client services (+ WorkerService); systemProtocol carries the reverse-direction
|
|
36
|
+
// BridgeService (worker→tab).
|
|
34
37
|
export type CreateSessionProps = {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
shellPort?:
|
|
38
|
+
appProtocol: RpcServer.Protocol['Type'];
|
|
39
|
+
systemProtocol: RpcClient.Protocol['Type'];
|
|
40
|
+
shellPort?: MessagePort;
|
|
38
41
|
onClose?: () => Promise<void>;
|
|
39
42
|
};
|
|
40
43
|
|
|
41
44
|
export type WorkerRuntimeOptions = {
|
|
42
|
-
channel?: string;
|
|
43
45
|
configProvider: () => MaybePromise<Config>;
|
|
44
46
|
acquireLock: () => Promise<void>;
|
|
45
47
|
releaseLock: () => void;
|
|
@@ -57,241 +59,233 @@ export type WorkerRuntimeOptions = {
|
|
|
57
59
|
};
|
|
58
60
|
|
|
59
61
|
/**
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
62
|
+
* Effect service surface for the dedicated-worker runtime.
|
|
63
|
+
*
|
|
64
|
+
* Manages connections from proxies (in tabs): tabs make requests to the `ClientServicesHost`, and
|
|
65
|
+
* provide a WebRTC gateway. Lifecycle (`start` / `stop`) is caller-driven — the worker framework
|
|
66
|
+
* builds the runtime after receiving init config, then drives sessions for their lifetime — so these
|
|
67
|
+
* are explicit programs rather than Layer finalizers.
|
|
63
68
|
*/
|
|
64
|
-
export
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
private _broadcastChannel?: BroadcastChannel;
|
|
77
|
-
private _sessionForNetworking?: WorkerSession; // TODO(burdon): Expose to client QueryStatusResponse.
|
|
78
|
-
private _config!: Config;
|
|
79
|
-
private _signalMetadataTags: any = { runtime: 'worker-runtime' };
|
|
80
|
-
private _signalTelemetryEnabled: boolean = false;
|
|
81
|
-
private _runtime!: ManagedRuntime.ManagedRuntime<
|
|
82
|
-
SqlTransaction.SqlTransaction | SqlClient.SqlClient | SqlExport.SqlExport,
|
|
83
|
-
never
|
|
84
|
-
>;
|
|
85
|
-
|
|
86
|
-
constructor({
|
|
87
|
-
channel = DEFAULT_WORKER_BROADCAST_CHANNEL,
|
|
88
|
-
configProvider,
|
|
89
|
-
acquireLock,
|
|
90
|
-
releaseLock,
|
|
91
|
-
onStop,
|
|
92
|
-
automaticallyConnectWebrtc = true,
|
|
93
|
-
sqliteLayer,
|
|
94
|
-
}: WorkerRuntimeOptions) {
|
|
95
|
-
this._configProvider = configProvider;
|
|
96
|
-
this._acquireLock = acquireLock;
|
|
97
|
-
this._releaseLock = releaseLock;
|
|
98
|
-
this._onStop = onStop;
|
|
99
|
-
this._channel = channel;
|
|
100
|
-
if (sqliteLayer) {
|
|
101
|
-
log.warn('Using testing SQLite layer');
|
|
102
|
-
}
|
|
103
|
-
this._runtime = ManagedRuntime.make(
|
|
104
|
-
SqlTransaction.layer
|
|
105
|
-
.pipe(Layer.provideMerge(sqliteLayer ?? LocalSqliteOpfsLayer), Layer.provideMerge(Reactivity.layer))
|
|
106
|
-
.pipe(Layer.orDie),
|
|
107
|
-
);
|
|
108
|
-
this._clientServices = new ClientServicesHost({
|
|
109
|
-
callbacks: {
|
|
110
|
-
onReset: async () => this.stop(),
|
|
111
|
-
},
|
|
112
|
-
runtime: this._runtime.runtimeEffect,
|
|
113
|
-
runtimeProps: {
|
|
114
|
-
// Auto-activate spaces that were previously active after leader changeover.
|
|
115
|
-
autoActivateSpaces: true,
|
|
116
|
-
},
|
|
117
|
-
});
|
|
118
|
-
this._automaticallyConnectWebrtc = automaticallyConnectWebrtc;
|
|
119
|
-
}
|
|
69
|
+
export interface WorkerRuntimeService {
|
|
70
|
+
/** The client services host served to connected tabs. */
|
|
71
|
+
readonly host: ClientServicesHost;
|
|
72
|
+
/** Resolve config, open the services host, and signal readiness. Never fails: startup errors are surfaced to session callers via the readiness gate. */
|
|
73
|
+
readonly start: () => Effect.Effect<void>;
|
|
74
|
+
/** Tear down sessions' host, dispose the runtime, release the storage lock, and run `onStop`. Idempotent. */
|
|
75
|
+
readonly stop: () => Effect.Effect<void>;
|
|
76
|
+
/** Open a new tab session over the supplied effect-rpc protocols and register it for WebRTC bridging. */
|
|
77
|
+
readonly createSession: (props: CreateSessionProps) => Effect.Effect<WorkerSession>;
|
|
78
|
+
/** Route the WebRTC bridge through the given session (or disconnect when `undefined`). */
|
|
79
|
+
readonly connectWebrtcBridge: (session: WorkerSession | undefined) => Effect.Effect<void>;
|
|
80
|
+
}
|
|
120
81
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
82
|
+
/**
|
|
83
|
+
* Context tag for the dedicated-worker runtime service. Provided by {@link layerWorkerRuntime}.
|
|
84
|
+
*/
|
|
85
|
+
export class WorkerRuntime extends Context_.Tag('@dxos/client-services/WorkerRuntime')<
|
|
86
|
+
WorkerRuntime,
|
|
87
|
+
WorkerRuntimeService
|
|
88
|
+
>() {}
|
|
124
89
|
|
|
125
|
-
|
|
126
|
-
|
|
90
|
+
/**
|
|
91
|
+
* Constructs the {@link WorkerRuntimeService}. The SQLite {@link ManagedRuntime} and
|
|
92
|
+
* {@link ClientServicesHost} are built eagerly; the async open sequence runs in {@link start}.
|
|
93
|
+
*/
|
|
94
|
+
export const makeWorkerRuntime = ({
|
|
95
|
+
configProvider,
|
|
96
|
+
acquireLock,
|
|
97
|
+
releaseLock,
|
|
98
|
+
onStop,
|
|
99
|
+
automaticallyConnectWebrtc = true,
|
|
100
|
+
sqliteLayer,
|
|
101
|
+
}: WorkerRuntimeOptions): WorkerRuntimeService => {
|
|
102
|
+
const transportFactory = new RtcTransportProxyFactory();
|
|
103
|
+
const ready = new Trigger<Error | undefined>();
|
|
104
|
+
const sessions = new Set<WorkerSession>();
|
|
105
|
+
const signalMetadataTags: any = { runtime: 'worker-runtime' };
|
|
106
|
+
|
|
107
|
+
let stopped = false;
|
|
108
|
+
let sessionForNetworking: WorkerSession | undefined;
|
|
109
|
+
let config: Config;
|
|
110
|
+
let serviceScope: Scope.CloseableScope | undefined;
|
|
111
|
+
|
|
112
|
+
if (sqliteLayer) {
|
|
113
|
+
log.warn('Using testing SQLite layer');
|
|
127
114
|
}
|
|
128
115
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
116
|
+
const runtime = ManagedRuntime.make(
|
|
117
|
+
SqlTransaction.layer
|
|
118
|
+
.pipe(Layer.provideMerge(sqliteLayer ?? LocalSqliteOpfsLayer), Layer.provideMerge(Reactivity.layer))
|
|
119
|
+
.pipe(Layer.orDie),
|
|
120
|
+
);
|
|
134
121
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
122
|
+
const stop = (): Effect.Effect<void> =>
|
|
123
|
+
Effect.promise(async () => {
|
|
124
|
+
if (stopped) {
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
stopped = true;
|
|
128
|
+
// Release the lock to notify remote clients that the worker is terminating.
|
|
129
|
+
releaseLock();
|
|
130
|
+
// Always dispose the SQLite runtime and run onStop, even if host / scope teardown rejects —
|
|
131
|
+
// otherwise a failed close would leak the runtime and skip the shutdown signal.
|
|
132
|
+
try {
|
|
133
|
+
await clientServices.close(Context.default());
|
|
134
|
+
if (serviceScope) {
|
|
135
|
+
await EffectEx.runPromise(Scope.close(serviceScope, Exit.void));
|
|
136
|
+
serviceScope = undefined;
|
|
143
137
|
}
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
await this._acquireLock();
|
|
148
|
-
log('worker-runtime: storage lock acquired, resolving config');
|
|
149
|
-
this._config = await this._configProvider();
|
|
150
|
-
log('worker-runtime: config resolved');
|
|
151
|
-
this._signalTelemetryEnabled = this._config.get('runtime.client.signalTelemetryEnabled') ?? false;
|
|
152
|
-
const observabilityGroup = this._config.get('runtime.client.observabilityGroup');
|
|
153
|
-
if (observabilityGroup) {
|
|
154
|
-
this._signalMetadataTags.group = observabilityGroup;
|
|
138
|
+
} finally {
|
|
139
|
+
await runtime.dispose();
|
|
140
|
+
await onStop?.();
|
|
155
141
|
}
|
|
156
|
-
|
|
157
|
-
log('worker-runtime: initializing client services host');
|
|
158
|
-
this._clientServices.initialize({
|
|
159
|
-
config: this._config,
|
|
160
|
-
signalManager: this._config.get('runtime.client.edgeFeatures')?.signaling
|
|
161
|
-
? undefined
|
|
162
|
-
: signals
|
|
163
|
-
? new WebsocketSignalManager(signals, () => (this._signalTelemetryEnabled ? this._signalMetadataTags : {}))
|
|
164
|
-
: new MemorySignalManager(new MemorySignalManagerContext()), // TODO(dmaretskyi): Inject this context.
|
|
165
|
-
transportFactory: this._transportFactory,
|
|
166
|
-
});
|
|
167
|
-
log('worker-runtime: client services host initialized, opening');
|
|
168
|
-
|
|
169
|
-
await this._clientServices.open(new Context());
|
|
170
|
-
log('worker-runtime: client services host opened, signalling ready');
|
|
171
|
-
this._ready.wake(undefined);
|
|
172
|
-
log('started');
|
|
173
|
-
setIdentityTags({
|
|
174
|
-
identityService: this._clientServices.services.IdentityService!,
|
|
175
|
-
devicesService: this._clientServices.services.DevicesService!,
|
|
176
|
-
setTag: (k: string, v: string) => {
|
|
177
|
-
this._signalMetadataTags[k] = v;
|
|
178
|
-
},
|
|
179
|
-
});
|
|
180
|
-
} catch (err: any) {
|
|
181
|
-
this._ready.wake(err);
|
|
182
|
-
log.error('starting', err);
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
async stop(): Promise<void> {
|
|
187
|
-
// Release the lock to notify remote clients that the worker is terminating.
|
|
188
|
-
this._releaseLock();
|
|
189
|
-
this._broadcastChannel?.close();
|
|
190
|
-
this._broadcastChannel = undefined;
|
|
191
|
-
await this._clientServices.close(Context.default());
|
|
192
|
-
await this._runtime.dispose();
|
|
193
|
-
await this._onStop?.();
|
|
194
|
-
await this._livenessLock.release();
|
|
195
|
-
}
|
|
142
|
+
});
|
|
196
143
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
144
|
+
const clientServices = new ClientServicesHost({
|
|
145
|
+
callbacks: {
|
|
146
|
+
onReset: async () => {
|
|
147
|
+
await EffectEx.runPromise(stop());
|
|
148
|
+
},
|
|
149
|
+
},
|
|
150
|
+
runtime: runtime.runtimeEffect,
|
|
151
|
+
runtimeProps: {
|
|
152
|
+
// Auto-activate spaces that were previously active after leader changeover.
|
|
153
|
+
autoActivateSpaces: true,
|
|
154
|
+
},
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
const connectBridge = (session: WorkerSession | undefined): void => {
|
|
158
|
+
sessionForNetworking = session;
|
|
159
|
+
transportFactory.setBridgeService(session?.bridgeService);
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
// Selects one of the existing sessions for WebRTC networking.
|
|
163
|
+
const reconnectWebrtc = Effect.sync(() => {
|
|
164
|
+
log('reconnecting webrtc...');
|
|
165
|
+
// Drop the current session if it has since closed.
|
|
166
|
+
if (sessionForNetworking && !sessions.has(sessionForNetworking)) {
|
|
167
|
+
sessionForNetworking = undefined;
|
|
214
168
|
}
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
this._signalTelemetryEnabled = signalTelemetryEnabled;
|
|
169
|
+
if (!sessionForNetworking) {
|
|
170
|
+
connectBridge(Array.from(sessions).find((session) => session.bridgeService));
|
|
218
171
|
}
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
// When tab is closed or client is destroyed.
|
|
234
|
-
session.onClose.set(async () => {
|
|
235
|
-
this._sessions.delete(session);
|
|
236
|
-
if (this._sessions.size === 0) {
|
|
237
|
-
// Terminate the worker when all sessions are closed.
|
|
238
|
-
await this.stop();
|
|
239
|
-
} else {
|
|
240
|
-
if (this._automaticallyConnectWebrtc) {
|
|
241
|
-
this._reconnectWebrtc();
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
const start = (): Effect.Effect<void> =>
|
|
175
|
+
Effect.promise(async () => {
|
|
176
|
+
log('starting...');
|
|
177
|
+
try {
|
|
178
|
+
log('worker-runtime: acquiring storage lock');
|
|
179
|
+
await acquireLock();
|
|
180
|
+
log('worker-runtime: storage lock acquired, resolving config');
|
|
181
|
+
config = await configProvider();
|
|
182
|
+
log('worker-runtime: config resolved');
|
|
183
|
+
const observabilityGroup = config.get('runtime.client.observabilityGroup');
|
|
184
|
+
if (observabilityGroup) {
|
|
185
|
+
signalMetadataTags.group = observabilityGroup;
|
|
242
186
|
}
|
|
187
|
+
log('worker-runtime: initializing client services host');
|
|
188
|
+
clientServices.initialize({
|
|
189
|
+
config,
|
|
190
|
+
// Edge signaling is created in the services host from the edge connection; otherwise fall
|
|
191
|
+
// back to an isolated in-memory manager (KUBE `WebsocketSignalManager` removed).
|
|
192
|
+
signalManager: config.get('runtime.client.edgeFeatures')?.signaling
|
|
193
|
+
? undefined
|
|
194
|
+
: new MemorySignalManager(new MemorySignalManagerContext()), // TODO(dmaretskyi): Inject this context.
|
|
195
|
+
transportFactory,
|
|
196
|
+
});
|
|
197
|
+
log('worker-runtime: client services host initialized, opening');
|
|
198
|
+
|
|
199
|
+
await clientServices.open(new Context());
|
|
200
|
+
log('worker-runtime: client services host opened, signalling ready');
|
|
201
|
+
ready.wake(undefined);
|
|
202
|
+
log('started');
|
|
203
|
+
// Bridge the host identity/devices Handlers to the effect-rpc client surface in-process.
|
|
204
|
+
serviceScope = Effect.runSync(Scope.make());
|
|
205
|
+
const { IdentityService: identityHandlers, DevicesService: devicesHandlers } = clientServices.services;
|
|
206
|
+
invariant(identityHandlers, 'IdentityService handler not available');
|
|
207
|
+
invariant(devicesHandlers, 'DevicesService handler not available');
|
|
208
|
+
const [identityService, devicesService] = await EffectEx.runPromise(
|
|
209
|
+
Effect.all([
|
|
210
|
+
makeInProcessClient(IdentityService.Rpcs, identityHandlers),
|
|
211
|
+
makeInProcessClient(DevicesService.Rpcs, devicesHandlers),
|
|
212
|
+
]).pipe(Effect.provideService(Scope.Scope, serviceScope)),
|
|
213
|
+
);
|
|
214
|
+
setIdentityTags({
|
|
215
|
+
identityService,
|
|
216
|
+
devicesService,
|
|
217
|
+
setTag: (key: string, value: string) => {
|
|
218
|
+
signalMetadataTags[key] = value;
|
|
219
|
+
},
|
|
220
|
+
});
|
|
221
|
+
} catch (err: any) {
|
|
222
|
+
ready.wake(err);
|
|
223
|
+
log.error('starting', err);
|
|
243
224
|
}
|
|
244
|
-
await onClose?.();
|
|
245
225
|
});
|
|
246
226
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
227
|
+
const createSession = ({
|
|
228
|
+
appProtocol,
|
|
229
|
+
systemProtocol,
|
|
230
|
+
shellPort,
|
|
231
|
+
onClose,
|
|
232
|
+
}: CreateSessionProps): Effect.Effect<WorkerSession> =>
|
|
233
|
+
Effect.gen(function* () {
|
|
234
|
+
const session = new WorkerSession({
|
|
235
|
+
serviceHost: clientServices,
|
|
236
|
+
appProtocol,
|
|
237
|
+
systemProtocol,
|
|
238
|
+
shellPort,
|
|
239
|
+
readySignal: ready,
|
|
240
|
+
});
|
|
255
241
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
242
|
+
// When tab is closed or client is destroyed.
|
|
243
|
+
session.onClose.set(async () => {
|
|
244
|
+
await EffectEx.runPromise(
|
|
245
|
+
Effect.gen(function* () {
|
|
246
|
+
sessions.delete(session);
|
|
247
|
+
if (sessions.size === 0) {
|
|
248
|
+
// Terminate the worker when all sessions are closed.
|
|
249
|
+
yield* stop();
|
|
250
|
+
} else if (automaticallyConnectWebrtc) {
|
|
251
|
+
yield* reconnectWebrtc;
|
|
252
|
+
}
|
|
253
|
+
}),
|
|
254
|
+
);
|
|
255
|
+
await onClose?.();
|
|
256
|
+
});
|
|
259
257
|
|
|
260
|
-
|
|
261
|
-
|
|
258
|
+
yield* session.open();
|
|
259
|
+
// A worker can only service one origin currently.
|
|
260
|
+
invariant(
|
|
261
|
+
!signalMetadataTags.origin || signalMetadataTags.origin === session.origin,
|
|
262
|
+
`worker origin changed from ${signalMetadataTags.origin} to ${session.origin}?`,
|
|
263
|
+
);
|
|
264
|
+
signalMetadataTags.origin = session.origin;
|
|
265
|
+
sessions.add(session);
|
|
266
|
+
|
|
267
|
+
if (automaticallyConnectWebrtc) {
|
|
268
|
+
yield* reconnectWebrtc;
|
|
269
|
+
}
|
|
262
270
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
* If no session is provided, disconnects the WebRTC bridge.
|
|
266
|
-
*
|
|
267
|
-
* Called automatically if `automaticallyConnectWebrtc` is true.
|
|
268
|
-
*
|
|
269
|
-
* @param session The session to connect the WebRTC bridge to.
|
|
270
|
-
*/
|
|
271
|
-
connectWebrtcBridge(session: WorkerSession | undefined): void {
|
|
272
|
-
this._sessionForNetworking = session;
|
|
273
|
-
this._transportFactory.setBridgeService(session?.bridgeService);
|
|
274
|
-
}
|
|
271
|
+
return session;
|
|
272
|
+
});
|
|
275
273
|
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
this._sessionForNetworking = undefined;
|
|
285
|
-
}
|
|
286
|
-
}
|
|
274
|
+
return {
|
|
275
|
+
host: clientServices,
|
|
276
|
+
start,
|
|
277
|
+
stop,
|
|
278
|
+
createSession,
|
|
279
|
+
connectWebrtcBridge: (session) => Effect.sync(() => connectBridge(session)),
|
|
280
|
+
};
|
|
281
|
+
};
|
|
287
282
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
}
|
|
283
|
+
/**
|
|
284
|
+
* Layer providing the {@link WorkerRuntime} service. The service is constructed synchronously;
|
|
285
|
+
* callers drive `start` / `stop` explicitly (see {@link WorkerRuntimeService}).
|
|
286
|
+
*/
|
|
287
|
+
export const layerWorkerRuntime = (options: WorkerRuntimeOptions): Layer.Layer<WorkerRuntime> =>
|
|
288
|
+
Layer.sync(WorkerRuntime, () => makeWorkerRuntime(options));
|
|
295
289
|
|
|
296
290
|
const DB_NAME = 'DXOS';
|
|
297
291
|
|
|
@@ -317,35 +311,3 @@ const LocalSqliteOpfsLayer = SqlExportLayer.pipe(
|
|
|
317
311
|
Layer.provideMerge(SqliteClient.layerOpfs({ dbName: DB_NAME })),
|
|
318
312
|
Layer.provideMerge(Reactivity.layer),
|
|
319
313
|
);
|
|
320
|
-
|
|
321
|
-
// TODO(wittjosiah): Factor out to a separate module.
|
|
322
|
-
class WebLockWrapper {
|
|
323
|
-
readonly #key: string;
|
|
324
|
-
#release?: () => void;
|
|
325
|
-
|
|
326
|
-
constructor(key: string) {
|
|
327
|
-
this.#key = key;
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
get key(): string {
|
|
331
|
-
return this.#key;
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
acquire(options: LockOptions = {}) {
|
|
335
|
-
return navigator.locks.request(this.#key, options, async () => {
|
|
336
|
-
await new Promise<void>((resolve) => {
|
|
337
|
-
this.#release = resolve;
|
|
338
|
-
}); // Blocks for the duration of the worker's lifetime.
|
|
339
|
-
this.#release = undefined;
|
|
340
|
-
});
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
release() {
|
|
344
|
-
this.#release?.();
|
|
345
|
-
this.#release = undefined;
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
[Symbol.dispose]() {
|
|
349
|
-
this.release();
|
|
350
|
-
}
|
|
351
|
-
}
|