@waku/core 0.0.28 → 0.0.29-3ec2344.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.
- package/bundle/{base_protocol-D0Zdzb-v.js → base_protocol-3fdjkRTX.js} +60 -18
- package/bundle/{browser-DoQRY-an.js → browser-H8Jgqifo.js} +5 -0
- package/bundle/{index-BJwgMx4y.js → index-BQ8SG1DC.js} +11 -20
- package/bundle/index.js +106 -362
- package/bundle/lib/base_protocol.js +3 -3
- package/bundle/lib/message/version_0.js +3 -3
- package/bundle/lib/predefined_bootstrap_nodes.js +1 -1
- package/bundle/{version_0-C6o0DvNW.js → version_0-D_Nwtppu.js} +5 -1
- package/dist/.tsbuildinfo +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/lib/filter/index.d.ts +13 -2
- package/dist/lib/filter/index.js +74 -259
- package/dist/lib/filter/index.js.map +1 -1
- package/dist/lib/keep_alive_manager.js +1 -1
- package/dist/lib/light_push/index.js +3 -3
- package/dist/lib/light_push/index.js.map +1 -1
- package/dist/lib/metadata/index.js +11 -1
- package/dist/lib/metadata/index.js.map +1 -1
- package/dist/lib/store/index.js +8 -1
- package/dist/lib/store/index.js.map +1 -1
- package/dist/lib/stream_manager.d.ts +4 -2
- package/dist/lib/stream_manager.js +58 -16
- package/dist/lib/stream_manager.js.map +1 -1
- package/dist/lib/wait_for_remote_peer.js +1 -1
- package/dist/lib/wait_for_remote_peer.js.map +1 -1
- package/package.json +1 -136
- package/src/index.ts +1 -1
- package/src/lib/filter/index.ts +138 -455
- package/src/lib/keep_alive_manager.ts +1 -1
- package/src/lib/light_push/index.ts +4 -7
- package/src/lib/metadata/index.ts +10 -1
- package/src/lib/store/index.ts +7 -1
- package/src/lib/stream_manager.ts +73 -23
- package/src/lib/wait_for_remote_peer.ts +1 -1
package/src/lib/filter/index.ts
CHANGED
@@ -1,30 +1,13 @@
|
|
1
|
-
import { Stream } from "@libp2p/interface";
|
2
|
-
import type { Peer } from "@libp2p/interface";
|
1
|
+
import type { Peer, Stream } from "@libp2p/interface";
|
3
2
|
import type { IncomingStreamData } from "@libp2p/interface-internal";
|
4
3
|
import type {
|
5
|
-
Callback,
|
6
4
|
ContentTopic,
|
7
|
-
|
8
|
-
IDecodedMessage,
|
9
|
-
IDecoder,
|
10
|
-
IFilter,
|
11
|
-
IProtoMessage,
|
12
|
-
IReceiver,
|
5
|
+
IBaseProtocolCore,
|
13
6
|
Libp2p,
|
14
7
|
ProtocolCreateOptions,
|
15
|
-
PubsubTopic
|
16
|
-
SingleShardInfo,
|
17
|
-
Unsubscribe
|
8
|
+
PubsubTopic
|
18
9
|
} from "@waku/interfaces";
|
19
|
-
import { DefaultPubsubTopic } from "@waku/interfaces";
|
20
|
-
import { messageHashStr } from "@waku/message-hash";
|
21
10
|
import { WakuMessage } from "@waku/proto";
|
22
|
-
import {
|
23
|
-
ensurePubsubTopicIsConfigured,
|
24
|
-
groupByContentTopic,
|
25
|
-
singleShardInfoToPubsubTopic,
|
26
|
-
toAsyncIterator
|
27
|
-
} from "@waku/utils";
|
28
11
|
import { Logger } from "@waku/utils";
|
29
12
|
import all from "it-all";
|
30
13
|
import * as lp from "it-length-prefixed";
|
@@ -40,329 +23,20 @@ import {
|
|
40
23
|
|
41
24
|
const log = new Logger("filter:v2");
|
42
25
|
|
43
|
-
type SubscriptionCallback<T extends IDecodedMessage> = {
|
44
|
-
decoders: IDecoder<T>[];
|
45
|
-
callback: Callback<T>;
|
46
|
-
};
|
47
|
-
|
48
26
|
export const FilterCodecs = {
|
49
27
|
SUBSCRIBE: "/vac/waku/filter-subscribe/2.0.0-beta1",
|
50
28
|
PUSH: "/vac/waku/filter-push/2.0.0-beta1"
|
51
29
|
};
|
52
30
|
|
53
|
-
|
54
|
-
* A subscription object refers to a subscription to a given pubsub topic.
|
55
|
-
*/
|
56
|
-
class Subscription {
|
57
|
-
readonly peers: Peer[];
|
58
|
-
private readonly pubsubTopic: PubsubTopic;
|
59
|
-
private newStream: (peer: Peer) => Promise<Stream>;
|
60
|
-
readonly receivedMessagesHashStr: string[] = [];
|
61
|
-
|
62
|
-
private subscriptionCallbacks: Map<
|
63
|
-
ContentTopic,
|
64
|
-
SubscriptionCallback<IDecodedMessage>
|
65
|
-
>;
|
66
|
-
|
31
|
+
export class FilterCore extends BaseProtocol implements IBaseProtocolCore {
|
67
32
|
constructor(
|
68
|
-
|
69
|
-
|
70
|
-
|
33
|
+
private handleIncomingMessage: (
|
34
|
+
pubsubTopic: PubsubTopic,
|
35
|
+
wakuMessage: WakuMessage
|
36
|
+
) => Promise<void>,
|
37
|
+
libp2p: Libp2p,
|
38
|
+
options?: ProtocolCreateOptions
|
71
39
|
) {
|
72
|
-
this.peers = remotePeers;
|
73
|
-
this.pubsubTopic = pubsubTopic;
|
74
|
-
this.newStream = newStream;
|
75
|
-
this.subscriptionCallbacks = new Map();
|
76
|
-
}
|
77
|
-
|
78
|
-
async subscribe<T extends IDecodedMessage>(
|
79
|
-
decoders: IDecoder<T> | IDecoder<T>[],
|
80
|
-
callback: Callback<T>
|
81
|
-
): Promise<void> {
|
82
|
-
const decodersArray = Array.isArray(decoders) ? decoders : [decoders];
|
83
|
-
|
84
|
-
// check that all decoders are configured for the same pubsub topic as this subscription
|
85
|
-
decodersArray.forEach((decoder) => {
|
86
|
-
if (decoder.pubsubTopic !== this.pubsubTopic) {
|
87
|
-
throw new Error(
|
88
|
-
`Pubsub topic not configured: decoder is configured for pubsub topic ${decoder.pubsubTopic} but this subscription is for pubsub topic ${this.pubsubTopic}. Please create a new Subscription for the different pubsub topic.`
|
89
|
-
);
|
90
|
-
}
|
91
|
-
});
|
92
|
-
|
93
|
-
const decodersGroupedByCT = groupByContentTopic(decodersArray);
|
94
|
-
const contentTopics = Array.from(decodersGroupedByCT.keys());
|
95
|
-
|
96
|
-
const promises = this.peers.map(async (peer) => {
|
97
|
-
const stream = await this.newStream(peer);
|
98
|
-
|
99
|
-
const request = FilterSubscribeRpc.createSubscribeRequest(
|
100
|
-
this.pubsubTopic,
|
101
|
-
contentTopics
|
102
|
-
);
|
103
|
-
|
104
|
-
try {
|
105
|
-
const res = await pipe(
|
106
|
-
[request.encode()],
|
107
|
-
lp.encode,
|
108
|
-
stream,
|
109
|
-
lp.decode,
|
110
|
-
async (source) => await all(source)
|
111
|
-
);
|
112
|
-
|
113
|
-
if (!res || !res.length) {
|
114
|
-
throw Error(
|
115
|
-
`No response received for request ${request.requestId}: ${res}`
|
116
|
-
);
|
117
|
-
}
|
118
|
-
|
119
|
-
const { statusCode, requestId, statusDesc } =
|
120
|
-
FilterSubscribeResponse.decode(res[0].slice());
|
121
|
-
|
122
|
-
if (statusCode < 200 || statusCode >= 300) {
|
123
|
-
throw new Error(
|
124
|
-
`Filter subscribe request ${requestId} failed with status code ${statusCode}: ${statusDesc}`
|
125
|
-
);
|
126
|
-
}
|
127
|
-
|
128
|
-
log.info(
|
129
|
-
"Subscribed to peer ",
|
130
|
-
peer.id.toString(),
|
131
|
-
"for content topics",
|
132
|
-
contentTopics
|
133
|
-
);
|
134
|
-
} catch (e) {
|
135
|
-
throw new Error(
|
136
|
-
"Error subscribing to peer: " +
|
137
|
-
peer.id.toString() +
|
138
|
-
" for content topics: " +
|
139
|
-
contentTopics +
|
140
|
-
": " +
|
141
|
-
e
|
142
|
-
);
|
143
|
-
}
|
144
|
-
});
|
145
|
-
|
146
|
-
const results = await Promise.allSettled(promises);
|
147
|
-
|
148
|
-
this.handleErrors(results, "subscribe");
|
149
|
-
|
150
|
-
// Save the callback functions by content topics so they
|
151
|
-
// can easily be removed (reciprocally replaced) if `unsubscribe` (reciprocally `subscribe`)
|
152
|
-
// is called for those content topics
|
153
|
-
decodersGroupedByCT.forEach((decoders, contentTopic) => {
|
154
|
-
// Cast the type because a given `subscriptionCallbacks` map may hold
|
155
|
-
// Decoder that decode to different implementations of `IDecodedMessage`
|
156
|
-
const subscriptionCallback = {
|
157
|
-
decoders,
|
158
|
-
callback
|
159
|
-
} as unknown as SubscriptionCallback<IDecodedMessage>;
|
160
|
-
|
161
|
-
// The callback and decoder may override previous values, this is on
|
162
|
-
// purpose as the user may call `subscribe` to refresh the subscription
|
163
|
-
this.subscriptionCallbacks.set(contentTopic, subscriptionCallback);
|
164
|
-
});
|
165
|
-
}
|
166
|
-
|
167
|
-
async unsubscribe(contentTopics: ContentTopic[]): Promise<void> {
|
168
|
-
const promises = this.peers.map(async (peer) => {
|
169
|
-
const stream = await this.newStream(peer);
|
170
|
-
const unsubscribeRequest = FilterSubscribeRpc.createUnsubscribeRequest(
|
171
|
-
this.pubsubTopic,
|
172
|
-
contentTopics
|
173
|
-
);
|
174
|
-
|
175
|
-
try {
|
176
|
-
await pipe([unsubscribeRequest.encode()], lp.encode, stream.sink);
|
177
|
-
} catch (error) {
|
178
|
-
throw new Error("Error unsubscribing: " + error);
|
179
|
-
}
|
180
|
-
|
181
|
-
contentTopics.forEach((contentTopic: string) => {
|
182
|
-
this.subscriptionCallbacks.delete(contentTopic);
|
183
|
-
});
|
184
|
-
});
|
185
|
-
|
186
|
-
const results = await Promise.allSettled(promises);
|
187
|
-
|
188
|
-
this.handleErrors(results, "unsubscribe");
|
189
|
-
}
|
190
|
-
|
191
|
-
async ping(): Promise<void> {
|
192
|
-
const promises = this.peers.map(async (peer) => {
|
193
|
-
const stream = await this.newStream(peer);
|
194
|
-
|
195
|
-
const request = FilterSubscribeRpc.createSubscriberPingRequest();
|
196
|
-
|
197
|
-
try {
|
198
|
-
const res = await pipe(
|
199
|
-
[request.encode()],
|
200
|
-
lp.encode,
|
201
|
-
stream,
|
202
|
-
lp.decode,
|
203
|
-
async (source) => await all(source)
|
204
|
-
);
|
205
|
-
|
206
|
-
if (!res || !res.length) {
|
207
|
-
throw Error(
|
208
|
-
`No response received for request ${request.requestId}: ${res}`
|
209
|
-
);
|
210
|
-
}
|
211
|
-
|
212
|
-
const { statusCode, requestId, statusDesc } =
|
213
|
-
FilterSubscribeResponse.decode(res[0].slice());
|
214
|
-
|
215
|
-
if (statusCode < 200 || statusCode >= 300) {
|
216
|
-
throw new Error(
|
217
|
-
`Filter ping request ${requestId} failed with status code ${statusCode}: ${statusDesc}`
|
218
|
-
);
|
219
|
-
}
|
220
|
-
log.info(`Ping successful for peer ${peer.id.toString()}`);
|
221
|
-
} catch (error) {
|
222
|
-
log.error("Error pinging: ", error);
|
223
|
-
throw error; // Rethrow the actual error instead of wrapping it
|
224
|
-
}
|
225
|
-
});
|
226
|
-
|
227
|
-
const results = await Promise.allSettled(promises);
|
228
|
-
|
229
|
-
this.handleErrors(results, "ping");
|
230
|
-
}
|
231
|
-
|
232
|
-
async unsubscribeAll(): Promise<void> {
|
233
|
-
const promises = this.peers.map(async (peer) => {
|
234
|
-
const stream = await this.newStream(peer);
|
235
|
-
|
236
|
-
const request = FilterSubscribeRpc.createUnsubscribeAllRequest(
|
237
|
-
this.pubsubTopic
|
238
|
-
);
|
239
|
-
|
240
|
-
try {
|
241
|
-
const res = await pipe(
|
242
|
-
[request.encode()],
|
243
|
-
lp.encode,
|
244
|
-
stream,
|
245
|
-
lp.decode,
|
246
|
-
async (source) => await all(source)
|
247
|
-
);
|
248
|
-
|
249
|
-
if (!res || !res.length) {
|
250
|
-
throw Error(
|
251
|
-
`No response received for request ${request.requestId}: ${res}`
|
252
|
-
);
|
253
|
-
}
|
254
|
-
|
255
|
-
const { statusCode, requestId, statusDesc } =
|
256
|
-
FilterSubscribeResponse.decode(res[0].slice());
|
257
|
-
|
258
|
-
if (statusCode < 200 || statusCode >= 300) {
|
259
|
-
throw new Error(
|
260
|
-
`Filter unsubscribe all request ${requestId} failed with status code ${statusCode}: ${statusDesc}`
|
261
|
-
);
|
262
|
-
}
|
263
|
-
|
264
|
-
this.subscriptionCallbacks.clear();
|
265
|
-
log.info(
|
266
|
-
`Unsubscribed from all content topics for pubsub topic ${this.pubsubTopic}`
|
267
|
-
);
|
268
|
-
} catch (error) {
|
269
|
-
throw new Error(
|
270
|
-
"Error unsubscribing from all content topics: " + error
|
271
|
-
);
|
272
|
-
}
|
273
|
-
});
|
274
|
-
|
275
|
-
const results = await Promise.allSettled(promises);
|
276
|
-
|
277
|
-
this.handleErrors(results, "unsubscribeAll");
|
278
|
-
}
|
279
|
-
|
280
|
-
async processMessage(message: WakuMessage): Promise<void> {
|
281
|
-
const hashedMessageStr = messageHashStr(
|
282
|
-
this.pubsubTopic,
|
283
|
-
message as IProtoMessage
|
284
|
-
);
|
285
|
-
if (this.receivedMessagesHashStr.includes(hashedMessageStr)) {
|
286
|
-
log.info("Message already received, skipping");
|
287
|
-
return;
|
288
|
-
}
|
289
|
-
this.receivedMessagesHashStr.push(hashedMessageStr);
|
290
|
-
|
291
|
-
const { contentTopic } = message;
|
292
|
-
const subscriptionCallback = this.subscriptionCallbacks.get(contentTopic);
|
293
|
-
if (!subscriptionCallback) {
|
294
|
-
log.error("No subscription callback available for ", contentTopic);
|
295
|
-
return;
|
296
|
-
}
|
297
|
-
log.info(
|
298
|
-
"Processing message with content topic ",
|
299
|
-
contentTopic,
|
300
|
-
" on pubsub topic ",
|
301
|
-
this.pubsubTopic
|
302
|
-
);
|
303
|
-
await pushMessage(subscriptionCallback, this.pubsubTopic, message);
|
304
|
-
}
|
305
|
-
|
306
|
-
// Filter out only the rejected promises and extract & handle their reasons
|
307
|
-
private handleErrors(
|
308
|
-
results: PromiseSettledResult<void>[],
|
309
|
-
type: "ping" | "subscribe" | "unsubscribe" | "unsubscribeAll"
|
310
|
-
): void {
|
311
|
-
const errors = results
|
312
|
-
.filter(
|
313
|
-
(result): result is PromiseRejectedResult =>
|
314
|
-
result.status === "rejected"
|
315
|
-
)
|
316
|
-
.map((rejectedResult) => rejectedResult.reason);
|
317
|
-
|
318
|
-
if (errors.length === this.peers.length) {
|
319
|
-
const errorCounts = new Map<string, number>();
|
320
|
-
// TODO: streamline error logging with https://github.com/orgs/waku-org/projects/2/views/1?pane=issue&itemId=42849952
|
321
|
-
errors.forEach((error) => {
|
322
|
-
const message = error instanceof Error ? error.message : String(error);
|
323
|
-
errorCounts.set(message, (errorCounts.get(message) || 0) + 1);
|
324
|
-
});
|
325
|
-
|
326
|
-
const uniqueErrorMessages = Array.from(
|
327
|
-
errorCounts,
|
328
|
-
([message, count]) => `${message} (occurred ${count} times)`
|
329
|
-
).join(", ");
|
330
|
-
throw new Error(`Error ${type} all peers: ${uniqueErrorMessages}`);
|
331
|
-
} else if (errors.length > 0) {
|
332
|
-
// TODO: handle renewing faulty peers with new peers (https://github.com/waku-org/js-waku/issues/1463)
|
333
|
-
log.warn(
|
334
|
-
`Some ${type} failed. These will be refreshed with new peers`,
|
335
|
-
errors
|
336
|
-
);
|
337
|
-
} else {
|
338
|
-
log.info(`${type} successful for all peers`);
|
339
|
-
}
|
340
|
-
}
|
341
|
-
}
|
342
|
-
|
343
|
-
const DEFAULT_NUM_PEERS = 3;
|
344
|
-
|
345
|
-
class Filter extends BaseProtocol implements IReceiver {
|
346
|
-
private activeSubscriptions = new Map<string, Subscription>();
|
347
|
-
|
348
|
-
private getActiveSubscription(
|
349
|
-
pubsubTopic: PubsubTopic
|
350
|
-
): Subscription | undefined {
|
351
|
-
return this.activeSubscriptions.get(pubsubTopic);
|
352
|
-
}
|
353
|
-
|
354
|
-
private setActiveSubscription(
|
355
|
-
pubsubTopic: PubsubTopic,
|
356
|
-
subscription: Subscription
|
357
|
-
): Subscription {
|
358
|
-
this.activeSubscriptions.set(pubsubTopic, subscription);
|
359
|
-
return subscription;
|
360
|
-
}
|
361
|
-
|
362
|
-
//TODO: Remove when FilterCore and FilterSDK are introduced
|
363
|
-
private readonly numPeersToUse: number;
|
364
|
-
|
365
|
-
constructor(libp2p: Libp2p, options?: ProtocolCreateOptions) {
|
366
40
|
super(
|
367
41
|
FilterCodecs.SUBSCRIBE,
|
368
42
|
libp2p.components,
|
@@ -371,92 +45,9 @@ class Filter extends BaseProtocol implements IReceiver {
|
|
371
45
|
options
|
372
46
|
);
|
373
47
|
|
374
|
-
this.numPeersToUse = options?.numPeersToUse ?? DEFAULT_NUM_PEERS;
|
375
|
-
|
376
48
|
libp2p.handle(FilterCodecs.PUSH, this.onRequest.bind(this)).catch((e) => {
|
377
49
|
log.error("Failed to register ", FilterCodecs.PUSH, e);
|
378
50
|
});
|
379
|
-
|
380
|
-
this.activeSubscriptions = new Map();
|
381
|
-
}
|
382
|
-
|
383
|
-
/**
|
384
|
-
* Creates a new subscription to the given pubsub topic.
|
385
|
-
* The subscription is made to multiple peers for decentralization.
|
386
|
-
* @param pubsubTopicShardInfo The pubsub topic to subscribe to.
|
387
|
-
* @returns The subscription object.
|
388
|
-
*/
|
389
|
-
async createSubscription(
|
390
|
-
pubsubTopicShardInfo: SingleShardInfo | PubsubTopic = DefaultPubsubTopic
|
391
|
-
): Promise<Subscription> {
|
392
|
-
const pubsubTopic =
|
393
|
-
typeof pubsubTopicShardInfo == "string"
|
394
|
-
? pubsubTopicShardInfo
|
395
|
-
: singleShardInfoToPubsubTopic(pubsubTopicShardInfo);
|
396
|
-
|
397
|
-
ensurePubsubTopicIsConfigured(pubsubTopic, this.pubsubTopics);
|
398
|
-
|
399
|
-
const peers = await this.getPeers({
|
400
|
-
maxBootstrapPeers: 1,
|
401
|
-
numPeers: this.numPeersToUse
|
402
|
-
});
|
403
|
-
if (peers.length === 0) {
|
404
|
-
throw new Error("No peer found to initiate subscription.");
|
405
|
-
}
|
406
|
-
|
407
|
-
log.info(
|
408
|
-
`Creating filter subscription with ${peers.length} peers: `,
|
409
|
-
peers.map((peer) => peer.id.toString())
|
410
|
-
);
|
411
|
-
|
412
|
-
const subscription =
|
413
|
-
this.getActiveSubscription(pubsubTopic) ??
|
414
|
-
this.setActiveSubscription(
|
415
|
-
pubsubTopic,
|
416
|
-
new Subscription(pubsubTopic, peers, this.getStream.bind(this))
|
417
|
-
);
|
418
|
-
|
419
|
-
return subscription;
|
420
|
-
}
|
421
|
-
|
422
|
-
public toSubscriptionIterator<T extends IDecodedMessage>(
|
423
|
-
decoders: IDecoder<T> | IDecoder<T>[]
|
424
|
-
): Promise<IAsyncIterator<T>> {
|
425
|
-
return toAsyncIterator(this, decoders);
|
426
|
-
}
|
427
|
-
|
428
|
-
/**
|
429
|
-
* This method is used to satisfy the `IReceiver` interface.
|
430
|
-
*
|
431
|
-
* @hidden
|
432
|
-
*
|
433
|
-
* @param decoders The decoders to use for the subscription.
|
434
|
-
* @param callback The callback function to use for the subscription.
|
435
|
-
* @param opts Optional protocol options for the subscription.
|
436
|
-
*
|
437
|
-
* @returns A Promise that resolves to a function that unsubscribes from the subscription.
|
438
|
-
*
|
439
|
-
* @remarks
|
440
|
-
* This method should not be used directly.
|
441
|
-
* Instead, use `createSubscription` to create a new subscription.
|
442
|
-
*/
|
443
|
-
async subscribe<T extends IDecodedMessage>(
|
444
|
-
decoders: IDecoder<T> | IDecoder<T>[],
|
445
|
-
callback: Callback<T>
|
446
|
-
): Promise<Unsubscribe> {
|
447
|
-
const subscription = await this.createSubscription();
|
448
|
-
|
449
|
-
await subscription.subscribe(decoders, callback);
|
450
|
-
|
451
|
-
const contentTopics = Array.from(
|
452
|
-
groupByContentTopic(
|
453
|
-
Array.isArray(decoders) ? decoders : [decoders]
|
454
|
-
).keys()
|
455
|
-
);
|
456
|
-
|
457
|
-
return async () => {
|
458
|
-
await subscription.unsubscribe(contentTopics);
|
459
|
-
};
|
460
51
|
}
|
461
52
|
|
462
53
|
private onRequest(streamData: IncomingStreamData): void {
|
@@ -480,16 +71,7 @@ class Filter extends BaseProtocol implements IReceiver {
|
|
480
71
|
return;
|
481
72
|
}
|
482
73
|
|
483
|
-
|
484
|
-
|
485
|
-
if (!subscription) {
|
486
|
-
log.error(
|
487
|
-
`No subscription locally registered for topic ${pubsubTopic}`
|
488
|
-
);
|
489
|
-
return;
|
490
|
-
}
|
491
|
-
|
492
|
-
await subscription.processMessage(wakuMessage);
|
74
|
+
await this.handleIncomingMessage(pubsubTopic, wakuMessage);
|
493
75
|
}
|
494
76
|
}).then(
|
495
77
|
() => {
|
@@ -503,38 +85,139 @@ class Filter extends BaseProtocol implements IReceiver {
|
|
503
85
|
log.error("Error decoding message", e);
|
504
86
|
}
|
505
87
|
}
|
506
|
-
}
|
507
88
|
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
89
|
+
async subscribe(
|
90
|
+
pubsubTopic: PubsubTopic,
|
91
|
+
peer: Peer,
|
92
|
+
contentTopics: ContentTopic[]
|
93
|
+
): Promise<void> {
|
94
|
+
let stream: Stream;
|
95
|
+
try {
|
96
|
+
stream = await this.getStream(peer);
|
97
|
+
} catch (error) {
|
98
|
+
throw new Error(`Failed to get stream for peer ${peer.id.toString()}`);
|
99
|
+
}
|
100
|
+
|
101
|
+
const request = FilterSubscribeRpc.createSubscribeRequest(
|
102
|
+
pubsubTopic,
|
103
|
+
contentTopics
|
104
|
+
);
|
513
105
|
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
106
|
+
const res = await pipe(
|
107
|
+
[request.encode()],
|
108
|
+
lp.encode,
|
109
|
+
stream,
|
110
|
+
lp.decode,
|
111
|
+
async (source) => await all(source)
|
112
|
+
);
|
113
|
+
|
114
|
+
if (!res || !res.length) {
|
115
|
+
throw Error(
|
116
|
+
`No response received for request ${request.requestId}: ${res}`
|
117
|
+
);
|
118
|
+
}
|
119
|
+
|
120
|
+
const { statusCode, requestId, statusDesc } =
|
121
|
+
FilterSubscribeResponse.decode(res[0].slice());
|
122
|
+
|
123
|
+
if (statusCode < 200 || statusCode >= 300) {
|
124
|
+
throw new Error(
|
125
|
+
`Filter subscribe request ${requestId} failed with status code ${statusCode}: ${statusDesc}`
|
126
|
+
);
|
127
|
+
}
|
525
128
|
}
|
526
129
|
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
130
|
+
async unsubscribe(
|
131
|
+
pubsubTopic: PubsubTopic,
|
132
|
+
peer: Peer,
|
133
|
+
contentTopics: ContentTopic[]
|
134
|
+
): Promise<void> {
|
135
|
+
let stream: Stream;
|
136
|
+
try {
|
137
|
+
stream = await this.getStream(peer);
|
138
|
+
} catch (error) {
|
139
|
+
throw new Error(`Failed to get stream for peer ${peer.id.toString()}`);
|
140
|
+
}
|
141
|
+
|
142
|
+
const unsubscribeRequest = FilterSubscribeRpc.createUnsubscribeRequest(
|
143
|
+
pubsubTopic,
|
144
|
+
contentTopics
|
532
145
|
);
|
533
146
|
|
534
|
-
|
147
|
+
await pipe([unsubscribeRequest.encode()], lp.encode, stream.sink);
|
148
|
+
}
|
149
|
+
|
150
|
+
async unsubscribeAll(pubsubTopic: PubsubTopic, peer: Peer): Promise<void> {
|
151
|
+
let stream: Stream;
|
152
|
+
try {
|
153
|
+
stream = await this.getStream(peer);
|
154
|
+
} catch (error) {
|
155
|
+
throw new Error(`Failed to get stream for peer ${peer.id.toString()}`);
|
156
|
+
}
|
535
157
|
|
536
|
-
|
537
|
-
|
538
|
-
|
158
|
+
const request = FilterSubscribeRpc.createUnsubscribeAllRequest(pubsubTopic);
|
159
|
+
|
160
|
+
const res = await pipe(
|
161
|
+
[request.encode()],
|
162
|
+
lp.encode,
|
163
|
+
stream,
|
164
|
+
lp.decode,
|
165
|
+
async (source) => await all(source)
|
166
|
+
);
|
167
|
+
|
168
|
+
if (!res || !res.length) {
|
169
|
+
throw Error(
|
170
|
+
`No response received for request ${request.requestId}: ${res}`
|
171
|
+
);
|
172
|
+
}
|
173
|
+
|
174
|
+
const { statusCode, requestId, statusDesc } =
|
175
|
+
FilterSubscribeResponse.decode(res[0].slice());
|
176
|
+
|
177
|
+
if (statusCode < 200 || statusCode >= 300) {
|
178
|
+
throw new Error(
|
179
|
+
`Filter unsubscribe all request ${requestId} failed with status code ${statusCode}: ${statusDesc}`
|
180
|
+
);
|
181
|
+
}
|
182
|
+
}
|
183
|
+
|
184
|
+
async ping(peer: Peer): Promise<void> {
|
185
|
+
let stream: Stream;
|
186
|
+
try {
|
187
|
+
stream = await this.getStream(peer);
|
188
|
+
} catch (error) {
|
189
|
+
throw new Error(`Failed to get stream for peer ${peer.id.toString()}`);
|
190
|
+
}
|
191
|
+
|
192
|
+
const request = FilterSubscribeRpc.createSubscriberPingRequest();
|
193
|
+
|
194
|
+
try {
|
195
|
+
const res = await pipe(
|
196
|
+
[request.encode()],
|
197
|
+
lp.encode,
|
198
|
+
stream,
|
199
|
+
lp.decode,
|
200
|
+
async (source) => await all(source)
|
201
|
+
);
|
202
|
+
|
203
|
+
if (!res || !res.length) {
|
204
|
+
throw Error(
|
205
|
+
`No response received for request ${request.requestId}: ${res}`
|
206
|
+
);
|
207
|
+
}
|
208
|
+
|
209
|
+
const { statusCode, requestId, statusDesc } =
|
210
|
+
FilterSubscribeResponse.decode(res[0].slice());
|
211
|
+
|
212
|
+
if (statusCode < 200 || statusCode >= 300) {
|
213
|
+
throw new Error(
|
214
|
+
`Filter ping request ${requestId} failed with status code ${statusCode}: ${statusDesc}`
|
215
|
+
);
|
216
|
+
}
|
217
|
+
log.info(`Ping successful for peer ${peer.id.toString()}`);
|
218
|
+
} catch (error) {
|
219
|
+
log.error("Error pinging: ", error);
|
220
|
+
throw error; // Rethrow the actual error instead of wrapping it
|
221
|
+
}
|
539
222
|
}
|
540
223
|
}
|
@@ -100,18 +100,15 @@ export class LightPushCore extends BaseProtocol implements IBaseProtocolCore {
|
|
100
100
|
};
|
101
101
|
}
|
102
102
|
|
103
|
-
let stream: Stream
|
103
|
+
let stream: Stream;
|
104
104
|
try {
|
105
105
|
stream = await this.getStream(peer);
|
106
|
-
} catch (
|
107
|
-
log.error(
|
108
|
-
`Failed to get a stream for remote peer${peer.id.toString()}`,
|
109
|
-
err
|
110
|
-
);
|
106
|
+
} catch (error) {
|
107
|
+
log.error("Failed to get stream", error);
|
111
108
|
return {
|
112
109
|
success: null,
|
113
110
|
failure: {
|
114
|
-
error: ProtocolError.
|
111
|
+
error: ProtocolError.NO_STREAM_AVAILABLE,
|
115
112
|
peerId: peer.id
|
116
113
|
}
|
117
114
|
};
|
@@ -85,7 +85,16 @@ class Metadata extends BaseProtocol implements IMetadata {
|
|
85
85
|
};
|
86
86
|
}
|
87
87
|
|
88
|
-
|
88
|
+
let stream;
|
89
|
+
try {
|
90
|
+
stream = await this.getStream(peer);
|
91
|
+
} catch (error) {
|
92
|
+
log.error("Failed to get stream", error);
|
93
|
+
return {
|
94
|
+
shardInfo: null,
|
95
|
+
error: ProtocolError.NO_STREAM_AVAILABLE
|
96
|
+
};
|
97
|
+
}
|
89
98
|
|
90
99
|
const encodedResponse = await pipe(
|
91
100
|
[request],
|