@dxos/client-services 0.1.56-main.5ff23aa → 0.1.56-main.6293c6e

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/dist/lib/browser/{chunk-MM7EFAUT.mjs → chunk-BD23GURE.mjs} +428 -366
  2. package/dist/lib/browser/chunk-BD23GURE.mjs.map +7 -0
  3. package/dist/lib/browser/index.mjs +20 -23
  4. package/dist/lib/browser/index.mjs.map +3 -3
  5. package/dist/lib/browser/meta.json +1 -1
  6. package/dist/lib/browser/packlets/testing/index.mjs +31 -46
  7. package/dist/lib/browser/packlets/testing/index.mjs.map +3 -3
  8. package/dist/lib/node/index.cjs +443 -384
  9. package/dist/lib/node/index.cjs.map +3 -3
  10. package/dist/lib/node/meta.json +1 -1
  11. package/dist/lib/node/packlets/testing/index.cjs +443 -392
  12. package/dist/lib/node/packlets/testing/index.cjs.map +3 -3
  13. package/dist/types/src/packlets/identity/identity-manager.d.ts +7 -1
  14. package/dist/types/src/packlets/identity/identity-manager.d.ts.map +1 -1
  15. package/dist/types/src/packlets/identity/identity-service.d.ts +7 -3
  16. package/dist/types/src/packlets/identity/identity-service.d.ts.map +1 -1
  17. package/dist/types/src/packlets/identity/identity.d.ts +3 -2
  18. package/dist/types/src/packlets/identity/identity.d.ts.map +1 -1
  19. package/dist/types/src/packlets/services/client-rpc-server.d.ts.map +1 -1
  20. package/dist/types/src/packlets/services/service-context.d.ts +2 -1
  21. package/dist/types/src/packlets/services/service-context.d.ts.map +1 -1
  22. package/dist/types/src/packlets/services/service-host.d.ts +3 -1
  23. package/dist/types/src/packlets/services/service-host.d.ts.map +1 -1
  24. package/dist/types/src/packlets/spaces/data-space.d.ts.map +1 -1
  25. package/dist/types/src/packlets/vault/iframe-host-runtime.d.ts.map +1 -1
  26. package/dist/types/src/packlets/vault/worker-runtime.d.ts.map +1 -1
  27. package/dist/types/src/version.d.ts +1 -1
  28. package/package.json +34 -33
  29. package/src/packlets/devices/devices-service.test.ts +2 -1
  30. package/src/packlets/identity/identity-manager.test.ts +15 -3
  31. package/src/packlets/identity/identity-manager.ts +27 -6
  32. package/src/packlets/identity/identity-service.test.ts +17 -2
  33. package/src/packlets/identity/identity-service.ts +23 -14
  34. package/src/packlets/identity/identity.test.ts +7 -6
  35. package/src/packlets/identity/identity.ts +8 -3
  36. package/src/packlets/invitations/device-invitation-protocol.test.ts +2 -1
  37. package/src/packlets/network/network-service.test.ts +2 -1
  38. package/src/packlets/services/client-rpc-server.ts +4 -4
  39. package/src/packlets/services/service-context.test.ts +59 -0
  40. package/src/packlets/services/service-context.ts +14 -6
  41. package/src/packlets/services/service-host.test.ts +6 -5
  42. package/src/packlets/services/service-host.ts +26 -10
  43. package/src/packlets/services/service-registry.test.ts +2 -1
  44. package/src/packlets/spaces/data-space.ts +17 -5
  45. package/src/packlets/spaces/spaces-service.test.ts +2 -1
  46. package/src/packlets/testing/test-builder.ts +1 -1
  47. package/src/packlets/vault/iframe-host-runtime.ts +2 -1
  48. package/src/packlets/vault/worker-runtime.ts +2 -1
  49. package/src/version.ts +1 -1
  50. package/dist/lib/browser/chunk-MM7EFAUT.mjs.map +0 -7
@@ -4,6 +4,7 @@
4
4
 
5
5
  import { Event } from '@dxos/async';
