@dxos/client-services 0.8.1 → 0.8.2-main.10c050d
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-MHDASPY5.mjs → chunk-LY3V7LMQ.mjs} +535 -551
- package/dist/lib/browser/chunk-LY3V7LMQ.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +1 -1
- package/dist/lib/browser/index.mjs.map +3 -3
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/testing/index.mjs +1 -1
- package/dist/lib/browser/testing/index.mjs.map +3 -3
- package/dist/lib/node/{chunk-A2WCOW6P.cjs → chunk-LYHT7662.cjs} +704 -709
- package/dist/lib/node/chunk-LYHT7662.cjs.map +7 -0
- package/dist/lib/node/index.cjs +47 -47
- package/dist/lib/node/index.cjs.map +3 -3
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node/testing/index.cjs +8 -8
- package/dist/lib/node/testing/index.cjs.map +3 -3
- package/dist/lib/node-esm/{chunk-SK52YZK7.mjs → chunk-LLRVFL7L.mjs} +535 -540
- package/dist/lib/node-esm/chunk-LLRVFL7L.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +1 -1
- package/dist/lib/node-esm/index.mjs.map +3 -3
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/testing/index.mjs +1 -1
- package/dist/lib/node-esm/testing/index.mjs.map +3 -3
- 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 +1 -1
- package/dist/types/src/packlets/agents/edge-agent-service.d.ts.map +1 -1
- package/dist/types/src/packlets/devices/devices-service.d.ts.map +1 -1
- package/dist/types/src/packlets/devtools/feeds.d.ts.map +1 -1
- package/dist/types/src/packlets/devtools/keys.d.ts.map +1 -1
- package/dist/types/src/packlets/devtools/metadata.d.ts.map +1 -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/browser-diagnostics-broadcast.d.ts.map +1 -1
- package/dist/types/src/packlets/diagnostics/diagnostics-broadcast.d.ts.map +1 -1
- package/dist/types/src/packlets/diagnostics/diagnostics.d.ts.map +1 -1
- package/dist/types/src/packlets/identity/authenticator.d.ts.map +1 -1
- 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 +2 -2
- package/dist/types/src/packlets/identity/identity-manager.d.ts.map +1 -1
- package/dist/types/src/packlets/identity/identity-recovery-manager.d.ts +1 -1
- package/dist/types/src/packlets/identity/identity-recovery-manager.d.ts.map +1 -1
- package/dist/types/src/packlets/identity/identity-service.d.ts.map +1 -1
- package/dist/types/src/packlets/identity/identity.d.ts.map +1 -1
- package/dist/types/src/packlets/invitations/device-invitation-protocol.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/invitation-guest-extenstion.d.ts.map +1 -1
- package/dist/types/src/packlets/invitations/invitation-host-extension.d.ts.map +1 -1
- package/dist/types/src/packlets/invitations/invitation-state.d.ts.map +1 -1
- package/dist/types/src/packlets/invitations/invitation-topology.d.ts.map +1 -1
- package/dist/types/src/packlets/invitations/invitations-manager.d.ts.map +1 -1
- package/dist/types/src/packlets/invitations/space-invitation-protocol.d.ts +1 -1
- package/dist/types/src/packlets/invitations/space-invitation-protocol.d.ts.map +1 -1
- package/dist/types/src/packlets/invitations/utils.d.ts.map +1 -1
- package/dist/types/src/packlets/locks/browser.d.ts.map +1 -1
- package/dist/types/src/packlets/locks/node.d.ts.map +1 -1
- package/dist/types/src/packlets/logging/logging-service.d.ts.map +1 -1
- package/dist/types/src/packlets/network/network-service.d.ts +3 -1
- package/dist/types/src/packlets/network/network-service.d.ts.map +1 -1
- package/dist/types/src/packlets/services/client-rpc-server.d.ts.map +1 -1
- package/dist/types/src/packlets/services/service-context.d.ts +1 -0
- package/dist/types/src/packlets/services/service-context.d.ts.map +1 -1
- package/dist/types/src/packlets/services/service-host.d.ts.map +1 -1
- package/dist/types/src/packlets/services/service-registry.d.ts.map +1 -1
- package/dist/types/src/packlets/services/util.d.ts.map +1 -1
- package/dist/types/src/packlets/space-export/space-archive-reader.d.ts +1 -1
- package/dist/types/src/packlets/space-export/space-archive-reader.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/automerge-space-state.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/data-space-manager.d.ts +1 -1
- package/dist/types/src/packlets/spaces/data-space-manager.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/data-space.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/edge-feed-replicator.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/epoch-migrations.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/genesis.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/notarization-plugin.d.ts.map +1 -1
- 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/storage/profile-archive.d.ts.map +1 -1
- package/dist/types/src/packlets/storage/storage.d.ts.map +1 -1
- package/dist/types/src/packlets/storage/util.d.ts.map +1 -1
- package/dist/types/src/packlets/system/system-service.d.ts.map +1 -1
- package/dist/types/src/packlets/testing/credential-utils.d.ts.map +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.map +1 -1
- package/dist/types/src/packlets/worker/worker-runtime.d.ts.map +1 -1
- 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/src/version.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +39 -38
- package/src/packlets/agents/edge-agent-manager.ts +6 -6
- package/src/packlets/agents/edge-agent-service.ts +8 -11
- package/src/packlets/devices/devices-service.ts +5 -3
- package/src/packlets/identity/authenticator.ts +2 -2
- package/src/packlets/identity/default-space-state-machine.ts +1 -1
- package/src/packlets/identity/identity-manager.ts +13 -9
- package/src/packlets/identity/identity-recovery-manager.ts +6 -4
- package/src/packlets/identity/identity-service.ts +4 -4
- package/src/packlets/identity/identity.test.ts +9 -6
- package/src/packlets/identity/identity.ts +5 -5
- package/src/packlets/invitations/device-invitation-protocol.ts +1 -1
- package/src/packlets/invitations/edge-invitation-handler.ts +3 -3
- package/src/packlets/invitations/invitation-guest-extenstion.ts +3 -3
- package/src/packlets/invitations/invitation-host-extension.ts +5 -5
- package/src/packlets/invitations/invitation-topology.ts +1 -1
- package/src/packlets/invitations/invitations-handler.ts +2 -2
- package/src/packlets/invitations/invitations-manager.ts +15 -4
- package/src/packlets/invitations/space-invitation-protocol.ts +1 -1
- package/src/packlets/locks/browser.ts +4 -4
- package/src/packlets/locks/node.ts +2 -2
- package/src/packlets/logging/logging-service.ts +2 -2
- package/src/packlets/network/network-service.ts +11 -17
- package/src/packlets/services/client-rpc-server.ts +2 -2
- package/src/packlets/services/service-context.ts +10 -6
- package/src/packlets/services/service-host.ts +13 -5
- package/src/packlets/services/service-registry.ts +3 -3
- package/src/packlets/space-export/space-archive-reader.ts +2 -1
- package/src/packlets/space-export/space-archive-writer.ts +3 -3
- package/src/packlets/spaces/automerge-space-state.ts +3 -3
- package/src/packlets/spaces/data-space-manager.ts +47 -41
- package/src/packlets/spaces/data-space.ts +27 -20
- package/src/packlets/spaces/edge-feed-replicator.test.ts +2 -1
- package/src/packlets/spaces/edge-feed-replicator.ts +14 -13
- package/src/packlets/spaces/epoch-migrations.ts +3 -2
- package/src/packlets/spaces/notarization-plugin.test.ts +1 -1
- package/src/packlets/spaces/notarization-plugin.ts +18 -18
- package/src/packlets/spaces/spaces-service.ts +7 -6
- package/src/packlets/storage/profile-archive.ts +2 -1
- package/src/packlets/system/system-service.ts +2 -2
- package/src/packlets/testing/test-builder.ts +3 -3
- package/src/packlets/worker/worker-runtime.ts +4 -4
- package/src/packlets/worker/worker-session.ts +3 -3
- package/src/version.ts +1 -5
- package/dist/lib/browser/chunk-MHDASPY5.mjs.map +0 -7
- package/dist/lib/node/chunk-A2WCOW6P.cjs.map +0 -7
- package/dist/lib/node-esm/chunk-SK52YZK7.mjs.map +0 -7
|
@@ -25,7 +25,7 @@ export class AutomergeSpaceState extends Resource implements CredentialProcessor
|
|
|
25
25
|
this._isProcessingRootDocs = false;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
async processCredential(credential: Credential) {
|
|
28
|
+
async processCredential(credential: Credential): Promise<void> {
|
|
29
29
|
if (!checkCredentialType(credential, 'dxos.halo.credentials.Epoch')) {
|
|
30
30
|
return;
|
|
31
31
|
}
|
|
@@ -42,7 +42,7 @@ export class AutomergeSpaceState extends Resource implements CredentialProcessor
|
|
|
42
42
|
this.onNewEpoch.emit(credential);
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
startProcessingRootDocs() {
|
|
45
|
+
startProcessingRootDocs(): void {
|
|
46
46
|
if (this._isProcessingRootDocs) {
|
|
47
47
|
return;
|
|
48
48
|
}
|
|
@@ -53,7 +53,7 @@ export class AutomergeSpaceState extends Resource implements CredentialProcessor
|
|
|
53
53
|
this._isProcessingRootDocs = true;
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
-
async ensureEpochInitialized() {
|
|
56
|
+
async ensureEpochInitialized(): Promise<void> {
|
|
57
57
|
await this.onNewEpoch.waitForCondition(() => !!this.lastEpoch);
|
|
58
58
|
}
|
|
59
59
|
}
|
|
@@ -2,14 +2,10 @@
|
|
|
2
2
|
// Copyright 2022 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
+
import { type Doc } from '@automerge/automerge';
|
|
6
|
+
import { interpretAsDocumentId, type AutomergeUrl, type DocHandle, type DocumentId } from '@automerge/automerge-repo';
|
|
7
|
+
|
|
5
8
|
import { Event, synchronized, trackLeaks } from '@dxos/async';
|
|
6
|
-
import { type Doc } from '@dxos/automerge/automerge';
|
|
7
|
-
import {
|
|
8
|
-
interpretAsDocumentId,
|
|
9
|
-
type AutomergeUrl,
|
|
10
|
-
type DocHandle,
|
|
11
|
-
type DocumentId,
|
|
12
|
-
} from '@dxos/automerge/automerge-repo';
|
|
13
9
|
import { PropertiesType, TYPE_PROPERTIES } from '@dxos/client-protocol';
|
|
14
10
|
import { Context, LifecycleState, Resource, cancelWithContext } from '@dxos/context';
|
|
15
11
|
import {
|
|
@@ -32,15 +28,16 @@ import {
|
|
|
32
28
|
type SpaceManager,
|
|
33
29
|
type SpaceProtocol,
|
|
34
30
|
type SpaceProtocolSession,
|
|
31
|
+
FIND_PARAMS,
|
|
35
32
|
} from '@dxos/echo-pipeline';
|
|
36
33
|
import {
|
|
37
34
|
SpaceDocVersion,
|
|
38
35
|
createIdFromSpaceKey,
|
|
39
36
|
encodeReference,
|
|
40
37
|
type ObjectStructure,
|
|
41
|
-
type
|
|
38
|
+
type DatabaseDirectory,
|
|
42
39
|
} from '@dxos/echo-protocol';
|
|
43
|
-
import {
|
|
40
|
+
import { ObjectId, getTypeReference } from '@dxos/echo-schema';
|
|
44
41
|
import type { EdgeConnection, EdgeHttpClient } from '@dxos/edge-client';
|
|
45
42
|
import { writeMessages, type FeedStore } from '@dxos/feed-store';
|
|
46
43
|
import { assertArgument, assertState, failedInvariant, invariant } from '@dxos/invariant';
|
|
@@ -177,24 +174,29 @@ export class DataSpaceManager extends Resource {
|
|
|
177
174
|
id: 'spaces',
|
|
178
175
|
name: 'Spaces',
|
|
179
176
|
fetch: async () => {
|
|
180
|
-
return
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
177
|
+
return Promise.all(
|
|
178
|
+
Array.from(this._spaces.values()).map(async (space) => {
|
|
179
|
+
const rootUrl = space.automergeSpaceState.rootUrl;
|
|
180
|
+
const rootHandle = rootUrl
|
|
181
|
+
? await this._echoHost.automergeRepo.find<Doc<DatabaseDirectory>>(rootUrl as AutomergeUrl, FIND_PARAMS)
|
|
182
|
+
: undefined;
|
|
183
|
+
await rootHandle?.whenReady();
|
|
184
|
+
const rootDoc = rootHandle?.doc();
|
|
185
|
+
|
|
186
|
+
const properties = rootDoc && findInlineObjectOfType(rootDoc, TYPE_PROPERTIES);
|
|
187
|
+
|
|
188
|
+
return {
|
|
189
|
+
key: space.key.toHex(),
|
|
190
|
+
state: SpaceState[space.state],
|
|
191
|
+
name: properties?.[1].data.name ?? null,
|
|
192
|
+
inlineObjects: rootDoc ? Object.keys(rootDoc.objects ?? {}).length : null,
|
|
193
|
+
linkedObjects: rootDoc ? Object.keys(rootDoc.links ?? {}).length : null,
|
|
194
|
+
credentials: space.inner.spaceState.credentials.length,
|
|
195
|
+
members: space.inner.spaceState.members.size,
|
|
196
|
+
rootUrl,
|
|
197
|
+
};
|
|
198
|
+
}),
|
|
199
|
+
);
|
|
198
200
|
},
|
|
199
201
|
});
|
|
200
202
|
}
|
|
@@ -209,7 +211,7 @@ export class DataSpaceManager extends Resource {
|
|
|
209
211
|
}
|
|
210
212
|
|
|
211
213
|
@synchronized
|
|
212
|
-
protected override async _open() {
|
|
214
|
+
protected override async _open(): Promise<void> {
|
|
213
215
|
log('open');
|
|
214
216
|
log.trace('dxos.echo.data-space-manager.open', Trace.begin({ id: this._instanceId }));
|
|
215
217
|
log('metadata loaded', { spaces: this._metadataStore.spaces.length });
|
|
@@ -229,7 +231,7 @@ export class DataSpaceManager extends Resource {
|
|
|
229
231
|
}
|
|
230
232
|
|
|
231
233
|
@synchronized
|
|
232
|
-
protected override async _close() {
|
|
234
|
+
protected override async _close(): Promise<void> {
|
|
233
235
|
log('close');
|
|
234
236
|
for (const space of this._spaces.values()) {
|
|
235
237
|
await space.close();
|
|
@@ -241,7 +243,7 @@ export class DataSpaceManager extends Resource {
|
|
|
241
243
|
* Creates a new space writing the genesis credentials to the control feed.
|
|
242
244
|
*/
|
|
243
245
|
@synchronized
|
|
244
|
-
async createSpace(options: CreateSpaceOptions = {}) {
|
|
246
|
+
async createSpace(options: CreateSpaceOptions = {}): Promise<DataSpace> {
|
|
245
247
|
assertArgument(!!options.rootUrl === !!options.documents, 'root url must be required when providing documents');
|
|
246
248
|
|
|
247
249
|
assertState(this._lifecycleState === LifecycleState.OPEN, 'Not open.');
|
|
@@ -283,7 +285,7 @@ export class DataSpaceManager extends Resource {
|
|
|
283
285
|
let root: DatabaseRoot;
|
|
284
286
|
if (options.rootUrl) {
|
|
285
287
|
const newRootDocId = documentIdMapping[interpretAsDocumentId(options.rootUrl)] ?? failedInvariant();
|
|
286
|
-
const rootDocHandle = await this._echoHost.loadDoc<
|
|
288
|
+
const rootDocHandle = await this._echoHost.loadDoc<DatabaseDirectory>(Context.default(), newRootDocId);
|
|
287
289
|
DatabaseRoot.mapLinks(rootDocHandle, documentIdMapping);
|
|
288
290
|
|
|
289
291
|
root = await this._echoHost.openSpaceRoot(spaceId, `automerge:${newRootDocId}` as AutomergeUrl);
|
|
@@ -319,7 +321,11 @@ export class DataSpaceManager extends Resource {
|
|
|
319
321
|
}
|
|
320
322
|
switch (space.databaseRoot.getVersion()) {
|
|
321
323
|
case SpaceDocVersion.CURRENT: {
|
|
322
|
-
|
|
324
|
+
if (!space.databaseRoot.handle.isReady()) {
|
|
325
|
+
log.warn('waiting for space root to be ready', { spaceId: space.id });
|
|
326
|
+
await space.databaseRoot.handle.whenReady();
|
|
327
|
+
}
|
|
328
|
+
const [_, properties] = findInlineObjectOfType(space.databaseRoot.doc()!, TYPE_PROPERTIES) ?? [];
|
|
323
329
|
return properties?.data?.[DEFAULT_SPACE_KEY] === this._signingContext.identityKey.toHex();
|
|
324
330
|
}
|
|
325
331
|
case SpaceDocVersion.LEGACY: {
|
|
@@ -332,7 +338,7 @@ export class DataSpaceManager extends Resource {
|
|
|
332
338
|
}
|
|
333
339
|
}
|
|
334
340
|
|
|
335
|
-
async createDefaultSpace() {
|
|
341
|
+
async createDefaultSpace(): Promise<DataSpace> {
|
|
336
342
|
const space = await this.createSpace();
|
|
337
343
|
const document = await this._getSpaceRootDocument(space);
|
|
338
344
|
|
|
@@ -349,8 +355,8 @@ export class DataSpaceManager extends Resource {
|
|
|
349
355
|
},
|
|
350
356
|
};
|
|
351
357
|
|
|
352
|
-
const propertiesId =
|
|
353
|
-
document.change((doc:
|
|
358
|
+
const propertiesId = ObjectId.random();
|
|
359
|
+
document.change((doc: DatabaseDirectory) => {
|
|
354
360
|
setDeep(doc, ['objects', propertiesId], properties);
|
|
355
361
|
});
|
|
356
362
|
|
|
@@ -358,10 +364,10 @@ export class DataSpaceManager extends Resource {
|
|
|
358
364
|
return space;
|
|
359
365
|
}
|
|
360
366
|
|
|
361
|
-
private async _getSpaceRootDocument(space: DataSpace): Promise<DocHandle<
|
|
367
|
+
private async _getSpaceRootDocument(space: DataSpace): Promise<DocHandle<DatabaseDirectory>> {
|
|
362
368
|
const automergeIndex = space.automergeSpaceState.rootUrl;
|
|
363
369
|
invariant(automergeIndex);
|
|
364
|
-
const document = this._echoHost.automergeRepo.find<
|
|
370
|
+
const document = await this._echoHost.automergeRepo.find<DatabaseDirectory>(automergeIndex as any, FIND_PARAMS);
|
|
365
371
|
await document.whenReady();
|
|
366
372
|
return document;
|
|
367
373
|
}
|
|
@@ -423,7 +429,7 @@ export class DataSpaceManager extends Resource {
|
|
|
423
429
|
* Used by invitation handler.
|
|
424
430
|
* TODO(dmaretskyi): Consider removing.
|
|
425
431
|
*/
|
|
426
|
-
async waitUntilSpaceReady(spaceKey: PublicKey) {
|
|
432
|
+
async waitUntilSpaceReady(spaceKey: PublicKey): Promise<void> {
|
|
427
433
|
await cancelWithContext(
|
|
428
434
|
this._ctx,
|
|
429
435
|
this.updated.waitForCondition(() => {
|
|
@@ -447,7 +453,7 @@ export class DataSpaceManager extends Resource {
|
|
|
447
453
|
});
|
|
448
454
|
}
|
|
449
455
|
|
|
450
|
-
async setSpaceEdgeReplicationSetting(spaceKey: PublicKey, setting: EdgeReplicationSetting) {
|
|
456
|
+
async setSpaceEdgeReplicationSetting(spaceKey: PublicKey, setting: EdgeReplicationSetting): Promise<void> {
|
|
451
457
|
const space = this._spaces.get(spaceKey);
|
|
452
458
|
invariant(space, 'Space not found.');
|
|
453
459
|
|
|
@@ -467,7 +473,7 @@ export class DataSpaceManager extends Resource {
|
|
|
467
473
|
space.stateUpdate.emit();
|
|
468
474
|
}
|
|
469
475
|
|
|
470
|
-
private async _constructSpace(metadata: SpaceMetadata) {
|
|
476
|
+
private async _constructSpace(metadata: SpaceMetadata): Promise<DataSpace> {
|
|
471
477
|
log('construct space', { metadata });
|
|
472
478
|
const gossip = new Gossip({
|
|
473
479
|
localPeerId: this._signingContext.deviceKey,
|
|
@@ -591,7 +597,7 @@ export class DataSpaceManager extends Resource {
|
|
|
591
597
|
return dataSpace;
|
|
592
598
|
}
|
|
593
599
|
|
|
594
|
-
private async _connectEchoMeshReplicator(space: Space, session: Teleport) {
|
|
600
|
+
private async _connectEchoMeshReplicator(space: Space, session: Teleport): Promise<void> {
|
|
595
601
|
const replicator = this._meshReplicator;
|
|
596
602
|
if (!replicator) {
|
|
597
603
|
log.warn('p2p automerge replication disabled', { space: space.key });
|
|
@@ -2,8 +2,10 @@
|
|
|
2
2
|
// Copyright 2022 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
+
import { save } from '@automerge/automerge';
|
|
6
|
+
import { type DocHandle } from '@automerge/automerge-repo';
|
|
7
|
+
|
|
5
8
|
import { Event, Mutex, scheduleTask, sleep, synchronized, trackLeaks } from '@dxos/async';
|
|
6
|
-
import { save } from '@dxos/automerge/automerge';
|
|
7
9
|
import { AUTH_TIMEOUT } from '@dxos/client-protocol';
|
|
8
10
|
import { Context, ContextDisposedError, cancelWithContext } from '@dxos/context';
|
|
9
11
|
import type { SpecificCredential } from '@dxos/credentials';
|
|
@@ -14,8 +16,9 @@ import {
|
|
|
14
16
|
createMappedFeedWriter,
|
|
15
17
|
type MetadataStore,
|
|
16
18
|
type Space,
|
|
19
|
+
FIND_PARAMS,
|
|
17
20
|
} from '@dxos/echo-pipeline';
|
|
18
|
-
import { SpaceDocVersion, type
|
|
21
|
+
import { SpaceDocVersion, type DatabaseDirectory } from '@dxos/echo-protocol';
|
|
19
22
|
import type { EdgeConnection, EdgeHttpClient } from '@dxos/edge-client';
|
|
20
23
|
import { type FeedStore, type FeedWrapper } from '@dxos/feed-store';
|
|
21
24
|
import { failedInvariant, invariant } from '@dxos/invariant';
|
|
@@ -226,13 +229,13 @@ export class DataSpace {
|
|
|
226
229
|
}
|
|
227
230
|
|
|
228
231
|
@synchronized
|
|
229
|
-
async open() {
|
|
232
|
+
async open(): Promise<void> {
|
|
230
233
|
if (this._state === SpaceState.SPACE_CLOSED) {
|
|
231
234
|
await this._open();
|
|
232
235
|
}
|
|
233
236
|
}
|
|
234
237
|
|
|
235
|
-
private async _open() {
|
|
238
|
+
private async _open(): Promise<void> {
|
|
236
239
|
await this._presence.open();
|
|
237
240
|
await this._gossip.open();
|
|
238
241
|
await this._notarizationPlugin.open();
|
|
@@ -259,11 +262,11 @@ export class DataSpace {
|
|
|
259
262
|
}
|
|
260
263
|
|
|
261
264
|
@synchronized
|
|
262
|
-
async close() {
|
|
265
|
+
async close(): Promise<void> {
|
|
263
266
|
await this._close();
|
|
264
267
|
}
|
|
265
268
|
|
|
266
|
-
private async _close() {
|
|
269
|
+
private async _close(): Promise<void> {
|
|
267
270
|
await this._callbacks.beforeClose?.();
|
|
268
271
|
|
|
269
272
|
await this.preClose.callSerial();
|
|
@@ -291,18 +294,18 @@ export class DataSpace {
|
|
|
291
294
|
await this._gossip.close();
|
|
292
295
|
}
|
|
293
296
|
|
|
294
|
-
async postMessage(channel: string, message: any) {
|
|
297
|
+
async postMessage(channel: string, message: any): Promise<void> {
|
|
295
298
|
return this._gossip.postMessage(channel, message);
|
|
296
299
|
}
|
|
297
300
|
|
|
298
|
-
listen(channel: string, callback: (message: GossipMessage) => void) {
|
|
301
|
+
listen(channel: string, callback: (message: GossipMessage) => void): { unsubscribe: () => void } {
|
|
299
302
|
return this._gossip.listen(channel, callback);
|
|
300
303
|
}
|
|
301
304
|
|
|
302
305
|
/**
|
|
303
306
|
* Initialize the data pipeline in a separate task.
|
|
304
307
|
*/
|
|
305
|
-
initializeDataPipelineAsync() {
|
|
308
|
+
initializeDataPipelineAsync(): void {
|
|
306
309
|
scheduleTask(this._ctx, async () => {
|
|
307
310
|
try {
|
|
308
311
|
this.metrics.pipelineInitBegin = new Date();
|
|
@@ -325,7 +328,7 @@ export class DataSpace {
|
|
|
325
328
|
}
|
|
326
329
|
|
|
327
330
|
@trace.span({ showInBrowserTimeline: true })
|
|
328
|
-
async initializeDataPipeline() {
|
|
331
|
+
async initializeDataPipeline(): Promise<void> {
|
|
329
332
|
if (this._state !== SpaceState.SPACE_CONTROL_ONLY) {
|
|
330
333
|
throw new SystemError('Invalid operation');
|
|
331
334
|
}
|
|
@@ -352,7 +355,7 @@ export class DataSpace {
|
|
|
352
355
|
|
|
353
356
|
async *getAllDocuments(): AsyncIterable<[string, Uint8Array]> {
|
|
354
357
|
invariant(this._databaseRoot, 'Space is not ready');
|
|
355
|
-
const doc = this._databaseRoot.
|
|
358
|
+
const doc = this._databaseRoot.doc() ?? failedInvariant();
|
|
356
359
|
const root = save(doc);
|
|
357
360
|
yield [this._databaseRoot.documentId, root];
|
|
358
361
|
|
|
@@ -362,7 +365,7 @@ export class DataSpace {
|
|
|
362
365
|
}
|
|
363
366
|
}
|
|
364
367
|
|
|
365
|
-
private async _enterReadyState() {
|
|
368
|
+
private async _enterReadyState(): Promise<void> {
|
|
366
369
|
await this._callbacks.beforeReady?.();
|
|
367
370
|
|
|
368
371
|
this._state = SpaceState.SPACE_READY;
|
|
@@ -373,7 +376,7 @@ export class DataSpace {
|
|
|
373
376
|
}
|
|
374
377
|
|
|
375
378
|
@trace.span({ showInBrowserTimeline: true })
|
|
376
|
-
private async _initializeAndReadControlPipeline() {
|
|
379
|
+
private async _initializeAndReadControlPipeline(): Promise<void> {
|
|
377
380
|
await this._inner.controlPipeline.state.waitUntilReachedTargetTimeframe({
|
|
378
381
|
ctx: this._ctx,
|
|
379
382
|
timeout: 10_000,
|
|
@@ -399,7 +402,7 @@ export class DataSpace {
|
|
|
399
402
|
}
|
|
400
403
|
|
|
401
404
|
@timed(10_000)
|
|
402
|
-
private async _createWritableFeeds() {
|
|
405
|
+
private async _createWritableFeeds(): Promise<void> {
|
|
403
406
|
const credentials: Credential[] = [];
|
|
404
407
|
if (!this.inner.controlFeedKey) {
|
|
405
408
|
const controlFeed = await this._feedStore.openFeed(await this._keyring.createKey(), { writable: true });
|
|
@@ -456,15 +459,19 @@ export class DataSpace {
|
|
|
456
459
|
}
|
|
457
460
|
}
|
|
458
461
|
|
|
459
|
-
private _onNewAutomergeRoot(rootUrl: string) {
|
|
462
|
+
private _onNewAutomergeRoot(rootUrl: string): void {
|
|
460
463
|
log('loading automerge root doc for space', { space: this.key, rootUrl });
|
|
461
464
|
|
|
462
|
-
|
|
465
|
+
let handle: DocHandle<DatabaseDirectory>;
|
|
463
466
|
|
|
464
467
|
// TODO(dmaretskyi): Make this single-threaded (but doc loading should still be parallel to not block epoch processing).
|
|
465
468
|
queueMicrotask(async () => {
|
|
466
469
|
try {
|
|
467
470
|
await warnAfterTimeout(5_000, 'Automerge root doc load timeout (DataSpace)', async () => {
|
|
471
|
+
handle = await cancelWithContext(
|
|
472
|
+
this._ctx,
|
|
473
|
+
this._echoHost.automergeRepo.find<DatabaseDirectory>(rootUrl as any, FIND_PARAMS),
|
|
474
|
+
);
|
|
468
475
|
await cancelWithContext(this._ctx, handle.whenReady());
|
|
469
476
|
});
|
|
470
477
|
if (this._ctx.disposed) {
|
|
@@ -475,7 +482,7 @@ export class DataSpace {
|
|
|
475
482
|
using _guard = await this._epochProcessingMutex.acquire();
|
|
476
483
|
|
|
477
484
|
// Attaching space keys to legacy documents.
|
|
478
|
-
const doc = handle.
|
|
485
|
+
const doc = handle.doc() ?? failedInvariant();
|
|
479
486
|
if (!doc.access?.spaceKey) {
|
|
480
487
|
handle.change((doc: any) => {
|
|
481
488
|
doc.access = { spaceKey: this.key.toHex() };
|
|
@@ -506,7 +513,7 @@ export class DataSpace {
|
|
|
506
513
|
}
|
|
507
514
|
|
|
508
515
|
// TODO(dmaretskyi): Use profile from signing context.
|
|
509
|
-
async updateOwnProfile(profile: ProfileDocument) {
|
|
516
|
+
async updateOwnProfile(profile: ProfileDocument): Promise<void> {
|
|
510
517
|
const credential = await this._signingContext.credentialSigner.createCredential({
|
|
511
518
|
subject: this._signingContext.identityKey,
|
|
512
519
|
assertion: {
|
|
@@ -561,7 +568,7 @@ export class DataSpace {
|
|
|
561
568
|
}
|
|
562
569
|
|
|
563
570
|
@synchronized
|
|
564
|
-
async activate() {
|
|
571
|
+
async activate(): Promise<void> {
|
|
565
572
|
if (![SpaceState.SPACE_CLOSED, SpaceState.SPACE_INACTIVE].includes(this._state)) {
|
|
566
573
|
return;
|
|
567
574
|
}
|
|
@@ -572,7 +579,7 @@ export class DataSpace {
|
|
|
572
579
|
}
|
|
573
580
|
|
|
574
581
|
@synchronized
|
|
575
|
-
async deactivate() {
|
|
582
|
+
async deactivate(): Promise<void> {
|
|
576
583
|
if (this._state === SpaceState.SPACE_INACTIVE) {
|
|
577
584
|
return;
|
|
578
585
|
}
|
|
@@ -14,6 +14,7 @@ import { createTestEdgeWsServer } from '@dxos/edge-client/testing';
|
|
|
14
14
|
import { FeedFactory, FeedStore, type FeedWrapper } from '@dxos/feed-store';
|
|
15
15
|
import { Keyring } from '@dxos/keyring';
|
|
16
16
|
import { SpaceId } from '@dxos/keys';
|
|
17
|
+
import { EdgeStatus } from '@dxos/protocols/proto/dxos/client/services';
|
|
17
18
|
import { type FeedMessage } from '@dxos/protocols/proto/dxos/echo/feed';
|
|
18
19
|
import { createStorage } from '@dxos/random-access-storage';
|
|
19
20
|
import { openAndClose } from '@dxos/test-utils';
|
|
@@ -44,7 +45,7 @@ describe('EdgeFeedReplicator', () => {
|
|
|
44
45
|
const { endpoint, admitConnection, messageSink } = await createEdge();
|
|
45
46
|
const { messenger } = await createClient(endpoint);
|
|
46
47
|
admitConnection.wake();
|
|
47
|
-
await expect.poll(() => messenger.
|
|
48
|
+
await expect.poll(() => messenger.status).toBe(EdgeStatus.CONNECTED);
|
|
48
49
|
|
|
49
50
|
await attachReplicator(messenger);
|
|
50
51
|
await expect.poll(() => messageSink.length).toEqual(1);
|
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
type Message as RouterMessage,
|
|
20
20
|
} from '@dxos/protocols/buf/dxos/edge/messenger_pb';
|
|
21
21
|
import type { FeedBlock, ProtocolMessage } from '@dxos/protocols/feed-replication';
|
|
22
|
+
import { EdgeStatus } from '@dxos/protocols/proto/dxos/client/services';
|
|
22
23
|
import { ComplexMap, arrayToBuffer, bufferToArray, defaultMap, rangeFromTo } from '@dxos/util';
|
|
23
24
|
|
|
24
25
|
export type EdgeFeedReplicatorParams = {
|
|
@@ -84,9 +85,9 @@ export class EdgeFeedReplicator extends Resource {
|
|
|
84
85
|
);
|
|
85
86
|
}
|
|
86
87
|
|
|
87
|
-
private async _handleReconnect() {
|
|
88
|
+
private async _handleReconnect(): Promise<void> {
|
|
88
89
|
await this._resetConnection();
|
|
89
|
-
if (this._messenger.
|
|
90
|
+
if (this._messenger.status === EdgeStatus.CONNECTED) {
|
|
90
91
|
this._startReplication();
|
|
91
92
|
}
|
|
92
93
|
}
|
|
@@ -96,7 +97,7 @@ export class EdgeFeedReplicator extends Resource {
|
|
|
96
97
|
await this._resetConnection();
|
|
97
98
|
}
|
|
98
99
|
|
|
99
|
-
private _startReplication() {
|
|
100
|
+
private _startReplication(): void {
|
|
100
101
|
this._connected = true;
|
|
101
102
|
const connectionCtx = this._createConnectionContext();
|
|
102
103
|
this._connectionCtx = connectionCtx;
|
|
@@ -108,7 +109,7 @@ export class EdgeFeedReplicator extends Resource {
|
|
|
108
109
|
});
|
|
109
110
|
}
|
|
110
111
|
|
|
111
|
-
private async _resetConnection() {
|
|
112
|
+
private async _resetConnection(): Promise<void> {
|
|
112
113
|
log('resetConnection');
|
|
113
114
|
this._connected = false;
|
|
114
115
|
await this._connectionCtx?.dispose();
|
|
@@ -116,7 +117,7 @@ export class EdgeFeedReplicator extends Resource {
|
|
|
116
117
|
this._remoteLength.clear();
|
|
117
118
|
}
|
|
118
119
|
|
|
119
|
-
async addFeed(feed: FeedWrapper<any>) {
|
|
120
|
+
async addFeed(feed: FeedWrapper<any>): Promise<void> {
|
|
120
121
|
log('addFeed', { key: feed.key, connected: this._connected, hasConnectionCtx: !!this._connectionCtx });
|
|
121
122
|
this._feeds.set(feed.key, feed);
|
|
122
123
|
|
|
@@ -125,11 +126,11 @@ export class EdgeFeedReplicator extends Resource {
|
|
|
125
126
|
}
|
|
126
127
|
}
|
|
127
128
|
|
|
128
|
-
private _getPushMutex(key: PublicKey) {
|
|
129
|
+
private _getPushMutex(key: PublicKey): Mutex {
|
|
129
130
|
return defaultMap(this._pushMutex, key, () => new Mutex());
|
|
130
131
|
}
|
|
131
132
|
|
|
132
|
-
private async _replicateFeed(ctx: Context, feed: FeedWrapper<any>) {
|
|
133
|
+
private async _replicateFeed(ctx: Context, feed: FeedWrapper<any>): Promise<void> {
|
|
133
134
|
log('replicateFeed', { key: feed.key });
|
|
134
135
|
await this._sendMessage({
|
|
135
136
|
type: 'get-metadata',
|
|
@@ -141,7 +142,7 @@ export class EdgeFeedReplicator extends Resource {
|
|
|
141
142
|
});
|
|
142
143
|
}
|
|
143
144
|
|
|
144
|
-
private async _sendMessage(message: ProtocolMessage) {
|
|
145
|
+
private async _sendMessage(message: ProtocolMessage): Promise<void> {
|
|
145
146
|
if (!this._connectionCtx) {
|
|
146
147
|
log('message dropped because connection was disposed');
|
|
147
148
|
return;
|
|
@@ -170,7 +171,7 @@ export class EdgeFeedReplicator extends Resource {
|
|
|
170
171
|
);
|
|
171
172
|
}
|
|
172
173
|
|
|
173
|
-
private _onMessage(message: ProtocolMessage) {
|
|
174
|
+
private _onMessage(message: ProtocolMessage): void {
|
|
174
175
|
if (!this._connectionCtx) {
|
|
175
176
|
log.warn('received message after connection context was disposed');
|
|
176
177
|
return;
|
|
@@ -228,7 +229,7 @@ export class EdgeFeedReplicator extends Resource {
|
|
|
228
229
|
});
|
|
229
230
|
}
|
|
230
231
|
|
|
231
|
-
private async _pushBlocks(feed: FeedWrapper<any>, from: number, to: number) {
|
|
232
|
+
private async _pushBlocks(feed: FeedWrapper<any>, from: number, to: number): Promise<void> {
|
|
232
233
|
log('pushing blocks', { feed: feed.key.toHex(), from, to });
|
|
233
234
|
|
|
234
235
|
const blocks: FeedBlock[] = await Promise.all(
|
|
@@ -254,7 +255,7 @@ export class EdgeFeedReplicator extends Resource {
|
|
|
254
255
|
this._remoteLength.set(feed.key, to);
|
|
255
256
|
}
|
|
256
257
|
|
|
257
|
-
private async _integrateBlocks(feed: FeedWrapper<any>, blocks: FeedBlock[]) {
|
|
258
|
+
private async _integrateBlocks(feed: FeedWrapper<any>, blocks: FeedBlock[]): Promise<void> {
|
|
258
259
|
log('integrating blocks', { feed: feed.key.toHex(), blocks: blocks.length });
|
|
259
260
|
|
|
260
261
|
for (const block of blocks) {
|
|
@@ -272,7 +273,7 @@ export class EdgeFeedReplicator extends Resource {
|
|
|
272
273
|
}
|
|
273
274
|
}
|
|
274
275
|
|
|
275
|
-
private async _pushBlocksIfNeeded(feed: FeedWrapper<any>) {
|
|
276
|
+
private async _pushBlocksIfNeeded(feed: FeedWrapper<any>): Promise<void> {
|
|
276
277
|
using _ = await this._getPushMutex(feed.key).acquire();
|
|
277
278
|
|
|
278
279
|
if (!this._remoteLength.has(feed.key)) {
|
|
@@ -286,7 +287,7 @@ export class EdgeFeedReplicator extends Resource {
|
|
|
286
287
|
}
|
|
287
288
|
}
|
|
288
289
|
|
|
289
|
-
private _createConnectionContext() {
|
|
290
|
+
private _createConnectionContext(): Context {
|
|
290
291
|
const connectionCtx = new Context({
|
|
291
292
|
onError: async (err: any) => {
|
|
292
293
|
if (connectionCtx !== this._connectionCtx) {
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
// Copyright 2024 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import type { AutomergeUrl } from '@
|
|
5
|
+
import type { AutomergeUrl } from '@automerge/automerge-repo';
|
|
6
|
+
|
|
6
7
|
import { type Context } from '@dxos/context';
|
|
7
8
|
import { type EchoHost } from '@dxos/echo-pipeline';
|
|
8
9
|
import { invariant } from '@dxos/invariant';
|
|
@@ -47,7 +48,7 @@ export const runEpochMigration = async (ctx: Context, context: MigrationContext)
|
|
|
47
48
|
timeout: LOAD_DOC_TIMEOUT,
|
|
48
49
|
});
|
|
49
50
|
|
|
50
|
-
const newRoot = context.echoHost.createDoc(rootHandle.
|
|
51
|
+
const newRoot = context.echoHost.createDoc(rootHandle.doc());
|
|
51
52
|
await context.echoHost.flush();
|
|
52
53
|
return { newRoot: newRoot.url };
|
|
53
54
|
}
|