@dxos/client-services 0.8.4-main.c85a9c8dae → 0.8.4-main.cb12b3f963
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-MQ6PWJ76.mjs → chunk-TZQLGPMV.mjs} +1596 -3099
- package/dist/lib/browser/chunk-TZQLGPMV.mjs.map +7 -0
- package/dist/lib/browser/{chunk-NQSC7HOE.mjs → chunk-XJRPB3GA.mjs} +1 -1
- package/dist/lib/browser/index.mjs +106 -194
- package/dist/lib/browser/index.mjs.map +3 -3
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/packlets/diagnostics/browser-diagnostics-broadcast.mjs +1 -6
- package/dist/lib/browser/packlets/diagnostics/browser-diagnostics-broadcast.mjs.map +2 -2
- package/dist/lib/browser/packlets/diagnostics/diagnostics-broadcast.mjs +1 -1
- package/dist/lib/browser/packlets/locks/browser.mjs +9 -49
- package/dist/lib/browser/packlets/locks/browser.mjs.map +2 -2
- package/dist/lib/browser/packlets/locks/node.mjs +4 -22
- package/dist/lib/browser/packlets/locks/node.mjs.map +2 -2
- package/dist/lib/browser/testing/index.mjs +9 -22
- package/dist/lib/browser/testing/index.mjs.map +3 -3
- package/dist/lib/node-esm/{chunk-PKEGMOQ4.mjs → chunk-2DT3MZRL.mjs} +1 -1
- package/dist/lib/node-esm/{chunk-GUAL4U7S.mjs → chunk-6DX3BNLB.mjs} +1596 -3099
- package/dist/lib/node-esm/chunk-6DX3BNLB.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +106 -194
- package/dist/lib/node-esm/index.mjs.map +3 -3
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/packlets/diagnostics/browser-diagnostics-broadcast.mjs +1 -6
- package/dist/lib/node-esm/packlets/diagnostics/browser-diagnostics-broadcast.mjs.map +2 -2
- package/dist/lib/node-esm/packlets/diagnostics/diagnostics-broadcast.mjs +1 -1
- package/dist/lib/node-esm/packlets/locks/browser.mjs +9 -49
- package/dist/lib/node-esm/packlets/locks/browser.mjs.map +2 -2
- package/dist/lib/node-esm/packlets/locks/node.mjs +4 -22
- package/dist/lib/node-esm/packlets/locks/node.mjs.map +2 -2
- package/dist/lib/node-esm/testing/index.mjs +9 -22
- package/dist/lib/node-esm/testing/index.mjs.map +3 -3
- package/dist/types/src/index.d.ts +1 -0
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/packlets/agents/edge-agent-manager.d.ts +3 -2
- 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 +2 -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/devtools.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-collector.d.ts.map +1 -1
- package/dist/types/src/packlets/diagnostics/diagnostics.d.ts +2 -3
- 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/contacts-service.d.ts.map +1 -1
- package/dist/types/src/packlets/identity/identity-manager.d.ts +3 -3
- package/dist/types/src/packlets/identity/identity-manager.d.ts.map +1 -1
- package/dist/types/src/packlets/identity/identity-recovery-manager.d.ts +6 -5
- package/dist/types/src/packlets/identity/identity-recovery-manager.d.ts.map +1 -1
- package/dist/types/src/packlets/identity/identity-service.d.ts +6 -10
- package/dist/types/src/packlets/identity/identity-service.d.ts.map +1 -1
- package/dist/types/src/packlets/identity/identity.d.ts +6 -9
- package/dist/types/src/packlets/identity/identity.d.ts.map +1 -1
- package/dist/types/src/packlets/invitations/device-invitation-protocol.d.ts +2 -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 +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-protocol.d.ts +5 -1
- package/dist/types/src/packlets/invitations/invitation-protocol.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-handler.d.ts.map +1 -1
- package/dist/types/src/packlets/invitations/invitations-manager.d.ts +3 -3
- package/dist/types/src/packlets/invitations/invitations-manager.d.ts.map +1 -1
- package/dist/types/src/packlets/invitations/invitations-service.d.ts +3 -3
- package/dist/types/src/packlets/invitations/invitations-service.d.ts.map +1 -1
- package/dist/types/src/packlets/invitations/space-invitation-protocol.d.ts +2 -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 +5 -4
- package/dist/types/src/packlets/network/network-service.d.ts.map +1 -1
- package/dist/types/src/packlets/services/client-rpc-server.d.ts +3 -3
- package/dist/types/src/packlets/services/client-rpc-server.d.ts.map +1 -1
- package/dist/types/src/packlets/services/feed-syncer.d.ts +2 -2
- package/dist/types/src/packlets/services/feed-syncer.d.ts.map +1 -1
- package/dist/types/src/packlets/services/service-context.d.ts +2 -3
- package/dist/types/src/packlets/services/service-context.d.ts.map +1 -1
- package/dist/types/src/packlets/services/service-host.d.ts +2 -3
- 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/archive-format.d.ts +9 -0
- package/dist/types/src/packlets/space-export/archive-format.d.ts.map +1 -0
- package/dist/types/src/packlets/space-export/index.d.ts +4 -1
- package/dist/types/src/packlets/space-export/index.d.ts.map +1 -1
- package/dist/types/src/packlets/space-export/serialized-space-reader.d.ts +23 -0
- package/dist/types/src/packlets/space-export/serialized-space-reader.d.ts.map +1 -0
- package/dist/types/src/packlets/space-export/serialized-space-writer.d.ts +36 -0
- package/dist/types/src/packlets/space-export/serialized-space-writer.d.ts.map +1 -0
- package/dist/types/src/packlets/space-export/space-archive-reader.d.ts +9 -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 +7 -1
- package/dist/types/src/packlets/space-export/space-archive-writer.d.ts.map +1 -1
- package/dist/types/src/packlets/space-export/space-archive.test.d.ts +2 -0
- package/dist/types/src/packlets/space-export/space-archive.test.d.ts.map +1 -0
- 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 +18 -12
- package/dist/types/src/packlets/spaces/data-space-manager.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/data-space.d.ts +24 -7
- 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 +2 -1
- package/dist/types/src/packlets/spaces/genesis.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/notarization-plugin.d.ts +1 -4
- package/dist/types/src/packlets/spaces/notarization-plugin.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/spaces-service.d.ts +10 -7
- 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 +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 +11 -1
- package/dist/types/src/packlets/worker/worker-runtime.d.ts.map +1 -1
- package/dist/types/src/packlets/worker/worker-session.d.ts +0 -2
- package/dist/types/src/packlets/worker/worker-session.d.ts.map +1 -1
- package/dist/types/src/testing/setup.d.ts.map +1 -1
- package/dist/types/src/version.d.ts +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +42 -49
- package/src/index.ts +1 -0
- package/src/packlets/agents/edge-agent-manager.ts +8 -5
- package/src/packlets/agents/edge-agent-service.ts +4 -2
- package/src/packlets/devices/devices-service.test.ts +0 -1
- package/src/packlets/devtools/devtools.ts +0 -1
- package/src/packlets/diagnostics/diagnostics.ts +1 -2
- package/src/packlets/identity/contacts-service.ts +0 -1
- package/src/packlets/identity/identity-manager.test.ts +5 -5
- package/src/packlets/identity/identity-manager.ts +18 -17
- package/src/packlets/identity/identity-recovery-manager.ts +20 -16
- package/src/packlets/identity/identity-service.test.ts +6 -27
- package/src/packlets/identity/identity-service.ts +13 -81
- package/src/packlets/identity/identity.test.ts +2 -2
- package/src/packlets/identity/identity.ts +9 -32
- package/src/packlets/invitations/device-invitation-protocol.ts +3 -2
- package/src/packlets/invitations/edge-invitation-handler.ts +9 -5
- package/src/packlets/invitations/invitation-host-extension.ts +7 -10
- package/src/packlets/invitations/invitation-protocol.ts +5 -1
- package/src/packlets/invitations/invitation-state.ts +1 -15
- package/src/packlets/invitations/invitations-handler.test.ts +4 -5
- package/src/packlets/invitations/invitations-handler.ts +67 -15
- package/src/packlets/invitations/invitations-manager.ts +40 -15
- package/src/packlets/invitations/invitations-service.ts +9 -9
- package/src/packlets/invitations/space-invitation-protocol.test.ts +17 -16
- package/src/packlets/invitations/space-invitation-protocol.ts +4 -3
- package/src/packlets/logging/logging-service.ts +15 -15
- package/src/packlets/network/network-service.test.ts +0 -1
- package/src/packlets/network/network-service.ts +10 -8
- package/src/packlets/services/client-rpc-server.ts +15 -12
- package/src/packlets/services/feed-syncer.test.ts +3 -3
- package/src/packlets/services/feed-syncer.ts +24 -17
- package/src/packlets/services/service-context.test.ts +3 -2
- package/src/packlets/services/service-context.ts +91 -40
- package/src/packlets/services/service-host.test.ts +8 -8
- package/src/packlets/services/service-host.ts +17 -24
- package/src/packlets/services/service-registry.test.ts +0 -1
- package/src/packlets/space-export/archive-format.ts +42 -0
- package/src/packlets/space-export/index.ts +4 -1
- package/src/packlets/space-export/serialized-space-reader.ts +111 -0
- package/src/packlets/space-export/serialized-space-writer.ts +252 -0
- package/src/packlets/space-export/space-archive-reader.ts +64 -3
- package/src/packlets/space-export/space-archive-writer.ts +38 -2
- package/src/packlets/space-export/space-archive.test.ts +461 -0
- package/src/packlets/spaces/data-space-manager.test.ts +79 -13
- package/src/packlets/spaces/data-space-manager.ts +75 -111
- package/src/packlets/spaces/data-space.ts +49 -29
- package/src/packlets/spaces/edge-feed-replicator.test.ts +1 -1
- package/src/packlets/spaces/edge-feed-replicator.ts +9 -7
- package/src/packlets/spaces/epoch-migrations.ts +3 -3
- package/src/packlets/spaces/genesis.ts +6 -1
- package/src/packlets/spaces/notarization-plugin.ts +2 -1
- package/src/packlets/spaces/spaces-service.test.ts +18 -11
- package/src/packlets/spaces/spaces-service.ts +113 -17
- package/src/packlets/testing/invitation-utils.ts +3 -2
- package/src/packlets/worker/worker-runtime.ts +39 -6
- package/src/packlets/worker/worker-session.ts +4 -10
- package/src/version.ts +1 -1
- package/dist/lib/browser/chunk-MQ6PWJ76.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-GUAL4U7S.mjs.map +0 -7
- package/dist/types/src/packlets/identity/default-space-state-machine.d.ts +0 -19
- package/dist/types/src/packlets/identity/default-space-state-machine.d.ts.map +0 -1
- package/src/packlets/identity/default-space-state-machine.ts +0 -44
- /package/dist/lib/browser/{chunk-NQSC7HOE.mjs.map → chunk-XJRPB3GA.mjs.map} +0 -0
- /package/dist/lib/node-esm/{chunk-PKEGMOQ4.mjs.map → chunk-2DT3MZRL.mjs.map} +0 -0
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
import { type Doc } from '@automerge/automerge';
|
|
6
|
-
import { type AutomergeUrl, type
|
|
6
|
+
import { type AutomergeUrl, type DocumentId, interpretAsDocumentId } from '@automerge/automerge-repo';
|
|
7
7
|
|
|
8
8
|
import { Event, synchronized, trackLeaks } from '@dxos/async';
|
|
9
9
|
import { SpaceProperties } from '@dxos/client-protocol';
|
|
@@ -16,7 +16,6 @@ import {
|
|
|
16
16
|
getCredentialAssertion,
|
|
17
17
|
} from '@dxos/credentials';
|
|
18
18
|
import { Type } from '@dxos/echo';
|
|
19
|
-
import { getSchemaDXN } from '@dxos/echo/internal';
|
|
20
19
|
import {
|
|
21
20
|
AuthStatus,
|
|
22
21
|
CredentialServerExtension,
|
|
@@ -31,45 +30,40 @@ import {
|
|
|
31
30
|
type SpaceProtocolSession,
|
|
32
31
|
findInlineObjectOfType,
|
|
33
32
|
} from '@dxos/echo-pipeline';
|
|
34
|
-
import {
|
|
35
|
-
type DatabaseDirectory,
|
|
36
|
-
EncodedReference,
|
|
37
|
-
type ObjectStructure,
|
|
38
|
-
SpaceDocVersion,
|
|
39
|
-
createIdFromSpaceKey,
|
|
40
|
-
} from '@dxos/echo-protocol';
|
|
33
|
+
import { type DatabaseDirectory, createIdFromSpaceKey } from '@dxos/echo-protocol';
|
|
41
34
|
import type { EdgeConnection, EdgeHttpClient } from '@dxos/edge-client';
|
|
42
35
|
import { type FeedStore, writeMessages } from '@dxos/feed-store';
|
|
43
36
|
import { assertArgument, assertState, failedInvariant, invariant } from '@dxos/invariant';
|
|
44
37
|
import { type Keyring } from '@dxos/keyring';
|
|
45
|
-
import {
|
|
38
|
+
import { PublicKey, type SpaceId } from '@dxos/keys';
|
|
46
39
|
import { log } from '@dxos/log';
|
|
47
|
-
import { AlreadyJoinedError
|
|
40
|
+
import { AlreadyJoinedError } from '@dxos/protocols';
|
|
48
41
|
import { Invitation, SpaceState } from '@dxos/protocols/proto/dxos/client/services';
|
|
49
42
|
import { type Runtime } from '@dxos/protocols/proto/dxos/config';
|
|
50
43
|
import { type FeedMessage } from '@dxos/protocols/proto/dxos/echo/feed';
|
|
51
44
|
import { EdgeReplicationSetting, type SpaceMetadata } from '@dxos/protocols/proto/dxos/echo/metadata';
|
|
52
|
-
import {
|
|
45
|
+
import {
|
|
46
|
+
type Credential,
|
|
47
|
+
MembershipPolicy,
|
|
48
|
+
type ProfileDocument,
|
|
49
|
+
SpaceMember,
|
|
50
|
+
} from '@dxos/protocols/proto/dxos/halo/credentials';
|
|
53
51
|
import { type DelegateSpaceInvitation } from '@dxos/protocols/proto/dxos/halo/invitations';
|
|
54
52
|
import { type PeerState } from '@dxos/protocols/proto/dxos/mesh/presence';
|
|
55
53
|
import { type Teleport } from '@dxos/teleport';
|
|
56
54
|
import { Gossip, Presence } from '@dxos/teleport-extension-gossip';
|
|
57
55
|
import { type Timeframe } from '@dxos/timeframe';
|
|
58
56
|
import { trace } from '@dxos/tracing';
|
|
59
|
-
import { ComplexMap, deferFunction, forEachAsync
|
|
57
|
+
import { ComplexMap, deferFunction, forEachAsync } from '@dxos/util';
|
|
60
58
|
|
|
61
59
|
import { createAuthProvider } from '../identity';
|
|
62
60
|
import { type InvitationsManager } from '../invitations';
|
|
63
|
-
|
|
64
61
|
import { DataSpace } from './data-space';
|
|
65
62
|
import { spaceGenesis } from './genesis';
|
|
66
63
|
|
|
67
64
|
const PRESENCE_ANNOUNCE_INTERVAL = 10_000;
|
|
68
65
|
const PRESENCE_OFFLINE_TIMEOUT = 20_000;
|
|
69
66
|
|
|
70
|
-
// Space properties key for default metadata.
|
|
71
|
-
const DEFAULT_SPACE_KEY = '__DEFAULT__';
|
|
72
|
-
|
|
73
67
|
export interface SigningContext {
|
|
74
68
|
identityKey: PublicKey;
|
|
75
69
|
deviceKey: PublicKey;
|
|
@@ -94,6 +88,9 @@ export type AcceptSpaceOptions = {
|
|
|
94
88
|
* We will try to catch up to this timeframe before initializing the database.
|
|
95
89
|
*/
|
|
96
90
|
dataTimeframe?: Timeframe;
|
|
91
|
+
|
|
92
|
+
/** Tags assigned to the space member. */
|
|
93
|
+
tags?: string[];
|
|
97
94
|
};
|
|
98
95
|
|
|
99
96
|
export type AdmitMemberOptions = {
|
|
@@ -102,6 +99,7 @@ export type AdmitMemberOptions = {
|
|
|
102
99
|
role: SpaceMember.Role;
|
|
103
100
|
profile?: ProfileDocument;
|
|
104
101
|
delegationCredentialId?: PublicKey;
|
|
102
|
+
tags?: string[];
|
|
105
103
|
};
|
|
106
104
|
|
|
107
105
|
export type DataSpaceManagerProps = {
|
|
@@ -135,16 +133,17 @@ export type DataSpaceManagerRuntimeProps = {
|
|
|
135
133
|
export type CreateSpaceOptions = {
|
|
136
134
|
rootUrl?: AutomergeUrl;
|
|
137
135
|
documents?: Record<DocumentId, Uint8Array>;
|
|
136
|
+
tags?: string[];
|
|
137
|
+
membershipPolicy?: MembershipPolicy;
|
|
138
138
|
};
|
|
139
139
|
|
|
140
140
|
@trackLeaks('open', 'close')
|
|
141
|
+
@trace.resource({ lifecycle: true })
|
|
141
142
|
export class DataSpaceManager extends Resource {
|
|
142
143
|
public readonly updated = new Event();
|
|
143
144
|
|
|
144
145
|
private readonly _spaces = new ComplexMap<PublicKey, DataSpace>(PublicKey.hash);
|
|
145
146
|
|
|
146
|
-
private readonly _instanceId = PublicKey.random().toHex();
|
|
147
|
-
|
|
148
147
|
private readonly _spaceManager: SpaceManager;
|
|
149
148
|
private readonly _metadataStore: MetadataStore;
|
|
150
149
|
private readonly _keyring: Keyring;
|
|
@@ -184,9 +183,8 @@ export class DataSpaceManager extends Resource {
|
|
|
184
183
|
Array.from(this._spaces.values()).map(async (space) => {
|
|
185
184
|
const rootUrl = space.automergeSpaceState.rootUrl;
|
|
186
185
|
const rootHandle = rootUrl
|
|
187
|
-
? await this._echoHost.loadDoc<Doc<DatabaseDirectory>>(
|
|
186
|
+
? await this._echoHost.loadDoc<Doc<DatabaseDirectory>>(this._ctx, rootUrl as AutomergeUrl)
|
|
188
187
|
: undefined;
|
|
189
|
-
await rootHandle?.whenReady();
|
|
190
188
|
const rootDoc = rootHandle?.doc();
|
|
191
189
|
|
|
192
190
|
const properties = rootDoc && findInlineObjectOfType(rootDoc, Type.getTypename(SpaceProperties));
|
|
@@ -217,16 +215,16 @@ export class DataSpaceManager extends Resource {
|
|
|
217
215
|
}
|
|
218
216
|
|
|
219
217
|
@synchronized
|
|
220
|
-
|
|
218
|
+
@trace.span({ showInBrowserTimeline: true, op: 'lifecycle' })
|
|
219
|
+
protected override async _open(ctx: Context): Promise<void> {
|
|
221
220
|
log('open');
|
|
222
|
-
log.trace('dxos.echo.data-space-manager.open', Trace.begin({ id: this._instanceId }));
|
|
223
221
|
log('metadata loaded', { spaces: this._metadataStore.spaces.length });
|
|
224
222
|
|
|
225
223
|
const spacesToActivate: DataSpace[] = [];
|
|
226
224
|
await forEachAsync(this._metadataStore.spaces, async (spaceMetadata) => {
|
|
227
225
|
try {
|
|
228
226
|
log('load space', { spaceMetadata });
|
|
229
|
-
const space = await this._constructSpace(spaceMetadata);
|
|
227
|
+
const space = await this._constructSpace(ctx, spaceMetadata);
|
|
230
228
|
// Track spaces that were previously active for auto-activation (used in dedicated worker mode).
|
|
231
229
|
if (this._runtimeProps?.autoActivateSpaces && spaceMetadata.state === SpaceState.SPACE_ACTIVE) {
|
|
232
230
|
spacesToActivate.push(space);
|
|
@@ -239,21 +237,19 @@ export class DataSpaceManager extends Resource {
|
|
|
239
237
|
// Auto-activate spaces that were previously active (used in dedicated worker mode after leader changeover).
|
|
240
238
|
for (const space of spacesToActivate) {
|
|
241
239
|
log('auto-activating space', { spaceKey: space.key });
|
|
242
|
-
space.activate().catch((err) => {
|
|
240
|
+
space.activate(ctx).catch((err) => {
|
|
243
241
|
log.error('Error auto-activating space', { spaceKey: space.key, err });
|
|
244
242
|
});
|
|
245
243
|
}
|
|
246
244
|
|
|
247
245
|
this.updated.emit();
|
|
248
|
-
|
|
249
|
-
log.trace('dxos.echo.data-space-manager.open', Trace.end({ id: this._instanceId }));
|
|
250
246
|
}
|
|
251
247
|
|
|
252
248
|
@synchronized
|
|
253
|
-
protected override async _close(): Promise<void> {
|
|
249
|
+
protected override async _close(ctx: Context): Promise<void> {
|
|
254
250
|
log('close');
|
|
255
251
|
for (const space of this._spaces.values()) {
|
|
256
|
-
await space.close();
|
|
252
|
+
await space.close(ctx);
|
|
257
253
|
}
|
|
258
254
|
this._spaces.clear();
|
|
259
255
|
}
|
|
@@ -262,7 +258,8 @@ export class DataSpaceManager extends Resource {
|
|
|
262
258
|
* Creates a new space writing the genesis credentials to the control feed.
|
|
263
259
|
*/
|
|
264
260
|
@synchronized
|
|
265
|
-
|
|
261
|
+
@trace.span({ showInBrowserTimeline: true, op: 'lifecycle' })
|
|
262
|
+
async createSpace(ctx: Context, options: CreateSpaceOptions = {}): Promise<DataSpace> {
|
|
266
263
|
assertArgument(
|
|
267
264
|
!!options.rootUrl === !!options.documents,
|
|
268
265
|
'options',
|
|
@@ -270,6 +267,8 @@ export class DataSpaceManager extends Resource {
|
|
|
270
267
|
);
|
|
271
268
|
|
|
272
269
|
assertState(this._lifecycleState === LifecycleState.OPEN, 'Not open.');
|
|
270
|
+
|
|
271
|
+
const tags = options.tags ? Array.from(options.tags) : [];
|
|
273
272
|
const spaceKey = await this._keyring.createKey();
|
|
274
273
|
const controlFeedKey = await this._keyring.createKey();
|
|
275
274
|
const dataFeedKey = await this._keyring.createKey();
|
|
@@ -282,6 +281,7 @@ export class DataSpaceManager extends Resource {
|
|
|
282
281
|
controlFeedKey,
|
|
283
282
|
dataFeedKey,
|
|
284
283
|
state: SpaceState.SPACE_ACTIVE,
|
|
284
|
+
tags,
|
|
285
285
|
};
|
|
286
286
|
|
|
287
287
|
log('creating space...', { spaceId, spaceKey });
|
|
@@ -319,30 +319,37 @@ export class DataSpaceManager extends Resource {
|
|
|
319
319
|
let root: DatabaseRoot;
|
|
320
320
|
if (options.rootUrl) {
|
|
321
321
|
const newRootDocId = documentIdMapping[interpretAsDocumentId(options.rootUrl)] ?? failedInvariant();
|
|
322
|
-
const rootDocHandle = await this._echoHost.loadDoc<DatabaseDirectory>(
|
|
322
|
+
const rootDocHandle = await this._echoHost.loadDoc<DatabaseDirectory>(ctx, newRootDocId);
|
|
323
323
|
DatabaseRoot.mapLinks(rootDocHandle, documentIdMapping);
|
|
324
324
|
|
|
325
|
-
root = await this._echoHost.openSpaceRoot(spaceId, `automerge:${newRootDocId}` as AutomergeUrl);
|
|
325
|
+
root = await this._echoHost.openSpaceRoot(ctx, spaceId, `automerge:${newRootDocId}` as AutomergeUrl);
|
|
326
326
|
} else {
|
|
327
|
-
root = await this._echoHost.createSpaceRoot(spaceKey);
|
|
327
|
+
root = await this._echoHost.createSpaceRoot(ctx, spaceKey);
|
|
328
328
|
}
|
|
329
|
-
await this._echoHost.flush();
|
|
329
|
+
await this._echoHost.flush(ctx);
|
|
330
330
|
|
|
331
331
|
log('constructing space...', { spaceKey });
|
|
332
332
|
|
|
333
|
-
const space = await this._constructSpace(metadata);
|
|
334
|
-
await space.open();
|
|
333
|
+
const space = await this._constructSpace(ctx, metadata);
|
|
334
|
+
await space.open(ctx);
|
|
335
335
|
|
|
336
336
|
log('adding space...', { spaceKey });
|
|
337
337
|
|
|
338
|
-
const credentials = await spaceGenesis(
|
|
338
|
+
const credentials = await spaceGenesis(
|
|
339
|
+
this._keyring,
|
|
340
|
+
this._signingContext,
|
|
341
|
+
space.inner,
|
|
342
|
+
root.url,
|
|
343
|
+
tags,
|
|
344
|
+
options.membershipPolicy,
|
|
345
|
+
);
|
|
339
346
|
await this._metadataStore.addSpace(metadata);
|
|
340
347
|
|
|
341
348
|
const memberCredential = credentials[1];
|
|
342
349
|
invariant(getCredentialAssertion(memberCredential)['@type'] === 'dxos.halo.credentials.SpaceMember');
|
|
343
350
|
await this._signingContext.recordCredential(memberCredential);
|
|
344
351
|
|
|
345
|
-
await space.initializeDataPipeline();
|
|
352
|
+
await space.initializeDataPipeline(ctx);
|
|
346
353
|
|
|
347
354
|
log('space ready.', { spaceId, spaceKey });
|
|
348
355
|
|
|
@@ -350,86 +357,36 @@ export class DataSpaceManager extends Resource {
|
|
|
350
357
|
return space;
|
|
351
358
|
}
|
|
352
359
|
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
case SpaceDocVersion.CURRENT: {
|
|
359
|
-
if (!space.databaseRoot.handle.isReady()) {
|
|
360
|
-
log.warn('waiting for space root to be ready', { spaceId: space.id });
|
|
361
|
-
await space.databaseRoot.handle.whenReady();
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
const [_, properties] =
|
|
365
|
-
findInlineObjectOfType(space.databaseRoot.doc()!, Type.getTypename(SpaceProperties)) ?? [];
|
|
366
|
-
return properties?.data?.[DEFAULT_SPACE_KEY] === this._signingContext.identityKey.toHex();
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
case SpaceDocVersion.LEGACY: {
|
|
370
|
-
throw new Error('Legacy space version is not supported');
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
default:
|
|
374
|
-
log.warn('unknown space version', { version: space.databaseRoot.getVersion(), spaceId: space.id });
|
|
375
|
-
return false;
|
|
376
|
-
}
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
async createDefaultSpace(): Promise<DataSpace> {
|
|
380
|
-
const space = await this.createSpace();
|
|
381
|
-
const document = await this._getSpaceRootDocument(space);
|
|
382
|
-
|
|
383
|
-
// TODO(dmaretskyi): Better API for low-level data access.
|
|
384
|
-
const properties: ObjectStructure = {
|
|
385
|
-
system: {
|
|
386
|
-
type: EncodedReference.fromDXN(getSchemaDXN(SpaceProperties)!),
|
|
387
|
-
},
|
|
388
|
-
data: {
|
|
389
|
-
[DEFAULT_SPACE_KEY]: this._signingContext.identityKey.toHex(),
|
|
390
|
-
},
|
|
391
|
-
meta: {
|
|
392
|
-
keys: [],
|
|
393
|
-
},
|
|
394
|
-
};
|
|
395
|
-
|
|
396
|
-
const propertiesId = ObjectId.random();
|
|
397
|
-
document.change((doc: DatabaseDirectory) => {
|
|
398
|
-
setDeep(doc, ['objects', propertiesId], properties);
|
|
399
|
-
});
|
|
400
|
-
|
|
401
|
-
await this._echoHost.flush();
|
|
402
|
-
return space;
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
private async _getSpaceRootDocument(space: DataSpace): Promise<DocHandle<DatabaseDirectory>> {
|
|
406
|
-
const automergeIndex = space.automergeSpaceState.rootUrl;
|
|
407
|
-
invariant(automergeIndex);
|
|
408
|
-
const document = await this._echoHost.loadDoc<DatabaseDirectory>(Context.default(), automergeIndex as any, {
|
|
409
|
-
fetchFromNetwork: true,
|
|
410
|
-
});
|
|
411
|
-
await document.whenReady();
|
|
412
|
-
return document;
|
|
413
|
-
}
|
|
414
|
-
|
|
360
|
+
/**
|
|
361
|
+
* Accepts an existing space by joining its swarm and initializing the data pipeline.
|
|
362
|
+
* @param ctx - Caller context for cancellation and tracing.
|
|
363
|
+
* @param opts - Space keys and optional timeframes for catch-up.
|
|
364
|
+
*/
|
|
415
365
|
// TODO(burdon): Rename join space.
|
|
416
366
|
@synchronized
|
|
417
|
-
|
|
367
|
+
@trace.span({ showInBrowserTimeline: true, op: 'lifecycle' })
|
|
368
|
+
async acceptSpace(ctx: Context, opts: AcceptSpaceOptions): Promise<DataSpace> {
|
|
418
369
|
log('accept space', { opts });
|
|
419
370
|
invariant(this._lifecycleState === LifecycleState.OPEN, 'Not open.');
|
|
420
371
|
invariant(!this._spaces.has(opts.spaceKey), 'Space already exists.');
|
|
421
372
|
|
|
373
|
+
const tags = opts.tags ? Array.from(opts.tags) : [];
|
|
422
374
|
const metadata: SpaceMetadata = {
|
|
423
375
|
key: opts.spaceKey,
|
|
424
376
|
genesisFeedKey: opts.genesisFeedKey,
|
|
425
377
|
controlTimeframe: opts.controlTimeframe,
|
|
426
378
|
dataTimeframe: opts.dataTimeframe,
|
|
379
|
+
tags,
|
|
427
380
|
};
|
|
428
381
|
|
|
429
|
-
const space = await this._constructSpace(metadata);
|
|
430
|
-
await space.open();
|
|
382
|
+
const space = await this._constructSpace(ctx, metadata);
|
|
383
|
+
await space.open(ctx);
|
|
431
384
|
await this._metadataStore.addSpace(metadata);
|
|
432
|
-
|
|
385
|
+
// Use DSM lifecycle ctx: the invitation accept flow disposes `ctx` as soon as
|
|
386
|
+
// `acceptSpace` returns (guardedState.complete -> ctx.dispose). Detached data-pipeline
|
|
387
|
+
// initialization must outlive the invitation flow, and its span must be parented to a
|
|
388
|
+
// long-lived context.
|
|
389
|
+
space.initializeDataPipelineAsync(this._ctx);
|
|
433
390
|
|
|
434
391
|
this.updated.emit();
|
|
435
392
|
return space;
|
|
@@ -453,6 +410,7 @@ export class DataSpaceManager extends Resource {
|
|
|
453
410
|
space.spaceState.membershipChainHeads,
|
|
454
411
|
options.profile,
|
|
455
412
|
options.delegationCredentialId,
|
|
413
|
+
space.spaceState.tags,
|
|
456
414
|
);
|
|
457
415
|
|
|
458
416
|
// TODO(dmaretskyi): Refactor.
|
|
@@ -479,8 +437,8 @@ export class DataSpaceManager extends Resource {
|
|
|
479
437
|
);
|
|
480
438
|
}
|
|
481
439
|
|
|
482
|
-
public async requestSpaceAdmissionCredential(spaceKey: PublicKey): Promise<Credential> {
|
|
483
|
-
return this._spaceManager.requestSpaceAdmissionCredential({
|
|
440
|
+
public async requestSpaceAdmissionCredential(ctx: Context, spaceKey: PublicKey): Promise<Credential> {
|
|
441
|
+
return this._spaceManager.requestSpaceAdmissionCredential(ctx, {
|
|
484
442
|
spaceKey,
|
|
485
443
|
identityKey: this._signingContext.identityKey,
|
|
486
444
|
timeout: 15_000,
|
|
@@ -493,7 +451,11 @@ export class DataSpaceManager extends Resource {
|
|
|
493
451
|
});
|
|
494
452
|
}
|
|
495
453
|
|
|
496
|
-
async setSpaceEdgeReplicationSetting(
|
|
454
|
+
async setSpaceEdgeReplicationSetting(
|
|
455
|
+
ctx: Context,
|
|
456
|
+
spaceKey: PublicKey,
|
|
457
|
+
setting: EdgeReplicationSetting,
|
|
458
|
+
): Promise<void> {
|
|
497
459
|
const space = this._spaces.get(spaceKey);
|
|
498
460
|
invariant(space, 'Space not found.');
|
|
499
461
|
|
|
@@ -505,7 +467,7 @@ export class DataSpaceManager extends Resource {
|
|
|
505
467
|
await this._echoEdgeReplicator?.disconnectFromSpace(space.id);
|
|
506
468
|
break;
|
|
507
469
|
case EdgeReplicationSetting.ENABLED:
|
|
508
|
-
await this._echoEdgeReplicator?.connectToSpace(space.id);
|
|
470
|
+
await this._echoEdgeReplicator?.connectToSpace(ctx, space.id);
|
|
509
471
|
break;
|
|
510
472
|
}
|
|
511
473
|
}
|
|
@@ -513,7 +475,7 @@ export class DataSpaceManager extends Resource {
|
|
|
513
475
|
space.stateUpdate.emit();
|
|
514
476
|
}
|
|
515
477
|
|
|
516
|
-
private async _constructSpace(metadata: SpaceMetadata): Promise<DataSpace> {
|
|
478
|
+
private async _constructSpace(ctx: Context, metadata: SpaceMetadata): Promise<DataSpace> {
|
|
517
479
|
log('construct space', { metadata });
|
|
518
480
|
const gossip = new Gossip({
|
|
519
481
|
localPeerId: this._signingContext.deviceKey,
|
|
@@ -603,6 +565,7 @@ export class DataSpaceManager extends Resource {
|
|
|
603
565
|
},
|
|
604
566
|
},
|
|
605
567
|
cache: metadata.cache,
|
|
568
|
+
tags: metadata.tags,
|
|
606
569
|
edgeConnection: this._edgeConnection,
|
|
607
570
|
edgeHttpClient: this._edgeHttpClient,
|
|
608
571
|
edgeFeatures: this._edgeFeatures,
|
|
@@ -611,7 +574,8 @@ export class DataSpaceManager extends Resource {
|
|
|
611
574
|
dataSpace.postOpen.append(async () => {
|
|
612
575
|
const setting = dataSpace.getEdgeReplicationSetting();
|
|
613
576
|
if (!setting || setting === EdgeReplicationSetting.ENABLED) {
|
|
614
|
-
|
|
577
|
+
// Use lifecycle ctx: the caller ctx from _constructSpace may be disposed by the time postOpen fires.
|
|
578
|
+
await this._echoEdgeReplicator?.connectToSpace(this._ctx, dataSpace.id);
|
|
615
579
|
} else if (this._echoEdgeReplicator) {
|
|
616
580
|
log('not connecting EchoEdgeReplicator because of EdgeReplicationSetting', { spaceId: dataSpace.id });
|
|
617
581
|
}
|
|
@@ -708,7 +672,7 @@ export class DataSpaceManager extends Resource {
|
|
|
708
672
|
invitations: Array<[PublicKey, DelegateSpaceInvitation]>,
|
|
709
673
|
): Promise<void> {
|
|
710
674
|
const tasks = invitations.map(([credentialId, invitation]) => {
|
|
711
|
-
return this._invitationsManager.createInvitation({
|
|
675
|
+
return this._invitationsManager.createInvitation(this._ctx, {
|
|
712
676
|
type: Invitation.Type.DELEGATED,
|
|
713
677
|
kind: Invitation.Kind.SPACE,
|
|
714
678
|
spaceKey: space.key,
|
|
@@ -24,7 +24,7 @@ import { failedInvariant, invariant } from '@dxos/invariant';
|
|
|
24
24
|
import { type Keyring } from '@dxos/keyring';
|
|
25
25
|
import { PublicKey } from '@dxos/keys';
|
|
26
26
|
import { log } from '@dxos/log';
|
|
27
|
-
import { CancelledError, SystemError } from '@dxos/protocols';
|
|
27
|
+
import { CancelledError, type FeedProtocol, SystemError } from '@dxos/protocols';
|
|
28
28
|
import {
|
|
29
29
|
type CreateEpochRequest,
|
|
30
30
|
type Space as SpaceProto,
|
|
@@ -37,6 +37,7 @@ import {
|
|
|
37
37
|
AdmittedFeed,
|
|
38
38
|
type Credential,
|
|
39
39
|
type Epoch,
|
|
40
|
+
MembershipPolicy,
|
|
40
41
|
type ProfileDocument,
|
|
41
42
|
SpaceMember,
|
|
42
43
|
} from '@dxos/protocols/proto/dxos/halo/credentials';
|
|
@@ -47,7 +48,6 @@ import { trace } from '@dxos/tracing';
|
|
|
47
48
|
import { type AsyncCallback, CallbackCollection, ComplexSet } from '@dxos/util';
|
|
48
49
|
|
|
49
50
|
import { TrustedKeySetAuthVerifier } from '../identity';
|
|
50
|
-
|
|
51
51
|
import { AutomergeSpaceState } from './automerge-space-state';
|
|
52
52
|
import { type SigningContext } from './data-space-manager';
|
|
53
53
|
import { EdgeFeedReplicator } from './edge-feed-replicator';
|
|
@@ -83,6 +83,7 @@ export type DataSpaceProps = {
|
|
|
83
83
|
signingContext: SigningContext;
|
|
84
84
|
callbacks?: DataSpaceCallbacks;
|
|
85
85
|
cache?: SpaceCache;
|
|
86
|
+
tags?: string[];
|
|
86
87
|
edgeConnection?: EdgeConnection;
|
|
87
88
|
edgeHttpClient?: EdgeHttpClient;
|
|
88
89
|
edgeFeatures?: Runtime.Client.EdgeFeatures;
|
|
@@ -120,6 +121,9 @@ export class DataSpace {
|
|
|
120
121
|
|
|
121
122
|
private _state = SpaceState.SPACE_CLOSED;
|
|
122
123
|
|
|
124
|
+
/** Immutable tags from space metadata, available immediately. */
|
|
125
|
+
readonly tags: string[];
|
|
126
|
+
|
|
123
127
|
private _databaseRoot: DatabaseRoot | null = null;
|
|
124
128
|
|
|
125
129
|
/**
|
|
@@ -167,6 +171,7 @@ export class DataSpace {
|
|
|
167
171
|
});
|
|
168
172
|
|
|
169
173
|
this._cache = params.cache;
|
|
174
|
+
this.tags = params.tags ?? [];
|
|
170
175
|
|
|
171
176
|
if (params.edgeConnection && params.edgeFeatures?.feedReplicator) {
|
|
172
177
|
this._edgeFeedReplicator = new EdgeFeedReplicator({ messenger: params.edgeConnection, spaceId: this.id });
|
|
@@ -212,6 +217,11 @@ export class DataSpace {
|
|
|
212
217
|
return this._cache;
|
|
213
218
|
}
|
|
214
219
|
|
|
220
|
+
/** Membership policy from the genesis credential, defaults to INVITE. */
|
|
221
|
+
get membershipPolicy(): MembershipPolicy {
|
|
222
|
+
return this._inner.spaceState.genesisCredential ? this._inner.spaceState.membershipPolicy : MembershipPolicy.INVITE;
|
|
223
|
+
}
|
|
224
|
+
|
|
215
225
|
get automergeSpaceState() {
|
|
216
226
|
return this._automergeSpaceState;
|
|
217
227
|
}
|
|
@@ -229,13 +239,14 @@ export class DataSpace {
|
|
|
229
239
|
}
|
|
230
240
|
|
|
231
241
|
@synchronized
|
|
232
|
-
|
|
242
|
+
@trace.span({ showInBrowserTimeline: true, op: 'lifecycle' })
|
|
243
|
+
async open(ctx: Context): Promise<void> {
|
|
233
244
|
if (this._state === SpaceState.SPACE_CLOSED) {
|
|
234
|
-
await this._open();
|
|
245
|
+
await this._open(ctx);
|
|
235
246
|
}
|
|
236
247
|
}
|
|
237
248
|
|
|
238
|
-
private async _open(): Promise<void> {
|
|
249
|
+
private async _open(ctx: Context): Promise<void> {
|
|
239
250
|
await this._presence.open();
|
|
240
251
|
await this._gossip.open();
|
|
241
252
|
await this._notarizationPlugin.open();
|
|
@@ -247,8 +258,8 @@ export class DataSpace {
|
|
|
247
258
|
this.inner.protocol.feedAdded.append(this._onFeedAdded);
|
|
248
259
|
}
|
|
249
260
|
|
|
250
|
-
await this._inner.open(
|
|
251
|
-
await this._inner.startProtocol();
|
|
261
|
+
await this._inner.open(ctx);
|
|
262
|
+
await this._inner.startProtocol(ctx);
|
|
252
263
|
|
|
253
264
|
await this._edgeFeedReplicator?.open();
|
|
254
265
|
|
|
@@ -262,11 +273,12 @@ export class DataSpace {
|
|
|
262
273
|
}
|
|
263
274
|
|
|
264
275
|
@synchronized
|
|
265
|
-
|
|
266
|
-
|
|
276
|
+
@trace.span({ showInBrowserTimeline: true, op: 'lifecycle' })
|
|
277
|
+
async close(ctx: Context): Promise<void> {
|
|
278
|
+
await this._close(ctx);
|
|
267
279
|
}
|
|
268
280
|
|
|
269
|
-
private async _close(): Promise<void> {
|
|
281
|
+
private async _close(ctx: Context): Promise<void> {
|
|
270
282
|
await this._callbacks.beforeClose?.();
|
|
271
283
|
|
|
272
284
|
await this.preClose.callSerial();
|
|
@@ -284,7 +296,7 @@ export class DataSpace {
|
|
|
284
296
|
|
|
285
297
|
await this.authVerifier.close();
|
|
286
298
|
|
|
287
|
-
await this._inner.close();
|
|
299
|
+
await this._inner.close(ctx);
|
|
288
300
|
await this._inner.spaceState.removeCredentialProcessor(this._automergeSpaceState);
|
|
289
301
|
await this._automergeSpaceState.close();
|
|
290
302
|
await this._inner.spaceState.removeCredentialProcessor(this._notarizationPlugin);
|
|
@@ -304,12 +316,14 @@ export class DataSpace {
|
|
|
304
316
|
|
|
305
317
|
/**
|
|
306
318
|
* Initialize the data pipeline in a separate task.
|
|
319
|
+
* @param callerCtx - Trace context from the caller (e.g., activate or createSpace) for span parenting.
|
|
307
320
|
*/
|
|
308
|
-
initializeDataPipelineAsync(): void {
|
|
321
|
+
initializeDataPipelineAsync(callerCtx?: Context): void {
|
|
322
|
+
const traceCtx = callerCtx ?? this._ctx;
|
|
309
323
|
scheduleTask(this._ctx, async () => {
|
|
310
324
|
try {
|
|
311
325
|
this.metrics.pipelineInitBegin = new Date();
|
|
312
|
-
await this.initializeDataPipeline();
|
|
326
|
+
await this.initializeDataPipeline(traceCtx);
|
|
313
327
|
} catch (err) {
|
|
314
328
|
if (err instanceof CancelledError || err instanceof ContextDisposedError) {
|
|
315
329
|
log('data pipeline initialization cancelled', err);
|
|
@@ -327,8 +341,8 @@ export class DataSpace {
|
|
|
327
341
|
});
|
|
328
342
|
}
|
|
329
343
|
|
|
330
|
-
@trace.span({ showInBrowserTimeline: true })
|
|
331
|
-
async initializeDataPipeline(): Promise<void> {
|
|
344
|
+
@trace.span({ showInBrowserTimeline: true, op: 'lifecycle' })
|
|
345
|
+
async initializeDataPipeline(ctx: Context): Promise<void> {
|
|
332
346
|
if (this._state !== SpaceState.SPACE_CONTROL_ONLY) {
|
|
333
347
|
throw new SystemError({ message: 'Invalid operation' });
|
|
334
348
|
}
|
|
@@ -337,7 +351,7 @@ export class DataSpace {
|
|
|
337
351
|
log('new state', { state: SpaceState[this._state] });
|
|
338
352
|
|
|
339
353
|
log('initializing control pipeline');
|
|
340
|
-
await this._initializeAndReadControlPipeline();
|
|
354
|
+
await this._initializeAndReadControlPipeline(ctx);
|
|
341
355
|
|
|
342
356
|
// Allow other tasks to run before loading the data pipeline.
|
|
343
357
|
await sleep(1);
|
|
@@ -360,11 +374,19 @@ export class DataSpace {
|
|
|
360
374
|
yield [this._databaseRoot.documentId, root];
|
|
361
375
|
|
|
362
376
|
for (const documentUrl of this._databaseRoot.getAllLinkedDocuments()) {
|
|
363
|
-
const data = await this._echoHost.exportDoc(
|
|
377
|
+
const data = await this._echoHost.exportDoc(documentUrl);
|
|
364
378
|
yield [documentUrl.replace(/^automerge:/, ''), data];
|
|
365
379
|
}
|
|
366
380
|
}
|
|
367
381
|
|
|
382
|
+
/**
|
|
383
|
+
* Get all feeds and their blocks for this space.
|
|
384
|
+
* Used for space archive export.
|
|
385
|
+
*/
|
|
386
|
+
async getAllFeeds(): Promise<Array<{ feedId: string; feedNamespace: string; blocks: FeedProtocol.Block[] }>> {
|
|
387
|
+
return this._echoHost.getAllFeedsForSpace(this.id);
|
|
388
|
+
}
|
|
389
|
+
|
|
368
390
|
private async _enterReadyState(): Promise<void> {
|
|
369
391
|
await this._callbacks.beforeReady?.();
|
|
370
392
|
|
|
@@ -375,10 +397,10 @@ export class DataSpace {
|
|
|
375
397
|
await this._callbacks.afterReady?.();
|
|
376
398
|
}
|
|
377
399
|
|
|
378
|
-
@trace.span({ showInBrowserTimeline: true })
|
|
379
|
-
private async _initializeAndReadControlPipeline(): Promise<void> {
|
|
400
|
+
@trace.span({ showInBrowserTimeline: true, op: 'lifecycle' })
|
|
401
|
+
private async _initializeAndReadControlPipeline(ctx: Context): Promise<void> {
|
|
380
402
|
await this._inner.controlPipeline.state.waitUntilReachedTargetTimeframe({
|
|
381
|
-
ctx
|
|
403
|
+
ctx,
|
|
382
404
|
timeout: 10_000,
|
|
383
405
|
breakOnStall: false,
|
|
384
406
|
});
|
|
@@ -473,11 +495,10 @@ export class DataSpace {
|
|
|
473
495
|
await warnAfterTimeout(5_000, 'Automerge root doc load timeout (DataSpace)', async () => {
|
|
474
496
|
handle = await cancelWithContext(
|
|
475
497
|
this._ctx,
|
|
476
|
-
this._echoHost.loadDoc<DatabaseDirectory>(
|
|
498
|
+
this._echoHost.loadDoc<DatabaseDirectory>(this._ctx, rootUrl as AutomergeUrl, {
|
|
477
499
|
fetchFromNetwork: true,
|
|
478
500
|
}),
|
|
479
501
|
);
|
|
480
|
-
await cancelWithContext(this._ctx, handle.whenReady());
|
|
481
502
|
});
|
|
482
503
|
if (this._ctx.disposed) {
|
|
483
504
|
return;
|
|
@@ -496,7 +517,7 @@ export class DataSpace {
|
|
|
496
517
|
|
|
497
518
|
// TODO(dmaretskyi): Close roots.
|
|
498
519
|
// TODO(dmaretskyi): How do we handle changing to the next EPOCH?
|
|
499
|
-
const root = await this._echoHost.openSpaceRoot(this.id, handle.url);
|
|
520
|
+
const root = await this._echoHost.openSpaceRoot(this._ctx, this.id, handle.url);
|
|
500
521
|
|
|
501
522
|
// NOTE: Make sure this assignment happens synchronously together with the state change.
|
|
502
523
|
this._databaseRoot = root;
|
|
@@ -573,25 +594,24 @@ export class DataSpace {
|
|
|
573
594
|
}
|
|
574
595
|
|
|
575
596
|
@synchronized
|
|
576
|
-
async activate(): Promise<void> {
|
|
597
|
+
async activate(ctx: Context): Promise<void> {
|
|
577
598
|
if (![SpaceState.SPACE_CLOSED, SpaceState.SPACE_INACTIVE].includes(this._state)) {
|
|
578
599
|
return;
|
|
579
600
|
}
|
|
580
601
|
|
|
581
602
|
await this._metadataStore.setSpaceState(this.key, SpaceState.SPACE_ACTIVE);
|
|
582
|
-
await this._open();
|
|
583
|
-
this.initializeDataPipelineAsync();
|
|
603
|
+
await this._open(ctx);
|
|
604
|
+
this.initializeDataPipelineAsync(ctx);
|
|
584
605
|
}
|
|
585
606
|
|
|
586
607
|
@synchronized
|
|
587
|
-
async deactivate(): Promise<void> {
|
|
608
|
+
async deactivate(ctx: Context): Promise<void> {
|
|
588
609
|
if (this._state === SpaceState.SPACE_INACTIVE) {
|
|
589
610
|
return;
|
|
590
611
|
}
|
|
591
|
-
// Unregister from data service.
|
|
592
612
|
await this._metadataStore.setSpaceState(this.key, SpaceState.SPACE_INACTIVE);
|
|
593
613
|
if (this._state !== SpaceState.SPACE_CLOSED) {
|
|
594
|
-
await this._close();
|
|
614
|
+
await this._close(ctx);
|
|
595
615
|
}
|
|
596
616
|
this._state = SpaceState.SPACE_INACTIVE;
|
|
597
617
|
log('new state', { state: SpaceState[this._state] });
|
|
@@ -107,7 +107,7 @@ describe('EdgeFeedReplicator', () => {
|
|
|
107
107
|
const { feed } = await attachReplicator(messenger);
|
|
108
108
|
await appendMessage(feed);
|
|
109
109
|
|
|
110
|
-
sendSpy.mockImplementationOnce(async (request: any) => {
|
|
110
|
+
sendSpy.mockImplementationOnce(async (_ctx: any, request: any) => {
|
|
111
111
|
sendResponseMessage(request, encodeCbor({ type: 'metadata', feedKey: feed.key.toHex(), length: 0 }));
|
|
112
112
|
return Promise.resolve();
|
|
113
113
|
});
|