@waku/core 0.0.30-682cc66.0 → 0.0.30-d8ed83f.0

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,5 +1,5 @@
1
- import { c as bytesToUtf8, L as Logger, e as ensureShardingConfigured } from './index-NYIjIEV5.js';
2
- import { T as Tags } from './browser-DoQRY-an.js';
1
+ import { c as bytesToUtf8, L as Logger, e as ensureShardingConfigured } from './index-BcSodzY4.js';
2
+ import { T as Tags } from './browser-zSUobdfj.js';
3
3
 
4
4
  const decodeRelayShard = (bytes) => {
5
5
  // explicitly converting to Uint8Array to avoid Buffer
@@ -175,6 +175,9 @@ function filterPeersByDiscovery(peers, numPeers, maxBootstrapPeers) {
175
175
  return selectedPeers;
176
176
  }
177
177
 
178
+ const CONNECTION_TIMEOUT = 5_000;
179
+ const RETRY_BACKOFF_BASE = 1_000;
180
+ const MAX_RETRIES = 3;
178
181
  class StreamManager {
179
182
  multicodec;
180
183
  getConnections;
@@ -186,47 +189,78 @@ class StreamManager {
186
189
  this.getConnections = getConnections;
187
190
  this.addEventListener = addEventListener;
188
191
  this.log = new Logger(`stream-manager:${multicodec}`);
189
- this.addEventListener("peer:update", this.handlePeerUpdateStreamPool.bind(this));
190
- this.getStream = this.getStream.bind(this);
191
192
  this.streamPool = new Map();
193
+ this.addEventListener("peer:update", this.handlePeerUpdateStreamPool);
192
194
  }
193
195
  async getStream(peer) {
194
196
  const peerIdStr = peer.id.toString();
195
197
  const streamPromise = this.streamPool.get(peerIdStr);
196
198
  if (!streamPromise) {
197
- return this.newStream(peer); // fallback by creating a new stream on the spot
199
+ return this.createStream(peer);
198
200
  }
199
- // We have the stream, let's remove it from the map
200
201
  this.streamPool.delete(peerIdStr);
201
- this.prepareNewStream(peer);
202
- const stream = await streamPromise;
203
- if (!stream || stream.status === "closed") {
204
- return this.newStream(peer); // fallback by creating a new stream on the spot
202
+ this.prepareStream(peer);
203
+ try {
204
+ const stream = await streamPromise;
205
+ if (stream && stream.status !== "closed") {
206
+ return stream;
207
+ }
208
+ }
209
+ catch (error) {
210
+ this.log.warn(`Failed to get stream for ${peerIdStr} -- `, error);
211
+ this.log.warn("Attempting to create a new stream for the peer");
205
212
  }
206
- return stream;
213
+ return this.createStream(peer);
207
214
  }
208
- async newStream(peer) {
215
+ async createStream(peer, retries = 0) {
209
216
  const connections = this.getConnections(peer.id);
210
217
  const connection = selectConnection(connections);
211
218
  if (!connection) {
212
219
  throw new Error("Failed to get a connection to the peer");
213
220
  }
214
- return connection.newStream(this.multicodec);
221
+ try {
222
+ return await connection.newStream(this.multicodec);
223
+ }
224
+ catch (error) {
225
+ if (retries < MAX_RETRIES) {
226
+ const backoff = RETRY_BACKOFF_BASE * Math.pow(2, retries);
227
+ await new Promise((resolve) => setTimeout(resolve, backoff));
228
+ return this.createStream(peer, retries + 1);
229
+ }
230
+ throw new Error(`Failed to create a new stream for ${peer.id.toString()} -- ` + error);
231
+ }
215
232
  }
216
- prepareNewStream(peer) {
217
- const streamPromise = this.newStream(peer).catch(() => {
218
- // No error thrown as this call is not triggered by the user
219
- this.log.error(`Failed to prepare a new stream for ${peer.id.toString()}`);
233
+ prepareStream(peer) {
234
+ const timeoutPromise = new Promise((resolve) => setTimeout(resolve, CONNECTION_TIMEOUT));
235
+ const streamPromise = Promise.race([
236
+ this.createStream(peer),
237
+ timeoutPromise.then(() => {
238
+ throw new Error("Connection timeout");
239
+ })
240
+ ]).catch((error) => {
241
+ this.log.error(`Failed to prepare a new stream for ${peer.id.toString()} -- `, error);
220
242
  });
221
243
  this.streamPool.set(peer.id.toString(), streamPromise);
222
244
  }
223
245
  handlePeerUpdateStreamPool = (evt) => {
224
- const peer = evt.detail.peer;
246
+ const { peer } = evt.detail;
225
247
  if (peer.protocols.includes(this.multicodec)) {
226
- this.log.info(`Preemptively opening a stream to ${peer.id.toString()}`);
227
- this.prepareNewStream(peer);
248
+ const isConnected = this.isConnectedTo(peer.id);
249
+ if (isConnected) {
250
+ this.log.info(`Preemptively opening a stream to ${peer.id.toString()}`);
251
+ this.prepareStream(peer);
252
+ }
253
+ else {
254
+ const peerIdStr = peer.id.toString();
255
+ this.streamPool.delete(peerIdStr);
256
+ this.log.info(`Removed pending stream for disconnected peer ${peerIdStr}`);
257
+ }
228
258
  }
229
259
  };
260
+ isConnectedTo(peerId) {
261
+ const connections = this.getConnections(peerId);
262
+ return connections.some((connection) => connection.status === "open");
263
+ }
230
264
  }
231
265
 
232
266
  /**
@@ -656,6 +656,11 @@ var ProtocolError;
656
656
  * Please ensure that the PubsubTopic is used when initializing the Waku node.
657
657
  */
658
658
  ProtocolError["TOPIC_NOT_CONFIGURED"] = "Topic not configured";
659
+ /**
660
+ * The pubsub topic configured on the decoder does not match the pubsub topic setup on the protocol.
661
+ * Ensure that the pubsub topic used for decoder creation is the same as the one used for protocol.
662
+ */
663
+ ProtocolError["TOPIC_DECODER_MISMATCH"] = "Topic decoder mismatch";
659
664
  /**
660
665
  * Failure to find a peer with suitable protocols. This may due to a connection issue.
661
666
  * Mitigation can be: retrying after a given time period, display connectivity issue
@@ -663,6 +668,11 @@ var ProtocolError;
663
668
  * on the connection manager before retrying.
664
669
  */
665
670
  ProtocolError["NO_PEER_AVAILABLE"] = "No peer available";
671
+ /**
672
+ * Failure to find a stream to the peer. This may be because the connection with the peer is not still alive.
673
+ * Mitigation can be: retrying after a given time period, or mitigation for `NO_PEER_AVAILABLE` can be used.
674
+ */
675
+ ProtocolError["NO_STREAM_AVAILABLE"] = "No stream available";
666
676
  /**
667
677
  * The remote peer did not behave as expected. Mitigation for `NO_PEER_AVAILABLE`
668
678
  * or `DECODE_FAILED` can be used.
@@ -1,4 +1,4 @@
1
- import { i as identityBase, c as base2, d as base8, e as base10, f as base16, h as base32, j as base36, k as base58, l as base64, m as base256emoji, n as debug } from './browser-DoQRY-an.js';
1
+ import { i as identityBase, c as base2, d as base8, e as base10, f as base16, h as base32, j as base36, k as base58, l as base64, m as base256emoji, n as debug } from './browser-zSUobdfj.js';
2
2
 
3
3
  /**
4
4
  * Returns a `Uint8Array` of the requested size. Referenced memory will
package/bundle/index.js CHANGED
@@ -1,9 +1,9 @@
1
- import { v as version_0, e as encodingLength, a as encode$1, d as decode$1, M as MessagePush, F as FilterSubscribeRequest, b as FilterSubscribeResponse$1, P as PushRpc$1, c as PushResponse, H as HistoryRpc$1, f as PagingInfo, g as HistoryResponse, h as createEncoder, W as WakuMetadataResponse, i as WakuMetadataRequest } from './version_0-C6GyvOeg.js';
2
- export { j as createDecoder } from './version_0-C6GyvOeg.js';
3
- import { g as getDefaultExportFromCjs, P as ProtocolError, a as Protocols, E as EConnectionStateEvents, T as Tags, b as EPeersByDiscoveryEvents } from './browser-DoQRY-an.js';
4
- import { a as allocUnsafe, b as alloc, L as Logger, u as utf8ToBytes, p as pubsubTopicToSingleShardInfo, s as shardInfoToPubsubTopics } from './index-NYIjIEV5.js';
5
- import { B as BaseProtocol, d as decodeRelayShard, e as encodeRelayShard } from './base_protocol-CrPXdVvO.js';
6
- export { S as StreamManager } from './base_protocol-CrPXdVvO.js';
1
+ import { v as version_0, e as encodingLength, a as encode$1, d as decode$1, M as MessagePush, F as FilterSubscribeRequest, b as FilterSubscribeResponse$1, P as PushRpc$1, c as PushResponse, H as HistoryRpc$1, f as PagingInfo, g as HistoryResponse, h as createEncoder, W as WakuMetadataResponse, i as WakuMetadataRequest } from './version_0-TEIsGmpJ.js';
2
+ export { j as createDecoder } from './version_0-TEIsGmpJ.js';
3
+ import { g as getDefaultExportFromCjs, P as ProtocolError, a as Protocols, E as EConnectionStateEvents, T as Tags, b as EPeersByDiscoveryEvents } from './browser-zSUobdfj.js';
4
+ import { a as allocUnsafe, b as alloc, L as Logger, u as utf8ToBytes, p as pubsubTopicToSingleShardInfo, s as shardInfoToPubsubTopics } from './index-BcSodzY4.js';
5
+ import { B as BaseProtocol, d as decodeRelayShard, e as encodeRelayShard } from './base_protocol-DCOj0QWD.js';
6
+ export { S as StreamManager } from './base_protocol-DCOj0QWD.js';
7
7
 
8
8
  const MB = 1024 ** 2;
9
9
  const SIZE_CAP_IN_MB = 1;
@@ -1615,7 +1615,11 @@ class FilterCore extends BaseProtocol {
1615
1615
  constructor(handleIncomingMessage, libp2p, options) {
1616
1616
  super(FilterCodecs.SUBSCRIBE, libp2p.components, log$6, options.pubsubTopics, options);
1617
1617
  this.handleIncomingMessage = handleIncomingMessage;
1618
- libp2p.handle(FilterCodecs.PUSH, this.onRequest.bind(this)).catch((e) => {
1618
+ libp2p
1619
+ .handle(FilterCodecs.PUSH, this.onRequest.bind(this), {
1620
+ maxInboundStreams: 100
1621
+ })
1622
+ .catch((e) => {
1619
1623
  log$6.error("Failed to register ", FilterCodecs.PUSH, e);
1620
1624
  });
1621
1625
  }
@@ -1651,50 +1655,153 @@ class FilterCore extends BaseProtocol {
1651
1655
  async subscribe(pubsubTopic, peer, contentTopics) {
1652
1656
  const stream = await this.getStream(peer);
1653
1657
  const request = FilterSubscribeRpc.createSubscribeRequest(pubsubTopic, contentTopics);
1654
- const res = await pipe([request.encode()], encode, stream, decode, async (source) => await all(source));
1655
- if (!res || !res.length) {
1656
- throw Error(`No response received for request ${request.requestId}: ${res}`);
1658
+ let res;
1659
+ try {
1660
+ res = await pipe([request.encode()], encode, stream, decode, async (source) => await all(source));
1661
+ }
1662
+ catch (error) {
1663
+ log$6.error("Failed to send subscribe request", error);
1664
+ return {
1665
+ success: null,
1666
+ failure: {
1667
+ error: ProtocolError.GENERIC_FAIL,
1668
+ peerId: peer.id
1669
+ }
1670
+ };
1657
1671
  }
1658
1672
  const { statusCode, requestId, statusDesc } = FilterSubscribeResponse.decode(res[0].slice());
1659
1673
  if (statusCode < 200 || statusCode >= 300) {
1660
- throw new Error(`Filter subscribe request ${requestId} failed with status code ${statusCode}: ${statusDesc}`);
1674
+ log$6.error(`Filter subscribe request ${requestId} failed with status code ${statusCode}: ${statusDesc}`);
1675
+ return {
1676
+ failure: {
1677
+ error: ProtocolError.REMOTE_PEER_REJECTED,
1678
+ peerId: peer.id
1679
+ },
1680
+ success: null
1681
+ };
1661
1682
  }
1683
+ return {
1684
+ failure: null,
1685
+ success: peer.id
1686
+ };
1662
1687
  }
1663
1688
  async unsubscribe(pubsubTopic, peer, contentTopics) {
1664
- const stream = await this.getStream(peer);
1689
+ let stream;
1690
+ try {
1691
+ stream = await this.getStream(peer);
1692
+ }
1693
+ catch (error) {
1694
+ log$6.error(`Failed to get a stream for remote peer${peer.id.toString()}`, error);
1695
+ return {
1696
+ success: null,
1697
+ failure: {
1698
+ error: ProtocolError.REMOTE_PEER_FAULT,
1699
+ peerId: peer.id
1700
+ }
1701
+ };
1702
+ }
1665
1703
  const unsubscribeRequest = FilterSubscribeRpc.createUnsubscribeRequest(pubsubTopic, contentTopics);
1666
- await pipe([unsubscribeRequest.encode()], encode, stream.sink);
1704
+ try {
1705
+ await pipe([unsubscribeRequest.encode()], encode, stream.sink);
1706
+ }
1707
+ catch (error) {
1708
+ log$6.error("Failed to send unsubscribe request", error);
1709
+ return {
1710
+ success: null,
1711
+ failure: {
1712
+ error: ProtocolError.GENERIC_FAIL,
1713
+ peerId: peer.id
1714
+ }
1715
+ };
1716
+ }
1717
+ return {
1718
+ success: peer.id,
1719
+ failure: null
1720
+ };
1667
1721
  }
1668
1722
  async unsubscribeAll(pubsubTopic, peer) {
1669
1723
  const stream = await this.getStream(peer);
1670
1724
  const request = FilterSubscribeRpc.createUnsubscribeAllRequest(pubsubTopic);
1671
1725
  const res = await pipe([request.encode()], encode, stream, decode, async (source) => await all(source));
1672
1726
  if (!res || !res.length) {
1673
- throw Error(`No response received for request ${request.requestId}: ${res}`);
1727
+ return {
1728
+ failure: {
1729
+ error: ProtocolError.REMOTE_PEER_FAULT,
1730
+ peerId: peer.id
1731
+ },
1732
+ success: null
1733
+ };
1674
1734
  }
1675
1735
  const { statusCode, requestId, statusDesc } = FilterSubscribeResponse.decode(res[0].slice());
1676
1736
  if (statusCode < 200 || statusCode >= 300) {
1677
- throw new Error(`Filter unsubscribe all request ${requestId} failed with status code ${statusCode}: ${statusDesc}`);
1737
+ log$6.error(`Filter unsubscribe all request ${requestId} failed with status code ${statusCode}: ${statusDesc}`);
1738
+ return {
1739
+ failure: {
1740
+ error: ProtocolError.REMOTE_PEER_REJECTED,
1741
+ peerId: peer.id
1742
+ },
1743
+ success: null
1744
+ };
1678
1745
  }
1746
+ return {
1747
+ failure: null,
1748
+ success: peer.id
1749
+ };
1679
1750
  }
1680
1751
  async ping(peer) {
1681
- const stream = await this.getStream(peer);
1752
+ let stream;
1753
+ try {
1754
+ stream = await this.getStream(peer);
1755
+ }
1756
+ catch (error) {
1757
+ log$6.error(`Failed to get a stream for remote peer${peer.id.toString()}`, error);
1758
+ return {
1759
+ success: null,
1760
+ failure: {
1761
+ error: ProtocolError.REMOTE_PEER_FAULT,
1762
+ peerId: peer.id
1763
+ }
1764
+ };
1765
+ }
1682
1766
  const request = FilterSubscribeRpc.createSubscriberPingRequest();
1767
+ let res;
1683
1768
  try {
1684
- const res = await pipe([request.encode()], encode, stream, decode, async (source) => await all(source));
1685
- if (!res || !res.length) {
1686
- throw Error(`No response received for request ${request.requestId}: ${res}`);
1687
- }
1688
- const { statusCode, requestId, statusDesc } = FilterSubscribeResponse.decode(res[0].slice());
1689
- if (statusCode < 200 || statusCode >= 300) {
1690
- throw new Error(`Filter ping request ${requestId} failed with status code ${statusCode}: ${statusDesc}`);
1691
- }
1692
- log$6.info(`Ping successful for peer ${peer.id.toString()}`);
1769
+ res = await pipe([request.encode()], encode, stream, decode, async (source) => await all(source));
1693
1770
  }
1694
1771
  catch (error) {
1695
- log$6.error("Error pinging: ", error);
1696
- throw error; // Rethrow the actual error instead of wrapping it
1772
+ log$6.error("Failed to send ping request", error);
1773
+ return {
1774
+ success: null,
1775
+ failure: {
1776
+ error: ProtocolError.GENERIC_FAIL,
1777
+ peerId: peer.id
1778
+ }
1779
+ };
1780
+ }
1781
+ if (!res || !res.length) {
1782
+ return {
1783
+ success: null,
1784
+ failure: {
1785
+ error: ProtocolError.REMOTE_PEER_FAULT,
1786
+ peerId: peer.id
1787
+ }
1788
+ };
1697
1789
  }
1790
+ const { statusCode, requestId, statusDesc } = FilterSubscribeResponse.decode(res[0].slice());
1791
+ if (statusCode < 200 || statusCode >= 300) {
1792
+ log$6.error(`Filter ping request ${requestId} failed with status code ${statusCode}: ${statusDesc}`);
1793
+ return {
1794
+ success: null,
1795
+ failure: {
1796
+ error: ProtocolError.REMOTE_PEER_REJECTED,
1797
+ peerId: peer.id
1798
+ }
1799
+ };
1800
+ }
1801
+ return {
1802
+ success: peer.id,
1803
+ failure: null
1804
+ };
1698
1805
  }
1699
1806
  }
1700
1807
 
@@ -1787,12 +1894,12 @@ class LightPushCore extends BaseProtocol {
1787
1894
  try {
1788
1895
  stream = await this.getStream(peer);
1789
1896
  }
1790
- catch (err) {
1791
- log$5.error(`Failed to get a stream for remote peer${peer.id.toString()}`, err);
1897
+ catch (error) {
1898
+ log$5.error("Failed to get stream", error);
1792
1899
  return {
1793
1900
  success: null,
1794
1901
  failure: {
1795
- error: ProtocolError.REMOTE_PEER_FAULT,
1902
+ error: ProtocolError.NO_STREAM_AVAILABLE,
1796
1903
  peerId: peer.id
1797
1904
  }
1798
1905
  };
@@ -1964,7 +2071,14 @@ class StoreCore extends BaseProtocol {
1964
2071
  while (true) {
1965
2072
  queryOpts.cursor = currentCursor;
1966
2073
  const historyRpcQuery = HistoryRpc.createQuery(queryOpts);
1967
- const stream = await this.getStream(peer);
2074
+ let stream;
2075
+ try {
2076
+ stream = await this.getStream(peer);
2077
+ }
2078
+ catch (e) {
2079
+ log$4.error("Failed to get stream", e);
2080
+ break;
2081
+ }
1968
2082
  const res = await pipe([historyRpcQuery.encode()], encode, stream, decode, async (source) => await all(source));
1969
2083
  const bytes = new Uint8ArrayList();
1970
2084
  res.forEach((chunk) => {
@@ -3031,7 +3145,17 @@ class Metadata extends BaseProtocol {
3031
3145
  error: ProtocolError.NO_PEER_AVAILABLE
3032
3146
  };
3033
3147
  }
3034
- const stream = await this.getStream(peer);
3148
+ let stream;
3149
+ try {
3150
+ stream = await this.getStream(peer);
3151
+ }
3152
+ catch (error) {
3153
+ log.error("Failed to get stream", error);
3154
+ return {
3155
+ shardInfo: null,
3156
+ error: ProtocolError.NO_STREAM_AVAILABLE
3157
+ };
3158
+ }
3035
3159
  const encodedResponse = await pipe([request], encode, stream, decode, async (source) => await all(source));
3036
3160
  const { error, shardInfo } = this.decodeMetadataResponse(encodedResponse);
3037
3161
  if (error) {
@@ -1,3 +1,3 @@
1
- import '../index-NYIjIEV5.js';
2
- import '../browser-DoQRY-an.js';
3
- export { B as BaseProtocol } from '../base_protocol-CrPXdVvO.js';
1
+ import '../index-BcSodzY4.js';
2
+ import '../browser-zSUobdfj.js';
3
+ export { B as BaseProtocol } from '../base_protocol-DCOj0QWD.js';
@@ -1,3 +1,3 @@
1
- export { D as DecodedMessage, k as Decoder, E as Encoder, V as Version, j as createDecoder, h as createEncoder, m as proto } from '../../version_0-C6GyvOeg.js';
2
- import '../../index-NYIjIEV5.js';
3
- import '../../browser-DoQRY-an.js';
1
+ export { D as DecodedMessage, k as Decoder, E as Encoder, V as Version, j as createDecoder, h as createEncoder, m as proto } from '../../version_0-TEIsGmpJ.js';
2
+ import '../../index-BcSodzY4.js';
3
+ import '../../browser-zSUobdfj.js';
@@ -1,4 +1,4 @@
1
- import '../browser-DoQRY-an.js';
1
+ import '../browser-zSUobdfj.js';
2
2
 
3
3
  /**
4
4
  * Return pseudo random subset of the input.
@@ -1,4 +1,4 @@
1
- import { a as allocUnsafe, f as fromString, b as alloc$1, L as Logger, d as determinePubsubTopic } from './index-NYIjIEV5.js';
1
+ import { a as allocUnsafe, f as fromString, b as alloc$1, L as Logger, d as determinePubsubTopic } from './index-BcSodzY4.js';
2
2
 
3
3
  /* eslint-disable no-fallthrough */
4
4
  const N1 = Math.pow(2, 7);