@peerbit/pubsub 5.0.7 → 5.1.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 +1 @@
1
- {"version":3,"file":"topic-root-control-plane.d.ts","sourceRoot":"","sources":["../../src/topic-root-control-plane.ts"],"names":[],"mappings":"AASA,MAAM,MAAM,iBAAiB,GAAG,CAC/B,KAAK,EAAE,MAAM,KACT,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;AAEtD,MAAM,MAAM,gBAAgB,GAAG;IAC9B,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;CAC7E,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG;IACvC,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B,QAAQ,CAAC,EAAE,iBAAiB,CAAC;CAC7B,CAAC;AAEF,qBAAa,kBAAkB;IAC9B,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAA6B;IAClE,OAAO,CAAC,iBAAiB,CAAgB;IACzC,OAAO,CAAC,QAAQ,CAAC,CAAoB;gBAEzB,OAAO,CAAC,EAAE,yBAAyB;IAOxC,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;IAInC,UAAU,CAAC,KAAK,EAAE,MAAM;IAIxB,OAAO,CAAC,KAAK,EAAE,MAAM;IAIrB,oBAAoB,CAAC,UAAU,EAAE,MAAM,EAAE;IAWzC,oBAAoB;IAIpB,WAAW,CAAC,QAAQ,CAAC,EAAE,iBAAiB;IAIlC,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAOvD,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAO9D,6BAA6B,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;CAKvE;AAED,MAAM,MAAM,4BAA4B,GAAG,yBAAyB,GAAG;IACtE,SAAS,CAAC,EAAE,kBAAkB,CAAC;IAC/B,QAAQ,CAAC,EAAE,gBAAgB,EAAE,CAAC;CAC9B,CAAC;AAEF,qBAAa,qBAAqB;IACjC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAqB;IAC/C,OAAO,CAAC,QAAQ,CAAqB;gBAEzB,OAAO,CAAC,EAAE,4BAA4B;IAU3C,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;IAIxC,cAAc,CAAC,KAAK,EAAE,MAAM;IAI5B,YAAY,CAAC,KAAK,EAAE,MAAM;IAI1B,sBAAsB,CAAC,UAAU,EAAE,MAAM,EAAE;IAI3C,sBAAsB;IAItB,oBAAoB,CAAC,QAAQ,CAAC,EAAE,iBAAiB;IAIjD,oBAAoB,CAAC,QAAQ,EAAE,gBAAgB,EAAE;IAIjD,oBAAoB;IAIpB,gBAAgB,CAAC,KAAK,EAAE,MAAM;YAIvB,mBAAmB;CAkBjC"}
1
+ {"version":3,"file":"topic-root-control-plane.d.ts","sourceRoot":"","sources":["../../src/topic-root-control-plane.ts"],"names":[],"mappings":"AASA,MAAM,MAAM,iBAAiB,GAAG,CAC/B,KAAK,EAAE,MAAM,KACT,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;AAEtD,MAAM,MAAM,gBAAgB,GAAG;IAC9B,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;CAC7E,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG;IACvC,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B,QAAQ,CAAC,EAAE,iBAAiB,CAAC;CAC7B,CAAC;AAEF,qBAAa,kBAAkB;IAC9B,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAA6B;IAClE,OAAO,CAAC,iBAAiB,CAAgB;IACzC,OAAO,CAAC,QAAQ,CAAC,CAAoB;gBAEzB,OAAO,CAAC,EAAE,yBAAyB;IAOxC,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;IAInC,UAAU,CAAC,KAAK,EAAE,MAAM;IAIxB,OAAO,CAAC,KAAK,EAAE,MAAM;IAIrB,oBAAoB,CAAC,UAAU,EAAE,MAAM,EAAE;IAWzC,oBAAoB;IAIpB,WAAW,CAAC,QAAQ,CAAC,EAAE,iBAAiB;IAIlC,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAOvD,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAO9D,6BAA6B,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;CAKvE;AAED,MAAM,MAAM,4BAA4B,GAAG,yBAAyB,GAAG;IACtE,SAAS,CAAC,EAAE,kBAAkB,CAAC;IAC/B,QAAQ,CAAC,EAAE,gBAAgB,EAAE,CAAC;CAC9B,CAAC;AAEF,qBAAa,qBAAqB;IACjC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAqB;IAC/C,OAAO,CAAC,QAAQ,CAAqB;gBAEzB,OAAO,CAAC,EAAE,4BAA4B;IAU3C,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;IAIxC,cAAc,CAAC,KAAK,EAAE,MAAM;IAI5B,YAAY,CAAC,KAAK,EAAE,MAAM;IAI1B,sBAAsB,CAAC,UAAU,EAAE,MAAM,EAAE;IAI3C,sBAAsB;IAItB,oBAAoB,CAAC,QAAQ,CAAC,EAAE,iBAAiB;IAIjD,oBAAoB,CAAC,QAAQ,EAAE,gBAAgB,EAAE;IAIjD,oBAAoB;IAIpB,qBAAqB,CAAC,KAAK,EAAE,MAAM;IAInC,6BAA6B,CAAC,KAAK,EAAE,MAAM;IAI3C,yBAAyB,CAAC,KAAK,EAAE,MAAM;IAIvC,uBAAuB,CAAC,KAAK,EAAE,MAAM;IAIrC,gBAAgB,CAAC,KAAK,EAAE,MAAM;YAIvB,mBAAmB;CAuBjC"}
@@ -95,10 +95,22 @@ export class TopicRootControlPlane {
95
95
  getTopicRootTrackers() {
96
96
  return [...this.trackers];
97
97
  }
98
+ resolveLocalTopicRoot(topic) {
99
+ return this.directory.resolveLocal(topic);
100
+ }
101
+ resolveDeterministicTopicRoot(topic) {
102
+ return this.directory.resolveDeterministicCandidate(topic);
103
+ }
104
+ resolveCanonicalTopicRoot(topic) {
105
+ return this.directory.resolveRoot(topic);
106
+ }
107
+ resolveTrackedTopicRoot(topic) {
108
+ return this.resolveWithTrackers(topic, false);
109
+ }
98
110
  resolveTopicRoot(topic) {
99
- return this.resolveWithTrackers(topic);
111
+ return this.resolveWithTrackers(topic, true);
100
112
  }
101
- async resolveWithTrackers(topic) {
113
+ async resolveWithTrackers(topic, fallbackToDeterministic = true) {
102
114
  const local = await this.directory.resolveLocal(topic);
103
115
  if (local) {
104
116
  return local;
@@ -114,7 +126,9 @@ export class TopicRootControlPlane {
114
126
  // ignore tracker failures and continue with remaining trackers
115
127
  }
116
128
  }
117
- return this.directory.resolveDeterministicCandidate(topic);
129
+ return fallbackToDeterministic
130
+ ? this.directory.resolveDeterministicCandidate(topic)
131
+ : undefined;
118
132
  }
119
133
  }
120
134
  //# sourceMappingURL=topic-root-control-plane.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"topic-root-control-plane.js","sourceRoot":"","sources":["../../src/topic-root-control-plane.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"topic-root-control-plane.js","sourceRoot":"","sources":["../../src/topic-root-control-plane.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@peerbit/pubsub",
3
- "version": "5.0.7",
3
+ "version": "5.1.0",
4
4
  "description": "Direct streaming for libp2p",
5
5
  "type": "module",
6
6
  "types": "./dist/src/index.d.ts",
@@ -86,11 +86,11 @@
86
86
  "p-defer": "^4.0.0",
87
87
  "uint8arraylist": "^2.4.8",
88
88
  "uint8arrays": "^5.1.0",
89
- "@peerbit/crypto": "3.1.0",
90
89
  "@peerbit/logger": "2.0.0",
91
- "@peerbit/stream": "5.0.5",
92
- "@peerbit/stream-interface": "6.0.5",
93
- "@peerbit/pubsub-interface": "5.0.6",
90
+ "@peerbit/crypto": "3.1.0",
91
+ "@peerbit/pubsub-interface": "5.1.0",
92
+ "@peerbit/stream": "5.0.6",
93
+ "@peerbit/stream-interface": "6.0.6",
94
94
  "@peerbit/time": "3.0.0",
95
95
  "@peerbit/any-store-interface": "1.1.0"
96
96
  },
