@peerbit/pubsub 4.1.4 → 5.0.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/README.md +23 -20
- package/dist/benchmark/fanout-tree-sim-lib.d.ts +201 -0
- package/dist/benchmark/fanout-tree-sim-lib.d.ts.map +1 -0
- package/dist/benchmark/fanout-tree-sim-lib.js +1225 -0
- package/dist/benchmark/fanout-tree-sim-lib.js.map +1 -0
- package/dist/benchmark/fanout-tree-sim.d.ts +11 -0
- package/dist/benchmark/fanout-tree-sim.d.ts.map +1 -0
- package/dist/benchmark/fanout-tree-sim.js +521 -0
- package/dist/benchmark/fanout-tree-sim.js.map +1 -0
- package/dist/benchmark/index.d.ts +6 -0
- package/dist/benchmark/index.d.ts.map +1 -1
- package/dist/benchmark/index.js +38 -80
- package/dist/benchmark/index.js.map +1 -1
- package/dist/benchmark/pubsub-topic-sim-lib.d.ts +82 -0
- package/dist/benchmark/pubsub-topic-sim-lib.d.ts.map +1 -0
- package/dist/benchmark/pubsub-topic-sim-lib.js +625 -0
- package/dist/benchmark/pubsub-topic-sim-lib.js.map +1 -0
- package/dist/benchmark/pubsub-topic-sim.d.ts +9 -0
- package/dist/benchmark/pubsub-topic-sim.d.ts.map +1 -0
- package/dist/benchmark/pubsub-topic-sim.js +116 -0
- package/dist/benchmark/pubsub-topic-sim.js.map +1 -0
- package/dist/benchmark/sim/bench-utils.d.ts +25 -0
- package/dist/benchmark/sim/bench-utils.d.ts.map +1 -0
- package/dist/benchmark/sim/bench-utils.js +141 -0
- package/dist/benchmark/sim/bench-utils.js.map +1 -0
- package/dist/src/fanout-channel.d.ts +62 -0
- package/dist/src/fanout-channel.d.ts.map +1 -0
- package/dist/src/fanout-channel.js +114 -0
- package/dist/src/fanout-channel.js.map +1 -0
- package/dist/src/fanout-tree.d.ts +551 -0
- package/dist/src/fanout-tree.d.ts.map +1 -0
- package/dist/src/fanout-tree.js +4980 -0
- package/dist/src/fanout-tree.js.map +1 -0
- package/dist/src/index.d.ts +168 -39
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +1416 -457
- package/dist/src/index.js.map +1 -1
- package/dist/src/topic-root-control-plane.d.ts +43 -0
- package/dist/src/topic-root-control-plane.d.ts.map +1 -0
- package/dist/src/topic-root-control-plane.js +120 -0
- package/dist/src/topic-root-control-plane.js.map +1 -0
- package/package.json +8 -7
- package/src/fanout-channel.ts +150 -0
- package/src/fanout-tree.ts +6346 -0
- package/src/index.ts +1693 -591
- package/src/topic-root-control-plane.ts +160 -0
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
const topicHash32 = (topic: string) => {
|
|
2
|
+
let hash = 0x811c9dc5; // FNV-1a
|
|
3
|
+
for (let index = 0; index < topic.length; index++) {
|
|
4
|
+
hash ^= topic.charCodeAt(index);
|
|
5
|
+
hash = (hash * 0x01000193) >>> 0;
|
|
6
|
+
}
|
|
7
|
+
return hash >>> 0;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export type TopicRootResolver = (
|
|
11
|
+
topic: string,
|
|
12
|
+
) => string | undefined | Promise<string | undefined>;
|
|
13
|
+
|
|
14
|
+
export type TopicRootTracker = {
|
|
15
|
+
resolveRoot(topic: string): string | undefined | Promise<string | undefined>;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export type TopicRootDirectoryOptions = {
|
|
19
|
+
defaultCandidates?: string[];
|
|
20
|
+
resolver?: TopicRootResolver;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export class TopicRootDirectory {
|
|
24
|
+
private readonly explicitRootsByTopic = new Map<string, string>();
|
|
25
|
+
private defaultCandidates: string[] = [];
|
|
26
|
+
private resolver?: TopicRootResolver;
|
|
27
|
+
|
|
28
|
+
constructor(options?: TopicRootDirectoryOptions) {
|
|
29
|
+
if (options?.defaultCandidates) {
|
|
30
|
+
this.setDefaultCandidates(options.defaultCandidates);
|
|
31
|
+
}
|
|
32
|
+
this.resolver = options?.resolver;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
public setRoot(topic: string, root: string) {
|
|
36
|
+
this.explicitRootsByTopic.set(topic, root);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
public deleteRoot(topic: string) {
|
|
40
|
+
this.explicitRootsByTopic.delete(topic);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
public getRoot(topic: string) {
|
|
44
|
+
return this.explicitRootsByTopic.get(topic);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
public setDefaultCandidates(candidates: string[]) {
|
|
48
|
+
const unique = new Set<string>();
|
|
49
|
+
for (const candidate of candidates) {
|
|
50
|
+
if (!candidate) continue;
|
|
51
|
+
unique.add(candidate);
|
|
52
|
+
}
|
|
53
|
+
this.defaultCandidates = [...unique].sort((a, b) =>
|
|
54
|
+
a < b ? -1 : a > b ? 1 : 0,
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
public getDefaultCandidates() {
|
|
59
|
+
return [...this.defaultCandidates];
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
public setResolver(resolver?: TopicRootResolver) {
|
|
63
|
+
this.resolver = resolver;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
public async resolveRoot(topic: string): Promise<string | undefined> {
|
|
67
|
+
const local = await this.resolveLocal(topic);
|
|
68
|
+
if (local) return local;
|
|
69
|
+
|
|
70
|
+
return this.resolveDeterministicCandidate(topic);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
public async resolveLocal(topic: string): Promise<string | undefined> {
|
|
74
|
+
const explicit = this.getRoot(topic);
|
|
75
|
+
if (explicit) return explicit;
|
|
76
|
+
|
|
77
|
+
return this.resolver?.(topic);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
public resolveDeterministicCandidate(topic: string): string | undefined {
|
|
81
|
+
if (this.defaultCandidates.length === 0) return undefined;
|
|
82
|
+
const index = topicHash32(topic) % this.defaultCandidates.length;
|
|
83
|
+
return this.defaultCandidates[index];
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export type TopicRootControlPlaneOptions = TopicRootDirectoryOptions & {
|
|
88
|
+
directory?: TopicRootDirectory;
|
|
89
|
+
trackers?: TopicRootTracker[];
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
export class TopicRootControlPlane {
|
|
93
|
+
private readonly directory: TopicRootDirectory;
|
|
94
|
+
private trackers: TopicRootTracker[];
|
|
95
|
+
|
|
96
|
+
constructor(options?: TopicRootControlPlaneOptions) {
|
|
97
|
+
this.directory =
|
|
98
|
+
options?.directory ||
|
|
99
|
+
new TopicRootDirectory({
|
|
100
|
+
defaultCandidates: options?.defaultCandidates,
|
|
101
|
+
resolver: options?.resolver,
|
|
102
|
+
});
|
|
103
|
+
this.trackers = options?.trackers ? [...options.trackers] : [];
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
public setTopicRoot(topic: string, root: string) {
|
|
107
|
+
this.directory.setRoot(topic, root);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
public clearTopicRoot(topic: string) {
|
|
111
|
+
this.directory.deleteRoot(topic);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
public getTopicRoot(topic: string) {
|
|
115
|
+
return this.directory.getRoot(topic);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
public setTopicRootCandidates(candidates: string[]) {
|
|
119
|
+
this.directory.setDefaultCandidates(candidates);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
public getTopicRootCandidates() {
|
|
123
|
+
return this.directory.getDefaultCandidates();
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
public setTopicRootResolver(resolver?: TopicRootResolver) {
|
|
127
|
+
this.directory.setResolver(resolver);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
public setTopicRootTrackers(trackers: TopicRootTracker[]) {
|
|
131
|
+
this.trackers = [...trackers];
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
public getTopicRootTrackers() {
|
|
135
|
+
return [...this.trackers];
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
public resolveTopicRoot(topic: string) {
|
|
139
|
+
return this.resolveWithTrackers(topic);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
private async resolveWithTrackers(topic: string): Promise<string | undefined> {
|
|
143
|
+
const local = await this.directory.resolveLocal(topic);
|
|
144
|
+
if (local) {
|
|
145
|
+
return local;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
for (const tracker of this.trackers) {
|
|
149
|
+
try {
|
|
150
|
+
const resolved = await tracker.resolveRoot(topic);
|
|
151
|
+
if (resolved) {
|
|
152
|
+
return resolved;
|
|
153
|
+
}
|
|
154
|
+
} catch {
|
|
155
|
+
// ignore tracker failures and continue with remaining trackers
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
return this.directory.resolveDeterministicCandidate(topic);
|
|
159
|
+
}
|
|
160
|
+
}
|