@dxos/messaging 0.8.4-main.84f28bd → 0.8.4-main.8baae0fced

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 (74) hide show
  1. package/LICENSE +102 -5
  2. package/dist/lib/neutral/chunk-EC4H56J5.mjs +497 -0
  3. package/dist/lib/neutral/chunk-EC4H56J5.mjs.map +7 -0
  4. package/dist/lib/neutral/index.mjs +1249 -0
  5. package/dist/lib/neutral/index.mjs.map +7 -0
  6. package/dist/lib/neutral/meta.json +1 -0
  7. package/dist/lib/{browser → neutral}/testing/index.mjs +13 -12
  8. package/dist/lib/neutral/testing/index.mjs.map +7 -0
  9. package/dist/types/src/messenger-monitor.d.ts.map +1 -1
  10. package/dist/types/src/messenger.blueprint-test.d.ts +1 -1
  11. package/dist/types/src/messenger.blueprint-test.d.ts.map +1 -1
  12. package/dist/types/src/messenger.d.ts +4 -3
  13. package/dist/types/src/messenger.d.ts.map +1 -1
  14. package/dist/types/src/signal-client/signal-client-monitor.d.ts.map +1 -1
  15. package/dist/types/src/signal-client/signal-client.d.ts +7 -8
  16. package/dist/types/src/signal-client/signal-client.d.ts.map +1 -1
  17. package/dist/types/src/signal-client/signal-local-state.d.ts +1 -1
  18. package/dist/types/src/signal-client/signal-local-state.d.ts.map +1 -1
  19. package/dist/types/src/signal-client/signal-rpc-client-monitor.d.ts.map +1 -1
  20. package/dist/types/src/signal-client/signal-rpc-client.d.ts +3 -3
  21. package/dist/types/src/signal-client/signal-rpc-client.d.ts.map +1 -1
  22. package/dist/types/src/signal-manager/edge-signal-manager.d.ts +6 -6
  23. package/dist/types/src/signal-manager/edge-signal-manager.d.ts.map +1 -1
  24. package/dist/types/src/signal-manager/index.d.ts +1 -1
  25. package/dist/types/src/signal-manager/index.d.ts.map +1 -1
  26. package/dist/types/src/signal-manager/memory-signal-manager.d.ts +6 -5
  27. package/dist/types/src/signal-manager/memory-signal-manager.d.ts.map +1 -1
  28. package/dist/types/src/signal-manager/signal-manager.d.ts +1 -1
  29. package/dist/types/src/signal-manager/signal-manager.d.ts.map +1 -1
  30. package/dist/types/src/signal-manager/utils.d.ts.map +1 -1
  31. package/dist/types/src/signal-manager/websocket-signal-manager-monitor.d.ts.map +1 -1
  32. package/dist/types/src/signal-manager/websocket-signal-manager.d.ts +6 -7
  33. package/dist/types/src/signal-manager/websocket-signal-manager.d.ts.map +1 -1
  34. package/dist/types/src/signal-methods.d.ts +7 -7
  35. package/dist/types/src/signal-methods.d.ts.map +1 -1
  36. package/dist/types/src/testing/test-builder.d.ts +1 -1
  37. package/dist/types/src/testing/test-builder.d.ts.map +1 -1
  38. package/dist/types/src/testing/test-peer.d.ts +1 -1
  39. package/dist/types/src/testing/test-peer.d.ts.map +1 -1
  40. package/dist/types/src/testing/utils.d.ts +1 -1
  41. package/dist/types/src/testing/utils.d.ts.map +1 -1
  42. package/dist/types/tsconfig.tsbuildinfo +1 -1
  43. package/package.json +27 -30
  44. package/src/messenger.blueprint-test.ts +15 -14
  45. package/src/messenger.node.test.ts +7 -38
  46. package/src/messenger.ts +38 -33
  47. package/src/signal-client/signal-client.node.test.ts +12 -11
  48. package/src/signal-client/signal-client.ts +12 -15
  49. package/src/signal-client/signal-local-state.ts +3 -3
  50. package/src/signal-client/signal-rpc-client.node.test.ts +1 -1
  51. package/src/signal-client/signal-rpc-client.ts +8 -10
  52. package/src/signal-manager/edge-signal-manager.ts +31 -18
  53. package/src/signal-manager/index.ts +1 -1
  54. package/src/signal-manager/memory-signal-manager.ts +18 -15
  55. package/src/signal-manager/signal-manager.ts +1 -1
  56. package/src/signal-manager/websocket-signal-manager.node.test.ts +15 -14
  57. package/src/signal-manager/websocket-signal-manager.ts +12 -18
  58. package/src/signal-methods.ts +8 -8
  59. package/src/testing/test-builder.ts +6 -4
  60. package/src/testing/test-peer.ts +2 -2
  61. package/src/testing/utils.ts +2 -2
  62. package/dist/lib/browser/chunk-PXN7MXD6.mjs +0 -2309
  63. package/dist/lib/browser/chunk-PXN7MXD6.mjs.map +0 -7
  64. package/dist/lib/browser/index.mjs +0 -22
  65. package/dist/lib/browser/index.mjs.map +0 -7
  66. package/dist/lib/browser/meta.json +0 -1
  67. package/dist/lib/browser/testing/index.mjs.map +0 -7
  68. package/dist/lib/node-esm/chunk-GJW3QPXP.mjs +0 -2309
  69. package/dist/lib/node-esm/chunk-GJW3QPXP.mjs.map +0 -7
  70. package/dist/lib/node-esm/index.mjs +0 -22
  71. package/dist/lib/node-esm/index.mjs.map +0 -7
  72. package/dist/lib/node-esm/meta.json +0 -1
  73. package/dist/lib/node-esm/testing/index.mjs +0 -143
  74. package/dist/lib/node-esm/testing/index.mjs.map +0 -7
