@dxos/client-services 0.8.4-main.f9ba587 → 0.8.4-main.fcfe5033a5

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.
Files changed (239) hide show
  1. package/dist/lib/browser/{chunk-ERQJUBAW.mjs → chunk-HYGNOM23.mjs} +4279 -3342
  2. package/dist/lib/browser/chunk-HYGNOM23.mjs.map +7 -0
  3. package/dist/lib/browser/chunk-NQSC7HOE.mjs +22 -0
  4. package/dist/lib/browser/chunk-NQSC7HOE.mjs.map +7 -0
  5. package/dist/lib/browser/chunk-QCWEHHJW.mjs +24 -0
  6. package/dist/lib/browser/chunk-QCWEHHJW.mjs.map +7 -0
  7. package/dist/lib/browser/index.mjs +539 -98
  8. package/dist/lib/browser/index.mjs.map +4 -4
  9. package/dist/lib/browser/meta.json +1 -1
  10. package/dist/lib/browser/packlets/diagnostics/browser-diagnostics-broadcast.mjs +93 -0
  11. package/dist/lib/browser/packlets/diagnostics/browser-diagnostics-broadcast.mjs.map +7 -0
  12. package/dist/lib/browser/packlets/diagnostics/diagnostics-broadcast.mjs +11 -0
  13. package/dist/lib/browser/packlets/diagnostics/diagnostics-broadcast.mjs.map +7 -0
  14. package/dist/lib/browser/packlets/locks/browser.mjs +126 -0
  15. package/dist/lib/browser/packlets/locks/browser.mjs.map +7 -0
  16. package/dist/lib/browser/packlets/locks/node.mjs +66 -0
  17. package/dist/lib/browser/packlets/locks/node.mjs.map +7 -0
  18. package/dist/lib/browser/testing/index.mjs +45 -26
  19. package/dist/lib/browser/testing/index.mjs.map +3 -3
  20. package/dist/lib/node-esm/chunk-2SZHAWBN.mjs +24 -0
  21. package/dist/lib/node-esm/chunk-2SZHAWBN.mjs.map +7 -0
  22. package/dist/lib/node-esm/{chunk-TMEG7JOG.mjs → chunk-GFT7MAQE.mjs} +3764 -2695
  23. package/dist/lib/node-esm/chunk-GFT7MAQE.mjs.map +7 -0
  24. package/dist/lib/node-esm/chunk-PKEGMOQ4.mjs +22 -0
  25. package/dist/lib/node-esm/chunk-PKEGMOQ4.mjs.map +7 -0
  26. package/dist/lib/node-esm/index.mjs +539 -98
  27. package/dist/lib/node-esm/index.mjs.map +4 -4
  28. package/dist/lib/node-esm/meta.json +1 -1
  29. package/dist/lib/node-esm/packlets/diagnostics/browser-diagnostics-broadcast.mjs +93 -0
  30. package/dist/lib/node-esm/packlets/diagnostics/browser-diagnostics-broadcast.mjs.map +7 -0
  31. package/dist/lib/node-esm/packlets/diagnostics/diagnostics-broadcast.mjs +11 -0
  32. package/dist/lib/node-esm/packlets/diagnostics/diagnostics-broadcast.mjs.map +7 -0
  33. package/dist/lib/node-esm/packlets/locks/browser.mjs +126 -0
  34. package/dist/lib/node-esm/packlets/locks/browser.mjs.map +7 -0
  35. package/dist/lib/node-esm/packlets/locks/node.mjs +66 -0
  36. package/dist/lib/node-esm/packlets/locks/node.mjs.map +7 -0
  37. package/dist/lib/node-esm/testing/index.mjs +45 -26
  38. package/dist/lib/node-esm/testing/index.mjs.map +3 -3
  39. package/dist/types/src/index.d.ts +1 -0
  40. package/dist/types/src/index.d.ts.map +1 -1
  41. package/dist/types/src/packlets/agents/edge-agent-manager.d.ts +3 -2
  42. package/dist/types/src/packlets/agents/edge-agent-manager.d.ts.map +1 -1
  43. package/dist/types/src/packlets/agents/edge-agent-service.d.ts +3 -2
  44. package/dist/types/src/packlets/agents/edge-agent-service.d.ts.map +1 -1
  45. package/dist/types/src/packlets/devices/devices-service.d.ts.map +1 -1
  46. package/dist/types/src/packlets/devtools/devtools.d.ts +20 -20
  47. package/dist/types/src/packlets/devtools/devtools.d.ts.map +1 -1
  48. package/dist/types/src/packlets/devtools/feeds.d.ts +1 -1
  49. package/dist/types/src/packlets/devtools/feeds.d.ts.map +1 -1
  50. package/dist/types/src/packlets/devtools/network.d.ts +1 -1
  51. package/dist/types/src/packlets/devtools/network.d.ts.map +1 -1
  52. package/dist/types/src/packlets/diagnostics/browser-diagnostics-broadcast.d.ts +1 -1
  53. package/dist/types/src/packlets/diagnostics/browser-diagnostics-broadcast.d.ts.map +1 -1
  54. package/dist/types/src/packlets/diagnostics/diagnostics-broadcast.d.ts +1 -1
  55. package/dist/types/src/packlets/diagnostics/diagnostics-broadcast.d.ts.map +1 -1
  56. package/dist/types/src/packlets/diagnostics/diagnostics.d.ts +2 -3
  57. package/dist/types/src/packlets/diagnostics/diagnostics.d.ts.map +1 -1
  58. package/dist/types/src/packlets/diagnostics/index.d.ts +1 -1
  59. package/dist/types/src/packlets/diagnostics/index.d.ts.map +1 -1
  60. package/dist/types/src/packlets/identity/authenticator.d.ts +2 -2
  61. package/dist/types/src/packlets/identity/authenticator.d.ts.map +1 -1
  62. package/dist/types/src/packlets/identity/contacts-service.d.ts +1 -1
  63. package/dist/types/src/packlets/identity/contacts-service.d.ts.map +1 -1
  64. package/dist/types/src/packlets/identity/identity-manager.d.ts +7 -7
  65. package/dist/types/src/packlets/identity/identity-manager.d.ts.map +1 -1
  66. package/dist/types/src/packlets/identity/identity-recovery-manager.d.ts +7 -6
  67. package/dist/types/src/packlets/identity/identity-recovery-manager.d.ts.map +1 -1
  68. package/dist/types/src/packlets/identity/identity-service.d.ts +6 -10
  69. package/dist/types/src/packlets/identity/identity-service.d.ts.map +1 -1
  70. package/dist/types/src/packlets/identity/identity.d.ts +9 -12
  71. package/dist/types/src/packlets/identity/identity.d.ts.map +1 -1
  72. package/dist/types/src/packlets/invitations/device-invitation-protocol.d.ts +6 -5
  73. package/dist/types/src/packlets/invitations/device-invitation-protocol.d.ts.map +1 -1
  74. package/dist/types/src/packlets/invitations/edge-invitation-handler.d.ts +2 -2
  75. package/dist/types/src/packlets/invitations/edge-invitation-handler.d.ts.map +1 -1
  76. package/dist/types/src/packlets/invitations/index.d.ts +1 -1
  77. package/dist/types/src/packlets/invitations/index.d.ts.map +1 -1
  78. package/dist/types/src/packlets/invitations/invitation-guest-extenstion.d.ts.map +1 -1
  79. package/dist/types/src/packlets/invitations/invitation-host-extension.d.ts.map +1 -1
  80. package/dist/types/src/packlets/invitations/invitation-protocol.d.ts +8 -5
  81. package/dist/types/src/packlets/invitations/invitation-protocol.d.ts.map +1 -1
  82. package/dist/types/src/packlets/invitations/invitation-state.d.ts.map +1 -1
  83. package/dist/types/src/packlets/invitations/invitations-handler.d.ts +4 -4
  84. package/dist/types/src/packlets/invitations/invitations-handler.d.ts.map +1 -1
  85. package/dist/types/src/packlets/invitations/invitations-manager.d.ts +3 -3
  86. package/dist/types/src/packlets/invitations/invitations-manager.d.ts.map +1 -1
  87. package/dist/types/src/packlets/invitations/invitations-service.d.ts +4 -4
  88. package/dist/types/src/packlets/invitations/invitations-service.d.ts.map +1 -1
  89. package/dist/types/src/packlets/invitations/space-invitation-protocol.d.ts +5 -4
  90. package/dist/types/src/packlets/invitations/space-invitation-protocol.d.ts.map +1 -1
  91. package/dist/types/src/packlets/invitations/utils.d.ts.map +1 -1
  92. package/dist/types/src/packlets/locks/index.d.ts +2 -2
  93. package/dist/types/src/packlets/locks/index.d.ts.map +1 -1
  94. package/dist/types/src/packlets/logging/logging-service.d.ts +5 -1
  95. package/dist/types/src/packlets/logging/logging-service.d.ts.map +1 -1
  96. package/dist/types/src/packlets/network/network-service.d.ts +7 -6
  97. package/dist/types/src/packlets/network/network-service.d.ts.map +1 -1
  98. package/dist/types/src/packlets/services/client-rpc-server.d.ts +5 -5
  99. package/dist/types/src/packlets/services/client-rpc-server.d.ts.map +1 -1
  100. package/dist/types/src/packlets/services/feed-syncer.d.ts +59 -0
  101. package/dist/types/src/packlets/services/feed-syncer.d.ts.map +1 -0
  102. package/dist/types/src/packlets/services/feed-syncer.test.d.ts +2 -0
  103. package/dist/types/src/packlets/services/feed-syncer.test.d.ts.map +1 -0
  104. package/dist/types/src/packlets/services/platform.d.ts.map +1 -1
  105. package/dist/types/src/packlets/services/service-context.d.ts +14 -9
  106. package/dist/types/src/packlets/services/service-context.d.ts.map +1 -1
  107. package/dist/types/src/packlets/services/service-host.d.ts +21 -8
  108. package/dist/types/src/packlets/services/service-host.d.ts.map +1 -1
  109. package/dist/types/src/packlets/space-export/archive-format.d.ts +9 -0
  110. package/dist/types/src/packlets/space-export/archive-format.d.ts.map +1 -0
  111. package/dist/types/src/packlets/space-export/index.d.ts +4 -1
  112. package/dist/types/src/packlets/space-export/index.d.ts.map +1 -1
  113. package/dist/types/src/packlets/space-export/serialized-space-reader.d.ts +23 -0
  114. package/dist/types/src/packlets/space-export/serialized-space-reader.d.ts.map +1 -0
  115. package/dist/types/src/packlets/space-export/serialized-space-writer.d.ts +36 -0
  116. package/dist/types/src/packlets/space-export/serialized-space-writer.d.ts.map +1 -0
  117. package/dist/types/src/packlets/space-export/space-archive-reader.d.ts +9 -1
  118. package/dist/types/src/packlets/space-export/space-archive-reader.d.ts.map +1 -1
  119. package/dist/types/src/packlets/space-export/space-archive-writer.d.ts +8 -2
  120. package/dist/types/src/packlets/space-export/space-archive-writer.d.ts.map +1 -1
  121. package/dist/types/src/packlets/space-export/space-archive.test.d.ts +2 -0
  122. package/dist/types/src/packlets/space-export/space-archive.test.d.ts.map +1 -0
  123. package/dist/types/src/packlets/spaces/automerge-space-state.d.ts +1 -1
  124. package/dist/types/src/packlets/spaces/automerge-space-state.d.ts.map +1 -1
  125. package/dist/types/src/packlets/spaces/data-space-manager.d.ts +29 -17
  126. package/dist/types/src/packlets/spaces/data-space-manager.d.ts.map +1 -1
  127. package/dist/types/src/packlets/spaces/data-space.d.ts +30 -13
  128. package/dist/types/src/packlets/spaces/data-space.d.ts.map +1 -1
  129. package/dist/types/src/packlets/spaces/edge-feed-replicator.d.ts +2 -2
  130. package/dist/types/src/packlets/spaces/edge-feed-replicator.d.ts.map +1 -1
  131. package/dist/types/src/packlets/spaces/genesis.d.ts +2 -1
  132. package/dist/types/src/packlets/spaces/genesis.d.ts.map +1 -1
  133. package/dist/types/src/packlets/spaces/notarization-plugin.d.ts +6 -6
  134. package/dist/types/src/packlets/spaces/notarization-plugin.d.ts.map +1 -1
  135. package/dist/types/src/packlets/spaces/spaces-service.d.ts +18 -8
  136. package/dist/types/src/packlets/spaces/spaces-service.d.ts.map +1 -1
  137. package/dist/types/src/packlets/storage/profile-archive.d.ts.map +1 -1
  138. package/dist/types/src/packlets/storage/storage.d.ts.map +1 -1
  139. package/dist/types/src/packlets/system/system-service.d.ts +1 -1
  140. package/dist/types/src/packlets/system/system-service.d.ts.map +1 -1
  141. package/dist/types/src/packlets/testing/invitation-utils.d.ts +6 -3
  142. package/dist/types/src/packlets/testing/invitation-utils.d.ts.map +1 -1
  143. package/dist/types/src/packlets/testing/test-builder.d.ts +8 -7
  144. package/dist/types/src/packlets/testing/test-builder.d.ts.map +1 -1
  145. package/dist/types/src/packlets/worker/worker-runtime.d.ts +41 -4
  146. package/dist/types/src/packlets/worker/worker-runtime.d.ts.map +1 -1
  147. package/dist/types/src/packlets/worker/worker-session.d.ts +2 -4
  148. package/dist/types/src/packlets/worker/worker-session.d.ts.map +1 -1
  149. package/dist/types/src/version.d.ts +1 -1
  150. package/dist/types/src/version.d.ts.map +1 -1
  151. package/dist/types/tsconfig.tsbuildinfo +1 -1
  152. package/package.json +72 -48
  153. package/src/index.ts +1 -0
  154. package/src/packlets/agents/edge-agent-manager.ts +10 -7
  155. package/src/packlets/agents/edge-agent-service.ts +17 -5
  156. package/src/packlets/devices/devices-service.test.ts +3 -3
  157. package/src/packlets/devices/devices-service.ts +2 -2
  158. package/src/packlets/devtools/devtools.ts +29 -29
  159. package/src/packlets/devtools/feeds.ts +2 -2
  160. package/src/packlets/devtools/network.ts +1 -1
  161. package/src/packlets/diagnostics/browser-diagnostics-broadcast.ts +1 -1
  162. package/src/packlets/diagnostics/diagnostics-broadcast.ts +1 -1
  163. package/src/packlets/diagnostics/diagnostics-collector.ts +1 -1
  164. package/src/packlets/diagnostics/diagnostics.ts +2 -3
  165. package/src/packlets/diagnostics/index.ts +1 -1
  166. package/src/packlets/identity/authenticator.node.test.ts +1 -1
  167. package/src/packlets/identity/authenticator.ts +3 -3
  168. package/src/packlets/identity/contacts-service.ts +2 -2
  169. package/src/packlets/identity/identity-manager.test.ts +8 -8
  170. package/src/packlets/identity/identity-manager.ts +23 -20
  171. package/src/packlets/identity/identity-recovery-manager.ts +22 -18
  172. package/src/packlets/identity/identity-service.test.ts +8 -28
  173. package/src/packlets/identity/identity-service.ts +13 -80
  174. package/src/packlets/identity/identity.test.ts +11 -11
  175. package/src/packlets/identity/identity.ts +17 -39
  176. package/src/packlets/invitations/device-invitation-protocol.test.ts +4 -4
  177. package/src/packlets/invitations/device-invitation-protocol.ts +8 -6
  178. package/src/packlets/invitations/edge-invitation-handler.ts +10 -6
  179. package/src/packlets/invitations/index.ts +1 -1
  180. package/src/packlets/invitations/invitation-guest-extenstion.ts +7 -5
  181. package/src/packlets/invitations/invitation-host-extension.ts +8 -6
  182. package/src/packlets/invitations/invitation-protocol.ts +8 -5
  183. package/src/packlets/invitations/invitation-state.ts +0 -10
  184. package/src/packlets/invitations/invitations-handler.test.ts +301 -292
  185. package/src/packlets/invitations/invitations-handler.ts +72 -16
  186. package/src/packlets/invitations/invitations-manager.ts +43 -18
  187. package/src/packlets/invitations/invitations-service.ts +10 -10
  188. package/src/packlets/invitations/space-invitation-protocol.test.ts +26 -25
  189. package/src/packlets/invitations/space-invitation-protocol.ts +13 -17
  190. package/src/packlets/invitations/utils.ts +1 -1
  191. package/src/packlets/locks/browser.ts +1 -1
  192. package/src/packlets/locks/index.ts +2 -2
  193. package/src/packlets/logging/logging-service.ts +8 -3
  194. package/src/packlets/logging/logging.test.ts +1 -1
  195. package/src/packlets/network/network-service.test.ts +3 -3
  196. package/src/packlets/network/network-service.ts +12 -10
  197. package/src/packlets/services/client-rpc-server.ts +20 -17
  198. package/src/packlets/services/feed-syncer.test.ts +340 -0
  199. package/src/packlets/services/feed-syncer.ts +337 -0
  200. package/src/packlets/services/platform.ts +7 -1
  201. package/src/packlets/services/service-context.test.ts +4 -3
  202. package/src/packlets/services/service-context.ts +145 -59
  203. package/src/packlets/services/service-host.test.ts +10 -9
  204. package/src/packlets/services/service-host.ts +85 -38
  205. package/src/packlets/services/service-registry.test.ts +1 -1
  206. package/src/packlets/space-export/archive-format.ts +42 -0
  207. package/src/packlets/space-export/index.ts +4 -1
  208. package/src/packlets/space-export/serialized-space-reader.ts +111 -0
  209. package/src/packlets/space-export/serialized-space-writer.ts +246 -0
  210. package/src/packlets/space-export/space-archive-reader.ts +65 -4
  211. package/src/packlets/space-export/space-archive-writer.ts +44 -6
  212. package/src/packlets/space-export/space-archive.test.ts +461 -0
  213. package/src/packlets/space-export/tar.test.ts +1 -1
  214. package/src/packlets/spaces/automerge-space-state.ts +1 -1
  215. package/src/packlets/spaces/data-space-manager.test.ts +79 -13
  216. package/src/packlets/spaces/data-space-manager.ts +131 -118
  217. package/src/packlets/spaces/data-space.ts +65 -39
  218. package/src/packlets/spaces/edge-feed-replicator.test.ts +4 -4
  219. package/src/packlets/spaces/edge-feed-replicator.ts +13 -11
  220. package/src/packlets/spaces/epoch-migrations.ts +5 -5
  221. package/src/packlets/spaces/genesis.ts +6 -1
  222. package/src/packlets/spaces/notarization-plugin.test.ts +3 -3
  223. package/src/packlets/spaces/notarization-plugin.ts +13 -12
  224. package/src/packlets/spaces/spaces-service.test.ts +20 -12
  225. package/src/packlets/spaces/spaces-service.ts +138 -38
  226. package/src/packlets/storage/profile-archive.ts +1 -1
  227. package/src/packlets/storage/storage.ts +7 -8
  228. package/src/packlets/system/system-service.test.ts +1 -1
  229. package/src/packlets/system/system-service.ts +4 -4
  230. package/src/packlets/testing/invitation-utils.ts +11 -7
  231. package/src/packlets/testing/test-builder.ts +39 -13
  232. package/src/packlets/worker/worker-runtime.ts +180 -17
  233. package/src/packlets/worker/worker-session.ts +15 -21
  234. package/src/version.ts +1 -1
  235. package/dist/lib/browser/chunk-ERQJUBAW.mjs.map +0 -7
  236. package/dist/lib/node-esm/chunk-TMEG7JOG.mjs.map +0 -7
  237. package/dist/types/src/packlets/identity/default-space-state-machine.d.ts +0 -19
  238. package/dist/types/src/packlets/identity/default-space-state-machine.d.ts.map +0 -1
  239. package/src/packlets/identity/default-space-state-machine.ts +0 -44