@@ -1493,6 +1493,15 @@ export class FanoutTree extends DirectStream<FanoutTreeEvents> {
1493
1493
  .filter((a) => Boolean(a));
1494
1494
  }
1495
1495
 
1496
+ public addBootstraps(addrs: Array<string | Multiaddr>) {
1497
+ const merged = new Map(this.bootstraps.map((addr) => [addr.toString(), addr]));
1498
+ for (const addr of addrs) {
1499
+ const multiaddrValue = typeof addr === "string" ? multiaddr(addr) : addr;
1500
+ merged.set(multiaddrValue.toString(), multiaddrValue);
1501
+ }
1502
+ this.bootstraps = [...merged.values()];
1503
+ }
1504
+
1496
1505
  private touchTrackerNamespace(suffixKey: string, now = Date.now()) {
1497
1506
  if (!suffixKey) return;
1498
1507
  // LRU touch
@@ -4102,7 +4111,6 @@ export class FanoutTree extends DirectStream<FanoutTreeEvents> {
4102
4111
 
4103
4112
  const bootstraps = this.getBootstrapsForChannel(ch);
4104
4113
  if (bootstraps.length === 0) return;
4105
-
4106
4114
  const peers = await this.ensureBootstrapPeers(
4107
4115
  bootstraps,
4108
4116
  ch.bootstrapDialTimeoutMs,
@@ -4691,8 +4699,12 @@ export class FanoutTree extends DirectStream<FanoutTreeEvents> {
4691
4699
  const rootNeighbor = Boolean(
4692
4700
  rootPeer && rootPeer.isReadable && rootPeer.isWritable,
4693
4701
  );
4702
+ const bootstrapHint =
4703
+ bootstrapsCount === 0 && !rootNeighbor
4704
+ ? " No fanout bootstraps are configured for this channel, and the root is not a direct neighbor. If this peer reached the network via a bootstrap or relay node, initialize it with Peerbit.bootstrap(...) instead of Peerbit.dial(...), or configure FanoutTree.setBootstraps(...) before joining sharded topics."
4705
+ : "";
4694
4706
  throw new Error(
4695
- `fanout join timed out after ${timeoutMs}ms (topic=${ch.id.topic} root=${ch.id.root} self=${this.publicKeyHash} rootNeighbor=${rootNeighbor} peers=${this.peers.size} bootstraps=${bootstrapsCount})`,
4707
+ `fanout join timed out after ${timeoutMs}ms (topic=${ch.id.topic} root=${ch.id.root} self=${this.publicKeyHash} rootNeighbor=${rootNeighbor} peers=${this.peers.size} bootstraps=${bootstrapsCount}).${bootstrapHint}`,
4696
4708
  );
4697
4709
  }
4698
4710
 
package/src/index.ts CHANGED
@@ -17,6 +17,8 @@ import {
17
17
  SubscriptionData,
18
18
  SubscriptionEvent,
19
19
  TopicRootCandidates,
20
+ TopicRootQuery,
21
+ TopicRootQueryResponse,
20
22
  UnsubcriptionEvent,
21
23
  type UnsubscriptionReason,
22
24
  Unsubscribe,
@@ -116,6 +118,9 @@ const DEFAULT_PUBSUB_SHARD_COUNT = 256;
116
118
  const PUBSUB_SHARD_COUNT_HARD_CAP = 16_384;
117
119
  const DEFAULT_PUBSUB_SHARD_TOPIC_PREFIX = "/peerbit/pubsub-shard/1/";
118
120
  const AUTO_TOPIC_ROOT_CANDIDATES_MAX = 64;
121
+ // Topic-root queries may need to wait for the responder to finish opening an
122
+ // outbound stream back to the requester after an inbound-only dial.
123
+ const DEFAULT_TOPIC_ROOT_QUERY_TIMEOUT_MS = 12_000;
119
124
 
120
125
  const DEFAULT_PUBSUB_FANOUT_CHANNEL_OPTIONS: Omit<
121
126
  FanoutTreeChannelOptions,
@@ -250,7 +255,10 @@ export class TopicControlPlane
250
255
  private readonly shardCount: number;
251
256
  private readonly shardTopicPrefix: string;
252
257
  private readonly hostShards: boolean;
253
- private readonly shardRootCache = new Map<string, string>();
258
+ private readonly shardRootCache = new Map<
259
+ string,
260
+ { root: string; authoritative: boolean }
261
+ >();
254
262
  private readonly shardTopicCache = new Map<string, string>();
255
263
  private readonly shardRefCounts = new Map<string, number>();
256
264
  private readonly pinnedShards = new Set<string>();
@@ -297,6 +305,15 @@ export class TopicControlPlane
297
305
  idleCloseTimeout?: ReturnType<typeof setTimeout>;
298
306
  }
299
307
  >();
308
+ private pendingTopicRootQueries = new Map<
309
+ number,
310
+ {
311
+ topic: string;
312
+ resolve: (root: string | undefined) => void;
313
+ timer: ReturnType<typeof setTimeout>;
314
+ }
315
+ >();
316
+ private nextTopicRootQueryId = 1;
300
317
 
301
318
  constructor(
302
319
  components: TopicControlPlaneComponents,
@@ -489,6 +506,11 @@ export class TopicControlPlane
489
506
  this.shardTopicCache.clear();
490
507
  this.shardRefCounts.clear();
491
508
  this.pinnedShards.clear();
509
+ for (const pending of this.pendingTopicRootQueries.values()) {
510
+ clearTimeout(pending.timer);
511
+ pending.resolve(undefined);
512
+ }
513
+ this.pendingTopicRootQueries.clear();
492
514
 
493
515
  this.debounceSubscribeAggregator.close();
494
516
  this.debounceUnsubscribeAggregator.close();
@@ -913,6 +935,41 @@ export class TopicControlPlane
913
935
  return shardTopic;
914
936
  }
915
937
 
938
+ private async resolveTopicRootState(
939
+ topic: string,
940
+ ): Promise<{ root?: string; authoritative: boolean }> {
941
+ const tracked = await this.topicRootControlPlane.resolveTrackedTopicRoot(topic);
942
+ if (tracked) {
943
+ return { root: tracked, authoritative: true };
944
+ }
945
+
946
+ const resolvedThroughPeers = await this.resolveTopicRootThroughPeers(topic);
947
+ if (resolvedThroughPeers) {
948
+ return { root: resolvedThroughPeers, authoritative: true };
949
+ }
950
+
951
+ const deterministic = this.topicRootControlPlane.resolveDeterministicTopicRoot(topic);
952
+ if (
953
+ deterministic === this.publicKeyHash &&
954
+ this.autoTopicRootCandidates &&
955
+ this.getConnectedTopicRootTrackers().length > 0
956
+ ) {
957
+ for (let attempt = 0; attempt < 8; attempt++) {
958
+ await delay(150 * (attempt < 4 ? 1 : 2));
959
+ const retried = await this.resolveTopicRootThroughPeers(topic);
960
+ if (retried) {
961
+ return { root: retried, authoritative: true };
962
+ }
963
+ }
964
+ }
965
+
966
+ return { root: deterministic, authoritative: false };
967
+ }
968
+
969
+ public async resolveTopicRoot(topic: string): Promise<string | undefined> {
970
+ return (await this.resolveTopicRootState(topic)).root;
971
+ }
972
+
916
973
  private async resolveShardRoot(shardTopic: string): Promise<string> {
917
974
  // If someone configured topic-root candidates externally (e.g. TestSession router
918
975
  // selection or Peerbit.bootstrap) after this peer entered auto mode, disable auto
@@ -921,17 +978,134 @@ export class TopicControlPlane
921
978
  this.maybeDisableAutoTopicRootCandidatesIfExternallyConfigured();
922
979
  }
923
980
 
981
+ const hasConnectedTrackers = this.getConnectedTopicRootTrackers().length > 0;
924
982
  const cached = this.shardRootCache.get(shardTopic);
925
- if (cached) return cached;
926
- const resolved =
927
- await this.topicRootControlPlane.resolveTopicRoot(shardTopic);
928
- if (!resolved) {
983
+ if (cached && (cached.authoritative || !hasConnectedTrackers)) {
984
+ return cached.root;
985
+ }
986
+ const resolved = await this.resolveTopicRootState(shardTopic);
987
+ if (!resolved.root) {
929
988
  throw new Error(
930
- `No root resolved for shard topic ${shardTopic}. Configure TopicRootControlPlane candidates/resolver/trackers.`,
989
+ `No root resolved for shard topic ${shardTopic}. Configure TopicRootControlPlane candidates/resolver/trackers, or dial/bootstrap a peer that can resolve shard roots.`,
990
+ );
991
+ }
992
+ if (resolved.authoritative || !hasConnectedTrackers) {
993
+ this.shardRootCache.set(shardTopic, resolved as {
994
+ root: string;
995
+ authoritative: boolean;
996
+ });
997
+ } else {
998
+ this.shardRootCache.delete(shardTopic);
999
+ }
1000
+ return resolved.root;
1001
+ }
1002
+
1003
+ private getConnectedTopicRootTrackers(): PeerStreams[] {
1004
+ return [...this.peers.values()]
1005
+ .filter((peer) => peer.isReadable || peer.isWritable)
1006
+ .sort((a, b) =>
1007
+ a.publicKey.hashcode() < b.publicKey.hashcode()
1008
+ ? -1
1009
+ : a.publicKey.hashcode() > b.publicKey.hashcode()
1010
+ ? 1
1011
+ : 0,
1012
+ );
1013
+ }
1014
+
1015
+ private nextTopicRootRequestIdValue() {
1016
+ let requestId = this.nextTopicRootQueryId >>> 0;
1017
+ do {
1018
+ requestId = requestId === 0 ? 1 : requestId;
1019
+ this.nextTopicRootQueryId = ((requestId + 1) >>> 0) || 1;
1020
+ if (!this.pendingTopicRootQueries.has(requestId)) {
1021
+ return requestId;
1022
+ }
1023
+ requestId = this.nextTopicRootQueryId >>> 0;
1024
+ } while (true);
1025
+ }
1026
+
1027
+ private async sendDirectControlMessage(
1028
+ peer: PeerStreams,
1029
+ pubsubMessage: PubSubMessage,
1030
+ ) {
1031
+ const embedded = await this.createMessage(toUint8Array(pubsubMessage.bytes()), {
1032
+ mode: new SilentDelivery({
1033
+ to: [peer.publicKey.hashcode()],
1034
+ redundancy: 1,
1035
+ }),
1036
+ priority: 1,
1037
+ skipRecipientValidation: true,
1038
+ } as any);
1039
+ await this.publishMessage(this.publicKey, embedded, [peer]);
1040
+ }
1041
+
1042
+ private resolvePendingTopicRootQuery(
1043
+ message: TopicRootQueryResponse,
1044
+ ): boolean {
1045
+ const pending = this.pendingTopicRootQueries.get(message.requestId);
1046
+ if (!pending || pending.topic !== message.topic) {
1047
+ return false;
1048
+ }
1049
+ this.pendingTopicRootQueries.delete(message.requestId);
1050
+ clearTimeout(pending.timer);
1051
+ pending.resolve(message.root);
1052
+ return true;
1053
+ }
1054
+
1055
+ private async queryTopicRootFromPeer(
1056
+ peer: PeerStreams,
1057
+ topic: string,
1058
+ ): Promise<string | undefined> {
1059
+ if (!this.started || this.stopping) return undefined;
1060
+
1061
+ const requestId = this.nextTopicRootRequestIdValue();
1062
+ const responsePromise = new Promise<string | undefined>((resolve) => {
1063
+ const timer = setTimeout(() => {
1064
+ this.pendingTopicRootQueries.delete(requestId);
1065
+ resolve(undefined);
1066
+ }, DEFAULT_TOPIC_ROOT_QUERY_TIMEOUT_MS);
1067
+ timer.unref?.();
1068
+ this.pendingTopicRootQueries.set(requestId, { topic, resolve, timer });
1069
+ });
1070
+
1071
+ try {
1072
+ await this.sendDirectControlMessage(
1073
+ peer,
1074
+ new TopicRootQuery({ requestId, topic }),
931
1075
  );
1076
+ } catch {
1077
+ const pending = this.pendingTopicRootQueries.get(requestId);
1078
+ if (pending) {
1079
+ this.pendingTopicRootQueries.delete(requestId);
1080
+ clearTimeout(pending.timer);
1081
+ pending.resolve(undefined);
1082
+ }
1083
+ }
1084
+
1085
+ return responsePromise;
1086
+ }
1087
+
1088
+ private async resolveTopicRootThroughPeers(
1089
+ topic: string,
1090
+ ): Promise<string | undefined> {
1091
+ const peers = this.getConnectedTopicRootTrackers();
1092
+ if (peers.length === 0) {
1093
+ return undefined;
1094
+ }
1095
+
1096
+ for (let attempt = 0; attempt < 3; attempt++) {
1097
+ for (const peer of peers) {
1098
+ const resolved = await this.queryTopicRootFromPeer(peer, topic);
1099
+ if (resolved) {
1100
+ return resolved;
1101
+ }
1102
+ }
1103
+
1104
+ if (attempt < 2) {
1105
+ await delay(150 * (attempt + 1));
1106
+ }
932
1107
  }
933
- this.shardRootCache.set(shardTopic, resolved);
934
- return resolved;
1108
+ return undefined;
935
1109
  }
936
1110
 
937
1111
  private async ensureFanoutChannel(
@@ -1884,8 +2058,9 @@ export class TopicControlPlane
1884
2058
  private async processDirectPubSubMessage(input: {
1885
2059
  pubsubMessage: PubSubMessage;
1886
2060
  message: DataMessage;
2061
+ stream: PeerStreams;
1887
2062
  }): Promise<void> {
1888
- const { pubsubMessage, message } = input;
2063
+ const { pubsubMessage, message, stream } = input;
1889
2064
 
1890
2065
  if (pubsubMessage instanceof TopicRootCandidates) {
1891
2066
  // Used only to converge deterministic shard-root candidates in auto mode.
@@ -1893,6 +2068,26 @@ export class TopicControlPlane
1893
2068
  return;
1894
2069
  }
1895
2070
 
2071
+ if (pubsubMessage instanceof TopicRootQuery) {
2072
+ const root = await this.topicRootControlPlane.resolveCanonicalTopicRoot(
2073
+ pubsubMessage.topic,
2074
+ );
2075
+ await this.sendDirectControlMessage(
2076
+ stream,
2077
+ new TopicRootQueryResponse({
2078
+ requestId: pubsubMessage.requestId,
2079
+ topic: pubsubMessage.topic,
2080
+ root,
2081
+ }),
2082
+ ).catch(() => {});
2083
+ return;
2084
+ }
2085
+
2086
+ if (pubsubMessage instanceof TopicRootQueryResponse) {
2087
+ this.resolvePendingTopicRootQuery(pubsubMessage);
2088
+ return;
2089
+ }
2090
+
1896
2091
  if (pubsubMessage instanceof PubSubData) {
1897
2092
  this.dispatchEvent(
1898
2093
  new CustomEvent("data", {
@@ -2149,7 +2344,9 @@ export class TopicControlPlane
2149
2344
  // messages. All membership/control traffic is shard-only.
2150
2345
  if (
2151
2346
  !(pubsubMessage instanceof PubSubData) &&
2152
- !(pubsubMessage instanceof TopicRootCandidates)
2347
+ !(pubsubMessage instanceof TopicRootCandidates) &&
2348
+ !(pubsubMessage instanceof TopicRootQuery) &&
2349
+ !(pubsubMessage instanceof TopicRootQueryResponse)
2153
2350
  ) {
2154
2351
  return true;
2155
2352
  }
@@ -2176,7 +2373,11 @@ export class TopicControlPlane
2176
2373
  if ((await this.verifyAndProcess(message)) === false) return false;
2177
2374
  await this.maybeAcknowledgeMessage(stream, message, seenBefore);
2178
2375
  if (seenBefore === 0) {
2179
- await this.processDirectPubSubMessage({ pubsubMessage, message });
2376
+ await this.processDirectPubSubMessage({
2377
+ pubsubMessage,
2378
+ message,
2379
+ stream,
2380
+ });
2180
2381
  }
2181
2382
  }
2182
2383
 
@@ -135,11 +135,30 @@ export class TopicRootControlPlane {
135
135
  return [...this.trackers];
136
136
  }
137
137
 
138
+ public resolveLocalTopicRoot(topic: string) {
139
+ return this.directory.resolveLocal(topic);
140
+ }
141
+
142
+ public resolveDeterministicTopicRoot(topic: string) {
143
+ return this.directory.resolveDeterministicCandidate(topic);
144
+ }
145
+
146
+ public resolveCanonicalTopicRoot(topic: string) {
147
+ return this.directory.resolveRoot(topic);
148
+ }
149
+
150
+ public resolveTrackedTopicRoot(topic: string) {
151
+ return this.resolveWithTrackers(topic, false);
152
+ }
153
+
138
154
  public resolveTopicRoot(topic: string) {
139
- return this.resolveWithTrackers(topic);
155
+ return this.resolveWithTrackers(topic, true);
140
156
  }
141
157
 
142
- private async resolveWithTrackers(topic: string): Promise<string | undefined> {
158
+ private async resolveWithTrackers(
159
+ topic: string,
160
+ fallbackToDeterministic = true,
161
+ ): Promise<string | undefined> {
143
162
  const local = await this.directory.resolveLocal(topic);
144
163
  if (local) {
145
164
  return local;
@@ -155,6 +174,8 @@ export class TopicRootControlPlane {
155
174
  // ignore tracker failures and continue with remaining trackers
156
175
  }
157
176
  }
158
- return this.directory.resolveDeterministicCandidate(topic);
177
+ return fallbackToDeterministic
178
+ ? this.directory.resolveDeterministicCandidate(topic)
179
+ : undefined;
159
180
  }
160
181
  }