@dxos/client-services 0.8.4-main.bc674ce → 0.8.4-main.bcb3aa67d6
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-J33W6T4Q.mjs → chunk-5A3KX2RY.mjs} +1745 -1208
- package/dist/lib/browser/chunk-5A3KX2RY.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +33 -16
- package/dist/lib/browser/index.mjs.map +3 -3
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/testing/index.mjs +14 -7
- package/dist/lib/browser/testing/index.mjs.map +3 -3
- package/dist/lib/node-esm/{chunk-34HKLADW.mjs → chunk-FNPO5UMU.mjs} +1745 -1208
- package/dist/lib/node-esm/chunk-FNPO5UMU.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +33 -16
- 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 +14 -7
- 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/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 +5 -4
- package/dist/types/src/packlets/identity/identity-recovery-manager.d.ts.map +1 -1
- package/dist/types/src/packlets/identity/identity-service.d.ts +1 -6
- 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/edge-invitation-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/space-invitation-protocol.d.ts.map +1 -1
- package/dist/types/src/packlets/logging/logging-service.d.ts +4 -0
- package/dist/types/src/packlets/logging/logging-service.d.ts.map +1 -1
- package/dist/types/src/packlets/network/network-service.d.ts.map +1 -1
- package/dist/types/src/packlets/services/feed-syncer.d.ts +59 -0
- package/dist/types/src/packlets/services/feed-syncer.d.ts.map +1 -0
- package/dist/types/src/packlets/services/feed-syncer.test.d.ts +2 -0
- package/dist/types/src/packlets/services/feed-syncer.test.d.ts.map +1 -0
- package/dist/types/src/packlets/services/platform.d.ts.map +1 -1
- package/dist/types/src/packlets/services/service-context.d.ts +3 -4
- package/dist/types/src/packlets/services/service-context.d.ts.map +1 -1
- package/dist/types/src/packlets/services/service-host.d.ts +1 -1
- package/dist/types/src/packlets/services/service-host.d.ts.map +1 -1
- 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 +6 -0
- 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/data-space-manager.d.ts +17 -10
- package/dist/types/src/packlets/spaces/data-space-manager.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/data-space.d.ts +22 -6
- 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/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.map +1 -1
- package/dist/types/src/packlets/spaces/spaces-service.d.ts +2 -2
- package/dist/types/src/packlets/spaces/spaces-service.d.ts.map +1 -1
- package/dist/types/src/packlets/testing/invitation-utils.d.ts.map +1 -1
- package/dist/types/src/packlets/worker/worker-runtime.d.ts +11 -3
- package/dist/types/src/packlets/worker/worker-runtime.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 +43 -43
- package/src/index.ts +1 -0
- package/src/packlets/agents/edge-agent-manager.ts +8 -5
- package/src/packlets/agents/edge-agent-service.ts +2 -2
- package/src/packlets/identity/identity-manager.test.ts +5 -5
- package/src/packlets/identity/identity-manager.ts +16 -13
- package/src/packlets/identity/identity-recovery-manager.ts +20 -16
- package/src/packlets/identity/identity-service.test.ts +6 -26
- package/src/packlets/identity/identity-service.ts +5 -76
- package/src/packlets/identity/identity.test.ts +2 -2
- package/src/packlets/identity/identity.ts +7 -29
- package/src/packlets/invitations/edge-invitation-handler.ts +4 -3
- package/src/packlets/invitations/invitations-handler.test.ts +4 -4
- package/src/packlets/invitations/invitations-handler.ts +3 -3
- package/src/packlets/invitations/invitations-manager.ts +37 -14
- package/src/packlets/invitations/invitations-service.ts +4 -4
- package/src/packlets/invitations/space-invitation-protocol.test.ts +17 -16
- package/src/packlets/invitations/space-invitation-protocol.ts +3 -1
- package/src/packlets/logging/logging-service.ts +4 -0
- package/src/packlets/network/network-service.ts +5 -4
- package/src/packlets/services/feed-syncer.test.ts +340 -0
- package/src/packlets/services/feed-syncer.ts +337 -0
- package/src/packlets/services/platform.ts +7 -1
- package/src/packlets/services/service-context.test.ts +3 -2
- package/src/packlets/services/service-context.ts +106 -31
- package/src/packlets/services/service-host.test.ts +8 -7
- package/src/packlets/services/service-host.ts +9 -7
- package/src/packlets/space-export/space-archive-reader.ts +64 -3
- package/src/packlets/space-export/space-archive-writer.ts +36 -1
- package/src/packlets/space-export/space-archive.test.ts +287 -0
- package/src/packlets/spaces/data-space-manager.test.ts +79 -13
- package/src/packlets/spaces/data-space-manager.ts +71 -103
- package/src/packlets/spaces/data-space.ts +46 -23
- package/src/packlets/spaces/edge-feed-replicator.test.ts +1 -1
- package/src/packlets/spaces/edge-feed-replicator.ts +8 -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 +9 -6
- package/src/packlets/spaces/spaces-service.ts +30 -8
- package/src/packlets/testing/invitation-utils.ts +3 -2
- package/src/packlets/worker/worker-runtime.ts +14 -6
- package/src/packlets/worker/worker-session.ts +4 -4
- package/src/version.ts +1 -1
- package/dist/lib/browser/chunk-J33W6T4Q.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-34HKLADW.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
|
@@ -3,10 +3,10 @@
|
|
|
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
|
-
import { SpaceProperties } from '@dxos/client-protocol';
|
|
9
|
+
import { LegacySpaceProperties, SpaceProperties } from '@dxos/client-protocol';
|
|
10
10
|
import { Context, LifecycleState, Resource, cancelWithContext } from '@dxos/context';
|
|
11
11
|
import {
|
|
12
12
|
type CredentialSigner,
|
|
@@ -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,32 +30,31 @@ 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
40
|
import { AlreadyJoinedError, trace as Trace } 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';
|
|
@@ -67,9 +65,6 @@ import { spaceGenesis } from './genesis';
|
|
|
67
65
|
const PRESENCE_ANNOUNCE_INTERVAL = 10_000;
|
|
68
66
|
const PRESENCE_OFFLINE_TIMEOUT = 20_000;
|
|
69
67
|
|
|
70
|
-
// Space properties key for default metadata.
|
|
71
|
-
const DEFAULT_SPACE_KEY = '__DEFAULT__';
|
|
72
|
-
|
|
73
68
|
export interface SigningContext {
|
|
74
69
|
identityKey: PublicKey;
|
|
75
70
|
deviceKey: PublicKey;
|
|
@@ -94,6 +89,9 @@ export type AcceptSpaceOptions = {
|
|
|
94
89
|
* We will try to catch up to this timeframe before initializing the database.
|
|
95
90
|
*/
|
|
96
91
|
dataTimeframe?: Timeframe;
|
|
92
|
+
|
|
93
|
+
/** Tags assigned to the space member. */
|
|
94
|
+
tags?: string[];
|
|
97
95
|
};
|
|
98
96
|
|
|
99
97
|
export type AdmitMemberOptions = {
|
|
@@ -102,6 +100,7 @@ export type AdmitMemberOptions = {
|
|
|
102
100
|
role: SpaceMember.Role;
|
|
103
101
|
profile?: ProfileDocument;
|
|
104
102
|
delegationCredentialId?: PublicKey;
|
|
103
|
+
tags?: string[];
|
|
105
104
|
};
|
|
106
105
|
|
|
107
106
|
export type DataSpaceManagerProps = {
|
|
@@ -135,9 +134,12 @@ export type DataSpaceManagerRuntimeProps = {
|
|
|
135
134
|
export type CreateSpaceOptions = {
|
|
136
135
|
rootUrl?: AutomergeUrl;
|
|
137
136
|
documents?: Record<DocumentId, Uint8Array>;
|
|
137
|
+
tags?: string[];
|
|
138
|
+
membershipPolicy?: MembershipPolicy;
|
|
138
139
|
};
|
|
139
140
|
|
|
140
141
|
@trackLeaks('open', 'close')
|
|
142
|
+
@trace.resource()
|
|
141
143
|
export class DataSpaceManager extends Resource {
|
|
142
144
|
public readonly updated = new Event();
|
|
143
145
|
|
|
@@ -184,12 +186,15 @@ export class DataSpaceManager extends Resource {
|
|
|
184
186
|
Array.from(this._spaces.values()).map(async (space) => {
|
|
185
187
|
const rootUrl = space.automergeSpaceState.rootUrl;
|
|
186
188
|
const rootHandle = rootUrl
|
|
187
|
-
? await this._echoHost.loadDoc<Doc<DatabaseDirectory>>(
|
|
189
|
+
? await this._echoHost.loadDoc<Doc<DatabaseDirectory>>(this._ctx, rootUrl as AutomergeUrl)
|
|
188
190
|
: undefined;
|
|
189
191
|
await rootHandle?.whenReady();
|
|
190
192
|
const rootDoc = rootHandle?.doc();
|
|
191
193
|
|
|
192
|
-
const properties =
|
|
194
|
+
const properties =
|
|
195
|
+
rootDoc &&
|
|
196
|
+
(findInlineObjectOfType(rootDoc, Type.getTypename(SpaceProperties)) ??
|
|
197
|
+
findInlineObjectOfType(rootDoc, Type.getTypename(LegacySpaceProperties)));
|
|
193
198
|
|
|
194
199
|
return {
|
|
195
200
|
key: space.key.toHex(),
|
|
@@ -226,7 +231,7 @@ export class DataSpaceManager extends Resource {
|
|
|
226
231
|
await forEachAsync(this._metadataStore.spaces, async (spaceMetadata) => {
|
|
227
232
|
try {
|
|
228
233
|
log('load space', { spaceMetadata });
|
|
229
|
-
const space = await this._constructSpace(spaceMetadata);
|
|
234
|
+
const space = await this._constructSpace(this._ctx, spaceMetadata);
|
|
230
235
|
// Track spaces that were previously active for auto-activation (used in dedicated worker mode).
|
|
231
236
|
if (this._runtimeProps?.autoActivateSpaces && spaceMetadata.state === SpaceState.SPACE_ACTIVE) {
|
|
232
237
|
spacesToActivate.push(space);
|
|
@@ -239,7 +244,7 @@ export class DataSpaceManager extends Resource {
|
|
|
239
244
|
// Auto-activate spaces that were previously active (used in dedicated worker mode after leader changeover).
|
|
240
245
|
for (const space of spacesToActivate) {
|
|
241
246
|
log('auto-activating space', { spaceKey: space.key });
|
|
242
|
-
space.activate().catch((err) => {
|
|
247
|
+
space.activate(this._ctx).catch((err) => {
|
|
243
248
|
log.error('Error auto-activating space', { spaceKey: space.key, err });
|
|
244
249
|
});
|
|
245
250
|
}
|
|
@@ -250,10 +255,10 @@ export class DataSpaceManager extends Resource {
|
|
|
250
255
|
}
|
|
251
256
|
|
|
252
257
|
@synchronized
|
|
253
|
-
protected override async _close(): Promise<void> {
|
|
258
|
+
protected override async _close(ctx: Context): Promise<void> {
|
|
254
259
|
log('close');
|
|
255
260
|
for (const space of this._spaces.values()) {
|
|
256
|
-
await space.close();
|
|
261
|
+
await space.close(ctx);
|
|
257
262
|
}
|
|
258
263
|
this._spaces.clear();
|
|
259
264
|
}
|
|
@@ -262,7 +267,8 @@ export class DataSpaceManager extends Resource {
|
|
|
262
267
|
* Creates a new space writing the genesis credentials to the control feed.
|
|
263
268
|
*/
|
|
264
269
|
@synchronized
|
|
265
|
-
|
|
270
|
+
@trace.span({ showInBrowserTimeline: true })
|
|
271
|
+
async createSpace(ctx: Context, options: CreateSpaceOptions = {}): Promise<DataSpace> {
|
|
266
272
|
assertArgument(
|
|
267
273
|
!!options.rootUrl === !!options.documents,
|
|
268
274
|
'options',
|
|
@@ -270,6 +276,8 @@ export class DataSpaceManager extends Resource {
|
|
|
270
276
|
);
|
|
271
277
|
|
|
272
278
|
assertState(this._lifecycleState === LifecycleState.OPEN, 'Not open.');
|
|
279
|
+
|
|
280
|
+
const tags = options.tags ? Array.from(options.tags) : [];
|
|
273
281
|
const spaceKey = await this._keyring.createKey();
|
|
274
282
|
const controlFeedKey = await this._keyring.createKey();
|
|
275
283
|
const dataFeedKey = await this._keyring.createKey();
|
|
@@ -282,6 +290,7 @@ export class DataSpaceManager extends Resource {
|
|
|
282
290
|
controlFeedKey,
|
|
283
291
|
dataFeedKey,
|
|
284
292
|
state: SpaceState.SPACE_ACTIVE,
|
|
293
|
+
tags,
|
|
285
294
|
};
|
|
286
295
|
|
|
287
296
|
log('creating space...', { spaceId, spaceKey });
|
|
@@ -319,30 +328,37 @@ export class DataSpaceManager extends Resource {
|
|
|
319
328
|
let root: DatabaseRoot;
|
|
320
329
|
if (options.rootUrl) {
|
|
321
330
|
const newRootDocId = documentIdMapping[interpretAsDocumentId(options.rootUrl)] ?? failedInvariant();
|
|
322
|
-
const rootDocHandle = await this._echoHost.loadDoc<DatabaseDirectory>(
|
|
331
|
+
const rootDocHandle = await this._echoHost.loadDoc<DatabaseDirectory>(ctx, newRootDocId);
|
|
323
332
|
DatabaseRoot.mapLinks(rootDocHandle, documentIdMapping);
|
|
324
333
|
|
|
325
|
-
root = await this._echoHost.openSpaceRoot(spaceId, `automerge:${newRootDocId}` as AutomergeUrl);
|
|
334
|
+
root = await this._echoHost.openSpaceRoot(ctx, spaceId, `automerge:${newRootDocId}` as AutomergeUrl);
|
|
326
335
|
} else {
|
|
327
|
-
root = await this._echoHost.createSpaceRoot(spaceKey);
|
|
336
|
+
root = await this._echoHost.createSpaceRoot(ctx, spaceKey);
|
|
328
337
|
}
|
|
329
|
-
await this._echoHost.flush();
|
|
338
|
+
await this._echoHost.flush(ctx);
|
|
330
339
|
|
|
331
340
|
log('constructing space...', { spaceKey });
|
|
332
341
|
|
|
333
|
-
const space = await this._constructSpace(metadata);
|
|
334
|
-
await space.open();
|
|
342
|
+
const space = await this._constructSpace(ctx, metadata);
|
|
343
|
+
await space.open(ctx);
|
|
335
344
|
|
|
336
345
|
log('adding space...', { spaceKey });
|
|
337
346
|
|
|
338
|
-
const credentials = await spaceGenesis(
|
|
347
|
+
const credentials = await spaceGenesis(
|
|
348
|
+
this._keyring,
|
|
349
|
+
this._signingContext,
|
|
350
|
+
space.inner,
|
|
351
|
+
root.url,
|
|
352
|
+
tags,
|
|
353
|
+
options.membershipPolicy,
|
|
354
|
+
);
|
|
339
355
|
await this._metadataStore.addSpace(metadata);
|
|
340
356
|
|
|
341
357
|
const memberCredential = credentials[1];
|
|
342
358
|
invariant(getCredentialAssertion(memberCredential)['@type'] === 'dxos.halo.credentials.SpaceMember');
|
|
343
359
|
await this._signingContext.recordCredential(memberCredential);
|
|
344
360
|
|
|
345
|
-
await space.initializeDataPipeline();
|
|
361
|
+
await space.initializeDataPipeline(ctx);
|
|
346
362
|
|
|
347
363
|
log('space ready.', { spaceId, spaceKey });
|
|
348
364
|
|
|
@@ -350,84 +366,30 @@ export class DataSpaceManager extends Resource {
|
|
|
350
366
|
return space;
|
|
351
367
|
}
|
|
352
368
|
|
|
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
|
-
|
|
369
|
+
/**
|
|
370
|
+
* Accepts an existing space by joining its swarm and initializing the data pipeline.
|
|
371
|
+
* @param ctx - Caller context for cancellation and tracing.
|
|
372
|
+
* @param opts - Space keys and optional timeframes for catch-up.
|
|
373
|
+
*/
|
|
415
374
|
// TODO(burdon): Rename join space.
|
|
416
375
|
@synchronized
|
|
417
|
-
|
|
376
|
+
@trace.span({ showInBrowserTimeline: true })
|
|
377
|
+
async acceptSpace(ctx: Context, opts: AcceptSpaceOptions): Promise<DataSpace> {
|
|
418
378
|
log('accept space', { opts });
|
|
419
379
|
invariant(this._lifecycleState === LifecycleState.OPEN, 'Not open.');
|
|
420
380
|
invariant(!this._spaces.has(opts.spaceKey), 'Space already exists.');
|
|
421
381
|
|
|
382
|
+
const tags = opts.tags ? Array.from(opts.tags) : [];
|
|
422
383
|
const metadata: SpaceMetadata = {
|
|
423
384
|
key: opts.spaceKey,
|
|
424
385
|
genesisFeedKey: opts.genesisFeedKey,
|
|
425
386
|
controlTimeframe: opts.controlTimeframe,
|
|
426
387
|
dataTimeframe: opts.dataTimeframe,
|
|
388
|
+
tags,
|
|
427
389
|
};
|
|
428
390
|
|
|
429
|
-
const space = await this._constructSpace(metadata);
|
|
430
|
-
await space.open();
|
|
391
|
+
const space = await this._constructSpace(ctx, metadata);
|
|
392
|
+
await space.open(ctx);
|
|
431
393
|
await this._metadataStore.addSpace(metadata);
|
|
432
394
|
space.initializeDataPipelineAsync();
|
|
433
395
|
|
|
@@ -453,6 +415,7 @@ export class DataSpaceManager extends Resource {
|
|
|
453
415
|
space.spaceState.membershipChainHeads,
|
|
454
416
|
options.profile,
|
|
455
417
|
options.delegationCredentialId,
|
|
418
|
+
space.spaceState.tags,
|
|
456
419
|
);
|
|
457
420
|
|
|
458
421
|
// TODO(dmaretskyi): Refactor.
|
|
@@ -479,8 +442,8 @@ export class DataSpaceManager extends Resource {
|
|
|
479
442
|
);
|
|
480
443
|
}
|
|
481
444
|
|
|
482
|
-
public async requestSpaceAdmissionCredential(spaceKey: PublicKey): Promise<Credential> {
|
|
483
|
-
return this._spaceManager.requestSpaceAdmissionCredential({
|
|
445
|
+
public async requestSpaceAdmissionCredential(ctx: Context, spaceKey: PublicKey): Promise<Credential> {
|
|
446
|
+
return this._spaceManager.requestSpaceAdmissionCredential(ctx, {
|
|
484
447
|
spaceKey,
|
|
485
448
|
identityKey: this._signingContext.identityKey,
|
|
486
449
|
timeout: 15_000,
|
|
@@ -493,7 +456,11 @@ export class DataSpaceManager extends Resource {
|
|
|
493
456
|
});
|
|
494
457
|
}
|
|
495
458
|
|
|
496
|
-
async setSpaceEdgeReplicationSetting(
|
|
459
|
+
async setSpaceEdgeReplicationSetting(
|
|
460
|
+
ctx: Context,
|
|
461
|
+
spaceKey: PublicKey,
|
|
462
|
+
setting: EdgeReplicationSetting,
|
|
463
|
+
): Promise<void> {
|
|
497
464
|
const space = this._spaces.get(spaceKey);
|
|
498
465
|
invariant(space, 'Space not found.');
|
|
499
466
|
|
|
@@ -505,7 +472,7 @@ export class DataSpaceManager extends Resource {
|
|
|
505
472
|
await this._echoEdgeReplicator?.disconnectFromSpace(space.id);
|
|
506
473
|
break;
|
|
507
474
|
case EdgeReplicationSetting.ENABLED:
|
|
508
|
-
await this._echoEdgeReplicator?.connectToSpace(space.id);
|
|
475
|
+
await this._echoEdgeReplicator?.connectToSpace(ctx, space.id);
|
|
509
476
|
break;
|
|
510
477
|
}
|
|
511
478
|
}
|
|
@@ -513,7 +480,7 @@ export class DataSpaceManager extends Resource {
|
|
|
513
480
|
space.stateUpdate.emit();
|
|
514
481
|
}
|
|
515
482
|
|
|
516
|
-
private async _constructSpace(metadata: SpaceMetadata): Promise<DataSpace> {
|
|
483
|
+
private async _constructSpace(ctx: Context, metadata: SpaceMetadata): Promise<DataSpace> {
|
|
517
484
|
log('construct space', { metadata });
|
|
518
485
|
const gossip = new Gossip({
|
|
519
486
|
localPeerId: this._signingContext.deviceKey,
|
|
@@ -603,6 +570,7 @@ export class DataSpaceManager extends Resource {
|
|
|
603
570
|
},
|
|
604
571
|
},
|
|
605
572
|
cache: metadata.cache,
|
|
573
|
+
tags: metadata.tags,
|
|
606
574
|
edgeConnection: this._edgeConnection,
|
|
607
575
|
edgeHttpClient: this._edgeHttpClient,
|
|
608
576
|
edgeFeatures: this._edgeFeatures,
|
|
@@ -611,7 +579,7 @@ export class DataSpaceManager extends Resource {
|
|
|
611
579
|
dataSpace.postOpen.append(async () => {
|
|
612
580
|
const setting = dataSpace.getEdgeReplicationSetting();
|
|
613
581
|
if (!setting || setting === EdgeReplicationSetting.ENABLED) {
|
|
614
|
-
await this._echoEdgeReplicator?.connectToSpace(dataSpace.id);
|
|
582
|
+
await this._echoEdgeReplicator?.connectToSpace(ctx, dataSpace.id);
|
|
615
583
|
} else if (this._echoEdgeReplicator) {
|
|
616
584
|
log('not connecting EchoEdgeReplicator because of EdgeReplicationSetting', { spaceId: dataSpace.id });
|
|
617
585
|
}
|
|
@@ -708,7 +676,7 @@ export class DataSpaceManager extends Resource {
|
|
|
708
676
|
invitations: Array<[PublicKey, DelegateSpaceInvitation]>,
|
|
709
677
|
): Promise<void> {
|
|
710
678
|
const tasks = invitations.map(([credentialId, invitation]) => {
|
|
711
|
-
return this._invitationsManager.createInvitation({
|
|
679
|
+
return this._invitationsManager.createInvitation(this._ctx, {
|
|
712
680
|
type: Invitation.Type.DELEGATED,
|
|
713
681
|
kind: Invitation.Kind.SPACE,
|
|
714
682
|
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';
|
|
@@ -83,6 +84,7 @@ export type DataSpaceProps = {
|
|
|
83
84
|
signingContext: SigningContext;
|
|
84
85
|
callbacks?: DataSpaceCallbacks;
|
|
85
86
|
cache?: SpaceCache;
|
|
87
|
+
tags?: string[];
|
|
86
88
|
edgeConnection?: EdgeConnection;
|
|
87
89
|
edgeHttpClient?: EdgeHttpClient;
|
|
88
90
|
edgeFeatures?: Runtime.Client.EdgeFeatures;
|
|
@@ -120,6 +122,9 @@ export class DataSpace {
|
|
|
120
122
|
|
|
121
123
|
private _state = SpaceState.SPACE_CLOSED;
|
|
122
124
|
|
|
125
|
+
/** Immutable tags from space metadata, available immediately. */
|
|
126
|
+
readonly tags: string[];
|
|
127
|
+
|
|
123
128
|
private _databaseRoot: DatabaseRoot | null = null;
|
|
124
129
|
|
|
125
130
|
/**
|
|
@@ -167,6 +172,7 @@ export class DataSpace {
|
|
|
167
172
|
});
|
|
168
173
|
|
|
169
174
|
this._cache = params.cache;
|
|
175
|
+
this.tags = params.tags ?? [];
|
|
170
176
|
|
|
171
177
|
if (params.edgeConnection && params.edgeFeatures?.feedReplicator) {
|
|
172
178
|
this._edgeFeedReplicator = new EdgeFeedReplicator({ messenger: params.edgeConnection, spaceId: this.id });
|
|
@@ -212,6 +218,11 @@ export class DataSpace {
|
|
|
212
218
|
return this._cache;
|
|
213
219
|
}
|
|
214
220
|
|
|
221
|
+
/** Membership policy from the genesis credential, defaults to INVITE. */
|
|
222
|
+
get membershipPolicy(): MembershipPolicy {
|
|
223
|
+
return this._inner.spaceState.genesisCredential ? this._inner.spaceState.membershipPolicy : MembershipPolicy.INVITE;
|
|
224
|
+
}
|
|
225
|
+
|
|
215
226
|
get automergeSpaceState() {
|
|
216
227
|
return this._automergeSpaceState;
|
|
217
228
|
}
|
|
@@ -229,13 +240,14 @@ export class DataSpace {
|
|
|
229
240
|
}
|
|
230
241
|
|
|
231
242
|
@synchronized
|
|
232
|
-
|
|
243
|
+
@trace.span({ showInBrowserTimeline: true })
|
|
244
|
+
async open(ctx: Context): Promise<void> {
|
|
233
245
|
if (this._state === SpaceState.SPACE_CLOSED) {
|
|
234
|
-
await this._open();
|
|
246
|
+
await this._open(ctx);
|
|
235
247
|
}
|
|
236
248
|
}
|
|
237
249
|
|
|
238
|
-
private async _open(): Promise<void> {
|
|
250
|
+
private async _open(ctx: Context): Promise<void> {
|
|
239
251
|
await this._presence.open();
|
|
240
252
|
await this._gossip.open();
|
|
241
253
|
await this._notarizationPlugin.open();
|
|
@@ -247,8 +259,8 @@ export class DataSpace {
|
|
|
247
259
|
this.inner.protocol.feedAdded.append(this._onFeedAdded);
|
|
248
260
|
}
|
|
249
261
|
|
|
250
|
-
await this._inner.open(
|
|
251
|
-
await this._inner.startProtocol();
|
|
262
|
+
await this._inner.open(ctx);
|
|
263
|
+
await this._inner.startProtocol(ctx);
|
|
252
264
|
|
|
253
265
|
await this._edgeFeedReplicator?.open();
|
|
254
266
|
|
|
@@ -262,11 +274,12 @@ export class DataSpace {
|
|
|
262
274
|
}
|
|
263
275
|
|
|
264
276
|
@synchronized
|
|
265
|
-
|
|
266
|
-
|
|
277
|
+
@trace.span({ showInBrowserTimeline: true })
|
|
278
|
+
async close(ctx: Context): Promise<void> {
|
|
279
|
+
await this._close(ctx);
|
|
267
280
|
}
|
|
268
281
|
|
|
269
|
-
private async _close(): Promise<void> {
|
|
282
|
+
private async _close(ctx: Context): Promise<void> {
|
|
270
283
|
await this._callbacks.beforeClose?.();
|
|
271
284
|
|
|
272
285
|
await this.preClose.callSerial();
|
|
@@ -284,7 +297,7 @@ export class DataSpace {
|
|
|
284
297
|
|
|
285
298
|
await this.authVerifier.close();
|
|
286
299
|
|
|
287
|
-
await this._inner.close();
|
|
300
|
+
await this._inner.close(ctx);
|
|
288
301
|
await this._inner.spaceState.removeCredentialProcessor(this._automergeSpaceState);
|
|
289
302
|
await this._automergeSpaceState.close();
|
|
290
303
|
await this._inner.spaceState.removeCredentialProcessor(this._notarizationPlugin);
|
|
@@ -309,7 +322,7 @@ export class DataSpace {
|
|
|
309
322
|
scheduleTask(this._ctx, async () => {
|
|
310
323
|
try {
|
|
311
324
|
this.metrics.pipelineInitBegin = new Date();
|
|
312
|
-
await this.initializeDataPipeline();
|
|
325
|
+
await this.initializeDataPipeline(this._ctx);
|
|
313
326
|
} catch (err) {
|
|
314
327
|
if (err instanceof CancelledError || err instanceof ContextDisposedError) {
|
|
315
328
|
log('data pipeline initialization cancelled', err);
|
|
@@ -328,7 +341,7 @@ export class DataSpace {
|
|
|
328
341
|
}
|
|
329
342
|
|
|
330
343
|
@trace.span({ showInBrowserTimeline: true })
|
|
331
|
-
async initializeDataPipeline(): Promise<void> {
|
|
344
|
+
async initializeDataPipeline(ctx: Context): Promise<void> {
|
|
332
345
|
if (this._state !== SpaceState.SPACE_CONTROL_ONLY) {
|
|
333
346
|
throw new SystemError({ message: 'Invalid operation' });
|
|
334
347
|
}
|
|
@@ -337,7 +350,7 @@ export class DataSpace {
|
|
|
337
350
|
log('new state', { state: SpaceState[this._state] });
|
|
338
351
|
|
|
339
352
|
log('initializing control pipeline');
|
|
340
|
-
await this._initializeAndReadControlPipeline();
|
|
353
|
+
await this._initializeAndReadControlPipeline(ctx);
|
|
341
354
|
|
|
342
355
|
// Allow other tasks to run before loading the data pipeline.
|
|
343
356
|
await sleep(1);
|
|
@@ -360,11 +373,19 @@ export class DataSpace {
|
|
|
360
373
|
yield [this._databaseRoot.documentId, root];
|
|
361
374
|
|
|
362
375
|
for (const documentUrl of this._databaseRoot.getAllLinkedDocuments()) {
|
|
363
|
-
const data = await this._echoHost.exportDoc(
|
|
376
|
+
const data = await this._echoHost.exportDoc(documentUrl);
|
|
364
377
|
yield [documentUrl.replace(/^automerge:/, ''), data];
|
|
365
378
|
}
|
|
366
379
|
}
|
|
367
380
|
|
|
381
|
+
/**
|
|
382
|
+
* Get all feeds and their blocks for this space.
|
|
383
|
+
* Used for space archive export.
|
|
384
|
+
*/
|
|
385
|
+
async getAllFeeds(): Promise<Array<{ feedId: string; feedNamespace: string; blocks: FeedProtocol.Block[] }>> {
|
|
386
|
+
return this._echoHost.getAllFeedsForSpace(this.id);
|
|
387
|
+
}
|
|
388
|
+
|
|
368
389
|
private async _enterReadyState(): Promise<void> {
|
|
369
390
|
await this._callbacks.beforeReady?.();
|
|
370
391
|
|
|
@@ -376,9 +397,9 @@ export class DataSpace {
|
|
|
376
397
|
}
|
|
377
398
|
|
|
378
399
|
@trace.span({ showInBrowserTimeline: true })
|
|
379
|
-
private async _initializeAndReadControlPipeline(): Promise<void> {
|
|
400
|
+
private async _initializeAndReadControlPipeline(ctx: Context): Promise<void> {
|
|
380
401
|
await this._inner.controlPipeline.state.waitUntilReachedTargetTimeframe({
|
|
381
|
-
ctx
|
|
402
|
+
ctx,
|
|
382
403
|
timeout: 10_000,
|
|
383
404
|
breakOnStall: false,
|
|
384
405
|
});
|
|
@@ -450,6 +471,9 @@ export class DataSpace {
|
|
|
450
471
|
|
|
451
472
|
log('credentials notarized');
|
|
452
473
|
} catch (err) {
|
|
474
|
+
if (err instanceof ContextDisposedError) {
|
|
475
|
+
return;
|
|
476
|
+
}
|
|
453
477
|
log.error('error notarizing credentials for feed admission', err);
|
|
454
478
|
throw err;
|
|
455
479
|
}
|
|
@@ -470,7 +494,7 @@ export class DataSpace {
|
|
|
470
494
|
await warnAfterTimeout(5_000, 'Automerge root doc load timeout (DataSpace)', async () => {
|
|
471
495
|
handle = await cancelWithContext(
|
|
472
496
|
this._ctx,
|
|
473
|
-
this._echoHost.loadDoc<DatabaseDirectory>(
|
|
497
|
+
this._echoHost.loadDoc<DatabaseDirectory>(this._ctx, rootUrl as AutomergeUrl, {
|
|
474
498
|
fetchFromNetwork: true,
|
|
475
499
|
}),
|
|
476
500
|
);
|
|
@@ -493,7 +517,7 @@ export class DataSpace {
|
|
|
493
517
|
|
|
494
518
|
// TODO(dmaretskyi): Close roots.
|
|
495
519
|
// TODO(dmaretskyi): How do we handle changing to the next EPOCH?
|
|
496
|
-
const root = await this._echoHost.openSpaceRoot(this.id, handle.url);
|
|
520
|
+
const root = await this._echoHost.openSpaceRoot(this._ctx, this.id, handle.url);
|
|
497
521
|
|
|
498
522
|
// NOTE: Make sure this assignment happens synchronously together with the state change.
|
|
499
523
|
this._databaseRoot = root;
|
|
@@ -570,25 +594,24 @@ export class DataSpace {
|
|
|
570
594
|
}
|
|
571
595
|
|
|
572
596
|
@synchronized
|
|
573
|
-
async activate(): Promise<void> {
|
|
597
|
+
async activate(ctx: Context): Promise<void> {
|
|
574
598
|
if (![SpaceState.SPACE_CLOSED, SpaceState.SPACE_INACTIVE].includes(this._state)) {
|
|
575
599
|
return;
|
|
576
600
|
}
|
|
577
601
|
|
|
578
602
|
await this._metadataStore.setSpaceState(this.key, SpaceState.SPACE_ACTIVE);
|
|
579
|
-
await this._open();
|
|
603
|
+
await this._open(ctx);
|
|
580
604
|
this.initializeDataPipelineAsync();
|
|
581
605
|
}
|
|
582
606
|
|
|
583
607
|
@synchronized
|
|
584
|
-
async deactivate(): Promise<void> {
|
|
608
|
+
async deactivate(ctx: Context): Promise<void> {
|
|
585
609
|
if (this._state === SpaceState.SPACE_INACTIVE) {
|
|
586
610
|
return;
|
|
587
611
|
}
|
|
588
|
-
// Unregister from data service.
|
|
589
612
|
await this._metadataStore.setSpaceState(this.key, SpaceState.SPACE_INACTIVE);
|
|
590
613
|
if (this._state !== SpaceState.SPACE_CLOSED) {
|
|
591
|
-
await this._close();
|
|
614
|
+
await this._close(ctx);
|
|
592
615
|
}
|
|
593
616
|
this._state = SpaceState.SPACE_INACTIVE;
|
|
594
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
|
});
|
|
@@ -132,7 +132,7 @@ export class EdgeFeedReplicator extends Resource {
|
|
|
132
132
|
|
|
133
133
|
private async _replicateFeed(ctx: Context, feed: FeedWrapper<any>): Promise<void> {
|
|
134
134
|
log('replicateFeed', { key: feed.key });
|
|
135
|
-
await this._sendMessage({
|
|
135
|
+
await this._sendMessage(ctx, {
|
|
136
136
|
type: 'get-metadata',
|
|
137
137
|
feedKey: feed.key.toHex(),
|
|
138
138
|
});
|
|
@@ -142,7 +142,7 @@ export class EdgeFeedReplicator extends Resource {
|
|
|
142
142
|
});
|
|
143
143
|
}
|
|
144
144
|
|
|
145
|
-
private async _sendMessage(message: ProtocolMessage): Promise<void> {
|
|
145
|
+
private async _sendMessage(ctx: Context, message: ProtocolMessage): Promise<void> {
|
|
146
146
|
if (!this._connectionCtx) {
|
|
147
147
|
log('message dropped because connection was disposed');
|
|
148
148
|
return;
|
|
@@ -160,6 +160,7 @@ export class EdgeFeedReplicator extends Resource {
|
|
|
160
160
|
|
|
161
161
|
log('send', { type: message.type });
|
|
162
162
|
await this._messenger.send(
|
|
163
|
+
ctx,
|
|
163
164
|
buf.create(RouterMessageSchema, {
|
|
164
165
|
source: {
|
|
165
166
|
identityKey: this._messenger.identityKey,
|
|
@@ -194,7 +195,7 @@ export class EdgeFeedReplicator extends Resource {
|
|
|
194
195
|
if (message.length > feed.length) {
|
|
195
196
|
log('requesting missing blocks', logMeta);
|
|
196
197
|
|
|
197
|
-
await this._sendMessage({
|
|
198
|
+
await this._sendMessage(this._connectionCtx!, {
|
|
198
199
|
type: 'request',
|
|
199
200
|
feedKey: feedKey.toHex(),
|
|
200
201
|
range: { from: feed.length, to: message.length },
|
|
@@ -202,7 +203,7 @@ export class EdgeFeedReplicator extends Resource {
|
|
|
202
203
|
} else if (message.length < feed.length) {
|
|
203
204
|
log('pushing blocks to remote', logMeta);
|
|
204
205
|
|
|
205
|
-
await this._pushBlocks(feed, message.length, feed.length);
|
|
206
|
+
await this._pushBlocks(this._connectionCtx!, feed, message.length, feed.length);
|
|
206
207
|
}
|
|
207
208
|
|
|
208
209
|
break;
|
|
@@ -229,7 +230,7 @@ export class EdgeFeedReplicator extends Resource {
|
|
|
229
230
|
});
|
|
230
231
|
}
|
|
231
232
|
|
|
232
|
-
private async _pushBlocks(feed: FeedWrapper<any>, from: number, to: number): Promise<void> {
|
|
233
|
+
private async _pushBlocks(ctx: Context, feed: FeedWrapper<any>, from: number, to: number): Promise<void> {
|
|
233
234
|
log('pushing blocks', { feed: feed.key.toHex(), from, to });
|
|
234
235
|
|
|
235
236
|
const blocks: FeedBlock[] = await Promise.all(
|
|
@@ -247,7 +248,7 @@ export class EdgeFeedReplicator extends Resource {
|
|
|
247
248
|
}),
|
|
248
249
|
);
|
|
249
250
|
|
|
250
|
-
await this._sendMessage({
|
|
251
|
+
await this._sendMessage(ctx, {
|
|
251
252
|
type: 'data',
|
|
252
253
|
feedKey: feed.key.toHex(),
|
|
253
254
|
blocks,
|
|
@@ -283,7 +284,7 @@ export class EdgeFeedReplicator extends Resource {
|
|
|
283
284
|
|
|
284
285
|
const remoteLength = this._remoteLength.get(feed.key)!;
|
|
285
286
|
if (remoteLength < feed.length) {
|
|
286
|
-
await this._pushBlocks(feed, remoteLength, feed.length);
|
|
287
|
+
await this._pushBlocks(this._connectionCtx!, feed, remoteLength, feed.length);
|
|
287
288
|
}
|
|
288
289
|
}
|
|
289
290
|
|