@@ -2,6 +2,12 @@
2
2
  // Copyright 2022 DXOS.org
3
3
  //
4
4
 
5
+ import * as Reactivity from '@effect/experimental/Reactivity';
6
+ import type * as SqlClient from '@effect/sql/SqlClient';
7
+ import * as Effect from 'effect/Effect';
8
+ import * as Layer from 'effect/Layer';
9
+ import * as ManagedRuntime from 'effect/ManagedRuntime';
10
+
5
11
  import { Trigger } from '@dxos/async';
6
12
  import { DEFAULT_WORKER_BROADCAST_CHANNEL } from '@dxos/client-protocol';
7
13
  import { type Config } from '@dxos/config';
@@ -16,16 +22,21 @@ import {
16
22
  } from '@dxos/messaging';
17
23
  import { RtcTransportProxyFactory } from '@dxos/network-manager';
18
24
  import { type RpcPort } from '@dxos/rpc';
25
+ import * as OpfsWorker from '@dxos/sql-sqlite/OpfsWorker';
26
+ import * as SqlExport from '@dxos/sql-sqlite/SqlExport';
27
+ import * as SqliteClient from '@dxos/sql-sqlite/SqliteClient';
28
+ import * as SqlTransaction from '@dxos/sql-sqlite/SqlTransaction';
19
29
  import { type MaybePromise } from '@dxos/util';
