@dxos/client-services 0.8.4-main.7ace549 → 0.8.4-main.937b3ca
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/browser/chunk-NQSC7HOE.mjs +22 -0
- package/dist/lib/browser/chunk-NQSC7HOE.mjs.map +7 -0
- package/dist/lib/browser/chunk-QCWEHHJW.mjs +24 -0
- package/dist/lib/browser/chunk-QCWEHHJW.mjs.map +7 -0
- package/dist/lib/browser/{chunk-NXGWBEOK.mjs → chunk-UDCUM4WV.mjs} +922 -1265
- package/dist/lib/browser/chunk-UDCUM4WV.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +432 -65
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/packlets/diagnostics/browser-diagnostics-broadcast.mjs +93 -0
- package/dist/lib/browser/packlets/diagnostics/browser-diagnostics-broadcast.mjs.map +7 -0
- package/dist/lib/browser/packlets/diagnostics/diagnostics-broadcast.mjs +11 -0
- package/dist/lib/browser/packlets/diagnostics/diagnostics-broadcast.mjs.map +7 -0
- package/dist/lib/browser/packlets/locks/browser.mjs +126 -0
- package/dist/lib/browser/packlets/locks/browser.mjs.map +7 -0
- package/dist/lib/browser/packlets/locks/node.mjs +66 -0
- package/dist/lib/browser/packlets/locks/node.mjs.map +7 -0
- package/dist/lib/browser/testing/index.mjs +24 -12
- package/dist/lib/browser/testing/index.mjs.map +3 -3
- package/dist/lib/node-esm/chunk-2SZHAWBN.mjs +24 -0
- package/dist/lib/node-esm/chunk-2SZHAWBN.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-PKEGMOQ4.mjs +22 -0
- package/dist/lib/node-esm/chunk-PKEGMOQ4.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-AO4R6IID.mjs → chunk-Q56HAUWS.mjs} +421 -633
- package/dist/lib/node-esm/chunk-Q56HAUWS.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +432 -65
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/packlets/diagnostics/browser-diagnostics-broadcast.mjs +93 -0
- package/dist/lib/node-esm/packlets/diagnostics/browser-diagnostics-broadcast.mjs.map +7 -0
- package/dist/lib/node-esm/packlets/diagnostics/diagnostics-broadcast.mjs +11 -0
- package/dist/lib/node-esm/packlets/diagnostics/diagnostics-broadcast.mjs.map +7 -0
- package/dist/lib/node-esm/packlets/locks/browser.mjs +126 -0
- package/dist/lib/node-esm/packlets/locks/browser.mjs.map +7 -0
- package/dist/lib/node-esm/packlets/locks/node.mjs +66 -0
- package/dist/lib/node-esm/packlets/locks/node.mjs.map +7 -0
- package/dist/lib/node-esm/testing/index.mjs +24 -12
- package/dist/lib/node-esm/testing/index.mjs.map +3 -3
- package/dist/types/src/packlets/devtools/devtools.d.ts +2 -2
- package/dist/types/src/packlets/devtools/devtools.d.ts.map +1 -1
- package/dist/types/src/packlets/diagnostics/index.d.ts +1 -1
- package/dist/types/src/packlets/diagnostics/index.d.ts.map +1 -1
- package/dist/types/src/packlets/identity/authenticator.d.ts +2 -2
- package/dist/types/src/packlets/identity/authenticator.d.ts.map +1 -1
- package/dist/types/src/packlets/identity/default-space-state-machine.d.ts +2 -2
- package/dist/types/src/packlets/identity/default-space-state-machine.d.ts.map +1 -1
- package/dist/types/src/packlets/identity/identity-manager.d.ts +4 -4
- package/dist/types/src/packlets/identity/identity-manager.d.ts.map +1 -1
- package/dist/types/src/packlets/identity/identity-recovery-manager.d.ts +2 -2
- package/dist/types/src/packlets/identity/identity-recovery-manager.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/device-invitation-protocol.d.ts +2 -2
- package/dist/types/src/packlets/invitations/device-invitation-protocol.d.ts.map +1 -1
- package/dist/types/src/packlets/invitations/invitations-handler.d.ts +4 -4
- package/dist/types/src/packlets/invitations/invitations-handler.d.ts.map +1 -1
- package/dist/types/src/packlets/locks/index.d.ts +1 -1
- package/dist/types/src/packlets/locks/index.d.ts.map +1 -1
- package/dist/types/src/packlets/services/client-rpc-server.d.ts +2 -2
- package/dist/types/src/packlets/services/client-rpc-server.d.ts.map +1 -1
- package/dist/types/src/packlets/services/service-context.d.ts +13 -7
- package/dist/types/src/packlets/services/service-context.d.ts.map +1 -1
- package/dist/types/src/packlets/services/service-host.d.ts +19 -5
- package/dist/types/src/packlets/services/service-host.d.ts.map +1 -1
- package/dist/types/src/packlets/space-export/space-archive-writer.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/data-space-manager.d.ts +10 -5
- package/dist/types/src/packlets/spaces/data-space-manager.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/data-space.d.ts +2 -2
- package/dist/types/src/packlets/spaces/data-space.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/edge-feed-replicator.d.ts +2 -2
- package/dist/types/src/packlets/spaces/edge-feed-replicator.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/notarization-plugin.d.ts +6 -6
- package/dist/types/src/packlets/spaces/notarization-plugin.d.ts.map +1 -1
- package/dist/types/src/packlets/testing/invitation-utils.d.ts +6 -3
- package/dist/types/src/packlets/testing/invitation-utils.d.ts.map +1 -1
- package/dist/types/src/packlets/testing/test-builder.d.ts +6 -5
- package/dist/types/src/packlets/testing/test-builder.d.ts.map +1 -1
- package/dist/types/src/packlets/worker/worker-runtime.d.ts +23 -4
- package/dist/types/src/packlets/worker/worker-runtime.d.ts.map +1 -1
- package/dist/types/src/packlets/worker/worker-session.d.ts +2 -2
- package/dist/types/src/packlets/worker/worker-session.d.ts.map +1 -1
- package/dist/types/src/version.d.ts +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +70 -48
- package/src/packlets/devtools/devtools.ts +2 -2
- package/src/packlets/diagnostics/index.ts +1 -1
- package/src/packlets/identity/authenticator.ts +2 -2
- package/src/packlets/identity/default-space-state-machine.ts +2 -2
- package/src/packlets/identity/identity-manager.ts +6 -6
- package/src/packlets/identity/identity-recovery-manager.ts +2 -2
- package/src/packlets/identity/identity.ts +2 -2
- package/src/packlets/invitations/device-invitation-protocol.ts +2 -2
- package/src/packlets/invitations/invitations-handler.ts +6 -6
- package/src/packlets/locks/index.ts +1 -1
- package/src/packlets/services/client-rpc-server.ts +4 -4
- package/src/packlets/services/service-context.ts +30 -19
- package/src/packlets/services/service-host.ts +56 -16
- package/src/packlets/space-export/space-archive-writer.ts +3 -2
- package/src/packlets/spaces/data-space-manager.ts +35 -16
- package/src/packlets/spaces/data-space.ts +6 -5
- package/src/packlets/spaces/edge-feed-replicator.ts +2 -2
- package/src/packlets/spaces/epoch-migrations.ts +2 -2
- package/src/packlets/spaces/notarization-plugin.test.ts +2 -2
- package/src/packlets/spaces/notarization-plugin.ts +6 -6
- package/src/packlets/testing/invitation-utils.ts +7 -4
- package/src/packlets/testing/test-builder.ts +36 -10
- package/src/packlets/worker/worker-runtime.ts +141 -11
- package/src/packlets/worker/worker-session.ts +4 -4
- package/src/version.ts +1 -1
- package/dist/lib/browser/chunk-NXGWBEOK.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-AO4R6IID.mjs.map +0 -7
|
@@ -2,11 +2,15 @@
|
|
|
2
2
|
// Copyright 2021 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
+
import * as SqlClient from '@effect/sql/SqlClient';
|
|
6
|
+
import * as Effect from 'effect/Effect';
|
|
7
|
+
|
|
5
8
|
import { Event, synchronized } from '@dxos/async';
|
|
6
9
|
import { type ClientServices, clientServiceBundle } from '@dxos/client-protocol';
|
|
7
10
|
import { type Config } from '@dxos/config';
|
|
8
11
|
import { Context } from '@dxos/context';
|
|
9
12
|
import { EdgeClient, type EdgeConnection, EdgeHttpClient, createStubEdgeIdentity } from '@dxos/edge-client';
|
|
13
|
+
import { RuntimeProvider } from '@dxos/effect';
|
|
10
14
|
import { invariant } from '@dxos/invariant';
|
|
11
15
|
import { PublicKey } from '@dxos/keys';
|
|
12
16
|
import { type LevelDB } from '@dxos/kv-store';
|
|
@@ -21,6 +25,8 @@ import {
|
|
|
21
25
|
import { trace } from '@dxos/protocols';
|
|
22
26
|
import { SystemStatus } from '@dxos/protocols/proto/dxos/client/services';
|
|
23
27
|
import { type Storage } from '@dxos/random-access-storage';
|
|
28
|
+
import * as SqlExport from '@dxos/sql-sqlite/SqlExport';
|
|
29
|
+
import type * as SqlTransaction from '@dxos/sql-sqlite/SqlTransaction';
|
|
24
30
|
import { TRACE_PROCESSOR, trace as Trace } from '@dxos/tracing';
|
|
25
31
|
import { WebsocketRpcClient } from '@dxos/websocket-rpc';
|
|
26
32
|
|
|
@@ -42,10 +48,10 @@ import { SpacesServiceImpl } from '../spaces';
|
|
|
42
48
|
import { createLevel, createStorageObjects } from '../storage';
|
|
43
49
|
import { SystemServiceImpl } from '../system';
|
|
44
50
|
|
|
45
|
-
import { ServiceContext, type
|
|
51
|
+
import { ServiceContext, type ServiceContextRuntimeProps } from './service-context';
|
|
46
52
|
import { ServiceRegistry } from './service-registry';
|
|
47
53
|
|
|
48
|
-
export type
|
|
54
|
+
export type ClientServicesHostProps = {
|
|
49
55
|
/**
|
|
50
56
|
* Can be omitted if `initialize` is later called.
|
|
51
57
|
*/
|
|
@@ -57,7 +63,8 @@ export type ClientServicesHostParams = {
|
|
|
57
63
|
level?: LevelDB;
|
|
58
64
|
lockKey?: string;
|
|
59
65
|
callbacks?: ClientServicesHostCallbacks;
|
|
60
|
-
|
|
66
|
+
runtime: RuntimeProvider.RuntimeProvider<SqlClient.SqlClient | SqlExport.SqlExport | SqlTransaction.SqlTransaction>;
|
|
67
|
+
runtimeProps?: ServiceContextRuntimeProps;
|
|
61
68
|
};
|
|
62
69
|
|
|
63
70
|
export type ClientServicesHostCallbacks = {
|
|
@@ -95,7 +102,10 @@ export class ClientServicesHost {
|
|
|
95
102
|
private _edgeHttpClient?: EdgeHttpClient = undefined;
|
|
96
103
|
|
|
97
104
|
private _serviceContext!: ServiceContext;
|
|
98
|
-
private readonly
|
|
105
|
+
private readonly _runtime: RuntimeProvider.RuntimeProvider<
|
|
106
|
+
SqlClient.SqlClient | SqlExport.SqlExport | SqlTransaction.SqlTransaction
|
|
107
|
+
>;
|
|
108
|
+
private readonly _runtimeProps: ServiceContextRuntimeProps;
|
|
99
109
|
private diagnosticsBroadcastHandler: CollectDiagnosticsBroadcastHandler;
|
|
100
110
|
|
|
101
111
|
@Trace.info()
|
|
@@ -116,20 +126,14 @@ export class ClientServicesHost {
|
|
|
116
126
|
// TODO(wittjosiah): Turn this on by default.
|
|
117
127
|
lockKey,
|
|
118
128
|
callbacks,
|
|
119
|
-
|
|
120
|
-
|
|
129
|
+
runtime,
|
|
130
|
+
runtimeProps,
|
|
131
|
+
}: ClientServicesHostProps) {
|
|
121
132
|
this._storage = storage;
|
|
122
133
|
this._level = level;
|
|
123
134
|
this._callbacks = callbacks;
|
|
124
|
-
this.
|
|
125
|
-
|
|
126
|
-
if (this._runtimeParams.disableP2pReplication === undefined) {
|
|
127
|
-
this._runtimeParams.disableP2pReplication = config?.get('runtime.client.disableP2pReplication', false);
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
if (this._runtimeParams.enableVectorIndexing === undefined) {
|
|
131
|
-
this._runtimeParams.enableVectorIndexing = config?.get('runtime.client.enableVectorIndexing', false);
|
|
132
|
-
}
|
|
135
|
+
this._runtime = runtime;
|
|
136
|
+
this._runtimeProps = runtimeProps ?? {};
|
|
133
137
|
|
|
134
138
|
if (config) {
|
|
135
139
|
this.initialize({ config, transportFactory, signalManager });
|
|
@@ -200,6 +204,30 @@ export class ClientServicesHost {
|
|
|
200
204
|
return this._serviceRegistry.services;
|
|
201
205
|
}
|
|
202
206
|
|
|
207
|
+
/**
|
|
208
|
+
* Debugging util.
|
|
209
|
+
*/
|
|
210
|
+
async exportSqliteDatabase(): Promise<Uint8Array> {
|
|
211
|
+
return await RuntimeProvider.runPromise(this._runtime)(
|
|
212
|
+
Effect.gen(function* () {
|
|
213
|
+
const sql = yield* SqlExport.SqlExport;
|
|
214
|
+
return yield* sql.export;
|
|
215
|
+
}),
|
|
216
|
+
);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Debugging util.
|
|
221
|
+
*/
|
|
222
|
+
async runSqliteQuery(query: string, params?: any[]): Promise<readonly Record<string, unknown>[]> {
|
|
223
|
+
return await RuntimeProvider.runPromise(this._runtime)(
|
|
224
|
+
Effect.gen(function* () {
|
|
225
|
+
const sql = yield* SqlClient.SqlClient;
|
|
226
|
+
return yield* sql`${sql.unsafe(query, params)}`;
|
|
227
|
+
}),
|
|
228
|
+
);
|
|
229
|
+
}
|
|
230
|
+
|
|
203
231
|
/**
|
|
204
232
|
* Initialize the service host with the config.
|
|
205
233
|
* Config can also be provided in the constructor.
|
|
@@ -210,6 +238,16 @@ export class ClientServicesHost {
|
|
|
210
238
|
log('initializing...');
|
|
211
239
|
|
|
212
240
|
if (config) {
|
|
241
|
+
if (this._runtimeProps.disableP2pReplication === undefined) {
|
|
242
|
+
this._runtimeProps.disableP2pReplication = config?.get('runtime.client.disableP2pReplication', false);
|
|
243
|
+
}
|
|
244
|
+
if (this._runtimeProps.enableVectorIndexing === undefined) {
|
|
245
|
+
this._runtimeProps.enableVectorIndexing = config?.get('runtime.client.enableVectorIndexing', false);
|
|
246
|
+
}
|
|
247
|
+
if (this._runtimeProps.enableLocalQueues === undefined) {
|
|
248
|
+
this._runtimeProps.enableLocalQueues = config?.get('runtime.client.enableLocalQueues', false);
|
|
249
|
+
}
|
|
250
|
+
|
|
213
251
|
invariant(!this._config, 'config already set');
|
|
214
252
|
this._config = config;
|
|
215
253
|
if (!this._storage) {
|
|
@@ -291,7 +329,8 @@ export class ClientServicesHost {
|
|
|
291
329
|
this._signalManager,
|
|
292
330
|
this._edgeConnection,
|
|
293
331
|
this._edgeHttpClient,
|
|
294
|
-
this.
|
|
332
|
+
this._runtime,
|
|
333
|
+
this._runtimeProps,
|
|
295
334
|
this._config.get('runtime.client.edgeFeatures'),
|
|
296
335
|
);
|
|
297
336
|
|
|
@@ -335,6 +374,7 @@ export class ClientServicesHost {
|
|
|
335
374
|
|
|
336
375
|
DataService: this._serviceContext.echoHost.dataService,
|
|
337
376
|
QueryService: this._serviceContext.echoHost.queryService,
|
|
377
|
+
QueueService: this._serviceContext.echoHost.queuesService,
|
|
338
378
|
|
|
339
379
|
NetworkService: new NetworkServiceImpl(
|
|
340
380
|
this._serviceContext.networkManager,
|
|
@@ -9,6 +9,7 @@ import { assertArgument, assertState } from '@dxos/invariant';
|
|
|
9
9
|
import type { IdentityDid, SpaceId } from '@dxos/keys';
|
|
10
10
|
import { SpaceArchiveFileStructure, type SpaceArchiveMetadata, SpaceArchiveVersion } from '@dxos/protocols';
|
|
11
11
|
import type { SpaceArchive } from '@dxos/protocols/proto/dxos/client/services';
|
|
12
|
+
import { createFilename } from '@dxos/util';
|
|
12
13
|
|
|
13
14
|
export type SpaceArchiveBeginProps = {
|
|
14
15
|
spaceId?: SpaceId;
|
|
@@ -59,6 +60,7 @@ export class SpaceArchiveWriter extends Resource {
|
|
|
59
60
|
async finish(): Promise<SpaceArchive> {
|
|
60
61
|
assertState(this._archive, 'Not open');
|
|
61
62
|
assertState(this._meta, 'Not started');
|
|
63
|
+
assertState(this._meta.spaceId, 'No space ID set');
|
|
62
64
|
assertState(this._currentRootUrl, 'No root URL set');
|
|
63
65
|
|
|
64
66
|
const metadata: SpaceArchiveMetadata = {
|
|
@@ -76,8 +78,7 @@ export class SpaceArchiveWriter extends Resource {
|
|
|
76
78
|
const binary = this._archive.toUint8Array();
|
|
77
79
|
|
|
78
80
|
return {
|
|
79
|
-
|
|
80
|
-
filename: `${new Date().toISOString()}-${this._meta.spaceId}.tar`,
|
|
81
|
+
filename: createFilename({ parts: [this._meta.spaceId], ext: 'tar' }),
|
|
81
82
|
contents: binary,
|
|
82
83
|
};
|
|
83
84
|
}
|
|
@@ -16,14 +16,13 @@ import {
|
|
|
16
16
|
getCredentialAssertion,
|
|
17
17
|
} from '@dxos/credentials';
|
|
18
18
|
import { Type } from '@dxos/echo';
|
|
19
|
-
import {
|
|
19
|
+
import { getSchemaDXN } from '@dxos/echo/internal';
|
|
20
20
|
import {
|
|
21
21
|
AuthStatus,
|
|
22
22
|
CredentialServerExtension,
|
|
23
23
|
DatabaseRoot,
|
|
24
24
|
type EchoEdgeReplicator,
|
|
25
25
|
type EchoHost,
|
|
26
|
-
FIND_PARAMS,
|
|
27
26
|
type MeshEchoReplicator,
|
|
28
27
|
type MetadataStore,
|
|
29
28
|
type Space,
|
|
@@ -34,10 +33,10 @@ import {
|
|
|
34
33
|
} from '@dxos/echo-pipeline';
|
|
35
34
|
import {
|
|
36
35
|
type DatabaseDirectory,
|
|
36
|
+
EncodedReference,
|
|
37
37
|
type ObjectStructure,
|
|
38
38
|
SpaceDocVersion,
|
|
39
39
|
createIdFromSpaceKey,
|
|
40
|
-
encodeReference,
|
|
41
40
|
} from '@dxos/echo-protocol';
|
|
42
41
|
import type { EdgeConnection, EdgeHttpClient } from '@dxos/edge-client';
|
|
43
42
|
import { type FeedStore, writeMessages } from '@dxos/feed-store';
|
|
@@ -105,7 +104,7 @@ export type AdmitMemberOptions = {
|
|
|
105
104
|
delegationCredentialId?: PublicKey;
|
|
106
105
|
};
|
|
107
106
|
|
|
108
|
-
export type
|
|
107
|
+
export type DataSpaceManagerProps = {
|
|
109
108
|
spaceManager: SpaceManager;
|
|
110
109
|
metadataStore: MetadataStore;
|
|
111
110
|
keyring: Keyring;
|
|
@@ -117,15 +116,20 @@ export type DataSpaceManagerParams = {
|
|
|
117
116
|
edgeHttpClient?: EdgeHttpClient;
|
|
118
117
|
meshReplicator?: MeshEchoReplicator;
|
|
119
118
|
echoEdgeReplicator?: EchoEdgeReplicator;
|
|
120
|
-
|
|
119
|
+
runtimeProps?: DataSpaceManagerRuntimeProps;
|
|
121
120
|
edgeFeatures?: Runtime.Client.EdgeFeatures;
|
|
122
121
|
};
|
|
123
122
|
|
|
124
|
-
export type
|
|
123
|
+
export type DataSpaceManagerRuntimeProps = {
|
|
125
124
|
spaceMemberPresenceAnnounceInterval?: number;
|
|
126
125
|
spaceMemberPresenceOfflineTimeout?: number;
|
|
127
126
|
activeEdgeNotarizationPollingInterval?: number;
|
|
128
127
|
disableP2pReplication?: boolean;
|
|
128
|
+
/**
|
|
129
|
+
* If true, spaces that were previously SPACE_ACTIVE will be automatically activated on startup.
|
|
130
|
+
* This is used in dedicated worker mode to restore space state after leader changeover.
|
|
131
|
+
*/
|
|
132
|
+
autoActivateSpaces?: boolean;
|
|
129
133
|
};
|
|
130
134
|
|
|
131
135
|
export type CreateSpaceOptions = {
|
|
@@ -153,9 +157,9 @@ export class DataSpaceManager extends Resource {
|
|
|
153
157
|
private readonly _edgeFeatures?: Runtime.Client.EdgeFeatures = undefined;
|
|
154
158
|
private readonly _meshReplicator?: MeshEchoReplicator = undefined;
|
|
155
159
|
private readonly _echoEdgeReplicator?: EchoEdgeReplicator = undefined;
|
|
156
|
-
private readonly
|
|
160
|
+
private readonly _runtimeProps?: DataSpaceManagerRuntimeProps = undefined;
|
|
157
161
|
|
|
158
|
-
constructor(params:
|
|
162
|
+
constructor(params: DataSpaceManagerProps) {
|
|
159
163
|
super();
|
|
160
164
|
|
|
161
165
|
this._spaceManager = params.spaceManager;
|
|
@@ -170,7 +174,7 @@ export class DataSpaceManager extends Resource {
|
|
|
170
174
|
this._edgeFeatures = params.edgeFeatures;
|
|
171
175
|
this._echoEdgeReplicator = params.echoEdgeReplicator;
|
|
172
176
|
this._edgeHttpClient = params.edgeHttpClient;
|
|
173
|
-
this.
|
|
177
|
+
this._runtimeProps = params.runtimeProps;
|
|
174
178
|
|
|
175
179
|
trace.diagnostic({
|
|
176
180
|
id: 'spaces',
|
|
@@ -180,7 +184,7 @@ export class DataSpaceManager extends Resource {
|
|
|
180
184
|
Array.from(this._spaces.values()).map(async (space) => {
|
|
181
185
|
const rootUrl = space.automergeSpaceState.rootUrl;
|
|
182
186
|
const rootHandle = rootUrl
|
|
183
|
-
? await this._echoHost.
|
|
187
|
+
? await this._echoHost.loadDoc<Doc<DatabaseDirectory>>(Context.default(), rootUrl as AutomergeUrl)
|
|
184
188
|
: undefined;
|
|
185
189
|
await rootHandle?.whenReady();
|
|
186
190
|
const rootDoc = rootHandle?.doc();
|
|
@@ -218,15 +222,28 @@ export class DataSpaceManager extends Resource {
|
|
|
218
222
|
log.trace('dxos.echo.data-space-manager.open', Trace.begin({ id: this._instanceId }));
|
|
219
223
|
log('metadata loaded', { spaces: this._metadataStore.spaces.length });
|
|
220
224
|
|
|
225
|
+
const spacesToActivate: DataSpace[] = [];
|
|
221
226
|
await forEachAsync(this._metadataStore.spaces, async (spaceMetadata) => {
|
|
222
227
|
try {
|
|
223
228
|
log('load space', { spaceMetadata });
|
|
224
|
-
await this._constructSpace(spaceMetadata);
|
|
229
|
+
const space = await this._constructSpace(spaceMetadata);
|
|
230
|
+
// Track spaces that were previously active for auto-activation (used in dedicated worker mode).
|
|
231
|
+
if (this._runtimeProps?.autoActivateSpaces && spaceMetadata.state === SpaceState.SPACE_ACTIVE) {
|
|
232
|
+
spacesToActivate.push(space);
|
|
233
|
+
}
|
|
225
234
|
} catch (err) {
|
|
226
235
|
log.error('Error loading space', { spaceMetadata, err });
|
|
227
236
|
}
|
|
228
237
|
});
|
|
229
238
|
|
|
239
|
+
// Auto-activate spaces that were previously active (used in dedicated worker mode after leader changeover).
|
|
240
|
+
for (const space of spacesToActivate) {
|
|
241
|
+
log('auto-activating space', { spaceKey: space.key });
|
|
242
|
+
space.activate().catch((err) => {
|
|
243
|
+
log.error('Error auto-activating space', { spaceKey: space.key, err });
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
|
|
230
247
|
this.updated.emit();
|
|
231
248
|
|
|
232
249
|
log.trace('dxos.echo.data-space-manager.open', Trace.end({ id: this._instanceId }));
|
|
@@ -366,7 +383,7 @@ export class DataSpaceManager extends Resource {
|
|
|
366
383
|
// TODO(dmaretskyi): Better API for low-level data access.
|
|
367
384
|
const properties: ObjectStructure = {
|
|
368
385
|
system: {
|
|
369
|
-
type:
|
|
386
|
+
type: EncodedReference.fromDXN(getSchemaDXN(SpaceProperties)!),
|
|
370
387
|
},
|
|
371
388
|
data: {
|
|
372
389
|
[DEFAULT_SPACE_KEY]: this._signingContext.identityKey.toHex(),
|
|
@@ -388,7 +405,9 @@ export class DataSpaceManager extends Resource {
|
|
|
388
405
|
private async _getSpaceRootDocument(space: DataSpace): Promise<DocHandle<DatabaseDirectory>> {
|
|
389
406
|
const automergeIndex = space.automergeSpaceState.rootUrl;
|
|
390
407
|
invariant(automergeIndex);
|
|
391
|
-
const document = await this._echoHost.
|
|
408
|
+
const document = await this._echoHost.loadDoc<DatabaseDirectory>(Context.default(), automergeIndex as any, {
|
|
409
|
+
fetchFromNetwork: true,
|
|
410
|
+
});
|
|
392
411
|
await document.whenReady();
|
|
393
412
|
return document;
|
|
394
413
|
}
|
|
@@ -500,8 +519,8 @@ export class DataSpaceManager extends Resource {
|
|
|
500
519
|
localPeerId: this._signingContext.deviceKey,
|
|
501
520
|
});
|
|
502
521
|
const presence = new Presence({
|
|
503
|
-
announceInterval: this.
|
|
504
|
-
offlineTimeout: this.
|
|
522
|
+
announceInterval: this._runtimeProps?.spaceMemberPresenceAnnounceInterval ?? PRESENCE_ANNOUNCE_INTERVAL,
|
|
523
|
+
offlineTimeout: this._runtimeProps?.spaceMemberPresenceOfflineTimeout ?? PRESENCE_OFFLINE_TIMEOUT,
|
|
505
524
|
identityKey: this._signingContext.identityKey,
|
|
506
525
|
gossip,
|
|
507
526
|
});
|
|
@@ -587,7 +606,7 @@ export class DataSpaceManager extends Resource {
|
|
|
587
606
|
edgeConnection: this._edgeConnection,
|
|
588
607
|
edgeHttpClient: this._edgeHttpClient,
|
|
589
608
|
edgeFeatures: this._edgeFeatures,
|
|
590
|
-
activeEdgeNotarizationPollingInterval: this.
|
|
609
|
+
activeEdgeNotarizationPollingInterval: this._runtimeProps?.activeEdgeNotarizationPollingInterval,
|
|
591
610
|
});
|
|
592
611
|
dataSpace.postOpen.append(async () => {
|
|
593
612
|
const setting = dataSpace.getEdgeReplicationSetting();
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
import { save } from '@automerge/automerge';
|
|
6
|
-
import { type DocHandle } from '@automerge/automerge-repo';
|
|
6
|
+
import { type AutomergeUrl, type DocHandle } from '@automerge/automerge-repo';
|
|
7
7
|
|
|
8
8
|
import { Event, Mutex, scheduleTask, sleep, synchronized, trackLeaks } from '@dxos/async';
|
|
9
9
|
import { AUTH_TIMEOUT } from '@dxos/client-protocol';
|
|
@@ -13,7 +13,6 @@ import { timed, warnAfterTimeout } from '@dxos/debug';
|
|
|
13
13
|
import {
|
|
14
14
|
type DatabaseRoot,
|
|
15
15
|
type EchoHost,
|
|
16
|
-
FIND_PARAMS,
|
|
17
16
|
type MetadataStore,
|
|
18
17
|
type Space,
|
|
19
18
|
createMappedFeedWriter,
|
|
@@ -72,7 +71,7 @@ export type DataSpaceCallbacks = {
|
|
|
72
71
|
beforeClose?: () => Promise<void>;
|
|
73
72
|
};
|
|
74
73
|
|
|
75
|
-
export type
|
|
74
|
+
export type DataSpaceProps = {
|
|
76
75
|
initialState: SpaceState;
|
|
77
76
|
inner: Space;
|
|
78
77
|
metadataStore: MetadataStore;
|
|
@@ -136,7 +135,7 @@ export class DataSpace {
|
|
|
136
135
|
|
|
137
136
|
public metrics: SpaceProto.Metrics = {};
|
|
138
137
|
|
|
139
|
-
constructor(params:
|
|
138
|
+
constructor(params: DataSpaceProps) {
|
|
140
139
|
this._inner = params.inner;
|
|
141
140
|
this._inner.stateUpdate.on(this._ctx, () => this.stateUpdate.emit());
|
|
142
141
|
|
|
@@ -471,7 +470,9 @@ export class DataSpace {
|
|
|
471
470
|
await warnAfterTimeout(5_000, 'Automerge root doc load timeout (DataSpace)', async () => {
|
|
472
471
|
handle = await cancelWithContext(
|
|
473
472
|
this._ctx,
|
|
474
|
-
this._echoHost.
|
|
473
|
+
this._echoHost.loadDoc<DatabaseDirectory>(Context.default(), rootUrl as AutomergeUrl, {
|
|
474
|
+
fetchFromNetwork: true,
|
|
475
|
+
}),
|
|
475
476
|
);
|
|
476
477
|
await cancelWithContext(this._ctx, handle.whenReady());
|
|
477
478
|
});
|
|
@@ -22,7 +22,7 @@ import type { FeedBlock, ProtocolMessage } from '@dxos/protocols/feed-replicatio
|
|
|
22
22
|
import { EdgeStatus } from '@dxos/protocols/proto/dxos/client/services';
|
|
23
23
|
import { ComplexMap, arrayToBuffer, bufferToArray, defaultMap, rangeFromTo } from '@dxos/util';
|
|
24
24
|
|
|
25
|
-
export type
|
|
25
|
+
export type EdgeFeedReplicatorProps = {
|
|
26
26
|
messenger: EdgeConnection;
|
|
27
27
|
spaceId: SpaceId;
|
|
28
28
|
};
|
|
@@ -47,7 +47,7 @@ export class EdgeFeedReplicator extends Resource {
|
|
|
47
47
|
*/
|
|
48
48
|
private _pushMutex = new ComplexMap<PublicKey, Mutex>(PublicKey.hash);
|
|
49
49
|
|
|
50
|
-
constructor({ messenger, spaceId }:
|
|
50
|
+
constructor({ messenger, spaceId }: EdgeFeedReplicatorProps) {
|
|
51
51
|
super();
|
|
52
52
|
this._messenger = messenger;
|
|
53
53
|
this._spaceId = spaceId;
|
|
@@ -36,7 +36,7 @@ const LOAD_DOC_TIMEOUT = 10_000;
|
|
|
36
36
|
export const runEpochMigration = async (ctx: Context, context: MigrationContext): Promise<MigrationResult> => {
|
|
37
37
|
switch (context.migration) {
|
|
38
38
|
case CreateEpochRequest.Migration.INIT_AUTOMERGE: {
|
|
39
|
-
const document = context.echoHost.createDoc();
|
|
39
|
+
const document = await context.echoHost.createDoc();
|
|
40
40
|
await context.echoHost.flush();
|
|
41
41
|
return { newRoot: document.url };
|
|
42
42
|
}
|
|
@@ -48,7 +48,7 @@ export const runEpochMigration = async (ctx: Context, context: MigrationContext)
|
|
|
48
48
|
timeout: LOAD_DOC_TIMEOUT,
|
|
49
49
|
});
|
|
50
50
|
|
|
51
|
-
const newRoot = context.echoHost.createDoc(rootHandle.doc());
|
|
51
|
+
const newRoot = await context.echoHost.createDoc(rootHandle.doc());
|
|
52
52
|
await context.echoHost.flush();
|
|
53
53
|
return { newRoot: newRoot.url };
|
|
54
54
|
}
|
|
@@ -13,7 +13,7 @@ import { log } from '@dxos/log';
|
|
|
13
13
|
import { AdmittedFeed, type Credential } from '@dxos/protocols/proto/dxos/halo/credentials';
|
|
14
14
|
import { TestBuilder, type TestConnection, TestPeer } from '@dxos/teleport/testing';
|
|
15
15
|
|
|
16
|
-
import { NotarizationPlugin, type
|
|
16
|
+
import { NotarizationPlugin, type NotarizationPluginProps } from './notarization-plugin';
|
|
17
17
|
|
|
18
18
|
class TestAgent extends TestPeer {
|
|
19
19
|
private readonly _ctx = new Context();
|
|
@@ -21,7 +21,7 @@ class TestAgent extends TestPeer {
|
|
|
21
21
|
feed = new MockFeedWriter<Credential>();
|
|
22
22
|
notarizationPlugin: NotarizationPlugin;
|
|
23
23
|
|
|
24
|
-
constructor(params:
|
|
24
|
+
constructor(params: NotarizationPluginProps) {
|
|
25
25
|
super();
|
|
26
26
|
this.notarizationPlugin = new NotarizationPlugin(params);
|
|
27
27
|
this.feed.written.on(this._ctx, async ([credential]) => {
|
|
@@ -33,14 +33,14 @@ const WRITER_NOT_SET_ERROR_CODE = 'WRITER_NOT_SET';
|
|
|
33
33
|
|
|
34
34
|
const credentialCodec = schema.getCodecForType('dxos.halo.credentials.Credential');
|
|
35
35
|
|
|
36
|
-
export type
|
|
36
|
+
export type NotarizationPluginProps = {
|
|
37
37
|
spaceId: SpaceId;
|
|
38
38
|
edgeClient?: EdgeHttpClient;
|
|
39
39
|
edgeFeatures?: Runtime.Client.EdgeFeatures;
|
|
40
40
|
activeEdgePollingInterval?: number;
|
|
41
41
|
};
|
|
42
42
|
|
|
43
|
-
export type
|
|
43
|
+
export type NotarizeProps = {
|
|
44
44
|
/**
|
|
45
45
|
* For cancellation.
|
|
46
46
|
*/
|
|
@@ -97,7 +97,7 @@ export class NotarizationPlugin extends Resource implements CredentialProcessor
|
|
|
97
97
|
|
|
98
98
|
private readonly _edgeClient: EdgeHttpClient | undefined;
|
|
99
99
|
|
|
100
|
-
constructor(params:
|
|
100
|
+
constructor(params: NotarizationPluginProps) {
|
|
101
101
|
super();
|
|
102
102
|
this._spaceId = params.spaceId;
|
|
103
103
|
this._activeEdgePollingInterval = params.activeEdgePollingInterval ?? DEFAULT_ACTIVE_EDGE_POLLING_INTERVAL;
|
|
@@ -149,7 +149,7 @@ export class NotarizationPlugin extends Resource implements CredentialProcessor
|
|
|
149
149
|
retryTimeout = DEFAULT_RETRY_TIMEOUT,
|
|
150
150
|
successDelay = DEFAULT_SUCCESS_DELAY,
|
|
151
151
|
edgeRetryJitter,
|
|
152
|
-
}:
|
|
152
|
+
}: NotarizeProps): Promise<void> {
|
|
153
153
|
log('notarize', { credentials });
|
|
154
154
|
invariant(
|
|
155
155
|
credentials.every((credential) => credential.id),
|
|
@@ -399,14 +399,14 @@ const handleEdgeError = (error: any) => {
|
|
|
399
399
|
}
|
|
400
400
|
};
|
|
401
401
|
|
|
402
|
-
export type
|
|
402
|
+
export type NotarizationTeleportExtensionProps = {
|
|
403
403
|
onOpen: () => Promise<void>;
|
|
404
404
|
onClose: () => Promise<void>;
|
|
405
405
|
onNotarize: (request: NotarizeRequest) => Promise<void>;
|
|
406
406
|
};
|
|
407
407
|
|
|
408
408
|
export class NotarizationTeleportExtension extends RpcExtension<Services, Services> {
|
|
409
|
-
constructor(private readonly _params:
|
|
409
|
+
constructor(private readonly _params: NotarizationTeleportExtensionProps) {
|
|
410
410
|
super({
|
|
411
411
|
requested: {
|
|
412
412
|
NotarizationService: schema.getService('dxos.mesh.teleport.notarization.NotarizationService'),
|
|
@@ -36,15 +36,15 @@ export type PerformInvitationCallbacks<T> = {
|
|
|
36
36
|
onError?: (value: T) => boolean | void;
|
|
37
37
|
};
|
|
38
38
|
|
|
39
|
-
export type
|
|
39
|
+
export type PerformInvitationProps = {
|
|
40
40
|
host: ServiceContext | InvitationHost;
|
|
41
41
|
guest: ServiceContext | InvitationGuest;
|
|
42
|
+
guestDeviceProfile?: DeviceProfileDocument;
|
|
42
43
|
options?: Partial<Invitation>;
|
|
43
44
|
hooks?: {
|
|
44
45
|
host?: PerformInvitationCallbacks<CancellableInvitation>;
|
|
45
46
|
guest?: PerformInvitationCallbacks<AuthenticatingInvitation>;
|
|
46
47
|
};
|
|
47
|
-
guestDeviceProfile?: DeviceProfileDocument;
|
|
48
48
|
codeInputDelay?: number;
|
|
49
49
|
};
|
|
50
50
|
|
|
@@ -52,14 +52,17 @@ export type Result = { invitation?: Invitation; error?: Error };
|
|
|
52
52
|
|
|
53
53
|
// TODO(burdon): Make async.
|
|
54
54
|
// TODO(burdon): Rename startInvitation.
|
|
55
|
+
/**
|
|
56
|
+
*
|
|
57
|
+
*/
|
|
55
58
|
export const performInvitation = ({
|
|
56
59
|
host,
|
|
57
60
|
guest,
|
|
61
|
+
guestDeviceProfile,
|
|
58
62
|
options,
|
|
59
63
|
hooks,
|
|
60
|
-
guestDeviceProfile,
|
|
61
64
|
codeInputDelay,
|
|
62
|
-
}:
|
|
65
|
+
}: PerformInvitationProps): [Promise<Result>, Promise<Result>] => {
|
|
63
66
|
let guestError = false;
|
|
64
67
|
let guestConnected = false;
|
|
65
68
|
let wereConnected = false;
|
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
// Copyright 2022 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
+
import * as Reactivity from '@effect/experimental/Reactivity';
|
|
6
|
+
import * as Layer from 'effect/Layer';
|
|
7
|
+
import * as ManagedRuntime from 'effect/ManagedRuntime';
|
|
8
|
+
|
|
5
9
|
import { type Config } from '@dxos/config';
|
|
6
10
|
import { Context } from '@dxos/context';
|
|
7
11
|
import { CredentialGenerator, createCredentialSignerWithChain } from '@dxos/credentials';
|
|
@@ -15,11 +19,13 @@ import { MemorySignalManager, MemorySignalManagerContext, type SignalManager } f
|
|
|
15
19
|
import { MemoryTransportFactory, SwarmNetworkManager } from '@dxos/network-manager';
|
|
16
20
|
import { Invitation } from '@dxos/protocols/proto/dxos/client/services';
|
|
17
21
|
import { type Storage, StorageType, createStorage } from '@dxos/random-access-storage';
|
|
22
|
+
import { layerMemory as sqliteLayerMemory } from '@dxos/sql-sqlite/platform';
|
|
23
|
+
import * as SqlTransaction from '@dxos/sql-sqlite/SqlTransaction';
|
|
18
24
|
import { BlobStore } from '@dxos/teleport-extension-object-sync';
|
|
19
25
|
|
|
20
26
|
import { InvitationsHandler, InvitationsManager, SpaceInvitationProtocol } from '../invitations';
|
|
21
|
-
import { ClientServicesHost, ServiceContext, type
|
|
22
|
-
import { DataSpaceManager, type
|
|
27
|
+
import { ClientServicesHost, ServiceContext, type ServiceContextRuntimeProps } from '../services';
|
|
28
|
+
import { DataSpaceManager, type DataSpaceManagerRuntimeProps, type SigningContext } from '../spaces';
|
|
23
29
|
|
|
24
30
|
//
|
|
25
31
|
// TODO(burdon): Replace with test builder.
|
|
@@ -30,6 +36,11 @@ export const createServiceHost = (config: Config, signalManagerContext: MemorySi
|
|
|
30
36
|
config,
|
|
31
37
|
signalManager: new MemorySignalManager(signalManagerContext),
|
|
32
38
|
transportFactory: MemoryTransportFactory,
|
|
39
|
+
runtime: ManagedRuntime.make(
|
|
40
|
+
SqlTransaction.layer
|
|
41
|
+
.pipe(Layer.provideMerge(sqliteLayerMemory), Layer.provideMerge(Reactivity.layer))
|
|
42
|
+
.pipe(Layer.orDie),
|
|
43
|
+
).runtimeEffect,
|
|
33
44
|
});
|
|
34
45
|
};
|
|
35
46
|
|
|
@@ -39,11 +50,11 @@ export const createServiceContext = async ({
|
|
|
39
50
|
return new MemorySignalManager(signalContext);
|
|
40
51
|
},
|
|
41
52
|
storage = createStorage({ type: StorageType.RAM }),
|
|
42
|
-
|
|
53
|
+
runtimeProps,
|
|
43
54
|
}: {
|
|
44
55
|
signalManagerFactory?: () => Promise<SignalManager>;
|
|
45
56
|
storage?: Storage;
|
|
46
|
-
|
|
57
|
+
runtimeProps?: ServiceContextRuntimeProps;
|
|
47
58
|
} = {}) => {
|
|
48
59
|
const signalManager = await signalManagerFactory();
|
|
49
60
|
const networkManager = new SwarmNetworkManager({
|
|
@@ -53,9 +64,15 @@ export const createServiceContext = async ({
|
|
|
53
64
|
const level = createTestLevel();
|
|
54
65
|
await level.open();
|
|
55
66
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
67
|
+
const runtime = ManagedRuntime.make(
|
|
68
|
+
SqlTransaction.layer
|
|
69
|
+
.pipe(Layer.provideMerge(sqliteLayerMemory), Layer.provideMerge(Reactivity.layer))
|
|
70
|
+
.pipe(Layer.orDie),
|
|
71
|
+
).runtimeEffect;
|
|
72
|
+
|
|
73
|
+
return new ServiceContext(storage, level, networkManager, signalManager, undefined, undefined, runtime, {
|
|
74
|
+
invitationConnectionDefaultProps: { teleport: { controlHeartbeatInterval: 200 } },
|
|
75
|
+
...runtimeProps,
|
|
59
76
|
});
|
|
60
77
|
};
|
|
61
78
|
|
|
@@ -95,7 +112,7 @@ export class TestBuilder {
|
|
|
95
112
|
|
|
96
113
|
export type TestPeerOpts = {
|
|
97
114
|
dataStore?: StorageType;
|
|
98
|
-
|
|
115
|
+
dataSpaceProps?: DataSpaceManagerRuntimeProps;
|
|
99
116
|
};
|
|
100
117
|
|
|
101
118
|
export type TestPeerProps = {
|
|
@@ -116,6 +133,11 @@ export type TestPeerProps = {
|
|
|
116
133
|
|
|
117
134
|
export class TestPeer {
|
|
118
135
|
private _props: TestPeerProps = {};
|
|
136
|
+
private readonly _runtime = ManagedRuntime.make(
|
|
137
|
+
SqlTransaction.layer
|
|
138
|
+
.pipe(Layer.provideMerge(sqliteLayerMemory), Layer.provideMerge(Reactivity.layer))
|
|
139
|
+
.pipe(Layer.orDie),
|
|
140
|
+
);
|
|
119
141
|
|
|
120
142
|
constructor(
|
|
121
143
|
private readonly _signalContext: MemorySignalManagerContext,
|
|
@@ -179,7 +201,10 @@ export class TestPeer {
|
|
|
179
201
|
}
|
|
180
202
|
|
|
181
203
|
get echoHost() {
|
|
182
|
-
return (this._props.echoHost ??= new EchoHost({
|
|
204
|
+
return (this._props.echoHost ??= new EchoHost({
|
|
205
|
+
kv: this.level,
|
|
206
|
+
runtime: this._runtime.runtimeEffect,
|
|
207
|
+
}));
|
|
183
208
|
}
|
|
184
209
|
|
|
185
210
|
get meshEchoReplicator() {
|
|
@@ -198,7 +223,7 @@ export class TestPeer {
|
|
|
198
223
|
edgeConnection: undefined,
|
|
199
224
|
meshReplicator: this.meshEchoReplicator,
|
|
200
225
|
echoEdgeReplicator: undefined,
|
|
201
|
-
|
|
226
|
+
runtimeProps: this._opts.dataSpaceProps,
|
|
202
227
|
}));
|
|
203
228
|
}
|
|
204
229
|
|
|
@@ -227,6 +252,7 @@ export class TestPeer {
|
|
|
227
252
|
async destroy(): Promise<void> {
|
|
228
253
|
await this.level.close();
|
|
229
254
|
await this.storage.reset();
|
|
255
|
+
await this._runtime.dispose();
|
|
230
256
|
}
|
|
231
257
|
}
|
|
232
258
|
|