@waku/core 0.0.29 → 0.0.30-e49e728.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;
@@ -1651,50 +1651,153 @@ class FilterCore extends BaseProtocol {
1651
1651
  async subscribe(pubsubTopic, peer, contentTopics) {
1652
1652
  const stream = await this.getStream(peer);
1653
1653
  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}`);
1654
+ let res;
1655
+ try {
1656
+ res = await pipe([request.encode()], encode, stream, decode, async (source) => await all(source));
1657
+ }
1658
+ catch (error) {
1659
+ log$6.error("Failed to send subscribe request", error);
1660
+ return {
1661
+ success: null,
1662
+ failure: {
1663
+ error: ProtocolError.GENERIC_FAIL,
1664
+ peerId: peer.id
1665
+ }
1666
+ };
1657
1667
  }
1658
1668
  const { statusCode, requestId, statusDesc } = FilterSubscribeResponse.decode(res[0].slice());
1659
1669
  if (statusCode < 200 || statusCode >= 300) {
1660
- throw new Error(`Filter subscribe request ${requestId} failed with status code ${statusCode}: ${statusDesc}`);
1670
+ log$6.error(`Filter subscribe request ${requestId} failed with status code ${statusCode}: ${statusDesc}`);
1671
+ return {
1672
+ failure: {
1673
+ error: ProtocolError.REMOTE_PEER_REJECTED,
1674
+ peerId: peer.id
1675
+ },
1676
+ success: null
1677
+ };
1661
1678
  }
1679
+ return {
1680
+ failure: null,
1681
+ success: peer.id
1682
+ };
1662
1683
  }
1663
1684
  async unsubscribe(pubsubTopic, peer, contentTopics) {
1664
- const stream = await this.getStream(peer);
1685
+ let stream;
1686
+ try {
1687
+ stream = await this.getStream(peer);
1688
+ }
1689
+ catch (error) {
1690
+ log$6.error(`Failed to get a stream for remote peer${peer.id.toString()}`, error);
1691
+ return {
1692
+ success: null,
1693
+ failure: {
1694
+ error: ProtocolError.REMOTE_PEER_FAULT,
1695
+ peerId: peer.id
1696
+ }
1697
+ };
1698
+ }
1665
1699
  const unsubscribeRequest = FilterSubscribeRpc.createUnsubscribeRequest(pubsubTopic, contentTopics);
1666
- await pipe([unsubscribeRequest.encode()], encode, stream.sink);
1700
+ try {
1701
+ await pipe([unsubscribeRequest.encode()], encode, stream.sink);
1702
+ }
1703
+ catch (error) {
1704
+ log$6.error("Failed to send unsubscribe request", error);
1705
+ return {
1706
+ success: null,
1707
+ failure: {
1708
+ error: ProtocolError.GENERIC_FAIL,
1709
+ peerId: peer.id
1710
+ }
1711
+ };
1712
+ }
1713
+ return {
1714
+ success: peer.id,
1715
+ failure: null
1716
+ };
1667
1717
  }
1668
1718
  async unsubscribeAll(pubsubTopic, peer) {
1669
1719
  const stream = await this.getStream(peer);
1670
1720
  const request = FilterSubscribeRpc.createUnsubscribeAllRequest(pubsubTopic);
1671
1721
  const res = await pipe([request.encode()], encode, stream, decode, async (source) => await all(source));
1672
1722
  if (!res || !res.length) {
1673
- throw Error(`No response received for request ${request.requestId}: ${res}`);
1723
+ return {
1724
+ failure: {
1725
+ error: ProtocolError.REMOTE_PEER_FAULT,
1726
+ peerId: peer.id
1727
+ },
1728
+ success: null
1729
+ };
1674
1730
  }
1675
1731
  const { statusCode, requestId, statusDesc } = FilterSubscribeResponse.decode(res[0].slice());
1676
1732
  if (statusCode < 200 || statusCode >= 300) {
1677
- throw new Error(`Filter unsubscribe all request ${requestId} failed with status code ${statusCode}: ${statusDesc}`);
1733
+ log$6.error(`Filter unsubscribe all request ${requestId} failed with status code ${statusCode}: ${statusDesc}`);
1734
+ return {
1735
+ failure: {
1736
+ error: ProtocolError.REMOTE_PEER_REJECTED,
1737
+ peerId: peer.id
1738
+ },
1739
+ success: null
1740
+ };
1678
1741
  }
1742
+ return {
1743
+ failure: null,
1744
+ success: peer.id
1745
+ };
1679
1746
  }
1680
1747
  async ping(peer) {
1681
- const stream = await this.getStream(peer);
1748
+ let stream;
1749
+ try {
1750
+ stream = await this.getStream(peer);
1751
+ }
1752
+ catch (error) {
1753
+ log$6.error(`Failed to get a stream for remote peer${peer.id.toString()}`, error);
1754
+ return {
1755
+ success: null,
1756
+ failure: {
1757
+ error: ProtocolError.REMOTE_PEER_FAULT,
1758
+ peerId: peer.id
1759
+ }
1760
+ };
1761
+ }
1682
1762
  const request = FilterSubscribeRpc.createSubscriberPingRequest();
1763
+ let res;
1683
1764
  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()}`);