6
6
  import { AUTH_TIMEOUT, LOAD_CONTROL_FEEDS_TIMEOUT } from '@dxos/client-protocol';
7
+ import { Context } from '@dxos/context';
7
8
  import {
8
9
  DeviceStateMachine,
9
10
  CredentialSigner,
@@ -21,6 +22,7 @@ import { log } from '@dxos/log';
21
22
  import { FeedMessage } from '@dxos/protocols/proto/dxos/echo/feed';
22
23
  import { AdmittedFeed, ProfileDocument } from '@dxos/protocols/proto/dxos/halo/credentials';
23
24
  import { DeviceAdmissionRequest } from '@dxos/protocols/proto/dxos/halo/invitations';
25
+ import { trace } from '@dxos/tracing';
24
26
  import { ComplexSet } from '@dxos/util';
25
27
 
26
28
  import { TrustedKeySetAuthVerifier } from './authenticator';
@@ -35,6 +37,7 @@ export type IdentityParams = {
35
37
  /**
36
38
  * Agent identity manager, which includes the agent's Halo space.
37
39
  */
40
+ @trace.resource()
38
41
  export class Identity {
39
42
  public readonly space: Space;
40
43
  private readonly _signer: Signer;
@@ -76,13 +79,15 @@ export class Identity {
76
79
  return this._deviceStateMachine.authorizedDeviceKeys;
77
80
  }
78
81
 
79
- async open() {
82
+ @trace.span()
83
+ async open(ctx: Context) {
80
84
  await this.space.spaceState.addCredentialProcessor(this._deviceStateMachine);
81
85
  await this.space.spaceState.addCredentialProcessor(this._profileStateMachine);
82
- await this.space.open();
86
+ await this.space.open(ctx);
83
87
  }
84
88
 
85
- async close() {
89
+ @trace.span()
90
+ async close(ctx: Context) {
86
91
  await this.authVerifier.close();
87
92
  await this.space.spaceState.removeCredentialProcessor(this._profileStateMachine);
88
93
  await this.space.spaceState.removeCredentialProcessor(this._deviceStateMachine);
@@ -5,6 +5,7 @@
5
5
  import { expect } from 'chai';
6
6
 
7
7
  import { asyncChain } from '@dxos/async';
8
+ import { Context } from '@dxos/context';
8
9
  import { Invitation } from '@dxos/protocols/proto/dxos/client/services';
9
10
  import { describe, test, afterTest } from '@dxos/test';
10
11
 
@@ -19,7 +20,7 @@ const closeAfterTest = async (peer: ServiceContext) => {
19
20
  describe('services/device', () => {
20
21
  test('creates identity', async () => {
21
22
  const peer = createServiceContext();
22
- await peer.open();
23
+ await peer.open(new Context());
23
24
  afterTest(() => peer.close());
24
25
 
25
26
  const identity = await peer.createIdentity();
@@ -5,6 +5,7 @@
5
5
  import { expect } from 'chai';
6
6
 
7
7
  import { Trigger } from '@dxos/async';
8
+ import { Context } from '@dxos/context';
8
9
  import { NetworkService, ConnectionState } from '@dxos/protocols/proto/dxos/client/services';
9
10
  import { afterEach, afterTest, beforeEach, describe, test } from '@dxos/test';
10
11
 
@@ -18,7 +19,7 @@ describe('NetworkService', () => {
18
19
 
19
20
  beforeEach(async () => {
20
21
  serviceContext = createServiceContext();
21
- await serviceContext.open();
22
+ await serviceContext.open(new Context());
22
23
  networkService = new NetworkServiceImpl(serviceContext.networkManager, serviceContext.signalManager);
23
24
  });
24
25
 
@@ -5,7 +5,7 @@
5
5
  import { ClientServices } from '@dxos/client-protocol';
6
6
  import { Any, ServiceHandler, Stream } from '@dxos/codec-protobuf';
7
7
  import { raise } from '@dxos/debug';
8
- import { parseMethodName, RpcPeer, RpcPeerOptions } from '@dxos/rpc';
8
+ import { parseMethodName, RpcPeer, RpcPeerOptions, ServiceBundle } from '@dxos/rpc';
9
9
  import { MaybePromise } from '@dxos/util';
10
10
 
11
11
  import { ServiceRegistry } from './service-registry';
@@ -74,16 +74,16 @@ export class ClientRpcServer {
74
74
  private _getServiceHandler(serviceName: string) {
75
75
  if (!this._handlerCache.has(serviceName)) {
76
76
  const [key, descriptor] =
77
- Object.entries(this._serviceRegistry.descriptors).find(
77
+ Object.entries(this._serviceRegistry.descriptors as ServiceBundle<Record<string, any>>).find(
78
78
  ([key, descriptor]) => descriptor.name === serviceName,
79
79
  ) ?? raise(new Error(`Service not available: ${serviceName}`));
80
80
 
81
- const service = this._serviceRegistry.services[key as keyof ClientServices];
81
+ const service = this._serviceRegistry.services[key as keyof ClientServices] as any;
82
82
  if (!service) {
83
83
  throw new Error(`Service not available: ${serviceName}`);
84
84
  }
85
85
 
86
- this._handlerCache.set(serviceName, descriptor.createServer(service as any));
86
+ this._handlerCache.set(serviceName, descriptor.createServer(service));
87
87
  }
88
88
 
89
89
  return this._handlerCache.get(serviceName)!;
@@ -2,9 +2,18 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
+ import { expect } from 'chai';
6
+
7
+ import { DocumentModel, DocumentModelState, MutationBuilder } from '@dxos/document-model';
8
+ import { createModelMutation, encodeModelMutation, genesisMutation } from '@dxos/echo-db';
9
+ import { WriteReceipt } from '@dxos/feed-store';
10
+ import { PublicKey } from '@dxos/keys';
11
+ import { log } from '@dxos/log';
5
12
  import { MemorySignalManagerContext } from '@dxos/messaging';
6
13
  import { Invitation } from '@dxos/protocols/proto/dxos/client/services';
7
14
  import { describe, test } from '@dxos/test';
15
+ import { Timeframe } from '@dxos/timeframe';
16
+ import { range } from '@dxos/util';
8
17
 
9
18
  import { createServiceContext, syncItemsLocal } from '../testing';
10
19
  import { performInvitation } from '../testing/invitation-utils';
@@ -16,11 +25,61 @@ describe('services/ServiceContext', () => {
16
25
  await device1.createIdentity();
17
26
  const space1 = await device1.dataSpaceManager!.createSpace();
18
27
 
28
+ const itemId = PublicKey.random().toHex();
29
+ await space1.dataPipeline.databaseHost!.getWriteStream()?.write({
30
+ batch: genesisMutation(itemId, DocumentModel.meta.type),
31
+ });
32
+
33
+ let counter = 0;
34
+
35
+ for (const _ in range(5)) {
36
+ const receipts: WriteReceipt[] = [];
37
+ for (const _ in range(50)) {
38
+ receipts.push(
39
+ await space1.dataPipeline.databaseHost!.getWriteStream()!.write({
40
+ batch: createModelMutation(
41
+ itemId,
42
+ encodeModelMutation(DocumentModel.meta, new MutationBuilder().set('counter', ++counter).build()),
43
+ ),
44
+ }),
45
+ );
46
+ }
47
+
48
+ await space1.dataPipeline.pipelineState!.waitUntilTimeframe(
49
+ Timeframe.merge(...receipts.map((receipt) => new Timeframe([[receipt.feedKey, receipt.seq]]))),
50
+ );
51
+
52
+ await space1.createEpoch();
53
+ log.info('epoch', { number: space1.dataPipeline.currentEpoch?.subject.assertion.number });
54
+ }
55
+
19
56
  const device2 = createServiceContext({ signalContext: networkContext });
20
57
  await Promise.all(performInvitation({ host: device1, guest: device2, options: { kind: Invitation.Kind.DEVICE } }));
21
58
 
22
59
  await device2.dataSpaceManager!.waitUntilSpaceReady(space1!.key);
23
60
  const space2 = await device2.dataSpaceManager!.spaces.get(space1.key);
61
+
62
+ log.info('peer 2', {
63
+ currentEpoch: space2!.dataPipeline.currentEpoch?.subject.assertion.number,
64
+ appliedEpoch: space2!.dataPipeline.appliedEpoch?.subject.assertion.number,
65
+ });
66
+
67
+ await space2?.dataPipeline.onNewEpoch.waitForCondition(
68
+ () =>
69
+ space2!.dataPipeline.appliedEpoch?.subject.assertion.number ===
70
+ space1.dataPipeline.currentEpoch?.subject.assertion.number,
71
+ );
72
+
73
+ expect(space2!.dataPipeline.currentEpoch!.subject.assertion.number).to.equal(
74
+ space1.dataPipeline.currentEpoch!.subject.assertion.number,
75
+ );
76
+ expect(space2!.dataPipeline.appliedEpoch!.subject.assertion.number).to.equal(
77
+ space1.dataPipeline.appliedEpoch!.subject.assertion.number,
78
+ );
79
+
80
+ const item2 = space2!.dataPipeline.itemManager.entities.get(itemId);
81
+ expect((item2!.state as DocumentModelState).data.counter).to.equal(counter);
82
+
24
83
  await syncItemsLocal(space1.dataPipeline, space2!.dataPipeline);
25
84
  });
26
85
 
@@ -3,6 +3,7 @@
3
3
  //
4
4
 
5
5
  import { Trigger } from '@dxos/async';
6
+ import { Context } from '@dxos/context';
6
7
  import { CredentialProcessor, getCredentialAssertion } from '@dxos/credentials';
7
8
  import { failUndefined } from '@dxos/debug';
8
9
  import {
@@ -26,6 +27,8 @@ import type { FeedMessage } from '@dxos/protocols/proto/dxos/echo/feed';
26
27
  import { Credential } from '@dxos/protocols/proto/dxos/halo/credentials';
27
28
  import { Storage } from '@dxos/random-access-storage';
28
29
  import { BlobStore } from '@dxos/teleport-extension-object-sync';
30
+ import { trace as Trace } from '@dxos/tracing';
31
+ import { safeInstanceof } from '@dxos/util';
29
32
 
30
33
  import { CreateIdentityOptions, IdentityManager, JoinIdentityParams } from '../identity';
31
34
  import {
@@ -40,6 +43,9 @@ import { DataSpaceManager, SigningContext } from '../spaces';
40
43
  * Shared backend for all client services.
41
44
  */
42
45
  // TODO(burdon): Rename/break-up into smaller components. And/or make members private.
46
+ // TODO(dmaretskyi): Gets duplicated in CJS build between normal and testing bundles.
47
+ @safeInstanceof('dxos.client-services.ServiceContext')
48
+ @Trace.resource()
43
49
  export class ServiceContext {
44
50
  public readonly initialized = new Trigger();
45
51
  public readonly dataServiceSubscriptions = new DataServiceSubscriptions();
@@ -121,7 +127,8 @@ export class ServiceContext {
121
127
  );
122
128
  }
123
129
 
124
- async open() {
130
+ @Trace.span()
131
+ async open(ctx: Context) {
125
132
  await this._checkStorageVersion();
126
133
 
127
134
  log('opening...');
@@ -129,9 +136,9 @@ export class ServiceContext {
129
136
  await this.signalManager.open();
130
137
  await this.networkManager.open();
131
138
  await this.spaceManager.open();
132
- await this.identityManager.open();
139
+ await this.identityManager.open(ctx);
133
140
  if (this.identityManager.identity) {
134
- await this._initialize();
141
+ await this._initialize(ctx);
135
142
  }
136
143
  log.trace('dxos.sdk.service-context.open', trace.end({ id: this._instanceId }));
137
144
  log('opened');
@@ -155,7 +162,7 @@ export class ServiceContext {
155
162
  async createIdentity(params: CreateIdentityOptions = {}) {
156
163
  const identity = await this.identityManager.createIdentity(params);
157
164
 
158
- await this._initialize();
165
+ await this._initialize(new Context());
159
166
  return identity;
160
167
  }
161
168
 
@@ -168,7 +175,7 @@ export class ServiceContext {
168
175
  private async _acceptIdentity(params: JoinIdentityParams) {
169
176
  const identity = await this.identityManager.acceptIdentity(params);
170
177
 
171
- await this._initialize();
178
+ await this._initialize(new Context());
172
179
  return identity;
173
180
  }
174
181
 
@@ -181,7 +188,8 @@ export class ServiceContext {
181
188
  }
182
189
 
183
190
  // Called when identity is created.
184
- private async _initialize() {
191
+ @Trace.span()
192
+ private async _initialize(ctx: Context) {
185
193
  log('initializing spaces...');
186
194
  const identity = this.identityManager.identity ?? failUndefined();
187
195
  const signingContext: SigningContext = {
@@ -8,6 +8,7 @@ import { rmSync } from 'node:fs';
8
8
 
9
9
  import { asyncTimeout, latch, Trigger } from '@dxos/async';
10
10
  import { Config } from '@dxos/config';
11
+ import { Context } from '@dxos/context';
11
12
  import { verifyPresentation } from '@dxos/credentials';
12
13
  import { PublicKey } from '@dxos/keys';
13
14
  import { MemorySignalManagerContext } from '@dxos/messaging';
@@ -30,7 +31,7 @@ describe('ClientServicesHost', () => {
30
31
 
31
32
  test('queryCredentials', async () => {
32
33
  const host = createServiceHost(new Config(), new MemorySignalManagerContext());
33
- await host.open();
34
+ await host.open(new Context());
34
35
  afterTest(() => host.close());
35
36
 
36
37
  await host.services.IdentityService!.createIdentity({});
@@ -49,7 +50,7 @@ describe('ClientServicesHost', () => {
49
50
 
50
51
  test('write and query credentials', async () => {
51
52
  const host = createServiceHost(new Config(), new MemorySignalManagerContext());
52
- await host.open();
53
+ await host.open(new Context());
53
54
  afterTest(() => host.close());
54
55
 
55
56
  await host.services.IdentityService!.createIdentity({});
@@ -86,7 +87,7 @@ describe('ClientServicesHost', () => {
86
87
 
87
88
  test('sign presentation', async () => {
88
89
  const host = createServiceHost(new Config(), new MemorySignalManagerContext());
89
- await host.open();
90
+ await host.open(new Context());
90
91
  afterTest(() => host.close());
91
92
 
92
93
  await host.services.IdentityService!.createIdentity({});
@@ -117,7 +118,7 @@ describe('ClientServicesHost', () => {
117
118
  });
118
119
  {
119
120
  const host = createServiceHost(config, new MemorySignalManagerContext());
120
- await host.open();
121
+ await host.open(new Context());
121
122
 
122
123
  await host.services.IdentityService?.createIdentity({});
123
124
 
@@ -129,7 +130,7 @@ describe('ClientServicesHost', () => {
129
130
 
130
131
  {
131
132
  const host = createServiceHost(config, new MemorySignalManagerContext());
132
- await host.open();
133
+ await host.open(new Context());
133
134
  const trigger = new Trigger<Identity>();
134
135
 
135
136
  const stream = host.services.IdentityService?.queryIdentity();
@@ -5,6 +5,7 @@
5
5
  import { Event, synchronized } from '@dxos/async';
6
6
  import { clientServiceBundle, ClientServices } from '@dxos/client-protocol';
7
7
  import { Config } from '@dxos/config';
8
+ import { Context } from '@dxos/context';
8
9
  import { DocumentModel } from '@dxos/document-model';
9
10
  import { DataServiceImpl } from '@dxos/echo-pipeline';
10
11
  import { invariant } from '@dxos/invariant';
@@ -17,6 +18,7 @@ import { trace } from '@dxos/protocols';
17
18
  import { SystemStatus } from '@dxos/protocols/proto/dxos/client/services';
18
19
  import { Storage } from '@dxos/random-access-storage';
19
20
  import { TextModel } from '@dxos/text-model';
21
+ import { TRACE_PROCESSOR, trace as Trace } from '@dxos/tracing';
20
22
 
21
23
  import { DevicesServiceImpl } from '../devices';
22
24
  import { DevtoolsServiceImpl, DevtoolsHostEvents } from '../devtools';
@@ -65,11 +67,13 @@ export type InitializeOptions = {
65
67
  /**
66
68
  * Remote service implementation.
67
69
  */
70
+ @Trace.resource()
68
71
  export class ClientServicesHost {
69
72
  private readonly _resourceLock?: ResourceLock;
70
73
  private readonly _serviceRegistry: ServiceRegistry<ClientServices>;
71
74
  private readonly _systemService: SystemServiceImpl;
72
75
  private readonly _loggingService: LoggingServiceImpl;
76
+ private readonly _tracingService = TRACE_PROCESSOR.createTraceSender();
73
77
 
74
78
  private _config?: Config;
75
79
  private readonly _statusUpdate = new Event<void>();
@@ -80,7 +84,11 @@ export class ClientServicesHost {
80
84
  private _callbacks?: ClientServicesHostCallbacks;
81
85
 
82
86
  private _serviceContext!: ServiceContext;
87
+
88
+ @Trace.info()
83
89
  private _opening = false;
90
+
91
+ @Trace.info()
84
92
  private _open = false;
85
93
 
86
94
  constructor({
@@ -106,7 +114,7 @@ export class ClientServicesHost {
106
114
  lockKey,
107
115
  onAcquire: () => {
108
116
  if (!this._opening) {
109
- void this.open();
117
+ void this.open(new Context());
110
118
  }
111
119
  },
112
120
  onRelease: () => this.close(),
@@ -136,6 +144,7 @@ export class ClientServicesHost {
136
144
 
137
145
  this._serviceRegistry = new ServiceRegistry<ClientServices>(clientServiceBundle, {
138
146
  SystemService: this._systemService,
147
+ TracingService: this._tracingService,
139
148
  });
140
149
  }
141
150
 
@@ -170,7 +179,7 @@ export class ClientServicesHost {
170
179
  */
171
180
  initialize({ config, ...options }: InitializeOptions) {
172
181
  invariant(!this._open, 'service host is open');
173
- log.info('initializing...');
182
+ log('initializing...');
174
183
 
175
184
  if (config) {
176
185
  invariant(!this._config, 'config already set');
@@ -196,11 +205,12 @@ export class ClientServicesHost {
196
205
  signalManager,
197
206
  });
198
207
 
199
- log.info('initialized');
208
+ log('initialized');
200
209
  }
201
210
 
202
211
  @synchronized
203
- async open() {
212
+ @Trace.span()
213
+ async open(ctx: Context) {
204
214
  if (this._open) {
205
215
  return;
206
216
  }
@@ -214,7 +224,7 @@ export class ClientServicesHost {
214
224
  invariant(this._networkManager, 'network manager not set');
215
225
 
216
226
  this._opening = true;
217
- log.info('opening...', { lockKey: this._resourceLock?.lockKey });
227
+ log('opening...', { lockKey: this._resourceLock?.lockKey });
218
228
  await this._resourceLock?.acquire();
219
229
 
220
230
  await this._loggingService.open();
@@ -229,7 +239,11 @@ export class ClientServicesHost {
229
239
  this._serviceRegistry.setServices({
230
240
  SystemService: this._systemService,
231
241
 
232
- IdentityService: new IdentityServiceImpl(this._serviceContext),
242
+ IdentityService: new IdentityServiceImpl(
243
+ (params) => this._serviceContext.createIdentity(params),
244
+ this._serviceContext.identityManager,
245
+ this._serviceContext.keyring,
246
+ ),
233
247
 
234
248
  InvitationsService: new InvitationsServiceImpl(this._serviceContext.invitations, (invitation) =>
235
249
  this._serviceContext.getInvitationHandler(invitation),
@@ -252,6 +266,7 @@ export class ClientServicesHost {
252
266
  NetworkService: new NetworkServiceImpl(this._serviceContext.networkManager, this._serviceContext.signalManager),
253
267
 
254
268
  LoggingService: this._loggingService,
269
+ TracingService: this._tracingService,
255
270
 
256
271
  // TODO(burdon): Move to new protobuf definitions.
257
272
  DevtoolsHost: new DevtoolsServiceImpl({
@@ -261,29 +276,30 @@ export class ClientServicesHost {
261
276
  }),
262
277
  });
263
278
 
264
- await this._serviceContext.open();
279
+ await this._serviceContext.open(ctx);
265
280
  this._opening = false;
266
281
  this._open = true;
267
282
  this._statusUpdate.emit();
268
283
  const deviceKey = this._serviceContext.identityManager.identity?.deviceKey;
269
- log.info('opened', { deviceKey });
284
+ log('opened', { deviceKey });
270
285
  log.trace('dxos.client-services.host.open', trace.end({ id: traceId }));
271
286
  }
272
287
 
273
288
  @synchronized
289
+ @Trace.span()
274
290
  async close() {
275
291
  if (!this._open) {
276
292
  return;
277
293
  }
278
294
 
279
295
  const deviceKey = this._serviceContext.identityManager.identity?.deviceKey;
280
- log.info('closing...', { deviceKey });
296
+ log('closing...', { deviceKey });
281
297
  this._serviceRegistry.setServices({ SystemService: this._systemService });
282
298
  await this._loggingService.close();
283
299
  await this._serviceContext.close();
284
300
  this._open = false;
285
301
  this._statusUpdate.emit();
286
- log.info('closed', { deviceKey });
302
+ log('closed', { deviceKey });
287
303
  }
288
304
 
289
305
  async reset() {
@@ -7,6 +7,7 @@ import { expect } from 'chai';
7
7
  import { Event } from '@dxos/async';
8
8
  import { ClientServices } from '@dxos/client-protocol';
9
9
  import { Config } from '@dxos/config';
10
+ import { Context } from '@dxos/context';
10
11
  import { log } from '@dxos/log';
11
12
  import { schema } from '@dxos/protocols';
12
13
  import { SystemService, SystemStatus } from '@dxos/protocols/proto/dxos/client/services';
@@ -31,7 +32,7 @@ describe('service registry', () => {
31
32
  test('builds a service registry', async () => {
32
33
  const remoteSource = 'https://remote.source';
33
34
  const serviceContext = createServiceContext();
34
- await serviceContext.open();
35
+ await serviceContext.open(new Context());
35
36
 
36
37
  const serviceRegistry = new ServiceRegistry(serviceBundle, {
37
38
  SystemService: new SystemServiceImpl({
@@ -55,6 +55,12 @@ export type DataSpaceParams = {
55
55
  cache?: SpaceCache;
56
56
  };
57
57
 
58
+ /**
59
+ * Delete feed blocks after an epoch is created.
60
+ */
61
+ // TODO(dmaretskyi): Disabled till better times https://github.com/dxos/dxos/issues/3949.
62
+ const ENABLE_FEED_PURGE = false;
63
+
58
64
  @trackLeaks('open', 'close')
59
65
  export class DataSpace {
60
66
  private _ctx = new Context();
@@ -145,7 +151,7 @@ export class DataSpace {
145
151
  private async _open() {
146
152
  await this._notarizationPlugin.open();
147
153
  await this._inner.spaceState.addCredentialProcessor(this._notarizationPlugin);
148
- await this._inner.open();
154
+ await this._inner.open(new Context());
149
155
  this._state = SpaceState.CONTROL_ONLY;
150
156
  this.stateUpdate.emit();
151
157
  this.metrics = {};
@@ -323,10 +329,16 @@ export class DataSpace {
323
329
  });
324
330
 
325
331
  await this.inner.controlPipeline.state.waitUntilTimeframe(new Timeframe([[receipt.feedKey, receipt.seq]]));
326
- for (const feed of this.inner.dataPipeline.pipelineState?.feeds ?? []) {
327
- const indexBeforeEpoch = epoch.timeframe.get(feed.key);
328
- if (indexBeforeEpoch) {
329
- await feed.clear(0, indexBeforeEpoch + 1);
332
+
333
+ // Clear feed blocks before epoch.
334
+ if (ENABLE_FEED_PURGE) {
335
+ for (const feed of this.inner.dataPipeline.pipelineState?.feeds ?? []) {
336
+ const indexBeforeEpoch = epoch.timeframe.get(feed.key);
337
+ if (indexBeforeEpoch === undefined) {
338
+ continue;
339
+ }
340
+
341
+ await feed.safeClear(0, indexBeforeEpoch + 1);
330
342
  }
331
343
  }
332
344
  }
@@ -6,6 +6,7 @@ import chai, { expect } from 'chai';
6
6
  import chaiAsPromised from 'chai-as-promised';
7
7
 
8
8
  import { Trigger } from '@dxos/async';
9
+ import { Context } from '@dxos/context';
9
10
  import { PublicKey } from '@dxos/keys';
10
11
  import { Space, SpacesService } from '@dxos/protocols/proto/dxos/client/services';
11
12
  import { afterEach, afterTest, beforeEach, describe, test } from '@dxos/test';
@@ -22,7 +23,7 @@ describe('SpacesService', () => {
22
23
 
23
24
  beforeEach(async () => {
24
25
  serviceContext = createServiceContext();
25
- await serviceContext.open();
26
+ await serviceContext.open(new Context());
26
27
  spacesService = new SpacesServiceImpl(
27
28
  serviceContext.identityManager,
28
29
  serviceContext.spaceManager,
@@ -60,7 +60,7 @@ export const createPeers = async (numPeers: number) => {
60
60
  return await Promise.all(
61
61
  Array.from(Array(numPeers)).map(async () => {
62
62
  const peer = createServiceContext({ signalContext });
63
- await peer.open();
63
+ await peer.open(new Context());
64
64
  return peer;
65
65
  }),
66
66
  );
@@ -5,6 +5,7 @@
5
5
  import { Trigger } from '@dxos/async';
6
6
  import { PROXY_CONNECTION_TIMEOUT, ShellRuntime } from '@dxos/client-protocol';
7
7
  import { Config } from '@dxos/config';
8
+ import { Context } from '@dxos/context';
8
9
  import { log, logInfo } from '@dxos/log';
9
10
  import { MemorySignalManager, MemorySignalManagerContext, WebsocketSignalManager } from '@dxos/messaging';
10
11
  import { createWebRTCTransportFactory, TransportFactory } from '@dxos/network-manager';
@@ -108,7 +109,7 @@ export class IFrameHostRuntime {
108
109
  ...middleware,
109
110
  });
110
111
 
111
- await Promise.all([this._clientServices.open(), this._clientRpc.open(), this._shellRuntime?.open()]);
112
+ await Promise.all([this._clientServices.open(new Context()), this._clientRpc.open(), this._shellRuntime?.open()]);
112
113
  this._ready.wake(undefined);
113
114
  log('started');
114
115
  } catch (err: any) {
@@ -4,6 +4,7 @@
4
4
 
5
5
  import { Trigger } from '@dxos/async';
6
6
  import { Config } from '@dxos/config';
7
+ import { Context } from '@dxos/context';
7
8
  import { log } from '@dxos/log';
8
9
  import { MemorySignalManager, MemorySignalManagerContext, WebsocketSignalManager } from '@dxos/messaging';
9
10
  import { WebRTCTransportProxyFactory } from '@dxos/network-manager';
@@ -57,7 +58,7 @@ export class WorkerRuntime {
57
58
  transportFactory: this._transportFactory,
58
59
  });
59
60
 
60
- await this._clientServices.open();
61
+ await this._clientServices.open(new Context());
61
62
  this._ready.wake(undefined);
62
63
  log('started');
63
64
  } catch (err: any) {
package/src/version.ts CHANGED
@@ -1 +1 @@
1
- export const DXOS_VERSION = "0.1.56-main.5ff23aa";
1
+ export const DXOS_VERSION = "0.1.56-main.6293c6e";