@peerbit/pubsub 4.1.4-0e16a6e → 4.1.4-1929680
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/dist/src/fanout-tree.d.ts +2 -1
- package/dist/src/fanout-tree.d.ts.map +1 -1
- package/dist/src/fanout-tree.js +38 -1
- package/dist/src/fanout-tree.js.map +1 -1
- package/dist/src/index.d.ts +8 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +52 -3
- package/dist/src/index.js.map +1 -1
- package/package.json +9 -9
- package/src/fanout-tree.ts +50 -1
- package/src/index.ts +65 -3
package/src/index.ts
CHANGED
|
@@ -36,6 +36,7 @@ import {
|
|
|
36
36
|
MessageHeader,
|
|
37
37
|
NotStartedError,
|
|
38
38
|
type PriorityOptions,
|
|
39
|
+
type RouteHint,
|
|
39
40
|
SilentDelivery,
|
|
40
41
|
type WithExtraSigners,
|
|
41
42
|
deliveryModeHasReceiver,
|
|
@@ -228,6 +229,8 @@ export class TopicControlPlane
|
|
|
228
229
|
public peerToTopic: Map<string, Set<string>>;
|
|
229
230
|
// Local topic -> reference count.
|
|
230
231
|
public subscriptions: Map<string, { counter: number }>;
|
|
232
|
+
// Local topics requested via debounced subscribe, not yet applied in `subscriptions`.
|
|
233
|
+
private pendingSubscriptions: Set<string>;
|
|
231
234
|
public lastSubscriptionMessages: Map<string, Map<string, bigint>> = new Map();
|
|
232
235
|
public dispatchEventOnSelfPublish: boolean;
|
|
233
236
|
public readonly topicRootControlPlane: TopicRootControlPlane;
|
|
@@ -289,6 +292,7 @@ export class TopicControlPlane
|
|
|
289
292
|
) {
|
|
290
293
|
super(components, ["/peerbit/topic-control-plane/2.0.0"], props);
|
|
291
294
|
this.subscriptions = new Map();
|
|
295
|
+
this.pendingSubscriptions = new Set();
|
|
292
296
|
this.topics = new Map();
|
|
293
297
|
this.peerToTopic = new Map();
|
|
294
298
|
|
|
@@ -448,6 +452,7 @@ export class TopicControlPlane
|
|
|
448
452
|
this.autoCandidatesGossipUntil = 0;
|
|
449
453
|
|
|
450
454
|
this.subscriptions.clear();
|
|
455
|
+
this.pendingSubscriptions.clear();
|
|
451
456
|
this.topics.clear();
|
|
452
457
|
this.peerToTopic.clear();
|
|
453
458
|
this.lastSubscriptionMessages.clear();
|
|
@@ -760,11 +765,24 @@ export class TopicControlPlane
|
|
|
760
765
|
const subscriptions: string[] = [];
|
|
761
766
|
if (topics) {
|
|
762
767
|
for (const topic of topics) {
|
|
763
|
-
if (
|
|
768
|
+
if (
|
|
769
|
+
this.subscriptions.get(topic) ||
|
|
770
|
+
this.pendingSubscriptions.has(topic)
|
|
771
|
+
) {
|
|
772
|
+
subscriptions.push(topic);
|
|
773
|
+
}
|
|
764
774
|
}
|
|
765
775
|
return subscriptions;
|
|
766
776
|
}
|
|
767
|
-
|
|
777
|
+
const seen = new Set<string>();
|
|
778
|
+
for (const [topic] of this.subscriptions) {
|
|
779
|
+
subscriptions.push(topic);
|
|
780
|
+
seen.add(topic);
|
|
781
|
+
}
|
|
782
|
+
for (const topic of this.pendingSubscriptions) {
|
|
783
|
+
if (seen.has(topic)) continue;
|
|
784
|
+
subscriptions.push(topic);
|
|
785
|
+
}
|
|
768
786
|
return subscriptions;
|
|
769
787
|
}
|
|
770
788
|
|
|
@@ -1098,6 +1116,10 @@ export class TopicControlPlane
|
|
|
1098
1116
|
}
|
|
1099
1117
|
|
|
1100
1118
|
async subscribe(topic: string) {
|
|
1119
|
+
this.pendingSubscriptions.add(topic);
|
|
1120
|
+
// `subscribe()` is debounced; start tracking immediately to avoid dropping
|
|
1121
|
+
// inbound subscription traffic during the debounce window.
|
|
1122
|
+
this.initializeTopic(topic);
|
|
1101
1123
|
return this.debounceSubscribeAggregator.add({ key: topic });
|
|
1102
1124
|
}
|
|
1103
1125
|
|
|
@@ -1111,10 +1133,12 @@ export class TopicControlPlane
|
|
|
1111
1133
|
let prev = this.subscriptions.get(topic);
|
|
1112
1134
|
if (prev) {
|
|
1113
1135
|
prev.counter += counter;
|
|
1136
|
+
this.pendingSubscriptions.delete(topic);
|
|
1114
1137
|
continue;
|
|
1115
1138
|
}
|
|
1116
1139
|
this.subscriptions.set(topic, { counter });
|
|
1117
1140
|
this.initializeTopic(topic);
|
|
1141
|
+
this.pendingSubscriptions.delete(topic);
|
|
1118
1142
|
|
|
1119
1143
|
const shardTopic = this.getShardTopicForUserTopic(topic);
|
|
1120
1144
|
byShard.set(shardTopic, [...(byShard.get(shardTopic) ?? []), topic]);
|
|
@@ -1156,8 +1180,13 @@ export class TopicControlPlane
|
|
|
1156
1180
|
data?: Uint8Array;
|
|
1157
1181
|
},
|
|
1158
1182
|
) {
|
|
1183
|
+
this.pendingSubscriptions.delete(topic);
|
|
1184
|
+
|
|
1159
1185
|
if (this.debounceSubscribeAggregator.has(topic)) {
|
|
1160
1186
|
this.debounceSubscribeAggregator.delete(topic);
|
|
1187
|
+
if (!this.subscriptions.has(topic)) {
|
|
1188
|
+
this.untrackTopic(topic);
|
|
1189
|
+
}
|
|
1161
1190
|
return false;
|
|
1162
1191
|
}
|
|
1163
1192
|
|
|
@@ -1252,6 +1281,39 @@ export class TopicControlPlane
|
|
|
1252
1281
|
return ret;
|
|
1253
1282
|
}
|
|
1254
1283
|
|
|
1284
|
+
/**
|
|
1285
|
+
* Returns best-effort route hints for a target peer by combining:
|
|
1286
|
+
* - DirectStream ACK-learned routes
|
|
1287
|
+
* - Fanout route tokens for the topic's shard overlay
|
|
1288
|
+
*/
|
|
1289
|
+
getUnifiedRouteHints(topic: string, targetHash: string): RouteHint[] {
|
|
1290
|
+
const hints: RouteHint[] = [];
|
|
1291
|
+
const directHint = this.getBestRouteHint(targetHash);
|
|
1292
|
+
if (directHint) {
|
|
1293
|
+
hints.push(directHint);
|
|
1294
|
+
}
|
|
1295
|
+
|
|
1296
|
+
const topicString = topic.toString();
|
|
1297
|
+
const shardTopic = topicString.startsWith(this.shardTopicPrefix)
|
|
1298
|
+
? topicString
|
|
1299
|
+
: this.getShardTopicForUserTopic(topicString);
|
|
1300
|
+
const shard = this.fanoutChannels.get(shardTopic);
|
|
1301
|
+
if (!shard) {
|
|
1302
|
+
return hints;
|
|
1303
|
+
}
|
|
1304
|
+
|
|
1305
|
+
const fanoutHint = this.fanout.getRouteHint(
|
|
1306
|
+
shardTopic,
|
|
1307
|
+
shard.root,
|
|
1308
|
+
targetHash,
|
|
1309
|
+
);
|
|
1310
|
+
if (fanoutHint) {
|
|
1311
|
+
hints.push(fanoutHint);
|
|
1312
|
+
}
|
|
1313
|
+
|
|
1314
|
+
return hints;
|
|
1315
|
+
}
|
|
1316
|
+
|
|
1255
1317
|
async requestSubscribers(
|
|
1256
1318
|
topic: string | string[],
|
|
1257
1319
|
to?: PublicSignKey,
|
|
@@ -1736,7 +1798,7 @@ export class TopicControlPlane
|
|
|
1736
1798
|
|
|
1737
1799
|
if (pubsubMessage instanceof PubSubData) {
|
|
1738
1800
|
const wantsTopic = pubsubMessage.topics.some((t) =>
|
|
1739
|
-
this.subscriptions.has(t),
|
|
1801
|
+
this.subscriptions.has(t) || this.pendingSubscriptions.has(t),
|
|
1740
1802
|
);
|
|
1741
1803
|
isForMe = pubsubMessage.strict ? isForMe && wantsTopic : wantsTopic;
|
|
1742
1804
|
}
|