@waku/core 0.0.19 → 0.0.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,26 @@ All notable changes to this project will be documented in this file.
5
5
  The file is maintained by [Release Please](https://github.com/googleapis/release-please) based on [Conventional Commits](https://www.conventionalcommits.org) specification,
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.0.20](https://github.com/waku-org/js-waku/compare/core-v0.0.19...core-v0.0.20) (2023-06-08)
9
+
10
+
11
+ ### ⚠ BREAKING CHANGES
12
+
13
+ * rename package from @waku/create to @waku/sdk ([#1386](https://github.com/waku-org/js-waku/issues/1386))
14
+
15
+ ### Features
16
+
17
+ * Allow passing of multiple ENR URLs to DNS Discovery & dial multiple peers in parallel ([#1379](https://github.com/waku-org/js-waku/issues/1379)) ([f32d7d9](https://github.com/waku-org/js-waku/commit/f32d7d9fe0b930b4fa9c46b8644e6d21be45d5c1))
18
+ * Rename package from @waku/create to @waku/sdk ([#1386](https://github.com/waku-org/js-waku/issues/1386)) ([951ebda](https://github.com/waku-org/js-waku/commit/951ebdac9d5b594583acf5e4a21f6471fa81ff74))
19
+
20
+
21
+ ### Dependencies
22
+
23
+ * The following workspace dependencies were updated
24
+ * dependencies
25
+ * @waku/interfaces bumped from 0.0.14 to 0.0.15
26
+ * @waku/utils bumped from 0.0.7 to 0.0.8
27
+
8
28
  ## [0.0.19](https://github.com/waku-org/js-waku/compare/core-v0.0.18...core-v0.0.19) (2023-05-26)
9
29
 
10
30
 
package/bundle/index.js CHANGED
@@ -3041,6 +3041,7 @@ class KeepAliveManager {
3041
3041
  const log$6 = debug("waku:connection-manager");
3042
3042
  const DEFAULT_MAX_BOOTSTRAP_PEERS_ALLOWED = 1;
3043
3043
  const DEFAULT_MAX_DIAL_ATTEMPTS_FOR_PEER = 3;
3044
+ const DEFAULT_MAX_PARALLEL_DIALS = 3;
3044
3045
  class ConnectionManager {
3045
3046
  static instances = new Map();
3046
3047
  keepAliveManager;
@@ -3048,6 +3049,8 @@ class ConnectionManager {
3048
3049
  libp2pComponents;
3049
3050
  dialAttemptsForPeer = new Map();
3050
3051
  dialErrorsForPeer = new Map();
3052
+ currentActiveDialCount = 0;
3053
+ pendingPeerDialQueue = [];
3051
3054
  static create(peerId, libp2p, keepAliveOptions, relay, options) {
3052
3055
  let instance = ConnectionManager.instances.get(peerId);
3053
3056
  if (!instance) {
@@ -3061,12 +3064,34 @@ class ConnectionManager {
3061
3064
  this.options = {
3062
3065
  maxDialAttemptsForPeer: DEFAULT_MAX_DIAL_ATTEMPTS_FOR_PEER,
3063
3066
  maxBootstrapPeersAllowed: DEFAULT_MAX_BOOTSTRAP_PEERS_ALLOWED,
3067
+ maxParallelDials: DEFAULT_MAX_PARALLEL_DIALS,
3064
3068
  ...options,
3065
3069
  };
3066
3070
  this.keepAliveManager = new KeepAliveManager(keepAliveOptions, relay);
3067
3071
  this.run()
3068
3072
  .then(() => log$6(`Connection Manager is now running`))
3069
3073
  .catch((error) => log$6(`Unexpected error while running service`, error));
3074
+ // libp2p emits `peer:discovery` events during its initialization
3075
+ // which means that before the ConnectionManager is initialized, some peers may have been discovered
3076
+ // we will dial the peers in peerStore ONCE before we start to listen to the `peer:discovery` events within the ConnectionManager
3077
+ this.dialPeerStorePeers();
3078
+ }
3079
+ async dialPeerStorePeers() {
3080
+ const peerInfos = await this.libp2pComponents.peerStore.all();
3081
+ const dialPromises = [];
3082
+ for (const peerInfo of peerInfos) {
3083
+ if (this.libp2pComponents
3084
+ .getConnections()
3085
+ .find((c) => c.remotePeer === peerInfo.id))
3086
+ continue;
3087
+ dialPromises.push(this.attemptDial(peerInfo.id));
3088
+ }
3089
+ try {
3090
+ await Promise.all(dialPromises);
3091
+ }
3092
+ catch (error) {
3093
+ log$6(`Unexpected error while dialing peer store peers`, error);
3094
+ }
3070
3095
  }
3071
3096
  async run() {
3072
3097
  // start event listeners
@@ -3081,6 +3106,7 @@ class ConnectionManager {
3081
3106
  this.libp2pComponents.removeEventListener("peer:discovery", this.onEventHandlers["peer:discovery"]);
3082
3107
  }
3083
3108
  async dialPeer(peerId) {
3109
+ this.currentActiveDialCount += 1;
3084
3110
  let dialAttempt = 0;
3085
3111
  while (dialAttempt <= this.options.maxDialAttemptsForPeer) {
3086
3112
  try {
@@ -3115,6 +3141,30 @@ class ConnectionManager {
3115
3141
  catch (error) {
3116
3142
  throw `Error deleting undialable peer ${peerId.toString()} from peer store - ${error}`;
3117
3143
  }
3144
+ finally {
3145
+ this.currentActiveDialCount -= 1;
3146
+ this.processDialQueue();
3147
+ }
3148
+ }
3149
+ async dropConnection(peerId) {
3150
+ try {
3151
+ await this.libp2pComponents.hangUp(peerId);
3152
+ log$6(`Dropped connection with peer ${peerId.toString()}`);
3153
+ }
3154
+ catch (error) {
3155
+ log$6(`Error dropping connection with peer ${peerId.toString()} - ${error}`);
3156
+ }
3157
+ }
3158
+ async processDialQueue() {
3159
+ if (this.pendingPeerDialQueue.length > 0 &&
3160
+ this.currentActiveDialCount < this.options.maxParallelDials) {
3161
+ const peerId = this.pendingPeerDialQueue.shift();
3162
+ if (!peerId)
3163
+ return;
3164
+ this.attemptDial(peerId).catch((error) => {
3165
+ log$6(error);
3166
+ });
3167
+ }
3118
3168
  }
3119
3169
  startPeerDiscoveryListener() {
3120
3170
  this.libp2pComponents.peerStore.addEventListener("peer", this.onEventHandlers["peer:discovery"]);
@@ -3137,16 +3187,34 @@ class ConnectionManager {
3137
3187
  */
3138
3188
  this.libp2pComponents.addEventListener("peer:disconnect", this.onEventHandlers["peer:disconnect"]);
3139
3189
  }
3190
+ async attemptDial(peerId) {
3191
+ if (this.currentActiveDialCount >= this.options.maxParallelDials) {
3192
+ this.pendingPeerDialQueue.push(peerId);
3193
+ return;
3194
+ }
3195
+ if (!(await this.shouldDialPeer(peerId)))
3196
+ return;
3197
+ this.dialPeer(peerId).catch((err) => {
3198
+ throw `Error dialing peer ${peerId.toString()} : ${err}`;
3199
+ });
3200
+ }
3140
3201
  onEventHandlers = {
3141
3202
  "peer:discovery": async (evt) => {
3142
3203
  const { id: peerId } = evt.detail;
3143
- if (!(await this.shouldDialPeer(peerId)))
3144
- return;
3145
- this.dialPeer(peerId).catch((err) => log$6(`Error dialing peer ${peerId.toString()} : ${err}`));
3204
+ this.attemptDial(peerId).catch((err) => log$6(`Error dialing peer ${peerId.toString()} : ${err}`));
3146
3205
  },
3147
- "peer:connect": (evt) => {
3148
- {
3149
- this.keepAliveManager.start(evt.detail.remotePeer, this.libp2pComponents.ping.bind(this));
3206
+ "peer:connect": async (evt) => {
3207
+ const { remotePeer: peerId } = evt.detail;
3208
+ this.keepAliveManager.start(peerId, this.libp2pComponents.ping.bind(this));
3209
+ const isBootstrap = (await this.getTagNamesForPeer(peerId)).includes(Tags.BOOTSTRAP);
3210
+ if (isBootstrap) {
3211
+ const bootstrapConnections = this.libp2pComponents
3212
+ .getConnections()
3213
+ .filter((conn) => conn.tags.includes(Tags.BOOTSTRAP));
3214
+ // If we have too many bootstrap connections, drop one
3215
+ if (bootstrapConnections.length > this.options.maxBootstrapPeersAllowed) {
3216
+ await this.dropConnection(peerId);
3217
+ }
3150
3218
  }
3151
3219
  },
3152
3220
  "peer:disconnect": () => {
@@ -3397,11 +3465,11 @@ const isSizeValid = (payload) => {
3397
3465
  return true;
3398
3466
  };
3399
3467
 
3400
- function isAsyncIterable$1(thing) {
3468
+ function isAsyncIterable$3(thing) {
3401
3469
  return thing[Symbol.asyncIterator] != null;
3402
3470
  }
3403
3471
  function all(source) {
3404
- if (isAsyncIterable$1(source)) {
3472
+ if (isAsyncIterable$3(source)) {
3405
3473
  return (async () => {
3406
3474
  const arr = [];
3407
3475
  for await (const entry of source) {
@@ -4158,7 +4226,7 @@ const unsigned = {
4158
4226
  }
4159
4227
  };
4160
4228
 
4161
- function isAsyncIterable(thing) {
4229
+ function isAsyncIterable$2(thing) {
4162
4230
  return thing[Symbol.asyncIterator] != null;
4163
4231
  }
4164
4232
 
@@ -4191,7 +4259,7 @@ function encode(source, options) {
4191
4259
  yield* chunk;
4192
4260
  }
4193
4261
  }
4194
- if (isAsyncIterable(source)) {
4262
+ if (isAsyncIterable$2(source)) {
4195
4263
  return (async function* () {
4196
4264
  for await (const chunk of source) {
4197
4265
  yield* maybeYield(chunk);
@@ -4347,7 +4415,7 @@ function decode(source, options) {
4347
4415
  }
4348
4416
  }
4349
4417
  }
4350
- if (isAsyncIterable(source)) {
4418
+ if (isAsyncIterable$2(source)) {
4351
4419
  return (async function* () {
4352
4420
  for await (const buf of source) {
4353
4421
  buffer.append(buf);
@@ -4662,77 +4730,56 @@ function _pushable(getNext, options) {
4662
4730
  return pushable;
4663
4731
  }
4664
4732
 
4665
- /**
4666
- * Treat one or more iterables as a single iterable.
4667
- *
4668
- * Nb. sources are iterated over in parallel so the
4669
- * order of emitted items is not guaranteed.
4670
- */
4671
- async function* merge(...sources) {
4672
- const output = pushable({
4673
- objectMode: true
4674
- });
4675
- void Promise.resolve().then(async () => {
4676
- try {
4677
- await Promise.all(sources.map(async (source) => {
4678
- for await (const item of source) {
4679
- output.push(item);
4680
- }
4681
- }));
4682
- output.end();
4683
- }
4684
- catch (err) {
4685
- output.end(err);
4733
+ function isAsyncIterable$1(thing) {
4734
+ return thing[Symbol.asyncIterator] != null;
4735
+ }
4736
+ function merge(...sources) {
4737
+ const syncSources = [];
4738
+ for (const source of sources) {
4739
+ if (!isAsyncIterable$1(source)) {
4740
+ syncSources.push(source);
4686
4741
  }
4687
- });
4688
- yield* output;
4742
+ }
4743
+ if (syncSources.length === sources.length) {
4744
+ // all sources are synchronous
4745
+ return (function* () {
4746
+ for (const source of syncSources) {
4747
+ yield* source;
4748
+ }
4749
+ })();
4750
+ }
4751
+ return (async function* () {
4752
+ const output = pushable({
4753
+ objectMode: true
4754
+ });
4755
+ void Promise.resolve().then(async () => {
4756
+ try {
4757
+ await Promise.all(sources.map(async (source) => {
4758
+ for await (const item of source) {
4759
+ output.push(item);
4760
+ }
4761
+ }));
4762
+ output.end();
4763
+ }
4764
+ catch (err) {
4765
+ output.end(err);
4766
+ }
4767
+ });
4768
+ yield* output;
4769
+ })();
4689
4770
  }
4690
4771
 
4691
- const rawPipe = (...fns) => {
4692
- let res;
4693
- while (fns.length > 0) {
4694
- res = fns.shift()(res);
4695
- }
4696
- return res;
4697
- };
4698
- const isIterable = (obj) => {
4699
- return obj != null && (typeof obj[Symbol.asyncIterator] === 'function' ||
4700
- typeof obj[Symbol.iterator] === 'function' ||
4701
- typeof obj.next === 'function' // Probably, right?
4702
- );
4703
- };
4704
- const isDuplex = (obj) => {
4705
- return obj != null && typeof obj.sink === 'function' && isIterable(obj.source);
4706
- };
4707
- const duplexPipelineFn = (duplex) => {
4708
- return (source) => {
4709
- const p = duplex.sink(source);
4710
- if (p.then != null) {
4711
- const stream = pushable({
4712
- objectMode: true
4713
- });
4714
- p.then(() => {
4715
- stream.end();
4716
- }, (err) => {
4717
- stream.end(err);
4718
- });
4719
- const sourceWrap = async function* () {
4720
- yield* duplex.source;
4721
- stream.end();
4722
- };
4723
- return merge(stream, sourceWrap());
4724
- }
4725
- return duplex.source;
4726
- };
4727
- };
4728
4772
  function pipe(first, ...rest) {
4773
+ if (first == null) {
4774
+ throw new Error('Empty pipeline');
4775
+ }
4729
4776
  // Duplex at start: wrap in function and return duplex source
4730
4777
  if (isDuplex(first)) {
4731
4778
  const duplex = first;
4732
4779
  first = () => duplex.source;
4733
4780
  // Iterable at start: wrap in function
4734
4781
  }
4735
- else if (isIterable(first)) {
4782
+ else if (isIterable(first) || isAsyncIterable(first)) {
4736
4783
  const source = first;
4737
4784
  first = () => source;
4738
4785
  }
@@ -4753,6 +4800,59 @@ function pipe(first, ...rest) {
4753
4800
  }
4754
4801
  return rawPipe(...fns);
4755
4802
  }
4803
+ const rawPipe = (...fns) => {
4804
+ let res;
4805
+ while (fns.length > 0) {
4806
+ res = fns.shift()(res);
4807
+ }
4808
+ return res;
4809
+ };
4810
+ const isAsyncIterable = (obj) => {
4811
+ return obj?.[Symbol.asyncIterator] != null;
4812
+ };
4813
+ const isIterable = (obj) => {
4814
+ return obj?.[Symbol.iterator] != null;
4815
+ };
4816
+ const isDuplex = (obj) => {
4817
+ if (obj == null) {
4818
+ return false;
4819
+ }
4820
+ return obj.sink != null && obj.source != null;
4821
+ };
4822
+ const duplexPipelineFn = (duplex) => {
4823
+ return (source) => {
4824
+ const p = duplex.sink(source);
4825
+ if (p?.then != null) {
4826
+ const stream = pushable({
4827
+ objectMode: true
4828
+ });
4829
+ p.then(() => {
4830
+ stream.end();
4831
+ }, (err) => {
4832
+ stream.end(err);
4833
+ });
4834
+ let sourceWrap;
4835
+ const source = duplex.source;
4836
+ if (isAsyncIterable(source)) {
4837
+ sourceWrap = async function* () {
4838
+ yield* source;
4839
+ stream.end();
4840
+ };
4841
+ }
4842
+ else if (isIterable(source)) {
4843
+ sourceWrap = function* () {
4844
+ yield* source;
4845
+ stream.end();
4846
+ };
4847
+ }
4848
+ else {
4849
+ throw new Error('Unknown duplex source type - must be Iterable or AsyncIterable');
4850
+ }
4851
+ return merge(stream, sourceWrap());
4852
+ }
4853
+ return duplex.source;
4854
+ };
4855
+ };
4756
4856
 
4757
4857
  const EmptyMessage = {
4758
4858
  payload: new Uint8Array(),
@@ -6313,7 +6413,7 @@ const log = debug("waku:wait-for-remote-peer");
6313
6413
  * Wait for a remote peer to be ready given the passed protocols.
6314
6414
  * Must be used after attempting to connect to nodes, using
6315
6415
  * {@link @waku/core.WakuNode.dial} or a bootstrap method with
6316
- * {@link @waku/create.createLightNode}.
6416
+ * {@link @waku/sdk.createLightNode}.
6317
6417
  *
6318
6418
  * If the passed protocols is a GossipSub protocol, then it resolves only once
6319
6419
  * a peer is in a mesh, to help ensure that other peers will send and receive
@@ -1,8 +1,10 @@
1
1
  import type { Libp2p } from "@libp2p/interface-libp2p";
2
+ import type { PeerId } from "@libp2p/interface-peer-id";
2
3
  import type { ConnectionManagerOptions, IRelay } from "@waku/interfaces";
3
4
  import { KeepAliveOptions } from "./keep_alive_manager.js";
4
5
  export declare const DEFAULT_MAX_BOOTSTRAP_PEERS_ALLOWED = 1;
5
6
  export declare const DEFAULT_MAX_DIAL_ATTEMPTS_FOR_PEER = 3;
7
+ export declare const DEFAULT_MAX_PARALLEL_DIALS = 3;
6
8
  export declare class ConnectionManager {
7
9
  private static instances;
8
10
  private keepAliveManager;
@@ -10,14 +12,20 @@ export declare class ConnectionManager {
10
12
  private libp2pComponents;
11
13
  private dialAttemptsForPeer;
12
14
  private dialErrorsForPeer;
15
+ private currentActiveDialCount;
16
+ private pendingPeerDialQueue;
13
17
  static create(peerId: string, libp2p: Libp2p, keepAliveOptions: KeepAliveOptions, relay?: IRelay, options?: ConnectionManagerOptions): ConnectionManager;
14
18
  private constructor();
19
+ private dialPeerStorePeers;
15
20
  private run;
16
21
  stop(): void;
17
22
  private dialPeer;
23
+ dropConnection(peerId: PeerId): Promise<void>;
24
+ private processDialQueue;
18
25
  private startPeerDiscoveryListener;
19
26
  private startPeerConnectionListener;
20
27
  private startPeerDisconnectionListener;
28
+ private attemptDial;
21
29
  private onEventHandlers;
22
30
  /**
23
31
  * Checks if the peer is dialable based on the following conditions:
@@ -4,6 +4,7 @@ import { KeepAliveManager } from "./keep_alive_manager.js";
4
4
  const log = debug("waku:connection-manager");
5
5
  export const DEFAULT_MAX_BOOTSTRAP_PEERS_ALLOWED = 1;
6
6
  export const DEFAULT_MAX_DIAL_ATTEMPTS_FOR_PEER = 3;
7
+ export const DEFAULT_MAX_PARALLEL_DIALS = 3;
7
8
  class ConnectionManager {
8
9
  static instances = new Map();
9
10
  keepAliveManager;
@@ -11,6 +12,8 @@ class ConnectionManager {
11
12
  libp2pComponents;
12
13
  dialAttemptsForPeer = new Map();
13
14
  dialErrorsForPeer = new Map();
15
+ currentActiveDialCount = 0;
16
+ pendingPeerDialQueue = [];
14
17
  static create(peerId, libp2p, keepAliveOptions, relay, options) {
15
18
  let instance = ConnectionManager.instances.get(peerId);
16
19
  if (!instance) {
@@ -24,12 +27,34 @@ class ConnectionManager {
24
27
  this.options = {
25
28
  maxDialAttemptsForPeer: DEFAULT_MAX_DIAL_ATTEMPTS_FOR_PEER,
26
29
  maxBootstrapPeersAllowed: DEFAULT_MAX_BOOTSTRAP_PEERS_ALLOWED,
30
+ maxParallelDials: DEFAULT_MAX_PARALLEL_DIALS,
27
31
  ...options,
28
32
  };
29
33
  this.keepAliveManager = new KeepAliveManager(keepAliveOptions, relay);
30
34
  this.run()
31
35
  .then(() => log(`Connection Manager is now running`))
32
36
  .catch((error) => log(`Unexpected error while running service`, error));
37
+ // libp2p emits `peer:discovery` events during its initialization
38
+ // which means that before the ConnectionManager is initialized, some peers may have been discovered
39
+ // we will dial the peers in peerStore ONCE before we start to listen to the `peer:discovery` events within the ConnectionManager
40
+ this.dialPeerStorePeers();
41
+ }
42
+ async dialPeerStorePeers() {
43
+ const peerInfos = await this.libp2pComponents.peerStore.all();
44
+ const dialPromises = [];
45
+ for (const peerInfo of peerInfos) {
46
+ if (this.libp2pComponents
47
+ .getConnections()
48
+ .find((c) => c.remotePeer === peerInfo.id))
49
+ continue;
50
+ dialPromises.push(this.attemptDial(peerInfo.id));
51
+ }
52
+ try {
53
+ await Promise.all(dialPromises);
54
+ }
55
+ catch (error) {
56
+ log(`Unexpected error while dialing peer store peers`, error);
57
+ }
33
58
  }
34
59
  async run() {
35
60
  // start event listeners
@@ -44,6 +69,7 @@ class ConnectionManager {
44
69
  this.libp2pComponents.removeEventListener("peer:discovery", this.onEventHandlers["peer:discovery"]);
45
70
  }
46
71
  async dialPeer(peerId) {
72
+ this.currentActiveDialCount += 1;
47
73
  let dialAttempt = 0;
48
74
  while (dialAttempt <= this.options.maxDialAttemptsForPeer) {
49
75
  try {
@@ -78,6 +104,30 @@ class ConnectionManager {
78
104
  catch (error) {
79
105
  throw `Error deleting undialable peer ${peerId.toString()} from peer store - ${error}`;
80
106
  }
107
+ finally {
108
+ this.currentActiveDialCount -= 1;
109
+ this.processDialQueue();
110
+ }
111
+ }
112
+ async dropConnection(peerId) {
113
+ try {
114
+ await this.libp2pComponents.hangUp(peerId);
115
+ log(`Dropped connection with peer ${peerId.toString()}`);
116
+ }
117
+ catch (error) {
118
+ log(`Error dropping connection with peer ${peerId.toString()} - ${error}`);
119
+ }
120
+ }
121
+ async processDialQueue() {
122
+ if (this.pendingPeerDialQueue.length > 0 &&
123
+ this.currentActiveDialCount < this.options.maxParallelDials) {
124
+ const peerId = this.pendingPeerDialQueue.shift();
125
+ if (!peerId)
126
+ return;
127
+ this.attemptDial(peerId).catch((error) => {
128
+ log(error);
129
+ });
130
+ }
81
131
  }
82
132
  startPeerDiscoveryListener() {
83
133
  this.libp2pComponents.peerStore.addEventListener("peer", this.onEventHandlers["peer:discovery"]);
@@ -100,16 +150,34 @@ class ConnectionManager {
100
150
  */
101
151
  this.libp2pComponents.addEventListener("peer:disconnect", this.onEventHandlers["peer:disconnect"]);
102
152
  }
153
+ async attemptDial(peerId) {
154
+ if (this.currentActiveDialCount >= this.options.maxParallelDials) {
155
+ this.pendingPeerDialQueue.push(peerId);
156
+ return;
157
+ }
158
+ if (!(await this.shouldDialPeer(peerId)))
159
+ return;
160
+ this.dialPeer(peerId).catch((err) => {
161
+ throw `Error dialing peer ${peerId.toString()} : ${err}`;
162
+ });
163
+ }
103
164
  onEventHandlers = {
104
165
  "peer:discovery": async (evt) => {
105
166
  const { id: peerId } = evt.detail;
106
- if (!(await this.shouldDialPeer(peerId)))
107
- return;
108
- this.dialPeer(peerId).catch((err) => log(`Error dialing peer ${peerId.toString()} : ${err}`));
167
+ this.attemptDial(peerId).catch((err) => log(`Error dialing peer ${peerId.toString()} : ${err}`));
109
168
  },
110
- "peer:connect": (evt) => {
111
- {
112
- this.keepAliveManager.start(evt.detail.remotePeer, this.libp2pComponents.ping.bind(this));
169
+ "peer:connect": async (evt) => {
170
+ const { remotePeer: peerId } = evt.detail;
171
+ this.keepAliveManager.start(peerId, this.libp2pComponents.ping.bind(this));
172
+ const isBootstrap = (await this.getTagNamesForPeer(peerId)).includes(Tags.BOOTSTRAP);
173
+ if (isBootstrap) {
174
+ const bootstrapConnections = this.libp2pComponents
175
+ .getConnections()
176
+ .filter((conn) => conn.tags.includes(Tags.BOOTSTRAP));
177
+ // If we have too many bootstrap connections, drop one
178
+ if (bootstrapConnections.length > this.options.maxBootstrapPeersAllowed) {
179
+ await this.dropConnection(peerId);
180
+ }
113
181
  }
114
182
  },
115
183
  "peer:disconnect": () => {
@@ -1 +1 @@
1
- {"version":3,"file":"connection_manager.js","sourceRoot":"","sources":["../../src/lib/connection_manager.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"connection_manager.js","sourceRoot":"","sources":["../../src/lib/connection_manager.ts"],"names":[],"mappings":"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"}
@@ -4,7 +4,7 @@ import { Protocols } from "@waku/interfaces";
4
4
  * Wait for a remote peer to be ready given the passed protocols.
5
5
  * Must be used after attempting to connect to nodes, using
6
6
  * {@link @waku/core.WakuNode.dial} or a bootstrap method with
7
- * {@link @waku/create.createLightNode}.
7
+ * {@link @waku/sdk.createLightNode}.
8
8
  *
9
9
  * If the passed protocols is a GossipSub protocol, then it resolves only once
10
10
  * a peer is in a mesh, to help ensure that other peers will send and receive
@@ -6,7 +6,7 @@ const log = debug("waku:wait-for-remote-peer");
6
6
  * Wait for a remote peer to be ready given the passed protocols.
7
7
  * Must be used after attempting to connect to nodes, using
8
8
  * {@link @waku/core.WakuNode.dial} or a bootstrap method with
9
- * {@link @waku/create.createLightNode}.
9
+ * {@link @waku/sdk.createLightNode}.
10
10
  *
11
11
  * If the passed protocols is a GossipSub protocol, then it resolves only once
12
12
  * a peer is in a mesh, to help ensure that other peers will send and receive
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@waku/core",
3
- "version": "0.0.19",
3
+ "version": "0.0.20",
4
4
  "description": "TypeScript implementation of the Waku v2 protocol",
5
5
  "types": "./dist/index.d.ts",
6
6
  "module": "./dist/index.js",
@@ -73,13 +73,13 @@
73
73
  },
74
74
  "dependencies": {
75
75
  "@noble/hashes": "^1.3.0",
76
- "@waku/interfaces": "0.0.14",
76
+ "@waku/interfaces": "0.0.15",
77
77
  "@waku/proto": "0.0.5",
78
- "@waku/utils": "0.0.7",
78
+ "@waku/utils": "0.0.8",
79
79
  "debug": "^4.3.4",
80
- "it-all": "^3.0.1",
80
+ "it-all": "^3.0.2",
81
81
  "it-length-prefixed": "^9.0.1",
82
- "it-pipe": "^2.0.5",
82
+ "it-pipe": "^3.0.1",
83
83
  "p-event": "^5.0.1",
84
84
  "uint8arraylist": "^2.4.3",
85
85
  "uuid": "^9.0.0"
@@ -99,11 +99,11 @@
99
99
  "@types/mocha": "^10.0.1",
100
100
  "@types/uuid": "^9.0.1",
101
101
  "@typescript-eslint/eslint-plugin": "^5.57.0",
102
- "@typescript-eslint/parser": "^5.51.0",
102
+ "@typescript-eslint/parser": "^5.59.8",
103
103
  "@waku/build-utils": "*",
104
104
  "chai": "^4.3.7",
105
105
  "cspell": "^6.31.1",
106
- "eslint": "^8.35.0",
106
+ "eslint": "^8.41.0",
107
107
  "eslint-config-prettier": "^8.6.0",
108
108
  "eslint-plugin-eslint-comments": "^3.2.0",
109
109
  "eslint-plugin-functional": "^5.0.4",
@@ -12,6 +12,7 @@ const log = debug("waku:connection-manager");
12
12
 
13
13
  export const DEFAULT_MAX_BOOTSTRAP_PEERS_ALLOWED = 1;
14
14
  export const DEFAULT_MAX_DIAL_ATTEMPTS_FOR_PEER = 3;
15
+ export const DEFAULT_MAX_PARALLEL_DIALS = 3;
15
16
 
16
17
  export class ConnectionManager {
17
18
  private static instances = new Map<string, ConnectionManager>();
@@ -21,6 +22,9 @@ export class ConnectionManager {
21
22
  private dialAttemptsForPeer: Map<string, number> = new Map();
22
23
  private dialErrorsForPeer: Map<string, any> = new Map();
23
24
 
25
+ private currentActiveDialCount = 0;
26
+ private pendingPeerDialQueue: Array<PeerId> = [];
27
+
24
28
  public static create(
25
29
  peerId: string,
26
30
  libp2p: Libp2p,
@@ -52,6 +56,7 @@ export class ConnectionManager {
52
56
  this.options = {
53
57
  maxDialAttemptsForPeer: DEFAULT_MAX_DIAL_ATTEMPTS_FOR_PEER,
54
58
  maxBootstrapPeersAllowed: DEFAULT_MAX_BOOTSTRAP_PEERS_ALLOWED,
59
+ maxParallelDials: DEFAULT_MAX_PARALLEL_DIALS,
55
60
  ...options,
56
61
  };
57
62
 
@@ -60,6 +65,31 @@ export class ConnectionManager {
60
65
  this.run()
61
66
  .then(() => log(`Connection Manager is now running`))
62
67
  .catch((error) => log(`Unexpected error while running service`, error));
68
+
69
+ // libp2p emits `peer:discovery` events during its initialization
70
+ // which means that before the ConnectionManager is initialized, some peers may have been discovered
71
+ // we will dial the peers in peerStore ONCE before we start to listen to the `peer:discovery` events within the ConnectionManager
72
+ this.dialPeerStorePeers();
73
+ }
74
+
75
+ private async dialPeerStorePeers(): Promise<void> {
76
+ const peerInfos = await this.libp2pComponents.peerStore.all();
77
+ const dialPromises = [];
78
+ for (const peerInfo of peerInfos) {
79
+ if (
80
+ this.libp2pComponents
81
+ .getConnections()
82
+ .find((c) => c.remotePeer === peerInfo.id)
83
+ )
84
+ continue;
85
+
86
+ dialPromises.push(this.attemptDial(peerInfo.id));
87
+ }
88
+ try {
89
+ await Promise.all(dialPromises);
90
+ } catch (error) {
91
+ log(`Unexpected error while dialing peer store peers`, error);
92
+ }
63
93
  }
64
94
 
65
95
  private async run(): Promise<void> {
@@ -86,6 +116,7 @@ export class ConnectionManager {
86
116
  }
87
117
 
88
118
  private async dialPeer(peerId: PeerId): Promise<void> {
119
+ this.currentActiveDialCount += 1;
89
120
  let dialAttempt = 0;
90
121
  while (dialAttempt <= this.options.maxDialAttemptsForPeer) {
91
122
  try {
@@ -105,6 +136,7 @@ export class ConnectionManager {
105
136
  return;
106
137
  } catch (e) {
107
138
  const error = e as AggregateError;
139
+
108
140
  this.dialErrorsForPeer.set(peerId.toString(), error);
109
141
  log(`Error dialing peer ${peerId.toString()} - ${error.errors}`);
110
142
 
@@ -128,6 +160,33 @@ export class ConnectionManager {
128
160
  return await this.libp2pComponents.peerStore.delete(peerId);
129
161
  } catch (error) {
130
162
  throw `Error deleting undialable peer ${peerId.toString()} from peer store - ${error}`;
163
+ } finally {
164
+ this.currentActiveDialCount -= 1;
165
+ this.processDialQueue();
166
+ }
167
+ }
168
+
169
+ async dropConnection(peerId: PeerId): Promise<void> {
170
+ try {
171
+ await this.libp2pComponents.hangUp(peerId);
172
+ log(`Dropped connection with peer ${peerId.toString()}`);
173
+ } catch (error) {
174
+ log(
175
+ `Error dropping connection with peer ${peerId.toString()} - ${error}`
176
+ );
177
+ }
178
+ }
179
+
180
+ private async processDialQueue(): Promise<void> {
181
+ if (
182
+ this.pendingPeerDialQueue.length > 0 &&
183
+ this.currentActiveDialCount < this.options.maxParallelDials
184
+ ) {
185
+ const peerId = this.pendingPeerDialQueue.shift();
186
+ if (!peerId) return;
187
+ this.attemptDial(peerId).catch((error) => {
188
+ log(error);
189
+ });
131
190
  }
132
191
  }
133
192
 
@@ -164,21 +223,50 @@ export class ConnectionManager {
164
223
  );
165
224
  }
166
225
 
226
+ private async attemptDial(peerId: PeerId): Promise<void> {
227
+ if (this.currentActiveDialCount >= this.options.maxParallelDials) {
228
+ this.pendingPeerDialQueue.push(peerId);
229
+ return;
230
+ }
231
+
232
+ if (!(await this.shouldDialPeer(peerId))) return;
233
+
234
+ this.dialPeer(peerId).catch((err) => {
235
+ throw `Error dialing peer ${peerId.toString()} : ${err}`;
236
+ });
237
+ }
238
+
167
239
  private onEventHandlers = {
168
240
  "peer:discovery": async (evt: CustomEvent<PeerInfo>): Promise<void> => {
169
241
  const { id: peerId } = evt.detail;
170
- if (!(await this.shouldDialPeer(peerId))) return;
171
242
 
172
- this.dialPeer(peerId).catch((err) =>
243
+ this.attemptDial(peerId).catch((err) =>
173
244
  log(`Error dialing peer ${peerId.toString()} : ${err}`)
174
245
  );
175
246
  },
176
- "peer:connect": (evt: CustomEvent<Connection>): void => {
177
- {
178
- this.keepAliveManager.start(
179
- evt.detail.remotePeer,
180
- this.libp2pComponents.ping.bind(this)
181
- );
247
+ "peer:connect": async (evt: CustomEvent<Connection>): Promise<void> => {
248
+ const { remotePeer: peerId } = evt.detail;
249
+
250
+ this.keepAliveManager.start(
251
+ peerId,
252
+ this.libp2pComponents.ping.bind(this)
253
+ );
254
+
255
+ const isBootstrap = (await this.getTagNamesForPeer(peerId)).includes(
256
+ Tags.BOOTSTRAP
257
+ );
258
+
259
+ if (isBootstrap) {
260
+ const bootstrapConnections = this.libp2pComponents
261
+ .getConnections()
262
+ .filter((conn) => conn.tags.includes(Tags.BOOTSTRAP));
263
+
264
+ // If we have too many bootstrap connections, drop one
265
+ if (
266
+ bootstrapConnections.length > this.options.maxBootstrapPeersAllowed
267
+ ) {
268
+ await this.dropConnection(peerId);
269
+ }
182
270
  }
183
271
  },
184
272
  "peer:disconnect": () => {
@@ -10,7 +10,7 @@ const log = debug("waku:wait-for-remote-peer");
10
10
  * Wait for a remote peer to be ready given the passed protocols.
11
11
  * Must be used after attempting to connect to nodes, using
12
12
  * {@link @waku/core.WakuNode.dial} or a bootstrap method with
13
- * {@link @waku/create.createLightNode}.
13
+ * {@link @waku/sdk.createLightNode}.
14
14
  *
15
15
  * If the passed protocols is a GossipSub protocol, then it resolves only once
16
16
  * a peer is in a mesh, to help ensure that other peers will send and receive