1765
+ res = await pipe([request.encode()], encode, stream, decode, async (source) => await all(source));
1693
1766
  }
1694
1767
  catch (error) {
1695
- log$6.error("Error pinging: ", error);
1696
- throw error; // Rethrow the actual error instead of wrapping it
1768
+ log$6.error("Failed to send ping request", error);
1769
+ return {
1770
+ success: null,
1771
+ failure: {
1772
+ error: ProtocolError.GENERIC_FAIL,
1773
+ peerId: peer.id
1774
+ }
1775
+ };
1776
+ }
1777
+ if (!res || !res.length) {
1778
+ return {
1779
+ success: null,
1780
+ failure: {
1781
+ error: ProtocolError.REMOTE_PEER_FAULT,
1782
+ peerId: peer.id
1783
+ }
1784
+ };
1697
1785
  }
1786
+ const { statusCode, requestId, statusDesc } = FilterSubscribeResponse.decode(res[0].slice());
1787
+ if (statusCode < 200 || statusCode >= 300) {
1788
+ log$6.error(`Filter ping request ${requestId} failed with status code ${statusCode}: ${statusDesc}`);
1789
+ return {
1790
+ success: null,
1791
+ failure: {
1792
+ error: ProtocolError.REMOTE_PEER_REJECTED,
1793
+ peerId: peer.id
1794
+ }
1795
+ };
1796
+ }
1797
+ return {
1798
+ success: peer.id,
1799
+ failure: null
1800
+ };
1698
1801
  }
1699
1802
  }
1700
1803
 
@@ -1787,12 +1890,12 @@ class LightPushCore extends BaseProtocol {
1787
1890
  try {
1788
1891
  stream = await this.getStream(peer);
1789
1892
  }
1790
- catch (err) {
1791
- log$5.error(`Failed to get a stream for remote peer${peer.id.toString()}`, err);
1893
+ catch (error) {
1894
+ log$5.error("Failed to get stream", error);
1792
1895
  return {
1793
1896
  success: null,
1794
1897
  failure: {
1795
- error: ProtocolError.REMOTE_PEER_FAULT,
1898
+ error: ProtocolError.NO_STREAM_AVAILABLE,
1796
1899
  peerId: peer.id
1797
1900
  }
1798
1901
  };
@@ -1964,7 +2067,14 @@ class StoreCore extends BaseProtocol {
1964
2067
  while (true) {
1965
2068
  queryOpts.cursor = currentCursor;
1966
2069
  const historyRpcQuery = HistoryRpc.createQuery(queryOpts);
1967
- const stream = await this.getStream(peer);
2070
+ let stream;
2071
+ try {
2072
+ stream = await this.getStream(peer);
2073
+ }
2074
+ catch (e) {
2075
+ log$4.error("Failed to get stream", e);
2076
+ break;
2077
+ }
1968
2078
  const res = await pipe([historyRpcQuery.encode()], encode, stream, decode, async (source) => await all(source));
1969
2079
  const bytes = new Uint8ArrayList();
1970
2080
  res.forEach((chunk) => {
@@ -3031,7 +3141,17 @@ class Metadata extends BaseProtocol {
3031
3141
  error: ProtocolError.NO_PEER_AVAILABLE
3032
3142
  };
3033
3143
  }
3034
- const stream = await this.getStream(peer);
3144
+ let stream;
3145
+ try {
3146
+ stream = await this.getStream(peer);
3147
+ }
3148
+ catch (error) {
3149
+ log.error("Failed to get stream", error);
3150
+ return {
3151
+ shardInfo: null,
3152
+ error: ProtocolError.NO_STREAM_AVAILABLE
3153
+ };
3154
+ }
3035
3155
  const encodedResponse = await pipe([request], encode, stream, decode, async (source) => await all(source));
3036
3156
  const { error, shardInfo } = this.decodeMetadataResponse(encodedResponse);
3037
3157
  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);