@@ -4,16 +4,15 @@
4
4
 
5
5
  import WebSocket from 'isomorphic-ws';
6
6
 
7
- import { scheduleTaskInterval, TimeoutError, Trigger } from '@dxos/async';
7
+ import { TimeoutError, Trigger, scheduleTaskInterval } from '@dxos/async';
8
8
  import { type Any, type Stream } from '@dxos/codec-protobuf';
9
9
  import { Context } from '@dxos/context';
10
10
  import { invariant } from '@dxos/invariant';
11
11
  import { PublicKey } from '@dxos/keys';
12
12
  import { log } from '@dxos/log';
13
- import { trace } from '@dxos/protocols';
14
13
  import { schema } from '@dxos/protocols/proto';
15
- import { type Message as SignalMessage, type Signal } from '@dxos/protocols/proto/dxos/mesh/signal';
16
- import { createProtoRpcPeer, type ProtoRpcPeer } from '@dxos/rpc';
14
+ import { type Signal, type Message as SignalMessage } from '@dxos/protocols/proto/dxos/mesh/signal';
15
+ import { type ProtoRpcPeer, createProtoRpcPeer } from '@dxos/rpc';
17
16
 
18
17
  import { SignalRpcClientMonitor } from './signal-rpc-client-monitor';
19
18
 
@@ -36,7 +35,7 @@ export type SignalCallbacks = {
36
35
  getMetadata?: () => any;
37
36
  };
38
37
 
