@dxos/network-manager 0.1.22 → 0.1.24-next.6b1f434

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.
@@ -17,7 +17,7 @@ export declare class ConnectionLog {
17
17
  readonly update: Event<void>;
18
18
  getSwarmInfo(swarmId: PublicKey): SwarmInfo;
19
19
  get swarms(): SwarmInfo[];
20
- swarmJoined(swarm: Swarm): void;
21
- swarmLeft(swarm: Swarm): void;
20
+ joinedSwarm(swarm: Swarm): void;
21
+ leftSwarm(swarm: Swarm): void;
22
22
  }
23
23
  //# sourceMappingURL=connection-log.d.ts.map
@@ -22,7 +22,6 @@ export declare class Swarm {
22
22
  private readonly _messenger;
23
23
  private readonly _transportFactory;
24
24
  private readonly _label;
25
- private readonly _peers;
26
25
  private readonly _swarmMessenger;
27
26
  private _ctx;
28
27
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"swarm.d.ts","sourceRoot":"","sources":["../../../../src/swarm/swarm.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvC,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,wCAAwC,CAAC;AACpE,OAAO,EAAE,MAAM,EAAE,MAAM,uCAAuC,CAAC;AAG/D,OAAO,EAAiB,YAAY,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AACvE,OAAO,EAAmB,QAAQ,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AACjC,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,EAAE,UAAU,EAAmB,MAAM,cAAc,CAAC;AAQ3D;;;;GAIG;AACH,qBAAa,KAAK;IAqCd,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,SAAS;IACjB,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAClC,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAClC,OAAO,CAAC,QAAQ,CAAC,MAAM;IA1CzB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAmD;IAE1E,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAgB;IAEhD,OAAO,CAAC,IAAI,CAAiB;IAE7B;;OAEG;IAEH,QAAQ,CAAC,UAAU,YAAsB;IAoBzC,QAAQ,CAAC,MAAM,cAAqB;gBAMjB,MAAM,EAAE,SAAS,EACjB,UAAU,EAAE,SAAS,EAC9B,SAAS,EAAE,QAAQ,EACV,iBAAiB,EAAE,oBAAoB,EACvC,UAAU,EAAE,SAAS,EACrB,iBAAiB,EAAE,gBAAgB,EACnC,MAAM,EAAE,MAAM,GAAG,SAAS;IAqB7C,IAAI,WAAW,iBAId;IAED,IACI,SAAS,cAEZ;IAED;;OAEG;IACH,IAAI,KAAK,IAAI,MAAM,GAAG,SAAS,CAE9B;IAED,IACI,KAAK,IAAI,KAAK,CAEjB;IAGK,OAAO;IAQP,WAAW,CAAC,QAAQ,EAAE,QAAQ;IAiBpC,YAAY,CAAC,UAAU,EAAE,UAAU;IA6B7B,OAAO,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC;IAwB/C,QAAQ,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAkB/C,SAAS;IAUT,QAAQ;IASd,OAAO,CAAC,gBAAgB;YA8CV,YAAY;IAM1B,OAAO,CAAC,mBAAmB;IAuC3B;;OAEG;YACW,mBAAmB;YAwBnB,gBAAgB;CAQ/B"}
1
+ {"version":3,"file":"swarm.d.ts","sourceRoot":"","sources":["../../../../src/swarm/swarm.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvC,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,wCAAwC,CAAC;AACpE,OAAO,EAAE,MAAM,EAAE,MAAM,uCAAuC,CAAC;AAG/D,OAAO,EAAiB,YAAY,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AACvE,OAAO,EAAmB,QAAQ,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AACjC,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,EAAE,UAAU,EAAmB,MAAM,cAAc,CAAC;AAQ3D;;;;GAIG;AACH,qBAAa,KAAK;IAwCd,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,SAAS;IACjB,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAClC,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAClC,OAAO,CAAC,QAAQ,CAAC,MAAM;IAxCzB,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAgB;IAEhD,OAAO,CAAC,IAAI,CAAiB;IAE7B;;OAEG;IAEH,QAAQ,CAAC,UAAU,YAAsB;IAoBzC,QAAQ,CAAC,MAAM,cAAqB;gBAMjB,MAAM,EAAE,SAAS,EACjB,UAAU,EAAE,SAAS,EAC9B,SAAS,EAAE,QAAQ,EACV,iBAAiB,EAAE,oBAAoB,EACvC,UAAU,EAAE,SAAS,EACrB,iBAAiB,EAAE,gBAAgB,EACnC,MAAM,EAAE,MAAM,GAAG,SAAS;IAqB7C,IAAI,WAAW,iBAId;IAED,IACI,SAAS,cAEZ;IAED;;OAEG;IACH,IAAI,KAAK,IAAI,MAAM,GAAG,SAAS,CAE9B;IAED,IACI,KAAK,IAAI,KAAK,CAEjB;IAGK,OAAO;IAQP,WAAW,CAAC,QAAQ,EAAE,QAAQ;IAiBpC,YAAY,CAAC,UAAU,EAAE,UAAU;IA8B7B,OAAO,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC;IAyB/C,QAAQ,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAmB/C,SAAS;IAOT,QAAQ;IAId,OAAO,CAAC,gBAAgB;YA8CV,YAAY;IAM1B,OAAO,CAAC,mBAAmB;IAuC3B;;OAEG;YACW,mBAAmB;YA0BnB,gBAAgB;CAQ/B"}
@@ -1 +1 @@
1
- {"version":3,"file":"test-wire-protocol.d.ts","sourceRoot":"","sources":["../../../../src/testing/test-wire-protocol.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvC,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAIxC,qBAAa,gBAAgB;aAIC,MAAM,EAAE,SAAS;IAH7C,SAAgB,WAAW,uCAA4D;IACvF,SAAgB,SAAS,mBAA0B;gBAEvB,MAAM,EAAE,SAAS;IAE7C,QAAQ,CAAC,OAAO,kDAUb;IAEG,iBAAiB,CAAC,MAAM,EAAE,SAAS;IASnC,cAAc,CAAC,MAAM,EAAE,SAAS;CAIvC"}
1
+ {"version":3,"file":"test-wire-protocol.d.ts","sourceRoot":"","sources":["../../../../src/testing/test-wire-protocol.ts"],"names":[],"mappings":"AAIA,OAAO,EAAgB,KAAK,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvC,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAIxC,qBAAa,gBAAgB;aAIC,MAAM,EAAE,SAAS;IAH7C,SAAgB,WAAW,uCAA4D;IACvF,SAAgB,SAAS,mBAA0B;gBAEvB,MAAM,EAAE,SAAS;IAE7C,QAAQ,CAAC,OAAO,kDAUb;IAEG,iBAAiB,CAAC,MAAM,EAAE,SAAS;IAYnC,cAAc,CAAC,MAAM,EAAE,SAAS;CAIvC"}
@@ -1 +1 @@
1
- {"version":3,"file":"basic-test-suite.d.ts","sourceRoot":"","sources":["../../../../src/tests/basic-test-suite.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAMzC;;GAEG;AACH,eAAO,MAAM,cAAc,gBAAiB,WAAW,6BAuItD,CAAC"}
1
+ {"version":3,"file":"basic-test-suite.d.ts","sourceRoot":"","sources":["../../../../src/tests/basic-test-suite.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAMzC;;GAEG;AACH,eAAO,MAAM,cAAc,gBAAiB,WAAW,6BAsKtD,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../../src/tests/utils.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtC,OAAO,EAAE,QAAQ,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAC3D,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAMvC;;GAEG;AACH,eAAO,MAAM,qBAAqB,UAAiB,QAAQ,EAAE,kBAK5D,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,SAAS,UAAiB,QAAQ,EAAE,SAAS,SAAS,aAAa,SAAS,QAAQ,CAAC,mCAOjG,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,UAAU,UAAiB,QAAQ,EAAE,SAAS,SAAS,mCAOnE,CAAC;AAEF;;GAEG;AAGH,eAAO,MAAM,gBAAgB,WAAkB,mBAAmB,UAAU,mBAAmB,kBAG9F,CAAC"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../../src/tests/utils.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtC,OAAO,EAAE,QAAQ,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAC3D,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAMvC;;GAEG;AACH,eAAO,MAAM,qBAAqB,UAAiB,QAAQ,EAAE,kBAK5D,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,SAAS,UAAiB,QAAQ,EAAE,SAAS,SAAS,aAAa,SAAS,QAAQ,CAAC,mCAOjG,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,UAAU,UAAiB,QAAQ,EAAE,SAAS,SAAS,mCAOnE,CAAC;AAEF;;GAEG;AAGH,eAAO,MAAM,gBAAgB,WAAkB,mBAAmB,UAAU,mBAAmB,kBAG9F,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dxos/network-manager",
3
- "version": "0.1.22",
3
+ "version": "0.1.24-next.6b1f434",
4
4
  "description": "Network Manager",
5
5
  "homepage": "https://dxos.org",
6
6
  "bugs": "https://github.com/dxos/dxos/issues",
@@ -25,20 +25,20 @@
25
25
  "simple-peer": "9.11.0",
26
26
  "ws": "^7.4.4",
27
27
  "xor-distance": "^2.0.0",
28
- "@dxos/async": "0.1.22",
29
- "@dxos/codec-protobuf": "0.1.22",
30
- "@dxos/context": "0.1.22",
31
- "@dxos/credentials": "0.1.22",
32
- "@dxos/crypto": "0.1.22",
33
- "@dxos/debug": "0.1.22",
34
- "@dxos/keys": "0.1.22",
35
- "@dxos/log": "0.1.22",
36
- "@dxos/messaging": "0.1.22",
37
- "@dxos/node-std": "0.1.22",
38
- "@dxos/protocols": "0.1.22",
39
- "@dxos/rpc": "0.1.22",
40
- "@dxos/teleport": "0.1.22",
41
- "@dxos/util": "0.1.22"
28
+ "@dxos/async": "0.1.24-next.6b1f434",
29
+ "@dxos/codec-protobuf": "0.1.24-next.6b1f434",
30
+ "@dxos/context": "0.1.24-next.6b1f434",
31
+ "@dxos/credentials": "0.1.24-next.6b1f434",
32
+ "@dxos/crypto": "0.1.24-next.6b1f434",
33
+ "@dxos/debug": "0.1.24-next.6b1f434",
34
+ "@dxos/keys": "0.1.24-next.6b1f434",
35
+ "@dxos/log": "0.1.24-next.6b1f434",
36
+ "@dxos/messaging": "0.1.24-next.6b1f434",
37
+ "@dxos/node-std": "0.1.24-next.6b1f434",
38
+ "@dxos/protocols": "0.1.24-next.6b1f434",
39
+ "@dxos/rpc": "0.1.24-next.6b1f434",
40
+ "@dxos/teleport": "0.1.24-next.6b1f434",
41
+ "@dxos/util": "0.1.24-next.6b1f434"
42
42
  },
43
43
  "devDependencies": {
44
44
  "@swc-node/register": "^1.5.4",
@@ -48,7 +48,7 @@
48
48
  "earljs": "~0.1.10",
49
49
  "fast-check": "~3.3.0",
50
50
  "typescript": "^4.8.4",
51
- "@dxos/signal": "0.1.22"
51
+ "@dxos/signal": "0.1.24-next.6b1f434"
52
52
  },
53
53
  "publishConfig": {
54
54
  "access": "public"
@@ -34,7 +34,7 @@ export class ConnectionLog {
34
34
  return Array.from(this._swarms.values());
35
35
  }
36
36
 
37
- swarmJoined(swarm: Swarm) {
37
+ joinedSwarm(swarm: Swarm) {
38
38
  const info: SwarmInfo = {
39
39
  id: swarm.instanceId,
40
40
  topic: swarm.topic,
@@ -95,7 +95,7 @@ export class ConnectionLog {
95
95
  });
96
96
  }
97
97
 
98
- swarmLeft(swarm: Swarm) {
98
+ leftSwarm(swarm: Swarm) {
99
99
  this.getSwarmInfo(swarm.instanceId).isActive = false;
100
100
  this.update.emit();
101
101
  }
@@ -170,7 +170,7 @@ export class NetworkManager {
170
170
  this._mappers.set(topic, new SwarmMapper(swarm));
171
171
 
172
172
  this.topicsUpdated.emit();
173
- this._connectionLog?.swarmJoined(swarm);
173
+ this._connectionLog?.joinedSwarm(swarm);
174
174
  log('joined', { topic: PublicKey.from(topic), count: this._swarms.size });
175
175
 
176
176
  return {
@@ -195,7 +195,7 @@ export class NetworkManager {
195
195
  map.destroy();
196
196
  this._mappers.delete(topic);
197
197
 
198
- this._connectionLog?.swarmLeft(swarm);
198
+ this._connectionLog?.leftSwarm(swarm);
199
199
 
200
200
  await swarm.destroy();
201
201
  this._swarms.delete(topic);
@@ -213,17 +213,17 @@ export class NetworkManager {
213
213
  case ConnectionState.OFFLINE: {
214
214
  this._connectionState = state;
215
215
  // go offline
216
+ await Promise.all([...this._swarms.values()].map((swarm) => swarm.goOffline()));
216
217
  await this._messenger.close();
217
218
  await this._signalManager.close();
218
- await Promise.all([...this._swarms.values()].map((swarm) => swarm.goOffline()));
219
219
  break;
220
220
  }
221
221
  case ConnectionState.ONLINE: {
222
222
  this._connectionState = state;
223
223
  // go online
224
224
  this._messenger.open();
225
- await this._signalManager.open();
226
225
  await Promise.all([...this._swarms.values()].map((swarm) => swarm.goOnline()));
226
+ await this._signalManager.open();
227
227
  break;
228
228
  }
229
229
  }
@@ -33,7 +33,10 @@ const getClassName = (obj: any) => Object.getPrototypeOf(obj).constructor.name;
33
33
  * Routes signal events and maintains swarm topology.
34
34
  */
35
35
  export class Swarm {
36
- private readonly _peers = new ComplexMap<PublicKey, Peer>(PublicKey.hash);
36
+ /**
37
+ * @internal
38
+ */
39
+ readonly _peers = new ComplexMap<PublicKey, Peer>(PublicKey.hash);
37
40
 
38
41
  private readonly _swarmMessenger: MessageRouter;
39
42
 
@@ -148,11 +151,12 @@ export class Swarm {
148
151
  onSwarmEvent(swarmEvent: SwarmEvent) {
149
152
  log('swarm event', { swarmEvent }); // TODO(burdon): Stringify.
150
153
 
154
+ if (this._ctx.disposed) {
155
+ log('swarm event ignored for disposed swarm');
156
+ return;
157
+ }
158
+
151
159
  if (swarmEvent.peerAvailable) {
152
- if (this._ctx.disposed) {
153
- log.warn('ignored for offline swarm');
154
- return;
155
- }
156
160
  const peerId = PublicKey.from(swarmEvent.peerAvailable.peer);
157
161
  log('new peer', { peerId });
158
162
  if (!peerId.equals(this._ownPeerId)) {
@@ -163,7 +167,7 @@ export class Swarm {
163
167
  const peer = this._peers.get(PublicKey.from(swarmEvent.peerLeft.peer));
164
168
  if (peer) {
165
169
  peer.advertizing = false;
166
- if (!peer.connection || peer.connection.state !== ConnectionState.CONNECTED) {
170
+ if (peer.connection?.state !== ConnectionState.CONNECTED) {
167
171
  // Destroy peer only if there is no p2p-connection established
168
172
  void this._destroyPeer(peer.id).catch((err) => log.catch(err));
169
173
  }
@@ -177,7 +181,7 @@ export class Swarm {
177
181
  async onOffer(message: OfferMessage): Promise<Answer> {
178
182
  log('offer', { message });
179
183
  if (this._ctx.disposed) {
180
- log.info('ignored for offline swarm');
184
+ log('ignored for disposed swarm');
181
185
  return { accept: false };
182
186
  }
183
187
 
@@ -198,6 +202,7 @@ export class Swarm {
198
202
  return answer;
199
203
  }
200
204
 
205
+ @synchronized
201
206
  async onSignal(message: SignalMessage): Promise<void> {
202
207
  log('signal', { message });
203
208
  if (this._ctx.disposed) {
@@ -216,23 +221,16 @@ export class Swarm {
216
221
  }
217
222
 
218
223
  // For debug purposes
224
+ @synchronized
219
225
  async goOffline() {
220
226
  await this._ctx.dispose();
221
- [...this._peers.values()].forEach((peer) => {
222
- peer.advertizing = false;
223
- });
224
- await Promise.all([...this._peers.keys()].map((peerId) => this._closeConnection(peerId)));
227
+ await Promise.all([...this._peers.keys()].map((peerId) => this._destroyPeer(peerId)));
225
228
  }
226
229
 
227
230
  // For debug purposes
228
231
  @synchronized
229
232
  async goOnline() {
230
233
  this._ctx = new Context();
231
-
232
- [...this._peers.values()].forEach((peer) => {
233
- peer.advertizing = true;
234
- });
235
- this._topology.update();
236
234
  }
237
235
 
238
236
  private _getOrCreatePeer(peerId: PublicKey): Peer {
@@ -330,13 +328,15 @@ export class Swarm {
330
328
  * Creates a connection then sends message over signal network.
331
329
  */
332
330
  private async _initiateConnection(remoteId: PublicKey) {
331
+ const ctx = this._ctx; // Copy to avoid getting reset while sleeping.
332
+
333
333
  // It is likely that the other peer will also try to connect to us at the same time.
334
334
  // If our peerId is higher, we will wait for a bit so that other peer has a chance to connect first.
335
335
  if (remoteId.toHex() < this._ownPeerId.toHex()) {
336
336
  log('initiation delay', { remoteId });
337
337
  await sleep(INITIATION_DELAY);
338
338
  }
339
- if (this._ctx.disposed) {
339
+ if (ctx.disposed) {
340
340
  return;
341
341
  }
342
342
 
@@ -2,7 +2,7 @@
2
2
  // Copyright 2022 DXOS.org
3
3
  //
4
4
 
5
- import { Event } from '@dxos/async';
5
+ import { asyncTimeout, Event } from '@dxos/async';
6
6
  import { PublicKey } from '@dxos/keys';
7
7
  import { log } from '@dxos/log';
8
8
  import { TestExtension } from '@dxos/teleport';
@@ -33,7 +33,10 @@ export class TestWireProtocol {
33
33
  return this.connections.get(peerId)!;
34
34
  }
35
35
  log('waitForConnection', { peerId });
36
- await this.connected.waitFor((connectedId) => connectedId.equals(peerId));
36
+ await asyncTimeout(
37
+ this.connected.waitFor((connectedId) => connectedId.equals(peerId)),
38
+ 1_000
39
+ );
37
40
  return this.connections.get(peerId)!;
38
41
  }
39
42
 
@@ -3,7 +3,9 @@
3
3
  //
4
4
 
5
5
  import { expect } from 'chai';
6
+ import waitForExpect from 'wait-for-expect';
6
7
 
8
+ import { asyncTimeout } from '@dxos/async';
7
9
  import { PublicKey } from '@dxos/keys';
8
10
  import { log } from '@dxos/log';
9
11
  import { afterTest, test } from '@dxos/test';
@@ -75,7 +77,7 @@ export const basicTestSuite = (testBuilder: TestBuilder, runTests = true) => {
75
77
  }
76
78
  });
77
79
 
78
- test.skip('joins multiple swarms', async () => {
80
+ test('joins multiple swarms', async () => {
79
81
  // TODO(burdon): N peers.
80
82
  // TODO(burdon): Merge with test below.
81
83
  const peer1 = testBuilder.createPeer();
@@ -87,7 +89,7 @@ export const basicTestSuite = (testBuilder: TestBuilder, runTests = true) => {
87
89
  expect(topics).to.have.length(numSwarms);
88
90
  });
89
91
 
90
- test.skip('joins multiple swarms concurrently', async () => {
92
+ test('joins multiple swarms concurrently', async () => {
91
93
  const createSwarm = async () => {
92
94
  const topicA = PublicKey.random();
93
95
  const peer1a = testBuilder.createPeer();
@@ -105,7 +107,7 @@ export const basicTestSuite = (testBuilder: TestBuilder, runTests = true) => {
105
107
 
106
108
  await Promise.all([
107
109
  test1.swarm1a.protocol.testConnection(test1.peer2a.peerId),
108
- test2.swarm1a.protocol.testConnection(test1.peer2a.peerId)
110
+ test2.swarm1a.protocol.testConnection(test2.peer2a.peerId)
109
111
  ]);
110
112
  });
111
113
 
@@ -114,43 +116,74 @@ export const basicTestSuite = (testBuilder: TestBuilder, runTests = true) => {
114
116
  const peer2 = testBuilder.createPeer();
115
117
  await openAndCloseAfterTest([peer1, peer2]);
116
118
 
117
- const topic1 = PublicKey.random();
119
+ const topic = PublicKey.random();
118
120
 
119
- const [swarm1, swarm2] = await joinSwarm([peer1, peer2], topic1);
121
+ const [swarm1, swarm2] = await joinSwarm([peer1, peer2], topic);
120
122
  await exchangeMessages(swarm1, swarm2);
121
123
 
122
124
  //
123
125
  // Going offline and back online
124
126
  //
125
- const peerLeft = peer2._networkManager.signalManager.swarmEvent.waitFor((event) => !!event.swarmEvent.peerLeft);
127
+ const connectionDropped = peer2._networkManager
128
+ .getSwarm(topic)
129
+ ?.disconnected.waitFor((peerId) => peerId.equals(peer1.peerId));
130
+
131
+ const peerLeft = peer2._networkManager.signalManager.swarmEvent.waitFor(
132
+ (event) => !!event.swarmEvent.peerLeft && peer1.peerId.equals(event.swarmEvent.peerLeft?.peer)
133
+ );
134
+
126
135
  await peer1.goOffline();
136
+ await connectionDropped;
127
137
  await peerLeft;
138
+
139
+ // Wait for peer to be removed from the swarm.
140
+ await waitForExpect(() => {
141
+ expect(!!peer2._networkManager.getSwarm(topic)!._peers.get(peer1.peerId)?.advertizing).to.be.false;
142
+ }, 1_000);
143
+
128
144
  await peer1.goOnline();
129
145
 
146
+ await waitForExpect(() => {
147
+ expect(peer1._networkManager.getSwarm(topic)?._peers.get(peer2.peerId)?.advertizing).to.be.true;
148
+
149
+ expect(peer2._networkManager.getSwarm(topic)?._peers.get(peer1.peerId)?.advertizing).to.be.true;
150
+ }, 2_000);
151
+
130
152
  await exchangeMessages(swarm1, swarm2);
131
- await leaveSwarm([peer1, peer2], topic1);
132
- }).timeout(2_000);
153
+ await leaveSwarm([peer1, peer2], topic);
154
+ })
155
+ .tag('e2e')
156
+ .timeout(2_000);
133
157
 
134
- // TODO(mykola): broken.
158
+ // TODO(mykola): Fails with large amount of peers ~10.
159
+ // Time wasted: 1 hour (increment when you work on it).
135
160
  test.skip('many peers and connections', async () => {
136
- const numTopics = 5;
137
- const peersPerTopic = 5;
138
-
139
- await Promise.all(
140
- range(numTopics).map(async () => {
141
- const topic = PublicKey.random();
142
-
143
- await Promise.all(
144
- range(peersPerTopic).map(async () => {
145
- const peer = testBuilder.createPeer();
146
- await openAndCloseAfterTest([peer]);
147
- const swarm = await peer.createSwarm(topic).join();
148
- await swarm.protocol.connected.waitForCondition(
149
- () => swarm.protocol.connections.size === peersPerTopic - 1
150
- );
151
- })
152
- );
153
- })
161
+ const numTopics = 2;
162
+ const peersPerTopic = 3;
163
+ const swarmsAllPeersConnected: Promise<any>[] = [];
164
+
165
+ await asyncTimeout(
166
+ Promise.all(
167
+ range(numTopics).map(async () => {
168
+ const topic = PublicKey.random();
169
+
170
+ return Promise.all(
171
+ range(peersPerTopic).map(async () => {
172
+ const peer = testBuilder.createPeer();
173
+ await openAndCloseAfterTest([peer]);
174
+ const swarm = peer.createSwarm(topic);
175
+
176
+ swarmsAllPeersConnected.push(
177
+ swarm.protocol.connected.waitFor(() => swarm.protocol.connections.size === peersPerTopic - 1)
178
+ );
179
+ await swarm.join();
180
+ })
181
+ );
182
+ })
183
+ ),
184
+ 2_000
154
185
  );
186
+
187
+ await asyncTimeout(Promise.all(swarmsAllPeersConnected), 2_000);
155
188
  });
156
189
  };
@@ -2,6 +2,7 @@
2
2
  // Copyright 2022 DXOS.org
3
3
  //
4
4
 
5
+ import { asyncTimeout } from '@dxos/async';
5
6
  import { PublicKey } from '@dxos/keys';
6
7
  import { afterTest } from '@dxos/test';
7
8
  import { Provider } from '@dxos/util';
@@ -19,7 +20,7 @@ import { Topology } from '../topology';
19
20
  export const openAndCloseAfterTest = async (peers: TestPeer[]) => {
20
21
  await Promise.all(peers.map((peer) => peer.open()));
21
22
  afterTest(async () => {
22
- await Promise.all(peers.map((peer) => peer.close()));
23
+ await asyncTimeout(Promise.all(peers.map((peer) => peer.close())), 1_000);
23
24
  });
24
25
  };
25
26
 
@@ -10,10 +10,7 @@ describe('WebRTC transport', () => {
10
10
  basicTestSuite(testBuilder);
11
11
  }).timeout(10_000);
12
12
 
13
- /*
14
- // TODO(burdon): Flaky.
15
13
  describe('WebRTC transport proxy', () => {
16
14
  const testBuilder = new TestBuilder({ signalHosts: [TEST_SIGNAL_URL], bridge: true });
17
15
  basicTestSuite(testBuilder);
18
16
  }).timeout(10_000);
19
- */
@@ -16,8 +16,7 @@ import { afterAll, afterTest, beforeAll, describe, test } from '@dxos/test';
16
16
  import { WebRTCTransportProxy } from './webrtc-transport-proxy';
17
17
  import { WebRTCTransportService } from './webrtc-transport-service';
18
18
 
19
- // TODO(burdon): Flaky.
20
- describe.skip('WebRTCTransportProxy', () => {
19
+ describe('WebRTCTransportProxy', () => {
21
20
  const setupProxy = async ({
22
21
  initiator = true,
23
22
  stream = new TestStream(),
@@ -91,7 +90,7 @@ describe.skip('WebRTCTransportProxy', () => {
91
90
  expect(callsCounter).toEqual(1);
92
91
  })
93
92
  .timeout(1_000)
94
- .retries(3);
93
+ .tag('e2e');
95
94
 
96
95
  test('establish connection and send data through with protocol', async () => {
97
96
  const stream1 = new TestStream();
@@ -118,7 +117,7 @@ describe.skip('WebRTCTransportProxy', () => {
118
117
  await TestStream.assertConnectivity(stream1, stream2);
119
118
  })
120
119
  .timeout(2_000)
121
- .retries(3);
120
+ .tag('e2e');
122
121
 
123
122
  describe('Multiplexing', () => {
124
123
  let service: any;
@@ -186,7 +185,7 @@ describe.skip('WebRTCTransportProxy', () => {
186
185
 
187
186
  await TestStream.assertConnectivity(stream1, stream2);
188
187
  })
189
- .timeout(5_000)
190
- .retries(3);
188
+ .timeout(3_000)
189
+ .tag('e2e');
191
190
  });
192
191
  });