20
30
 
21
- import { WorkerSession } from './worker-session';
22
31
  import { ClientServicesHost } from '../services';
32
+ import { WorkerSession } from './worker-session';
23
33
 
24
34
  // NOTE: Keep as RpcPorts to avoid dependency on @dxos/rpc-tunnel so we don't depend on browser-specific apis.
25
- export type CreateSessionParams = {
35
+ export type CreateSessionProps = {
26
36
  appPort: RpcPort;
27
37
  systemPort: RpcPort;
28
38
  shellPort?: RpcPort;
39
+ onClose?: () => Promise<void>;
29
40
  };
30
41
 
31
42
  export type WorkerRuntimeOptions = {
@@ -34,10 +45,20 @@ export type WorkerRuntimeOptions = {
34
45
  acquireLock: () => Promise<void>;
35
46
  releaseLock: () => void;
36
47
  onStop?: () => Promise<void>;
48
+ /**
49
+ * @default true
50
+ */
51
+ automaticallyConnectWebrtc?: boolean;
52
+
53
+ /**
54
+ * Optional SQLite layer for Effect. Defaults to LocalSqliteOpfsLayer.
55
+ * For testing in Node.js, use `sqliteLayerMemory` from `@dxos/sql-sqlite/platform`.
56
+ */
57
+ sqliteLayer?: Layer.Layer<SqlClient.SqlClient | SqlExport.SqlExport, unknown>;
37
58
  };
38
59
 
39
60
  /**
40
- * Runtime for the shared worker.
61
+ * Runtime for the shared and dedciated worker.
41
62
  * Manages connections from proxies (in tabs).
42
63
  * Tabs make requests to the `ClientServicesHost`, and provide a WebRTC gateway.
43
64
  */
@@ -51,11 +72,17 @@ export class WorkerRuntime {
51
72
  private readonly _sessions = new Set<WorkerSession>();
52
73
  private readonly _clientServices!: ClientServicesHost;
53
74
  private readonly _channel: string;
75
+ private readonly _automaticallyConnectWebrtc: boolean;
76
+ private readonly _livenessLock = new WebLockWrapper(`@dxos/client-services/WorkerRuntime/${crypto.randomUUID()}`);
54
77
  private _broadcastChannel?: BroadcastChannel;
55
78
  private _sessionForNetworking?: WorkerSession; // TODO(burdon): Expose to client QueryStatusResponse.
56
79
  private _config!: Config;
57
80
  private _signalMetadataTags: any = { runtime: 'worker-runtime' };
58
81
  private _signalTelemetryEnabled: boolean = false;
82
+ private _runtime!: ManagedRuntime.ManagedRuntime<
83
+ SqlTransaction.SqlTransaction | SqlClient.SqlClient | SqlExport.SqlExport,
84
+ never
85
+ >;
59
86
 
60
87
  constructor({
61
88
  channel = DEFAULT_WORKER_BROADCAST_CHANNEL,
@@ -63,26 +90,49 @@ export class WorkerRuntime {
63
90
  acquireLock,
64
91
  releaseLock,
65
92
  onStop,
93
+ automaticallyConnectWebrtc = true,
94
+ sqliteLayer,
66
95
  }: WorkerRuntimeOptions) {
67
96
  this._configProvider = configProvider;
68
97
  this._acquireLock = acquireLock;
69
98
  this._releaseLock = releaseLock;
70
99
  this._onStop = onStop;
71
100
  this._channel = channel;
101
+ if (sqliteLayer) {
102
+ log.warn('Using testing SQLite layer');
103
+ }
104
+ this._runtime = ManagedRuntime.make(
105
+ SqlTransaction.layer
106
+ .pipe(Layer.provideMerge(sqliteLayer ?? LocalSqliteOpfsLayer), Layer.provideMerge(Reactivity.layer))
107
+ .pipe(Layer.orDie),
108
+ );
72
109
  this._clientServices = new ClientServicesHost({
73
110
  callbacks: {
74
111
  onReset: async () => this.stop(),
75
112
  },
113
+ runtime: this._runtime.runtimeEffect,
114
+ runtimeProps: {
115
+ // Auto-activate spaces that were previously active after leader changeover.
116
+ autoActivateSpaces: true,
117
+ },
76
118
  });
119
+ this._automaticallyConnectWebrtc = automaticallyConnectWebrtc;
77
120
  }
78
121
 
79
122
  get host() {
80
123
  return this._clientServices;
81
124
  }
82
125
 
126
+ get livenessLockKey(): string {
127
+ return this._livenessLock.key;
128
+ }
129
+
83
130
  async start(): Promise<void> {
84
131
  log('starting...');
85
132
  try {
133
+ void this._livenessLock.acquire();
134
+
135
+ // Steal the lock from the other worker.
86
136
  this._broadcastChannel = new BroadcastChannel(this._channel);
87
137
  this._broadcastChannel.postMessage({ action: 'stop' });
88
138
  this._broadcastChannel.onmessage = async (event) => {
@@ -93,6 +143,11 @@ export class WorkerRuntime {
93
143
 
94
144
  await this._acquireLock();
95
145
  this._config = await this._configProvider();
146
+ this._signalTelemetryEnabled = this._config.get('runtime.client.signalTelemetryEnabled') ?? false;
147
+ const observabilityGroup = this._config.get('runtime.client.observabilityGroup');
148
+ if (observabilityGroup) {
149
+ this._signalMetadataTags.group = observabilityGroup;
150
+ }
96
151
  const signals = this._config.get('runtime.services.signaling');
97
152
  this._clientServices.initialize({
98
153
  config: this._config,
@@ -125,14 +180,40 @@ export class WorkerRuntime {
125
180
  this._releaseLock();
126
181
  this._broadcastChannel?.close();
127
182
  this._broadcastChannel = undefined;
128
- await this._clientServices.close();
183
+ await this._clientServices.close(Context.default());
184
+ await this._runtime.dispose();
129
185
  await this._onStop?.();
186
+ await this._livenessLock.release();
187
+ }
188
+
189
+ /**
190
+ * Update signaling telemetry tags from a client-supplied config overlay.
191
+ *
192
+ * The worker services outlive individual client connections, so the first client seeds the
193
+ * worker's core config (storage, signaling, edge features). For fields that can legitimately
194
+ * differ per tab — `observabilityGroup` and `signalTelemetryEnabled` — this method lets later
195
+ * connections refresh the signal metadata the worker attaches to its signaling requests
196
+ * (last-writer-wins, matching the pre-DX-930 per-session RPC behaviour).
197
+ */
198
+ updateSignalMetadata(config: Config): void {
199
+ const observabilityGroup = config.get('runtime.client.observabilityGroup');
200
+ if (observabilityGroup) {
201
+ this._signalMetadataTags.group = observabilityGroup;
202
+ } else {
203
+ // Clear stale group so a later config that removes observabilityGroup stops attributing
204
+ // telemetry to the previous client's group (last-writer-wins).
205
+ delete this._signalMetadataTags.group;
206
+ }
207
+ const signalTelemetryEnabled = config.get('runtime.client.signalTelemetryEnabled');
208
+ if (signalTelemetryEnabled !== undefined) {
209
+ this._signalTelemetryEnabled = signalTelemetryEnabled;
210
+ }
130
211
  }
131
212
 
132
213
  /**
133
214
  * Create a new session.
134
215
  */
135
- async createSession({ appPort, systemPort, shellPort }: CreateSessionParams): Promise<void> {
216
+ async createSession({ appPort, systemPort, shellPort, onClose }: CreateSessionProps): Promise<WorkerSession> {
136
217
  const session = new WorkerSession({
137
218
  serviceHost: this._clientServices,
138
219
  appPort,
@@ -148,8 +229,11 @@ export class WorkerRuntime {
148
229
  // Terminate the worker when all sessions are closed.
149
230
  await this.stop();
150
231
  } else {
151
- this._reconnectWebrtc();
232
+ if (this._automaticallyConnectWebrtc) {
233
+ this._reconnectWebrtc();
234
+ }
152
235
  }
236
+ await onClose?.();
153
237
  });
154
238
 
155
239
  await session.open();
@@ -158,14 +242,27 @@ export class WorkerRuntime {
158
242
  !this._signalMetadataTags.origin || this._signalMetadataTags.origin === session.origin,
159
243
  `worker origin changed from ${this._signalMetadataTags.origin} to ${session.origin}?`,
160
244
  );
161
- if (session.observabilityGroup) {
162
- this._signalMetadataTags.group = session.observabilityGroup;
163
- }
164
- this._signalTelemetryEnabled = session.signalTelemetryEnabled ?? false;
165
245
  this._signalMetadataTags.origin = session.origin;
166
246
  this._sessions.add(session);
167
247
 
168
- this._reconnectWebrtc();
248
+ if (this._automaticallyConnectWebrtc) {
249
+ this._reconnectWebrtc();
250
+ }
251
+
252
+ return session;
253
+ }
254
+
255
+ /**
256
+ * Connects the WebRTC bridge to the specified session.
257
+ * If no session is provided, disconnects the WebRTC bridge.
258
+ *
259
+ * Called automatically if `automaticallyConnectWebrtc` is true.
260
+ *
261
+ * @param session The session to connect the WebRTC bridge to.
262
+ */
263
+ connectWebrtcBridge(session: WorkerSession | undefined): void {
264
+ this._sessionForNetworking = session;
265
+ this._transportFactory.setBridgeService(session?.bridgeService);
169
266
  }
170
267
 
171
268
  /**
@@ -183,12 +280,78 @@ export class WorkerRuntime {
183
280
  // Select existing session.
184
281
  if (!this._sessionForNetworking) {
185
282
  const selected = Array.from(this._sessions).find((session) => session.bridgeService);
186
- if (selected) {
187
- this._sessionForNetworking = selected;
188
- this._transportFactory.setBridgeService(selected.bridgeService);
189
- } else {
190
- this._transportFactory.setBridgeService(undefined);
191
- }
283
+ this.connectWebrtcBridge(selected);
192
284
  }
193
285
  }
194
286
  }
287
+
288
+ const DB_NAME = 'DXOS';
289
+
290
+ /**
291
+ * SqlExport layer that wraps SqliteClient to provide export functionality.
292
+ */
293
+ const SqlExportLayer: Layer.Layer<SqlExport.SqlExport, never, SqliteClient.SqliteClient> = Layer.effect(
294
+ SqlExport.SqlExport,
295
+ Effect.gen(function* () {
296
+ const sql = yield* SqliteClient.SqliteClient;
297
+ return {
298
+ export: sql.export,
299
+ } satisfies SqlExport.Service;
300
+ }),
301
+ );
302
+
303
+ /**
304
+ * Local SQLite layer for the worker.
305
+ * Uses OPFS sync API as an FS backend.
306
+ * Does NOT spawn a new worker.
307
+ * NOTE: Only usable within a worker.
308
+ * TODO(mykola): This does not work right now. Fix.
309
+ */
310
+ const LocalSqliteOpfsLayer = Layer.unwrapScoped(
311
+ Effect.gen(function* () {
312
+ const { port1: clientPort, port2: serverPort } = new MessageChannel();
313
+ clientPort.start();
314
+ serverPort.start();
315
+ yield* Effect.addFinalizer(() =>
316
+ Effect.sync(() => {
317
+ clientPort.close();
318
+ serverPort.close();
319
+ }),
320
+ );
321
+
322
+ yield* Effect.forkScoped(OpfsWorker.run({ port: serverPort, dbName: DB_NAME }));
323
+ return SqlExportLayer.pipe(Layer.provideMerge(SqliteClient.layer({ worker: Effect.succeed(clientPort) })));
324
+ }),
325
+ );
326
+
327
+ // TODO(wittjosiah): Factor out to a separate module.
328
+ class WebLockWrapper {
329
+ readonly #key: string;
330
+ #release?: () => void;
331
+
332
+ constructor(key: string) {
333
+ this.#key = key;
334
+ }
335
+
336
+ get key(): string {
337
+ return this.#key;
338
+ }
339
+
340
+ acquire(options: LockOptions = {}) {
341
+ return navigator.locks.request(this.#key, options, async () => {
342
+ await new Promise<void>((resolve) => {
343
+ this.#release = resolve;
344
+ }); // Blocks for the duration of the worker's lifetime.
345
+ this.#release = undefined;
346
+ });
347
+ }
348
+
349
+ release() {
350
+ this.#release?.();
351
+ this.#release = undefined;
352
+ }
353
+
354
+ [Symbol.dispose]() {
355
+ this.release();
356
+ }
357
+ }
@@ -2,22 +2,22 @@
2
2
  // Copyright 2022 DXOS.org
3
3
  //
4
4
 
5
- import { asyncTimeout, Trigger } from '@dxos/async';
5
+ import { Trigger, asyncTimeout } from '@dxos/async';
6
6
  import {
7
- iframeServiceBundle,
8
7
  type IframeServiceBundle,
9
8
  PROXY_CONNECTION_TIMEOUT,
9
+ iframeServiceBundle,
10
10
  workerServiceBundle,
11
11
  } from '@dxos/client-protocol';
12
12
  import { invariant } from '@dxos/invariant';
13
13
  import { log, logInfo } from '@dxos/log';
14
14
  import { type BridgeService } from '@dxos/protocols/proto/dxos/mesh/bridge';
15
- import { createProtoRpcPeer, type ProtoRpcPeer, type RpcPort } from '@dxos/rpc';
15
+ import { type ProtoRpcPeer, type RpcPort, createProtoRpcPeer } from '@dxos/rpc';
16
16
  import { Callback, type MaybePromise } from '@dxos/util';
17
17
 
18
- import { type ClientServicesHost, ClientRpcServer, type ClientRpcServerParams } from '../services';
18
+ import { ClientRpcServer, type ClientRpcServerProps, type ClientServicesHost } from '../services';
19
19
 
20
- export type WorkerSessionParams = {
20
+ export type WorkerSessionProps = {
21
21
  serviceHost: ClientServicesHost;
22
22
  systemPort: RpcPort;
23
23
  appPort: RpcPort;
@@ -41,35 +41,31 @@ export class WorkerSession {
41
41
  @logInfo
42
42
  public origin?: string;
43
43
 
44
- // TODO(nf): factor out?
45
- public observabilityGroup?: string;
46
- public signalTelemetryEnabled?: boolean;
47
-
48
44
  @logInfo
49
45
  public lockKey?: string;
50
46
 
51
47
  public bridgeService?: BridgeService;
52
48
 
53
- constructor({ serviceHost, systemPort, appPort, shellPort, readySignal }: WorkerSessionParams) {
49
+ constructor({ serviceHost, systemPort, appPort, shellPort, readySignal }: WorkerSessionProps) {
54
50
  invariant(serviceHost);
55
51
  this._serviceHost = serviceHost;
56
52
 
57
- const middleware: Pick<ClientRpcServerParams, 'handleCall' | 'handleStream'> = {
58
- handleCall: async (method, params, handler) => {
53
+ const middleware: Pick<ClientRpcServerProps, 'handleCall' | 'handleStream'> = {
54
+ handleCall: async (method, params, handler, options) => {
59
55
  const error = await readySignal.wait({ timeout: PROXY_CONNECTION_TIMEOUT });
60
56
  if (error) {
61
57
  throw error;
62
58
  }
63
59
 
64
- return handler(method, params);
60
+ return handler(method, params, options);
65
61
  },
66
- handleStream: async (method, params, handler) => {
62
+ handleStream: async (method, params, handler, options) => {
67
63
  const error = await readySignal.wait({ timeout: PROXY_CONNECTION_TIMEOUT });
68
64
  if (error) {
69
65
  throw error;
70
66
  }
71
67
 
72
- return handler(method, params);
68
+ return handler(method, params, options);
73
69
  },
74
70
  };
75
71
 
@@ -95,8 +91,6 @@ export class WorkerSession {
95
91
  start: async (request) => {
96
92
  this.origin = request.origin;
97
93
  this.lockKey = request.lockKey;
98
- this.observabilityGroup = request.observabilityGroup;
99
- this.signalTelemetryEnabled = request.signalTelemetryEnabled;
100
94
  this._startTrigger.wake();
101
95
  },
102
96
 
@@ -119,7 +113,7 @@ export class WorkerSession {
119
113
  }
120
114
 
121
115
  async open(): Promise<void> {
122
- log.info('opening...');
116
+ log('opening...');
123
117
  await Promise.all([this._clientRpc.open(), this._iframeRpc.open(), this._maybeOpenShell()]);
124
118
 
125
119
  // Wait until the worker's RPC service has started.
@@ -130,11 +124,11 @@ export class WorkerSession {
130
124
  void this._afterLockReleases(this.lockKey, () => this.close());
131
125
  }
132
126
 
133
- log.info('opened');
127
+ log('opened');
134
128
  }
135
129
 
136
130
  async close(): Promise<void> {
137
- log.info('closing...');
131
+ log.debug('closing...');
138
132
  try {
139
133
  await this.onClose.callIfSet();
140
134
  } catch (err: any) {
@@ -142,7 +136,7 @@ export class WorkerSession {
142
136
  }
143
137
 
144
138
  await Promise.all([this._clientRpc.close(), this._iframeRpc.close()]);
145
- log.info('closed');
139
+ log.debug('closed');
146
140
  }
147
141
 
148
142
  private async _maybeOpenShell(): Promise<void> {
package/src/version.ts CHANGED
@@ -1 +1 @@
1
- export const DXOS_VERSION = "0.8.4-main.f9ba587";
1
+ export const DXOS_VERSION = "0.8.4-main.fcfe5033a5";