@dxos/messaging 0.4.10-main.fd4f2a3 → 0.4.10-main.fd8ea31

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.
@@ -1 +1 @@
1
- {"version":3,"file":"websocket-signal-manager.d.ts","sourceRoot":"","sources":["../../../../src/signal-manager/websocket-signal-manager.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,EAAuB,MAAM,aAAa,CAAC;AACzD,OAAO,EAAE,KAAK,GAAG,EAAE,MAAM,sBAAsB,CAAC;AAGhD,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAGvC,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,mCAAmC,CAAC;AACjE,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,wCAAwC,CAAC;AAEzE,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,KAAK,YAAY,EAAgB,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAItF;;GAEG;AACH,qBAAa,sBAAuB,YAAW,aAAa;IAuBxD,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC;IAvBhC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAmC;IAE5D,OAAO,CAAC,IAAI,CAAW;IACvB,OAAO,CAAC,OAAO,CAAS;IAExB,QAAQ,CAAC,YAAY,sBAA6B;IAClD,QAAQ,CAAC,aAAa,wBAA+B;IACrD,QAAQ,CAAC,YAAY,sBAA6B;IAClD,QAAQ,CAAC,UAAU;eACV,SAAS;oBACJ,UAAU;OACnB;IAEL,QAAQ,CAAC,SAAS;gBACR,SAAS;mBACN,SAAS;iBACX,GAAG;OACT;IAEL,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA8B;gBAGvC,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,MAAM,EAAE,EACjC,YAAY,CAAC,SAAQ,GAAG,aAAA;IAsBrC,IAAI;IAgBJ,KAAK;IAWL,aAAa,CAAC,UAAU,EAAE,MAAM;IAYtC,SAAS,IAAI,YAAY,EAAE;IAKrB,IAAI,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;QAAE,KAAK,EAAE,SAAS,CAAC;QAAC,MAAM,EAAE,SAAS,CAAA;KAAE;IAO/D,KAAK,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;QAAE,KAAK,EAAE,SAAS,CAAC;QAAC,MAAM,EAAE,SAAS,CAAA;KAAE;IAOhE,WAAW,CAAC,EAChB,MAAM,EACN,SAAS,EACT,OAAO,GACR,EAAE;QACD,MAAM,EAAE,SAAS,CAAC;QAClB,SAAS,EAAE,SAAS,CAAC;QACrB,OAAO,EAAE,GAAG,CAAC;KACd,GAAG,OAAO,CAAC,IAAI,CAAC;IAoBX,kBAAkB,CAAC,UAAU,EAAE,MAAM;IAWrC,iBAAiB,CAAC,MAAM,EAAE,SAAS;IAOnC,mBAAmB,CAAC,MAAM,EAAE,SAAS;IAO3C,OAAO,CAAC,YAAY;YAMN,cAAc;CAK7B"}
1
+ {"version":3,"file":"websocket-signal-manager.d.ts","sourceRoot":"","sources":["../../../../src/signal-manager/websocket-signal-manager.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,EAAuB,MAAM,aAAa,CAAC;AACzD,OAAO,EAAE,KAAK,GAAG,EAAE,MAAM,sBAAsB,CAAC;AAGhD,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAGvC,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,mCAAmC,CAAC;AACjE,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,wCAAwC,CAAC;AAEzE,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,KAAK,YAAY,EAAgB,MAAM,kBAAkB,CAAC;AACnE,OAAO,EAAgD,KAAK,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAKpG;;GAEG;AACH,qBAAa,sBAAuB,YAAW,aAAa;IAuBxD,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC;IAvBhC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA0C;IAEnE,OAAO,CAAC,IAAI,CAAW;IACvB,OAAO,CAAC,OAAO,CAAS;IAExB,QAAQ,CAAC,YAAY,sBAA6B;IAClD,QAAQ,CAAC,aAAa,wBAA+B;IACrD,QAAQ,CAAC,YAAY,sBAA6B;IAClD,QAAQ,CAAC,UAAU;eACV,SAAS;oBACJ,UAAU;OACnB;IAEL,QAAQ,CAAC,SAAS;gBACR,SAAS;mBACN,SAAS;iBACX,GAAG;OACT;IAEL,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA8B;gBAGvC,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,MAAM,EAAE,EACjC,YAAY,CAAC,SAAQ,GAAG,aAAA;IAyBrC,IAAI;IAiBJ,KAAK;IAWL,aAAa,CAAC,UAAU,EAAE,MAAM;IAYtC,SAAS,IAAI,YAAY,EAAE;IAKrB,IAAI,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;QAAE,KAAK,EAAE,SAAS,CAAC;QAAC,MAAM,EAAE,SAAS,CAAA;KAAE;IAO/D,KAAK,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;QAAE,KAAK,EAAE,SAAS,CAAC;QAAC,MAAM,EAAE,SAAS,CAAA;KAAE;IAOhE,WAAW,CAAC,EAChB,MAAM,EACN,SAAS,EACT,OAAO,GACR,EAAE;QACD,MAAM,EAAE,SAAS,CAAC;QAClB,SAAS,EAAE,SAAS,CAAC;QACrB,OAAO,EAAE,GAAG,CAAC;KACd,GAAG,OAAO,CAAC,IAAI,CAAC;IAoBX,kBAAkB,CAAC,UAAU,EAAE,MAAM;IAYrC,iBAAiB,CAAC,MAAM,EAAE,SAAS;IAOnC,mBAAmB,CAAC,MAAM,EAAE,SAAS;IAO3C,OAAO,CAAC,YAAY;YAMN,cAAc;CAK7B"}
@@ -1,10 +1,22 @@
1
1
  import { type Any } from '@dxos/codec-protobuf';
2
2
  import { type PublicKey } from '@dxos/keys';
3
+ import { type SignalState } from '@dxos/protocols/proto/dxos/mesh/signal';
3
4
  export interface Message {
4
5
  author: PublicKey;
5
6
  recipient: PublicKey;
6
7
  payload: Any;
7
8
  }
9
+ export type SignalStatus = {
10
+ host: string;
11
+ state: SignalState;
12
+ error?: string;
13
+ reconnectIn: number;
14
+ connectionStarted: Date;
15
+ lastStateChange: Date;
16
+ };
17
+ /**
18
+ * Message routing interface.
19
+ */
8
20
  export interface SignalMethods {
9
21
  /**
10
22
  * Join topic on signal network, to be discoverable by other peers.
@@ -33,4 +45,12 @@ export interface SignalMethods {
33
45
  */
34
46
  unsubscribeMessages: (peerId: PublicKey) => Promise<void>;
35
47
  }
48
+ /**
49
+ * Signaling client.
50
+ */
51
+ export interface SignalClientMethods extends SignalMethods {
52
+ open(): Promise<void>;
53
+ close(): Promise<void>;
54
+ getStatus(): SignalStatus;
55
+ }
36
56
  //# sourceMappingURL=signal-methods.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"signal-methods.d.ts","sourceRoot":"","sources":["../../../src/signal-methods.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,GAAG,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C,MAAM,WAAW,OAAO;IACtB,MAAM,EAAE,SAAS,CAAC;IAClB,SAAS,EAAE,SAAS,CAAC;IACrB,OAAO,EAAE,GAAG,CAAC;CACd;AAED,MAAM,WAAW,aAAa;IAC5B;;OAEG;IACH,IAAI,EAAE,CAAC,MAAM,EAAE;QAAE,KAAK,EAAE,SAAS,CAAC;QAAC,MAAM,EAAE,SAAS,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAEzE;;OAEG;IACH,KAAK,EAAE,CAAC,MAAM,EAAE;QAAE,KAAK,EAAE,SAAS,CAAC;QAAC,MAAM,EAAE,SAAS,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAE1E;;OAEG;IACH,WAAW,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAEjD;;OAEG;IACH,iBAAiB,EAAE,CAAC,MAAM,EAAE,SAAS,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAExD;;OAEG;IACH,mBAAmB,EAAE,CAAC,MAAM,EAAE,SAAS,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3D"}
1
+ {"version":3,"file":"signal-methods.d.ts","sourceRoot":"","sources":["../../../src/signal-methods.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,GAAG,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,wCAAwC,CAAC;AAE1E,MAAM,WAAW,OAAO;IACtB,MAAM,EAAE,SAAS,CAAC;IAClB,SAAS,EAAE,SAAS,CAAC;IACrB,OAAO,EAAE,GAAG,CAAC;CACd;AAED,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,WAAW,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,iBAAiB,EAAE,IAAI,CAAC;IACxB,eAAe,EAAE,IAAI,CAAC;CACvB,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B;;OAEG;IACH,IAAI,EAAE,CAAC,MAAM,EAAE;QAAE,KAAK,EAAE,SAAS,CAAC;QAAC,MAAM,EAAE,SAAS,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAEzE;;OAEG;IACH,KAAK,EAAE,CAAC,MAAM,EAAE;QAAE,KAAK,EAAE,SAAS,CAAC;QAAC,MAAM,EAAE,SAAS,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAE1E;;OAEG;IACH,WAAW,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAEjD;;OAEG;IACH,iBAAiB,EAAE,CAAC,MAAM,EAAE,SAAS,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAExD;;OAEG;IACH,mBAAmB,EAAE,CAAC,MAAM,EAAE,SAAS,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3D;AAED;;GAEG;AACH,MAAM,WAAW,mBAAoB,SAAQ,aAAa;IACxD,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACtB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,SAAS,IAAI,YAAY,CAAC;CAC3B"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dxos/messaging",
3
- "version": "0.4.10-main.fd4f2a3",
3
+ "version": "0.4.10-main.fd8ea31",
4
4
  "description": "Messaging",
5
5
  "homepage": "https://dxos.org",
6
6
  "bugs": "https://github.com/dxos/dxos/issues",
@@ -19,23 +19,23 @@
19
19
  "dependencies": {
20
20
  "isomorphic-ws": "^4.0.1",
21
21
  "ws": "^8.14.2",
22
- "@dxos/codec-protobuf": "0.4.10-main.fd4f2a3",
23
- "@dxos/async": "0.4.10-main.fd4f2a3",
24
- "@dxos/context": "0.4.10-main.fd4f2a3",
25
- "@dxos/keys": "0.4.10-main.fd4f2a3",
26
- "@dxos/log": "0.4.10-main.fd4f2a3",
27
- "@dxos/protocols": "0.4.10-main.fd4f2a3",
28
- "@dxos/node-std": "0.4.10-main.fd4f2a3",
29
- "@dxos/util": "0.4.10-main.fd4f2a3",
30
- "@dxos/rpc": "0.4.10-main.fd4f2a3",
31
- "@dxos/invariant": "0.4.10-main.fd4f2a3"
22
+ "@dxos/async": "0.4.10-main.fd8ea31",
23
+ "@dxos/context": "0.4.10-main.fd8ea31",
24
+ "@dxos/codec-protobuf": "0.4.10-main.fd8ea31",
25
+ "@dxos/invariant": "0.4.10-main.fd8ea31",
26
+ "@dxos/log": "0.4.10-main.fd8ea31",
27
+ "@dxos/keys": "0.4.10-main.fd8ea31",
28
+ "@dxos/node-std": "0.4.10-main.fd8ea31",
29
+ "@dxos/rpc": "0.4.10-main.fd8ea31",
30
+ "@dxos/util": "0.4.10-main.fd8ea31",
31
+ "@dxos/protocols": "0.4.10-main.fd8ea31"
32
32
  },
33
33
  "devDependencies": {
34
34
  "@types/node": "^18.11.9",
35
35
  "earljs": "~0.1.10",
36
36
  "typescript": "^5.2.2",
37
37
  "wait-for-expect": "^3.0.2",
38
- "@dxos/signal": "0.4.10-main.fd4f2a3"
38
+ "@dxos/signal": "0.4.10-main.fd8ea31"
39
39
  },
40
40
  "publishConfig": {
41
41
  "access": "public"
@@ -52,10 +52,10 @@ describe('SignalClient', () => {
52
52
  },
53
53
  async () => {},
54
54
  );
55
- api1.open();
55
+ void api1.open();
56
56
  afterTest(() => api1.close());
57
57
  const api2 = new SignalClient(broker1.url(), (async () => {}) as any, async () => {});
58
- api2.open();
58
+ void api2.open();
59
59
  afterTest(() => api2.close());
60
60
 
61
61
  await api1.subscribeMessages(peer1);
@@ -87,7 +87,7 @@ describe('SignalClient', () => {
87
87
  }
88
88
  },
89
89
  );
90
- api1.open();
90
+ void api1.open();
91
91
  afterTest(() => api1.close());
92
92
 
93
93
  const trigger2 = new Trigger();
@@ -100,7 +100,7 @@ describe('SignalClient', () => {
100
100
  }
101
101
  },
102
102
  );
103
- api2.open();
103
+ void api2.open();
104
104
  afterTest(() => api2.close());
105
105
  await api1.join({ topic, peerId: peer1 });
106
106
  await api2.join({ topic, peerId: peer2 });
@@ -122,7 +122,7 @@ describe('SignalClient', () => {
122
122
  },
123
123
  async () => {},
124
124
  );
125
- api1.open();
125
+ void api1.open();
126
126
  afterTest(() => api1.close());
127
127
 
128
128
  await api1.subscribeMessages(peer1);
@@ -150,11 +150,11 @@ describe('SignalClient', () => {
150
150
  },
151
151
  async () => {},
152
152
  );
153
- client1.open();
153
+ void client1.open();
154
154
  afterTest(() => client1.close());
155
155
 
156
156
  const client2 = new SignalClient(broker1.url(), (async () => {}) as any, async () => {});
157
- client2.open();
157
+ void client2.open();
158
158
  afterTest(() => client2.close());
159
159
 
160
160
  await client1.subscribeMessages(peer1);
@@ -203,11 +203,11 @@ describe('SignalClient', () => {
203
203
  },
204
204
  async () => {},
205
205
  );
206
- client1.open();
206
+ void client1.open();
207
207
  afterTest(() => client1.close());
208
208
 
209
209
  const client2 = new SignalClient(broker1.url(), (async () => {}) as any, async () => {});
210
- client2.open();
210
+ void client2.open();
211
211
  afterTest(() => client2.close());
212
212
 
213
213
  const message = {
@@ -233,7 +233,7 @@ describe('SignalClient', () => {
233
233
  //
234
234
 
235
235
  await client1.close();
236
- client1.open();
236
+ void client1.open();
237
237
  await waitForSubscription(client1, peer1);
238
238
 
239
239
  {
@@ -259,14 +259,14 @@ describe('SignalClient', () => {
259
259
  async () => {},
260
260
  async () => {},
261
261
  );
262
- api1.open();
262
+ void api1.open();
263
263
  afterTest(() => api1.close());
264
264
  const api2 = new SignalClient(
265
265
  broker2.url(),
266
266
  async () => {},
267
267
  async () => {},
268
268
  );
269
- api2.open();
269
+ void api2.open();
270
270
  afterTest(() => api2.close());
271
271
 
272
272
  await api1.join({ topic, peerId: peer1 });
@@ -300,10 +300,10 @@ describe('SignalClient', () => {
300
300
  async () => {},
301
301
  async () => {},
302
302
  );
303
- api1.open();
303
+ void api1.open();
304
304
  afterTest(() => api1.close());
305
305
  const api2 = new SignalClient(broker2.url(), signalMock, async () => {});
306
- api2.open();
306
+ void api2.open();
307
307
  afterTest(() => api2.close());
308
308
 
309
309
  await api1.join({ topic, peerId: peer1 });
@@ -13,22 +13,13 @@ import { type Message as SignalMessage, SignalState, type SwarmEvent } from '@dx
13
13
  import { ComplexMap, ComplexSet } from '@dxos/util';
14
14
 
15
15
  import { SignalRPCClient } from './signal-rpc-client';
16
- import { type Message, type SignalMethods } from '../signal-methods';
16
+ import { type Message, type SignalClientMethods, type SignalStatus } from '../signal-methods';
17
17
 
18
18
  const DEFAULT_RECONNECT_TIMEOUT = 100;
19
- const MAX_RECONNECT_TIMEOUT = 5000;
20
- const ERROR_RECONCILE_DELAY = 1000;
19
+ const MAX_RECONNECT_TIMEOUT = 5_000;
20
+ const ERROR_RECONCILE_DELAY = 1_000;
21
21
  const RECONCILE_INTERVAL = 5_000;
22
22
 
23
- export type SignalStatus = {
24
- host: string;
25
- state: SignalState;
26
- error?: string;
27
- reconnectIn: number;
28
- connectionStarted: Date;
29
- lastStateChange: Date;
30
- };
31
-
32
23
  export type CommandTrace = {
33
24
  messageId: string;
34
25
  host: string;
@@ -41,9 +32,11 @@ export type CommandTrace = {
41
32
  };
42
33
 
43
34
  /**
35
+ * KUBE-specific signaling client.
44
36
  * Establishes a websocket connection to signal server and provides RPC methods.
45
37
  */
46
- export class SignalClient implements SignalMethods {
38
+ // TODO(burdon): Rename impl.
39
+ export class SignalClient implements SignalClientMethods {
47
40
  private _state = SignalState.CLOSED;
48
41
 
49
42
  private _lastError?: Error;
@@ -119,7 +112,6 @@ export class SignalClient implements SignalMethods {
119
112
 
120
113
  /**
121
114
  * @param _host Signal server websocket URL.
122
- * @param _onMessage
123
115
  */
124
116
  constructor(
125
117
  private readonly _host: string,
@@ -132,7 +124,7 @@ export class SignalClient implements SignalMethods {
132
124
  }
133
125
  }
134
126
 
135
- open() {
127
+ async open() {
136
128
  log.trace('dxos.mesh.signal-client.open', trace.begin({ id: this._instanceId }));
137
129
 
138
130
  if ([SignalState.CONNECTED, SignalState.CONNECTING].includes(this._state)) {
@@ -213,7 +205,6 @@ export class SignalClient implements SignalMethods {
213
205
  async leave({ topic, peerId }: { topic: PublicKey; peerId: PublicKey }): Promise<void> {
214
206
  this._performance.leaveCounter++;
215
207
  log('leaving', { topic, peerId });
216
-
217
208
  void this._swarmStreams.get({ topic, peerId })?.close();
218
209
  this._swarmStreams.delete({ topic, peerId });
219
210
  this._joinedTopics.delete({ topic, peerId });
@@ -380,7 +371,7 @@ export class SignalClient implements SignalMethods {
380
371
 
381
372
  const swarmStream = await asyncTimeout(
382
373
  cancelWithContext(this._connectionCtx!, client.join({ topic, peerId })),
383
- 5000,
374
+ 5_000,
384
375
  );
385
376
  // Subscribing to swarm events.
386
377
  // TODO(mykola): What happens when the swarm stream is closed? Maybe send leave event for each peer?
@@ -419,7 +410,7 @@ export class SignalClient implements SignalMethods {
419
410
 
420
411
  const messageStream = await asyncTimeout(
421
412
  cancelWithContext(this._connectionCtx!, client.receiveMessages(peerId)),
422
- 5000,
413
+ 5_000,
423
414
  );
424
415
  messageStream.subscribe(async (message: SignalMessage) => {
425
416
  this._performance.receivedMessages++;
@@ -13,7 +13,8 @@ import { type SwarmEvent } from '@dxos/protocols/proto/dxos/mesh/signal';
13
13
  import { ComplexMap, ComplexSet } from '@dxos/util';
14
14
 
15
15
  import { type SignalManager } from './signal-manager';
16
- import { type CommandTrace, type SignalStatus } from '../signal-client';
16
+ import { type CommandTrace } from '../signal-client';
17
+ import { type SignalStatus } from '../signal-methods';
17
18
 
18
19
  /**
19
20
  * Common signaling context that connects multiple MemorySignalManager instances.
@@ -6,20 +6,20 @@ import { type Event } from '@dxos/async';
6
6
  import { type PublicKey } from '@dxos/keys';
7
7
  import { type SwarmEvent } from '@dxos/protocols/proto/dxos/mesh/signal';
8
8
 
9
- import { type CommandTrace, type SignalStatus } from '../signal-client';
10
- import { type Message, type SignalMethods } from '../signal-methods';
9
+ import { type CommandTrace } from '../signal-client';
10
+ import { type Message, type SignalMethods, type SignalStatus } from '../signal-methods';
11
11
 
12
12
  /**
13
- *
13
+ * Manages a collection of signaling clients.
14
14
  */
15
15
  export interface SignalManager extends SignalMethods {
16
+ open(): Promise<void>;
17
+ close(): Promise<void>;
18
+
19
+ getStatus(): SignalStatus[];
20
+
16
21
  statusChanged: Event<SignalStatus[]>;
17
22
  commandTrace: Event<CommandTrace>;
18
23
  swarmEvent: Event<{ topic: PublicKey; swarmEvent: SwarmEvent }>;
19
24
  onMessage: Event<Message>;
20
-
21
- getStatus(): SignalStatus[];
22
-
23
- open(): Promise<void>;
24
- close(): Promise<void>;
25
25
  }
@@ -13,15 +13,17 @@ import { type Runtime } from '@dxos/protocols/proto/dxos/config';
13
13
  import { type SwarmEvent } from '@dxos/protocols/proto/dxos/mesh/signal';
14
14
 
15
15
  import { type SignalManager } from './signal-manager';
16
- import { type CommandTrace, SignalClient, type SignalStatus } from '../signal-client';
16
+ import { type CommandTrace, SignalClient } from '../signal-client';
17
+ import { type SignalClientMethods, type SignalMethods, type SignalStatus } from '../signal-methods';
17
18
 
18
19
  const MAX_SERVER_FAILURES = 5;
19
20
  const WSS_SIGNAL_SERVER_REBOOT_DELAY = 3_000;
21
+
20
22
  /**
21
23
  * Manages connection to multiple Signal Servers over WebSocket
22
24
  */
23
25
  export class WebsocketSignalManager implements SignalManager {
24
- private readonly _servers = new Map<string, SignalClient>();
26
+ private readonly _servers = new Map<string, SignalClientMethods>();
25
27
 
26
28
  private _ctx!: Context;
27
29
  private _opened = false;
@@ -51,12 +53,15 @@ export class WebsocketSignalManager implements SignalManager {
51
53
  if (this._servers.has(host.server)) {
52
54
  continue;
53
55
  }
56
+
57
+ // TODO(burdon): Create factory to support different variants.
54
58
  const server = new SignalClient(
55
59
  host.server,
56
60
  async (message) => this.onMessage.emit(message),
57
61
  async (data) => this.swarmEvent.emit(data),
58
62
  this._getMetadata,
59
63
  );
64
+
60
65
  server.statusChanged.on(() => this.statusChanged.emit(this.getStatus()));
61
66
 
62
67
  this._servers.set(host.server, server);
@@ -75,6 +80,7 @@ export class WebsocketSignalManager implements SignalManager {
75
80
 
76
81
  this._initContext();
77
82
 
83
+ // TODO(burdon): Await.
78
84
  [...this._servers.values()].forEach((server) => server.open());
79
85
 
80
86
  this._opened = true;
@@ -94,7 +100,7 @@ export class WebsocketSignalManager implements SignalManager {
94
100
  }
95
101
 
96
102
  async restartServer(serverName: string) {
97
- log('Restarting server', { serverName });
103
+ log('restarting server', { serverName });
98
104
  invariant(this._opened, 'server already closed');
99
105
 
100
106
  const server = this._servers.get(serverName);
@@ -111,7 +117,7 @@ export class WebsocketSignalManager implements SignalManager {
111
117
 
112
118
  @synchronized
113
119
  async join({ topic, peerId }: { topic: PublicKey; peerId: PublicKey }) {
114
- log('Join', { topic, peerId });
120
+ log('join', { topic, peerId });
115
121
  invariant(this._opened, 'Closed');
116
122
  await this._forEachServer((server) => server.join({ topic, peerId }));
117
123
  }
@@ -133,7 +139,7 @@ export class WebsocketSignalManager implements SignalManager {
133
139
  recipient: PublicKey;
134
140
  payload: Any;
135
141
  }): Promise<void> {
136
- log(`Signal ${recipient.truncate()}`);
142
+ log('signal', { recipient });
137
143
  invariant(this._opened, 'Closed');
138
144
 
139
145
  void this._forEachServer(async (server, serverName) => {
@@ -155,23 +161,24 @@ export class WebsocketSignalManager implements SignalManager {
155
161
  async checkServerFailure(serverName: string) {
156
162
  const failureCount = this.failureCount.get(serverName!) ?? 0;
157
163
  if (failureCount > MAX_SERVER_FAILURES) {
158
- log.warn(`Too many failures sending to ${serverName} (${failureCount} > ${MAX_SERVER_FAILURES}), restarting`);
164
+ log.warn(`too many failures sending to ${serverName} (${failureCount} > ${MAX_SERVER_FAILURES}), restarting`);
159
165
  await this.restartServer(serverName!);
160
166
  this.failureCount.set(serverName!, 0);
161
167
  return;
162
168
  }
169
+
163
170
  this.failureCount.set(serverName!, (this.failureCount.get(serverName!) ?? 0) + 1);
164
171
  }
165
172
 
166
173
  async subscribeMessages(peerId: PublicKey) {
167
- log(`Subscribed for message stream peerId=${peerId}`);
174
+ log('subscribed for message stream', { peerId });
168
175
  invariant(this._opened, 'Closed');
169
176
 
170
177
  await this._forEachServer(async (server) => server.subscribeMessages(peerId));
171
178
  }
172
179
 
173
180
  async unsubscribeMessages(peerId: PublicKey) {
174
- log(`Subscribed for message stream peerId=${peerId}`);
181
+ log('subscribed for message stream', { peerId });
175
182
  invariant(this._opened, 'Closed');
176
183
 
177
184
  await this._forEachServer(async (server) => server.unsubscribeMessages(peerId));
@@ -184,7 +191,7 @@ export class WebsocketSignalManager implements SignalManager {
184
191
  }
185
192
 
186
193
  private async _forEachServer<ReturnType>(
187
- fn: (server: SignalClient, serverName: string) => Promise<ReturnType>,
194
+ fn: (server: SignalMethods, serverName: string) => Promise<ReturnType>,
188
195
  ): Promise<ReturnType[]> {
189
196
  return Promise.all(Array.from(this._servers.entries()).map(([serverName, server]) => fn(server, serverName)));
190
197
  }
@@ -4,6 +4,7 @@
4
4
 
5
5
  import { type Any } from '@dxos/codec-protobuf';
6
6
  import { type PublicKey } from '@dxos/keys';
7
+ import { type SignalState } from '@dxos/protocols/proto/dxos/mesh/signal';
7
8
 
8
9
  export interface Message {
9
10
  author: PublicKey;
@@ -11,6 +12,18 @@ export interface Message {
11
12
  payload: Any;
12
13
  }
13
14
 
15
+ export type SignalStatus = {
16
+ host: string;
17
+ state: SignalState;
18
+ error?: string;
19
+ reconnectIn: number;
20
+ connectionStarted: Date;
21
+ lastStateChange: Date;
22
+ };
23
+
24
+ /**
25
+ * Message routing interface.
26
+ */
14
27
  export interface SignalMethods {
15
28
  /**
16
29
  * Join topic on signal network, to be discoverable by other peers.
@@ -37,3 +50,12 @@ export interface SignalMethods {
37
50
  */
38
51
  unsubscribeMessages: (peerId: PublicKey) => Promise<void>;
39
52
  }
53
+
54
+ /**
55
+ * Signaling client.
56
+ */
57
+ export interface SignalClientMethods extends SignalMethods {
58
+ open(): Promise<void>;
59
+ close(): Promise<void>;
60
+ getStatus(): SignalStatus;
61
+ }