@peerbit/stream 1.0.20 → 2.0.1
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/lib/esm/index.d.ts +82 -71
- package/lib/esm/index.js +643 -602
- package/lib/esm/index.js.map +1 -1
- package/lib/esm/logger.d.ts +1 -1
- package/lib/esm/logger.js +1 -1
- package/lib/esm/logger.js.map +1 -1
- package/lib/esm/metrics.d.ts +6 -25
- package/lib/esm/metrics.js +14 -58
- package/lib/esm/metrics.js.map +1 -1
- package/lib/esm/routes.d.ts +47 -35
- package/lib/esm/routes.js +214 -192
- package/lib/esm/routes.js.map +1 -1
- package/package.json +9 -13
- package/src/index.ts +976 -766
- package/src/logger.ts +1 -1
- package/src/metrics.ts +11 -63
- package/src/routes.ts +279 -228
- package/lib/esm/peer-map.d.ts +0 -1
- package/lib/esm/peer-map.js +0 -2
- package/lib/esm/peer-map.js.map +0 -1
- package/src/peer-map.ts +0 -1
package/src/logger.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { logger as logFn } from "@peerbit/logger";
|
|
2
|
-
export const logger = logFn({ module: "
|
|
2
|
+
export const logger = logFn({ module: "lazystream", level: "warn" });
|
package/src/metrics.ts
CHANGED
|
@@ -1,70 +1,18 @@
|
|
|
1
1
|
import { PublicSignKey } from "@peerbit/crypto";
|
|
2
2
|
|
|
3
|
-
export class
|
|
4
|
-
private
|
|
5
|
-
private lastFrequency: number;
|
|
6
|
-
private events = 0;
|
|
7
|
-
private intervalTime: number;
|
|
8
|
-
constructor(properties: { intervalTime } = { intervalTime: 10 * 1000 }) {
|
|
9
|
-
this.intervalTime = properties.intervalTime;
|
|
10
|
-
this.interval = setInterval(() => {
|
|
11
|
-
this.lastFrequency = this.events / this.intervalTime;
|
|
12
|
-
this.events = 0;
|
|
13
|
-
}, properties.intervalTime);
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
count(event: number) {
|
|
17
|
-
this.events += event;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
close() {
|
|
21
|
-
clearInterval(this.interval);
|
|
22
|
-
this.events = 0;
|
|
23
|
-
}
|
|
3
|
+
export class MovingAverageTracker {
|
|
4
|
+
private lastTS = 0;
|
|
24
5
|
|
|
25
|
-
|
|
26
|
-
return this.lastFrequency;
|
|
27
|
-
}
|
|
28
|
-
}
|
|
6
|
+
value = 0;
|
|
29
7
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
private lastFrequency: Map<string, number>;
|
|
33
|
-
private events: Map<string, number>;
|
|
34
|
-
private intervalTime: number;
|
|
35
|
-
constructor(properties: { intervalTime } = { intervalTime: 10 * 1000 }) {
|
|
36
|
-
this.intervalTime = properties.intervalTime;
|
|
37
|
-
this.events = new Map();
|
|
8
|
+
constructor(readonly tau = 10) {
|
|
9
|
+
this.lastTS = +new Date();
|
|
38
10
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
increment(to: string, bytes: Uint8Array) {
|
|
48
|
-
let value = this.events.get(to);
|
|
49
|
-
if (value == null) {
|
|
50
|
-
value = 1;
|
|
51
|
-
this.events.set(to, bytes.length);
|
|
52
|
-
} else {
|
|
53
|
-
this.events.set(to, value + bytes.length);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
close() {
|
|
58
|
-
clearInterval(this.interval);
|
|
59
|
-
this.events.clear();
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
getFrequency(to: PublicSignKey) {
|
|
63
|
-
const count = this.lastFrequency.get(to.hashcode());
|
|
64
|
-
if (count) {
|
|
65
|
-
return count / this.intervalTime;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
return undefined;
|
|
11
|
+
add(number: number) {
|
|
12
|
+
const now = +new Date();
|
|
13
|
+
const dt = (now - this.lastTS) / 1000;
|
|
14
|
+
const alpha_t = 1 - Math.exp(-dt / this.tau);
|
|
15
|
+
this.value = (1 - alpha_t) * this.value + (alpha_t * number) / dt;
|
|
16
|
+
this.lastTS = now;
|
|
69
17
|
}
|
|
70
18
|
}
|
package/src/routes.ts
CHANGED
|
@@ -1,283 +1,334 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
import { logger } from "./logger.js";
|
|
5
|
-
import { MinimalEdgeMapper } from "graphology-utils/getters";
|
|
6
|
-
|
|
7
|
-
interface EdgeData {
|
|
8
|
-
weight: number;
|
|
9
|
-
time: number;
|
|
10
|
-
}
|
|
1
|
+
import { PublicSignKey } from "@peerbit/crypto";
|
|
2
|
+
|
|
3
|
+
export const MAX_ROUTE_DISTANCE = Number.MAX_SAFE_INTEGER;
|
|
11
4
|
export class Routes {
|
|
12
|
-
|
|
13
|
-
private peerId: string;
|
|
14
|
-
constructor(peerId: string) {
|
|
15
|
-
this.peerId = peerId;
|
|
16
|
-
this.graph = new (Graphs as any).UndirectedGraph();
|
|
17
|
-
}
|
|
5
|
+
// END receiver -> Neighbour
|
|
18
6
|
|
|
19
|
-
|
|
20
|
-
|
|
7
|
+
routes: Map<
|
|
8
|
+
string,
|
|
9
|
+
Map<string, { session: number; list: { hash: string; distance: number }[] }>
|
|
10
|
+
> = new Map();
|
|
11
|
+
|
|
12
|
+
pendingRoutes: Map<
|
|
13
|
+
number,
|
|
14
|
+
Map<
|
|
15
|
+
string,
|
|
16
|
+
{
|
|
17
|
+
from: string;
|
|
18
|
+
neighbour: string;
|
|
19
|
+
distance: number;
|
|
20
|
+
}[]
|
|
21
|
+
>
|
|
22
|
+
> = new Map();
|
|
23
|
+
latestSession: number;
|
|
24
|
+
|
|
25
|
+
constructor(readonly me: string) {
|
|
26
|
+
this.latestSession = 0;
|
|
21
27
|
}
|
|
22
28
|
|
|
23
|
-
|
|
24
|
-
|
|
29
|
+
clear() {
|
|
30
|
+
this.routes.clear();
|
|
31
|
+
this.pendingRoutes.clear();
|
|
25
32
|
}
|
|
26
33
|
|
|
27
|
-
|
|
28
|
-
*
|
|
29
|
-
* @param from
|
|
30
|
-
* @param to
|
|
31
|
-
* @returns new nodes
|
|
32
|
-
*/
|
|
33
|
-
addLink(
|
|
34
|
+
add(
|
|
34
35
|
from: string,
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
if (!
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
if (fromWasReachable) {
|
|
60
|
-
visited.add(from);
|
|
61
|
-
}
|
|
62
|
-
if (toWasReachable) {
|
|
63
|
-
visited.add(to);
|
|
36
|
+
neighbour: string,
|
|
37
|
+
target: string,
|
|
38
|
+
distance: number,
|
|
39
|
+
session: number
|
|
40
|
+
) {
|
|
41
|
+
let fromMap = this.routes.get(from);
|
|
42
|
+
if (!fromMap) {
|
|
43
|
+
fromMap = new Map();
|
|
44
|
+
this.routes.set(from, fromMap);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
let prev = fromMap.get(target) || {
|
|
48
|
+
session: session ?? +new Date(),
|
|
49
|
+
list: [] as { hash: string; distance: number }[]
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
this.latestSession = Math.max(this.latestSession, session);
|
|
53
|
+
|
|
54
|
+
if (session != null) {
|
|
55
|
+
// this condition means that when we add new routes in a session that is newer
|
|
56
|
+
if (prev.session < session) {
|
|
57
|
+
prev = { session, list: [] }; // reset route info how to reach this target
|
|
58
|
+
} else if (prev.session > session) {
|
|
59
|
+
return; // new routing information superseedes this
|
|
64
60
|
}
|
|
61
|
+
}
|
|
65
62
|
|
|
66
|
-
|
|
67
|
-
|
|
63
|
+
if (from === this.me && neighbour === target) {
|
|
64
|
+
// force distance to neighbour as targets to always favor directly sending to them
|
|
65
|
+
// i.e. if target is our neighbour, always assume the shortest path to them is the direct path
|
|
66
|
+
distance = -1;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
for (const route of prev.list) {
|
|
70
|
+
if (route.hash === neighbour) {
|
|
71
|
+
route.distance = Math.min(route.distance, distance);
|
|
72
|
+
prev.list.sort((a, b) => a.distance - b.distance);
|
|
73
|
+
return;
|
|
68
74
|
}
|
|
69
|
-
|
|
70
|
-
|
|
75
|
+
}
|
|
76
|
+
prev.list.push({ distance, hash: neighbour });
|
|
77
|
+
prev.list.sort((a, b) => a.distance - b.distance);
|
|
78
|
+
fromMap.set(target, prev);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
removeTarget(target: string) {
|
|
82
|
+
this.routes.delete(target);
|
|
83
|
+
for (const [fromMapKey, fromMap] of this.routes) {
|
|
84
|
+
// delete target
|
|
85
|
+
fromMap.delete(target);
|
|
86
|
+
if (fromMap.size === 0) {
|
|
87
|
+
this.routes.delete(fromMapKey);
|
|
71
88
|
}
|
|
89
|
+
}
|
|
90
|
+
return [target];
|
|
91
|
+
}
|
|
72
92
|
|
|
73
|
-
|
|
93
|
+
removeNeighbour(target: string) {
|
|
94
|
+
this.routes.delete(target);
|
|
95
|
+
const maybeUnreachable: Set<string> = new Set([target]);
|
|
96
|
+
for (const [fromMapKey, fromMap] of this.routes) {
|
|
97
|
+
// delete target
|
|
98
|
+
fromMap.delete(target);
|
|
74
99
|
|
|
75
|
-
|
|
76
|
-
|
|
100
|
+
// delete this as neighbour
|
|
101
|
+
for (const [remote, neighbours] of fromMap) {
|
|
102
|
+
neighbours.list = neighbours.list.filter((x) => x.hash !== target);
|
|
103
|
+
if (neighbours.list.length === 0) {
|
|
104
|
+
fromMap.delete(remote);
|
|
105
|
+
maybeUnreachable.add(remote);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
77
108
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
if (visited.has(node)) {
|
|
85
|
-
continue;
|
|
86
|
-
}
|
|
109
|
+
if (fromMap.size === 0) {
|
|
110
|
+
this.routes.delete(fromMapKey);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return [...maybeUnreachable].filter((x) => !this.isReachable(this.me, x));
|
|
114
|
+
}
|
|
87
115
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
const edge = this.graph.undirectedEdge(node, neighbor);
|
|
92
|
-
if (!edge) {
|
|
93
|
-
logger.warn(`Missing edge between: ${node} - ${neighbor}`);
|
|
94
|
-
continue;
|
|
95
|
-
}
|
|
116
|
+
findNeighbor(from: string, target: string) {
|
|
117
|
+
return this.routes.get(from)?.get(target);
|
|
118
|
+
}
|
|
96
119
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
120
|
+
isReachable(from: string, target: string) {
|
|
121
|
+
return (
|
|
122
|
+
(this.routes.get(from)?.get(target)?.list[0]?.distance ??
|
|
123
|
+
Number.MAX_SAFE_INTEGER) < MAX_ROUTE_DISTANCE
|
|
124
|
+
);
|
|
125
|
+
}
|
|
101
126
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
127
|
+
hasShortestPath(target: string) {
|
|
128
|
+
const path = this.routes.get(this.me)?.get(target);
|
|
129
|
+
if (!path) {
|
|
130
|
+
return false;
|
|
131
|
+
}
|
|
132
|
+
return path.list[0].distance <= 0;
|
|
133
|
+
}
|
|
105
134
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
135
|
+
hasTarget(target: string) {
|
|
136
|
+
for (const [k, v] of this.routes) {
|
|
137
|
+
if (v.has(target)) {
|
|
138
|
+
return true;
|
|
110
139
|
}
|
|
111
|
-
} else {
|
|
112
|
-
// update weight
|
|
113
|
-
const edge = this.graph.undirectedEdge(from, to);
|
|
114
|
-
this.graph.setEdgeAttribute(edge, "weight", weight);
|
|
115
|
-
this.graph.setEdgeAttribute(edge, "time", +new Date());
|
|
116
140
|
}
|
|
141
|
+
return false;
|
|
142
|
+
}
|
|
117
143
|
|
|
118
|
-
|
|
144
|
+
getDependent(target: string) {
|
|
145
|
+
const dependent: string[] = [];
|
|
146
|
+
for (const [fromMapKey, fromMap] of this.routes) {
|
|
147
|
+
if (fromMapKey !== this.me && fromMap.has(target)) {
|
|
148
|
+
dependent.push(fromMapKey);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return dependent;
|
|
119
152
|
}
|
|
120
153
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
if (link) {
|
|
131
|
-
const date = +new Date();
|
|
132
|
-
const fromWasReachable =
|
|
133
|
-
origin == from ||
|
|
134
|
-
this.getPath(origin, from, { unweighted: true }).length;
|
|
135
|
-
const toWasReachable =
|
|
136
|
-
origin === to || this.getPath(origin, to, { unweighted: true }).length;
|
|
137
|
-
this.graph.dropEdge(link);
|
|
138
|
-
|
|
139
|
-
const unreachableNodesFromOrigin: string[] = [];
|
|
140
|
-
if (
|
|
141
|
-
fromWasReachable &&
|
|
142
|
-
origin !== from &&
|
|
143
|
-
this.getPath(origin, from, { unweighted: true }).length === 0
|
|
144
|
-
) {
|
|
145
|
-
unreachableNodesFromOrigin.push(from);
|
|
154
|
+
count(from = this.me) {
|
|
155
|
+
const set: Set<string> = new Set();
|
|
156
|
+
const map = this.routes.get(from);
|
|
157
|
+
if (map) {
|
|
158
|
+
for (const [k, v] of map) {
|
|
159
|
+
set.add(k);
|
|
160
|
+
for (const peer of v.list) {
|
|
161
|
+
set.add(peer.hash);
|
|
162
|
+
}
|
|
146
163
|
}
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
164
|
+
}
|
|
165
|
+
return set.size;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
countAll() {
|
|
169
|
+
let size = 0;
|
|
170
|
+
for (const [from, map] of this.routes) {
|
|
171
|
+
for (const [k, v] of map) {
|
|
172
|
+
size += v.list.length;
|
|
153
173
|
}
|
|
174
|
+
}
|
|
175
|
+
return size;
|
|
176
|
+
}
|
|
154
177
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
178
|
+
// for all tos if
|
|
179
|
+
getFanout(
|
|
180
|
+
from: PublicSignKey,
|
|
181
|
+
tos: string[],
|
|
182
|
+
redundancy: number
|
|
183
|
+
): Map<string, { to: string; timestamp: number }[]> | undefined {
|
|
184
|
+
if (tos.length === 0) {
|
|
185
|
+
return undefined;
|
|
186
|
+
}
|
|
161
187
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
const node = stack.shift();
|
|
166
|
-
const nodeId = node;
|
|
167
|
-
if (!nodeId || !this.graph.hasNode(nodeId)) {
|
|
168
|
-
continue;
|
|
169
|
-
}
|
|
170
|
-
if (visited.has(nodeId)) {
|
|
171
|
-
continue;
|
|
172
|
-
}
|
|
188
|
+
let fanoutMap:
|
|
189
|
+
| Map<string, { to: string; timestamp: number }[]>
|
|
190
|
+
| undefined = undefined;
|
|
173
191
|
|
|
174
|
-
|
|
192
|
+
const fromKey = from.hashcode();
|
|
175
193
|
|
|
176
|
-
|
|
194
|
+
// Message to > 0
|
|
195
|
+
if (tos.length > 0) {
|
|
196
|
+
for (const to of tos) {
|
|
197
|
+
if (to === this.me || fromKey === to) {
|
|
198
|
+
continue; // don't send to me or backwards
|
|
199
|
+
}
|
|
177
200
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
201
|
+
const neighbour = this.findNeighbor(fromKey, to);
|
|
202
|
+
if (neighbour) {
|
|
203
|
+
let foundClosest = false;
|
|
204
|
+
for (
|
|
205
|
+
let i = 0;
|
|
206
|
+
i < Math.min(neighbour.list.length, redundancy);
|
|
207
|
+
i++
|
|
208
|
+
) {
|
|
209
|
+
const distance = neighbour.list[i].distance;
|
|
210
|
+
if (distance >= redundancy) {
|
|
211
|
+
break; // because neighbour listis sorted
|
|
183
212
|
}
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
continue; // don't follow path because this is a new link that might provide some new connectivity
|
|
213
|
+
if (distance <= 0) {
|
|
214
|
+
foundClosest = true;
|
|
187
215
|
}
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
216
|
+
const fanout: { to: string; timestamp: number }[] = (
|
|
217
|
+
fanoutMap || (fanoutMap = new Map())
|
|
218
|
+
).get(neighbour.list[i].hash);
|
|
219
|
+
if (!fanout) {
|
|
220
|
+
fanoutMap.set(neighbour.list[i].hash, [
|
|
221
|
+
{ to, timestamp: neighbour.session }
|
|
222
|
+
]);
|
|
223
|
+
} else {
|
|
224
|
+
fanout.push({ to, timestamp: neighbour.session });
|
|
191
225
|
}
|
|
192
|
-
|
|
193
|
-
stack.push(neighbor);
|
|
194
226
|
}
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
unreachableNodesFromOrigin.push(nodeId.toString());
|
|
227
|
+
if (!foundClosest && from.hashcode() === this.me) {
|
|
228
|
+
return undefined; // we dont have the shortest path to our target (yet). Send to all
|
|
198
229
|
}
|
|
230
|
+
|
|
231
|
+
continue;
|
|
199
232
|
}
|
|
233
|
+
|
|
234
|
+
// we can't find path, send message to all peers
|
|
235
|
+
return undefined;
|
|
200
236
|
}
|
|
201
|
-
return unreachableNodesFromOrigin;
|
|
202
237
|
}
|
|
203
|
-
return
|
|
238
|
+
return fanoutMap || (fanoutMap = new Map());
|
|
204
239
|
}
|
|
205
240
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
241
|
+
/**
|
|
242
|
+
* Returns a list of a prunable nodes that are not needed to reach all remote nodes
|
|
243
|
+
*/
|
|
244
|
+
getPrunable(neighbours: string[]): string[] {
|
|
245
|
+
const map = this.routes.get(this.me);
|
|
246
|
+
if (map) {
|
|
247
|
+
// check if all targets can be reached without it
|
|
248
|
+
return neighbours.filter((candidate) => {
|
|
249
|
+
for (const [target, neighbours] of map) {
|
|
250
|
+
if (
|
|
251
|
+
target !== candidate &&
|
|
252
|
+
neighbours.list.length === 1 &&
|
|
253
|
+
neighbours.list[0].hash === candidate
|
|
254
|
+
) {
|
|
255
|
+
return false;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
return true;
|
|
259
|
+
});
|
|
209
260
|
}
|
|
261
|
+
return [];
|
|
262
|
+
}
|
|
210
263
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
264
|
+
public addPendingRouteConnection(
|
|
265
|
+
session: number,
|
|
266
|
+
route: {
|
|
267
|
+
from: string;
|
|
268
|
+
neighbour: string;
|
|
269
|
+
target: string;
|
|
270
|
+
distance: number;
|
|
214
271
|
}
|
|
215
|
-
|
|
216
|
-
|
|
272
|
+
) {
|
|
273
|
+
let map = this.pendingRoutes.get(session);
|
|
274
|
+
if (!map) {
|
|
275
|
+
map = new Map();
|
|
276
|
+
this.pendingRoutes.set(session, map);
|
|
277
|
+
}
|
|
278
|
+
let arr = map.get(route.target);
|
|
279
|
+
if (!arr) {
|
|
280
|
+
arr = [];
|
|
281
|
+
map.set(route.target, arr);
|
|
217
282
|
}
|
|
218
|
-
return undefined;
|
|
219
|
-
}
|
|
220
283
|
|
|
221
|
-
|
|
222
|
-
const edgeId = this.getLink(from, to);
|
|
223
|
-
if (edgeId) return this.graph.getEdgeAttributes(edgeId);
|
|
224
|
-
return undefined;
|
|
225
|
-
}
|
|
284
|
+
arr.push(route);
|
|
226
285
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
286
|
+
const neighbour = this.findNeighbor(route.from, route.target);
|
|
287
|
+
if (!neighbour || neighbour.session === session) {
|
|
288
|
+
// Commit directly since we dont have any data at all (better have something than nothing)
|
|
289
|
+
this.commitPendingRouteConnection(session, route.target);
|
|
290
|
+
}
|
|
232
291
|
}
|
|
233
292
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
to: string,
|
|
237
|
-
options?: { unweighted?: boolean } | { block?: string }
|
|
238
|
-
): unweighted.ShortestPath | dijkstra.BidirectionalDijstraResult {
|
|
239
|
-
try {
|
|
240
|
-
let getEdgeWeight:
|
|
241
|
-
| keyof EdgeData
|
|
242
|
-
| MinimalEdgeMapper<number, EdgeData> = (edge) =>
|
|
243
|
-
this.graph.getEdgeAttribute(edge, "weight");
|
|
244
|
-
const blockId = (options as { block?: string })?.block;
|
|
245
|
-
if (blockId) {
|
|
246
|
-
const neighBourEdges = new Set(
|
|
247
|
-
this.graph
|
|
248
|
-
.inboundNeighbors(blockId)
|
|
249
|
-
.map((x) => this.graph.edges(x, blockId))
|
|
250
|
-
.flat()
|
|
251
|
-
);
|
|
252
|
-
getEdgeWeight = (edge) => {
|
|
253
|
-
if (neighBourEdges.has(edge)) {
|
|
254
|
-
return Number.MAX_SAFE_INTEGER;
|
|
255
|
-
}
|
|
256
|
-
return this.graph.getEdgeAttribute(edge, "weight");
|
|
257
|
-
};
|
|
258
|
-
}
|
|
293
|
+
// always commit if we dont know the peer yet
|
|
294
|
+
// do pending commits per remote (?)
|
|
259
295
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
296
|
+
public commitPendingRouteConnection(session: number, target?: string) {
|
|
297
|
+
const map = this.pendingRoutes.get(session);
|
|
298
|
+
if (!map) {
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
if (target) {
|
|
302
|
+
const routes = map.get(target);
|
|
303
|
+
if (routes) {
|
|
304
|
+
for (const route of routes) {
|
|
305
|
+
this.add(
|
|
306
|
+
route.from,
|
|
307
|
+
route.neighbour,
|
|
308
|
+
target,
|
|
309
|
+
route.distance,
|
|
310
|
+
session
|
|
311
|
+
);
|
|
312
|
+
}
|
|
313
|
+
map.delete(target);
|
|
314
|
+
return;
|
|
315
|
+
} else {
|
|
316
|
+
return;
|
|
267
317
|
}
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
318
|
+
} else {
|
|
319
|
+
for (const [target, routes] of map) {
|
|
320
|
+
for (const route of routes) {
|
|
321
|
+
this.add(
|
|
322
|
+
route.from,
|
|
323
|
+
route.neighbour,
|
|
324
|
+
target,
|
|
325
|
+
route.distance,
|
|
326
|
+
session
|
|
327
|
+
);
|
|
272
328
|
}
|
|
273
329
|
}
|
|
274
|
-
|
|
275
|
-
return path as any; // TODO fix types
|
|
276
|
-
} catch (error) {
|
|
277
|
-
return [];
|
|
278
330
|
}
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
this.graph.clear();
|
|
331
|
+
|
|
332
|
+
this.pendingRoutes.delete(session);
|
|
282
333
|
}
|
|
283
334
|
}
|
package/lib/esm/peer-map.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export type PeerMap<T> = Map<string, T>;
|
package/lib/esm/peer-map.js
DELETED
package/lib/esm/peer-map.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"peer-map.js","sourceRoot":"","sources":["../../src/peer-map.ts"],"names":[],"mappings":""}
|
package/src/peer-map.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export type PeerMap<T> = Map<string, T>;
|