39
- export type SignalRPCClientParams = {
38
+ export type SignalRPCClientProps = {
40
39
  url: string;
41
40
  callbacks?: SignalCallbacks;
42
41
  };
@@ -61,9 +60,8 @@ export class SignalRPCClient {
61
60
 
62
61
  private readonly _monitor = new SignalRpcClientMonitor();
63
62
 
64
- constructor({ url, callbacks = {} }: SignalRPCClientParams) {
65
- const traceId = PublicKey.random().toHex();
66
- log.trace('dxos.mesh.signal-rpc-client.constructor', trace.begin({ id: traceId }));
63
+ constructor({ url, callbacks = {} }: SignalRPCClientProps) {
64
+ log('creating signal rpc client', { url });
67
65
  this._url = url;
68
66
  this._callbacks = callbacks;
69
67
  this._socket = new WebSocket(this._url);
@@ -149,7 +147,7 @@ export class SignalRPCClient {
149
147
  log.warn(`Socket ${event.type ?? 'unknown'} error`, { message: event.message, url: this._url });
150
148
  };
151
149
 
152
- log.trace('dxos.mesh.signal-rpc-client.constructor', trace.end({ id: traceId }));
150
+ log('created signal rpc client', { url });
153
151
  }
154
152
 
155
153
  async close(): Promise<void> {
@@ -169,7 +167,7 @@ export class SignalRPCClient {
169
167
 
170
168
  await this._closeComplete.wait({ timeout: 1_000 });
171
169
  } catch (err) {
172
- const failureReason = err instanceof TimeoutError ? 'timeout' : err?.constructor?.name ?? 'unknown';
170
+ const failureReason = err instanceof TimeoutError ? 'timeout' : (err?.constructor?.name ?? 'unknown');
173
171
  this._monitor.recordClientCloseFailure({ failureReason });
174
172
  }
175
173
  }
@@ -3,25 +3,25 @@
3
3
  //
4
4
 
5
5
  import { Event, scheduleMicroTask } from '@dxos/async';
6
- import { cancelWithContext, Resource } from '@dxos/context';
7
- import { type EdgeConnection, protocol } from '@dxos/edge-client';
6
+ import { type Context, Resource, cancelWithContext } from '@dxos/context';
7
+ import { type EdgeConnection, EdgeIdentityChangedError, protocol } from '@dxos/edge-client';
8
8
  import { invariant } from '@dxos/invariant';
9
9
  import { PublicKey } from '@dxos/keys';
10
10
  import { log } from '@dxos/log';
11
11
  import { EdgeService } from '@dxos/protocols';
12
12
  import { type buf, bufWkt } from '@dxos/protocols/buf';
13
13
  import {
14
- SwarmRequestSchema,
15
- SwarmRequest_Action as SwarmRequestAction,
16
- SwarmResponseSchema,
17
14
  type Message as EdgeMessage,
18
15
  type PeerSchema,
16
+ SwarmRequest_Action as SwarmRequestAction,
17
+ SwarmRequestSchema,
18
+ SwarmResponseSchema,
19
19
  } from '@dxos/protocols/buf/dxos/edge/messenger_pb';
20
20
  import { type SwarmResponse } from '@dxos/protocols/proto/dxos/edge/messenger';
21
21
  import { ComplexMap, ComplexSet } from '@dxos/util';
22
22
 
23
+ import { type Message, type PeerInfo, PeerInfoHash, type SwarmEvent } from '../signal-methods';
23
24
  import { type SignalManager } from './signal-manager';
24
- import { type PeerInfo, type Message, type SwarmEvent, PeerInfoHash } from '../signal-methods';
25
25
 
26
26
  export class EdgeSignalManager extends Resource implements SignalManager {
27
27
  /**
@@ -59,7 +59,7 @@ export class EdgeSignalManager extends Resource implements SignalManager {
59
59
  /**
60
60
  * Warning: PeerInfo is inferred from edgeConnection.
61
61
  */
62
- async join({ topic, peer }: { topic: PublicKey; peer: PeerInfo }): Promise<void> {
62
+ async join(ctx: Context, { topic, peer }: { topic: PublicKey; peer: PeerInfo }): Promise<void> {
63
63
  if (!this._matchSelfPeerInfo(peer)) {
64
64
  // NOTE: Could only join swarm with the same peer info as the edge connection.
65
65
  log.warn('ignoring peer info on join request', {
@@ -76,6 +76,7 @@ export class EdgeSignalManager extends Resource implements SignalManager {
76
76
 
77
77
  this._swarmPeers.set(topic, { lastState: peer.state, joinedPeers: new ComplexSet<PeerInfo>(PeerInfoHash) });
78
78
  await this._edgeConnection.send(
79
+ ctx,
79
80
  protocol.createMessage(SwarmRequestSchema, {
80
81
  serviceId: EdgeService.SWARM,
81
82
  source: createMessageSource(topic, peer),
@@ -84,24 +85,35 @@ export class EdgeSignalManager extends Resource implements SignalManager {
84
85
  );
85
86
  }
86
87
 
87
- async leave({ topic, peer }: { topic: PublicKey; peer: PeerInfo }): Promise<void> {
88
+ async leave(ctx: Context, { topic, peer }: { topic: PublicKey; peer: PeerInfo }): Promise<void> {
88
89
  this._swarmPeers.delete(topic);
89
- await this._edgeConnection.send(
90
- protocol.createMessage(SwarmRequestSchema, {
91
- serviceId: EdgeService.SWARM,
92
- source: createMessageSource(topic, peer),
93
- payload: { action: SwarmRequestAction.LEAVE, swarmKeys: [topic.toHex()] },
94
- }),
95
- );
90
+ try {
91
+ await this._edgeConnection.send(
92
+ ctx,
93
+ protocol.createMessage(SwarmRequestSchema, {
94
+ serviceId: EdgeService.SWARM,
95
+ source: createMessageSource(topic, peer),
96
+ payload: { action: SwarmRequestAction.LEAVE, swarmKeys: [topic.toHex()] },
97
+ }),
98
+ );
99
+ } catch (err) {
100
+ if (err instanceof EdgeIdentityChangedError) {
101
+ // Note: On edge identity change, the connection is closed and EDGE will remove us from the swarm.
102
+ // So we should just delete the swarm from _swarmPeers.
103
+ return;
104
+ }
105
+ throw err;
106
+ }
96
107
  }
97
108
 
98
- async query({ topic }: { topic: PublicKey }): Promise<SwarmResponse> {
109
+ async query(ctx: Context, { topic }: { topic: PublicKey }): Promise<SwarmResponse> {
99
110
  const response = cancelWithContext(
100
111
  this._ctx,
101
112
  this.swarmState.waitFor((state) => state.swarmKey === topic.toHex()),
102
113
  );
103
114
 
104
115
  await this._edgeConnection.send(
116
+ ctx,
105
117
  protocol.createMessage(SwarmRequestSchema, {
106
118
  serviceId: EdgeService.SWARM,
107
119
  source: createMessageSource(topic, {
@@ -115,7 +127,7 @@ export class EdgeSignalManager extends Resource implements SignalManager {
115
127
  return response;
116
128
  }
117
129
 
118
- async sendMessage(message: Message): Promise<void> {
130
+ async sendMessage(ctx: Context, message: Message): Promise<void> {
119
131
  if (!this._matchSelfPeerInfo(message.author)) {
120
132
  // NOTE: Could only join swarm with the same peer info as the edge connection.
121
133
  log.warn('ignoring author on send request', {
@@ -125,6 +137,7 @@ export class EdgeSignalManager extends Resource implements SignalManager {
125
137
  }
126
138
 
127
139
  await this._edgeConnection.send(
140
+ ctx,
128
141
  protocol.createMessage(bufWkt.AnySchema, {
129
142
  serviceId: EdgeService.SIGNAL,
130
143
  source: message.author,
@@ -218,7 +231,7 @@ export class EdgeSignalManager extends Resource implements SignalManager {
218
231
  private async _rejoinAllSwarms(): Promise<void> {
219
232
  log('rejoin swarms', { swarms: Array.from(this._swarmPeers.keys()) });
220
233
  for (const [topic, { lastState }] of this._swarmPeers.entries()) {
221
- await this.join({
234
+ await this.join(this._ctx, {
222
235
  topic,
223
236
  peer: {
224
237
  peerKey: this._edgeConnection.peerKey,
@@ -3,7 +3,7 @@
3
3
  //
4
4
 
5
5
  export * from './memory-signal-manager';
6
- export * from './signal-manager';
6
+ export type * from './signal-manager';
7
7
  export * from './websocket-signal-manager';
8
8
  export * from './edge-signal-manager';
9
9
  export * from './utils';
@@ -13,8 +13,8 @@ import { type SwarmResponse } from '@dxos/protocols/proto/dxos/edge/messenger';
13
13
  import { type QueryRequest } from '@dxos/protocols/proto/dxos/edge/signal';
14
14
  import { ComplexMap, ComplexSet } from '@dxos/util';
15
15
 
16
+ import { type Message, type PeerInfo, PeerInfoHash, type SignalStatus, type SwarmEvent } from '../signal-methods';
16
17
  import { type SignalManager } from './signal-manager';
17
- import { type SwarmEvent, type PeerInfo, type SignalStatus, type Message, PeerInfoHash } from '../signal-methods';
18
18
 
19
19
  /**
20
20
  * Common signaling context that connects multiple MemorySignalManager instances.
@@ -62,7 +62,7 @@ export class MemorySignalManager implements SignalManager {
62
62
  this._ctx = new Context();
63
63
  this._ctx.onDispose(this._context.swarmEvent.on((data) => this.swarmEvent.emit(data)));
64
64
 
65
- await Promise.all([...this._joinedSwarms.values()].map((value) => this.join(value)));
65
+ await Promise.all([...this._joinedSwarms.values()].map((value) => this.join(this._ctx, value)));
66
66
  }
67
67
 
68
68
  async close(): Promise<void> {
@@ -75,7 +75,7 @@ export class MemorySignalManager implements SignalManager {
75
75
  [...this._joinedSwarms.values()],
76
76
  );
77
77
 
78
- await Promise.all([...this._joinedSwarms.values()].map((value) => this.leave(value)));
78
+ await Promise.all([...this._joinedSwarms.values()].map((value) => this.leave(this._ctx, value)));
79
79
 
80
80
  // assign joined swarms back because .leave() deletes it.
81
81
  this._joinedSwarms = joinedSwarmsCopy;
@@ -87,7 +87,7 @@ export class MemorySignalManager implements SignalManager {
87
87
  return [];
88
88
  }
89
89
 
90
- async join({ topic, peer }: { topic: PublicKey; peer: PeerInfo }): Promise<void> {
90
+ async join(_ctx: Context, { topic, peer }: { topic: PublicKey; peer: PeerInfo }): Promise<void> {
91
91
  invariant(!this._ctx.disposed, 'Closed');
92
92
 
93
93
  this._joinedSwarms.add({ topic, peer });
@@ -119,7 +119,7 @@ export class MemorySignalManager implements SignalManager {
119
119
  }
120
120
  }
121
121
 
122
- async leave({ topic, peer }: { topic: PublicKey; peer: PeerInfo }): Promise<void> {
122
+ async leave(_ctx: Context, { topic, peer }: { topic: PublicKey; peer: PeerInfo }): Promise<void> {
123
123
  invariant(!this._ctx.disposed, 'Closed');
124
124
 
125
125
  this._joinedSwarms.delete({ topic, peer });
@@ -140,19 +140,22 @@ export class MemorySignalManager implements SignalManager {
140
140
  this._context.swarmEvent.emit(swarmEvent);
141
141
  }
142
142
 
143
- async query(request: QueryRequest): Promise<SwarmResponse> {
143
+ async query(_ctx: Context, request: QueryRequest): Promise<SwarmResponse> {
144
144
  throw new Error('Not implemented');
145
145
  }
146
146
 
147
- async sendMessage({
148
- author,
149
- recipient,
150
- payload,
151
- }: {
152
- author: PeerInfo;
153
- recipient: PeerInfo;
154
- payload: Any;
155
- }): Promise<void> {
147
+ async sendMessage(
148
+ _ctx: Context,
149
+ {
150
+ author,
151
+ recipient,
152
+ payload,
153
+ }: {
154
+ author: PeerInfo;
155
+ recipient: PeerInfo;
156
+ payload: Any;
157
+ },
158
+ ): Promise<void> {
156
159
  log('send message', { author, recipient, ...dec(payload) });
157
160
 
158
161
  invariant(recipient);
@@ -5,7 +5,7 @@
5
5
  import { type Event } from '@dxos/async';
6
6
  import { type Lifecycle } from '@dxos/context';
7
7
 
8
- import { type SignalStatus, type SignalMethods } from '../signal-methods';
8
+ import { type SignalMethods, type SignalStatus } from '../signal-methods';
9
9
 
10
10
  /**
11
11
  * Manages a collection of signaling clients.
@@ -5,12 +5,13 @@
5
5
  import { afterAll, beforeAll, describe, test } from 'vitest';
6
6
 
7
7
  import { asyncTimeout, sleep } from '@dxos/async';
8
+ import { Context } from '@dxos/context';
8
9
  import { PublicKey } from '@dxos/keys';
9
- import { runTestSignalServer, type SignalServerRunner } from '@dxos/signal';
10
+ import { type SignalServerRunner, runTestSignalServer } from '@dxos/signal';
10
11
  import { openAndClose } from '@dxos/test-utils';
11
12
 
12
- import { WebsocketSignalManager } from './websocket-signal-manager';
13
13
  import { createMessage, expectPeerAvailable, expectReceivedMessage } from '../testing';
14
+ import { WebsocketSignalManager } from './websocket-signal-manager';
14
15
 
15
16
  describe.skip('WebSocketSignalManager', () => {
16
17
  let broker1: SignalServerRunner;
@@ -39,9 +40,9 @@ describe.skip('WebSocketSignalManager', () => {
39
40
  const joined21 = expectPeerAvailable(client2, topic, { peerKey: peer1.toHex() });
40
41
  const joined31 = expectPeerAvailable(client3, topic, { peerKey: peer1.toHex() });
41
42
 
42
- await client1.join({ topic, peer: { peerKey: peer1.toHex() } });
43
- await client2.join({ topic, peer: { peerKey: peer2.toHex() } });
44
- await client3.join({ topic, peer: { peerKey: peer3.toHex() } });
43
+ await client1.join(Context.default(), { topic, peer: { peerKey: peer1.toHex() } });
44
+ await client2.join(Context.default(), { topic, peer: { peerKey: peer2.toHex() } });
45
+ await client3.join(Context.default(), { topic, peer: { peerKey: peer3.toHex() } });
45
46
 
46
47
  await Promise.all([joined12, joined13, joined21, joined31]);
47
48
  });
@@ -56,8 +57,8 @@ describe.skip('WebSocketSignalManager', () => {
56
57
  const joined12 = expectPeerAvailable(client1, topic, { peerKey: peer2.toHex() });
57
58
  const joined21 = expectPeerAvailable(client2, topic, { peerKey: peer1.toHex() });
58
59
 
59
- await client1.join({ topic, peer: { peerKey: peer1.toHex() } });
60
- await client2.join({ topic, peer: { peerKey: peer2.toHex() } });
60
+ await client1.join(Context.default(), { topic, peer: { peerKey: peer1.toHex() } });
61
+ await client2.join(Context.default(), { topic, peer: { peerKey: peer2.toHex() } });
61
62
 
62
63
  await asyncTimeout(Promise.all([joined12, joined21]), 1_000);
63
64
 
@@ -66,7 +67,7 @@ describe.skip('WebSocketSignalManager', () => {
66
67
  const received = expectReceivedMessage(client2.onMessage, message);
67
68
  await client2.subscribeMessages({ peerKey: peer2.toHex() });
68
69
  await sleep(50);
69
- await client1.sendMessage(message);
70
+ await client1.sendMessage(Context.default(), message);
70
71
 
71
72
  await asyncTimeout(received, 1_000);
72
73
  });
@@ -81,8 +82,8 @@ describe.skip('WebSocketSignalManager', () => {
81
82
  const joined12 = expectPeerAvailable(client1, topic, { peerKey: peer2.toHex() });
82
83
  const joined21 = expectPeerAvailable(client2, topic, { peerKey: peer1.toHex() });
83
84
 
84
- await client1.join({ topic, peer: { peerKey: peer1.toHex() } });
85
- await client2.join({ topic, peer: { peerKey: peer2.toHex() } });
85
+ await client1.join(Context.default(), { topic, peer: { peerKey: peer1.toHex() } });
86
+ await client2.join(Context.default(), { topic, peer: { peerKey: peer2.toHex() } });
86
87
 
87
88
  await Promise.all([joined12, joined21]);
88
89
  });
@@ -97,15 +98,15 @@ describe.skip('WebSocketSignalManager', () => {
97
98
  const joined112 = expectPeerAvailable(client1, topic1, { peerKey: peer2.toHex() });
98
99
  const joined121 = expectPeerAvailable(client2, topic1, { peerKey: peer1.toHex() });
99
100
 
100
- await client1.join({ topic: topic1, peer: { peerKey: peer1.toHex() } });
101
- await client2.join({ topic: topic1, peer: { peerKey: peer2.toHex() } });
101
+ await client1.join(Context.default(), { topic: topic1, peer: { peerKey: peer1.toHex() } });
102
+ await client2.join(Context.default(), { topic: topic1, peer: { peerKey: peer2.toHex() } });
102
103
  await Promise.all([joined112, joined121]);
103
104
 
104
105
  const joined212 = expectPeerAvailable(client1, topic2, { peerKey: peer2.toHex() });
105
106
  const joined221 = expectPeerAvailable(client2, topic2, { peerKey: peer1.toHex() });
106
107
 
107
- await client1.join({ topic: topic2, peer: { peerKey: peer1.toHex() } });
108
- await client2.join({ topic: topic2, peer: { peerKey: peer2.toHex() } });
108
+ await client1.join(Context.default(), { topic: topic2, peer: { peerKey: peer1.toHex() } });
109
+ await client2.join(Context.default(), { topic: topic2, peer: { peerKey: peer2.toHex() } });
109
110
  await Promise.all([joined212, joined221]);
110
111
  });
111
112
  });
@@ -3,27 +3,26 @@
3
3
  //
4
4
 
5
5
  import { Event, sleep, synchronized } from '@dxos/async';
6
- import { LifecycleState, Resource } from '@dxos/context';
6
+ import { type Context, LifecycleState, Resource } from '@dxos/context';
7
7
  import { invariant } from '@dxos/invariant';
8
- import { PublicKey } from '@dxos/keys';
9
8
  import { log } from '@dxos/log';
10
- import { RateLimitExceededError, TimeoutError, trace } from '@dxos/protocols';
9
+ import { RateLimitExceededError, TimeoutError } from '@dxos/protocols';
11
10
  import { type Runtime } from '@dxos/protocols/proto/dxos/config';
12
11
  import { type SwarmResponse } from '@dxos/protocols/proto/dxos/edge/messenger';
13
12
  import { type JoinRequest, type LeaveRequest, type QueryRequest } from '@dxos/protocols/proto/dxos/edge/signal';
14
13
  import { BitField, safeAwaitAll } from '@dxos/util';
15
14
 
16
- import { type SignalManager } from './signal-manager';
17
- import { WebsocketSignalManagerMonitor } from './websocket-signal-manager-monitor';
18
15
  import { SignalClient } from '../signal-client';
19
16
  import {
20
- type PeerInfo,
21
17
  type Message,
18
+ type PeerInfo,
22
19
  type SignalClientMethods,
23
20
  type SignalMethods,
24
21
  type SignalStatus,
25
22
  type SwarmEvent,
26
23
  } from '../signal-methods';
24
+ import { type SignalManager } from './signal-manager';
25
+ import { WebsocketSignalManagerMonitor } from './websocket-signal-manager-monitor';
27
26
 
28
27
  const MAX_SERVER_FAILURES = 5;
29
28
  const WSS_SIGNAL_SERVER_REBOOT_DELAY = 3_000;
@@ -48,8 +47,6 @@ export class WebsocketSignalManager extends Resource implements SignalManager {
48
47
 
49
48
  readonly onMessage = new Event<Message>();
50
49
 
51
- private readonly _instanceId = PublicKey.random().toHex();
52
-
53
50
  constructor(
54
51
  private readonly _hosts: Runtime.Services.Signal[],
55
52
  private readonly _getMetadata?: () => any,
@@ -76,11 +73,8 @@ export class WebsocketSignalManager extends Resource implements SignalManager {
76
73
 
77
74
  protected override async _open(): Promise<void> {
78
75
  log('open signal manager', { hosts: this._hosts });
79
- log.trace('dxos.mesh.websocket-signal-manager.open', trace.begin({ id: this._instanceId }));
80
76
 
81
77
  await safeAwaitAll(this._servers.values(), (server) => server.open());
82
-
83
- log.trace('dxos.mesh.websocket-signal-manager.open', trace.end({ id: this._instanceId }));
84
78
  }
85
79
 
86
80
  protected override async _close(): Promise<void> {
@@ -104,30 +98,30 @@ export class WebsocketSignalManager extends Resource implements SignalManager {
104
98
  }
105
99
 
106
100
  @synchronized
107
- async join({ topic, peer }: JoinRequest): Promise<void> {
101
+ async join(_ctx: Context, { topic, peer }: JoinRequest): Promise<void> {
108
102
  log('join', { topic, peer });
109
103
  invariant(this._lifecycleState === LifecycleState.OPEN);
110
- await this._forEachServer((server) => server.join({ topic, peer }));
104
+ await this._forEachServer((server) => server.join(_ctx, { topic, peer }));
111
105
  }
112
106
 
113
107
  @synchronized
114
- async leave({ topic, peer }: LeaveRequest): Promise<void> {
108
+ async leave(_ctx: Context, { topic, peer }: LeaveRequest): Promise<void> {
115
109
  log('leaving', { topic, peer });
116
110
  invariant(this._lifecycleState === LifecycleState.OPEN);
117
- await this._forEachServer((server) => server.leave({ topic, peer }));
111
+ await this._forEachServer((server) => server.leave(_ctx, { topic, peer }));
118
112
  }
119
113
 
120
- async query({ topic }: QueryRequest): Promise<SwarmResponse> {
114
+ async query(_ctx: Context, { topic }: QueryRequest): Promise<SwarmResponse> {
121
115
  throw new Error('Not implemented');
122
116
  }
123
117
 
124
- async sendMessage({ author, recipient, payload }: Message): Promise<void> {
118
+ async sendMessage(_ctx: Context, { author, recipient, payload }: Message): Promise<void> {
125
119
  log('signal', { recipient });
126
120
  invariant(this._lifecycleState === LifecycleState.OPEN);
127
121
 
128
122
  void this._forEachServer(async (server, serverName, index) => {
129
123
  void server
130
- .sendMessage({ author, recipient, payload })
124
+ .sendMessage(_ctx, { author, recipient, payload })
131
125
  .then(() => this._clearServerFailedFlag(serverName, index))
132
126
  .catch((err) => {
133
127
  if (err instanceof RateLimitExceededError) {
@@ -3,14 +3,14 @@
3
3
  //
4
4
 
5
5
  import { type Event } from '@dxos/async';
6
- import { type Lifecycle } from '@dxos/context';
7
- import { type SwarmResponse, type Peer } from '@dxos/protocols/proto/dxos/edge/messenger';
6
+ import { type Context, type Lifecycle } from '@dxos/context';
7
+ import { type Peer, type SwarmResponse } from '@dxos/protocols/proto/dxos/edge/messenger';
8
8
  import {
9
+ type JoinRequest,
9
10
  type LeaveRequest,
10
11
  type Message,
11
- type SwarmEvent,
12
- type JoinRequest,
13
12
  type QueryRequest,
13
+ type SwarmEvent,
14
14
  } from '@dxos/protocols/proto/dxos/edge/signal';
15
15
  import { type SignalState } from '@dxos/protocols/proto/dxos/mesh/signal';
16
16
 
@@ -51,22 +51,22 @@ export interface SignalMethods {
51
51
  /**
52
52
  * Join topic on signal network, to be discoverable by other peers.
53
53
  */
54
- join: (params: JoinRequest) => Promise<void>;
54
+ join: (ctx: Context, params: JoinRequest) => Promise<void>;
55
55
 
56
56
  /**
57
57
  * Leave topic on signal network, to stop being discoverable by other peers.
58
58
  */
59
- leave: (params: LeaveRequest) => Promise<void>;
59
+ leave: (ctx: Context, params: LeaveRequest) => Promise<void>;
60
60
 
61
61
  /**
62
62
  * Query peers in the swarm without joining it.
63
63
  */
64
- query: (params: QueryRequest) => Promise<SwarmResponse>;
64
+ query: (ctx: Context, params: QueryRequest) => Promise<SwarmResponse>;
65
65
 
66
66
  /**
67
67
  * Send message to peer.
68
68
  */
69
- sendMessage: (message: Message) => Promise<void>;
69
+ sendMessage: (ctx: Context, message: Message) => Promise<void>;
70
70
 
71
71
  /**
72
72
  * Start receiving messages from peer.
@@ -2,9 +2,11 @@
2
2
  // Copyright 2022 DXOS.org
3
3
  //
4
4
 
5
- import { TestPeer } from './test-peer';
6
- import { type SignalManager, MemorySignalManager, MemorySignalManagerContext } from '../signal-manager';
5
+ import { type Context } from '@dxos/context';
6
+
7
+ import { MemorySignalManager, MemorySignalManagerContext, type SignalManager } from '../signal-manager';
7
8
  import { type Message } from '../signal-methods';
9
+ import { TestPeer } from './test-peer';
8
10
 
9
11
  export type TestBuilderOptions = {
10
12
  signalManagerFactory?: (peer: TestPeer) => Promise<SignalManager>;
@@ -24,9 +26,9 @@ export class TestBuilder {
24
26
  if (this.options.messageDisruption) {
25
27
  // Imitates signal network disruptions (e. g. message doubling, ).
26
28
  const trueSend = signalManager.sendMessage.bind(signalManager);
27
- signalManager.sendMessage = async (message: Message) => {
29
+ signalManager.sendMessage = async (ctx: Context, message: Message) => {
28
30
  for (const msg of this.options.messageDisruption!(message)) {
29
- await trueSend(msg);
31
+ await trueSend(ctx, msg);
30
32
  }
31
33
  };
32
34
  }
@@ -9,11 +9,11 @@ import { PublicKey } from '@dxos/keys';
9
9
  import { log } from '@dxos/log';
10
10
  import { buf } from '@dxos/protocols/buf';
11
11
 
12
- import { type TestBuilder } from './test-builder';
13
- import { expectPeerAvailable, expectPeerLeft, expectReceivedMessage } from './utils';
14
12
  import { Messenger } from '../messenger';
15
13
  import { type SignalManager } from '../signal-manager';
16
14
  import { type Message, type PeerInfo } from '../signal-methods';
15
+ import { type TestBuilder } from './test-builder';
16
+ import { expectPeerAvailable, expectPeerLeft, expectReceivedMessage } from './utils';
17
17
 
18
18
  export class TestPeer extends Resource {
19
19
  public peerId = PublicKey.random();
@@ -2,12 +2,12 @@
2
2
  // Copyright 2022 DXOS.org
3
3
  //
4
4
 
5
- import { asyncTimeout, type Event } from '@dxos/async';
5
+ import { type Event, asyncTimeout } from '@dxos/async';
6
6
  import { type Any } from '@dxos/codec-protobuf';
7
7
  import { PublicKey } from '@dxos/keys';
8
8
 
9
+ import { type Message, type PeerInfo, type SignalMethods } from '../signal-methods';
9
10
  import { PAYLOAD_1 } from './test-messages';
10
- import { type SignalMethods, type Message, type PeerInfo } from '../signal-methods';
11
11
 
12
12
  export const expectPeerAvailable = (client: SignalMethods, expectedTopic: PublicKey, peer: PeerInfo) =>
13
13
  asyncTimeout(