@streamr/trackerless-network 0.0.1-tatum.5 → 0.0.1-tatum.7
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/package.json +10 -8
- package/dist/src/NetworkNode.js +1 -1
- package/dist/src/NetworkNode.js.map +1 -1
- package/dist/src/NetworkStack.d.ts +1 -3
- package/dist/src/NetworkStack.js +18 -47
- package/dist/src/NetworkStack.js.map +1 -1
- package/dist/src/identifiers.js +2 -2
- package/dist/src/identifiers.js.map +1 -1
- package/dist/src/logic/{StreamNodeServer.d.ts → DeliveryRpcLocal.d.ts} +6 -5
- package/dist/src/logic/{StreamNodeServer.js → DeliveryRpcLocal.js} +5 -5
- package/dist/src/logic/{StreamNodeServer.js.map → DeliveryRpcLocal.js.map} +1 -1
- package/dist/src/logic/{RemoteRandomGraphNode.d.ts → DeliveryRpcRemote.d.ts} +2 -2
- package/dist/src/logic/{RemoteRandomGraphNode.js → DeliveryRpcRemote.js} +5 -5
- package/dist/src/logic/DeliveryRpcRemote.js.map +1 -0
- package/dist/src/logic/EntryPointDiscovery.d.ts +35 -0
- package/dist/src/logic/EntryPointDiscovery.js +145 -0
- package/dist/src/logic/EntryPointDiscovery.js.map +1 -0
- package/dist/src/logic/ILayer0.d.ts +3 -6
- package/dist/src/logic/ILayer1.d.ts +2 -2
- package/dist/src/logic/NodeList.d.ts +10 -10
- package/dist/src/logic/NodeList.js +2 -2
- package/dist/src/logic/NodeList.js.map +1 -1
- package/dist/src/logic/RandomGraphNode.d.ts +8 -12
- package/dist/src/logic/RandomGraphNode.js +47 -46
- package/dist/src/logic/RandomGraphNode.js.map +1 -1
- package/dist/src/logic/StreamrNode.d.ts +9 -11
- package/dist/src/logic/StreamrNode.js +72 -75
- package/dist/src/logic/StreamrNode.js.map +1 -1
- package/dist/src/logic/createRandomGraphNode.d.ts +6 -1
- package/dist/src/logic/createRandomGraphNode.js +17 -23
- package/dist/src/logic/createRandomGraphNode.js.map +1 -1
- package/dist/src/logic/formStreamPartDeliveryServiceId.d.ts +2 -0
- package/dist/src/logic/formStreamPartDeliveryServiceId.js +8 -0
- package/dist/src/logic/formStreamPartDeliveryServiceId.js.map +1 -0
- package/dist/src/logic/inspect/Inspector.d.ts +3 -2
- package/dist/src/logic/inspect/Inspector.js +5 -5
- package/dist/src/logic/inspect/Inspector.js.map +1 -1
- package/dist/src/logic/neighbor-discovery/{HandshakerServer.d.ts → HandshakeRpcLocal.d.ts} +10 -10
- package/dist/src/logic/neighbor-discovery/{HandshakerServer.js → HandshakeRpcLocal.js} +13 -13
- package/dist/src/logic/neighbor-discovery/HandshakeRpcLocal.js.map +1 -0
- package/dist/src/logic/neighbor-discovery/{RemoteHandshaker.d.ts → HandshakeRpcRemote.d.ts} +1 -1
- package/dist/src/logic/neighbor-discovery/{RemoteHandshaker.js → HandshakeRpcRemote.js} +8 -7
- package/dist/src/logic/neighbor-discovery/HandshakeRpcRemote.js.map +1 -0
- package/dist/src/logic/neighbor-discovery/Handshaker.d.ts +8 -7
- package/dist/src/logic/neighbor-discovery/Handshaker.js +23 -24
- package/dist/src/logic/neighbor-discovery/Handshaker.js.map +1 -1
- package/dist/src/logic/neighbor-discovery/NeighborFinder.d.ts +1 -1
- package/dist/src/logic/neighbor-discovery/NeighborFinder.js +5 -5
- package/dist/src/logic/neighbor-discovery/NeighborFinder.js.map +1 -1
- package/dist/src/logic/neighbor-discovery/NeighborUpdateManager.d.ts +3 -2
- package/dist/src/logic/neighbor-discovery/NeighborUpdateManager.js +7 -7
- package/dist/src/logic/neighbor-discovery/NeighborUpdateManager.js.map +1 -1
- package/dist/src/logic/neighbor-discovery/{NeighborUpdateManagerServer.d.ts → NeighborUpdateRpcLocal.d.ts} +6 -6
- package/dist/src/logic/neighbor-discovery/{NeighborUpdateManagerServer.js → NeighborUpdateRpcLocal.js} +11 -11
- package/dist/src/logic/neighbor-discovery/NeighborUpdateRpcLocal.js.map +1 -0
- package/dist/src/logic/neighbor-discovery/{RemoteNeighborUpdateManager.d.ts → NeighborUpdateRpcRemote.d.ts} +1 -1
- package/dist/src/logic/neighbor-discovery/{RemoteNeighborUpdateManager.js → NeighborUpdateRpcRemote.js} +5 -5
- package/dist/src/logic/neighbor-discovery/NeighborUpdateRpcRemote.js.map +1 -0
- package/dist/src/logic/propagation/Propagation.js +2 -2
- package/dist/src/logic/propagation/Propagation.js.map +1 -1
- package/dist/src/logic/proxy/{ProxyStreamConnectionClient.d.ts → ProxyClient.d.ts} +8 -12
- package/dist/src/logic/proxy/{ProxyStreamConnectionClient.js → ProxyClient.js} +28 -29
- package/dist/src/logic/proxy/ProxyClient.js.map +1 -0
- package/dist/src/logic/proxy/{ProxyStreamConnectionServer.d.ts → ProxyConnectionRpcLocal.d.ts} +5 -7
- package/dist/src/logic/proxy/{ProxyStreamConnectionServer.js → ProxyConnectionRpcLocal.js} +6 -12
- package/dist/src/logic/proxy/ProxyConnectionRpcLocal.js.map +1 -0
- package/dist/src/logic/proxy/{RemoteProxyServer.d.ts → ProxyConnectionRpcRemote.d.ts} +1 -1
- package/dist/src/logic/proxy/{RemoteProxyServer.js → ProxyConnectionRpcRemote.js} +4 -4
- package/dist/src/logic/proxy/ProxyConnectionRpcRemote.js.map +1 -0
- package/dist/src/logic/temporary-connection/{TemporaryConnectionRpcServer.d.ts → TemporaryConnectionRpcLocal.d.ts} +5 -4
- package/dist/src/logic/temporary-connection/{TemporaryConnectionRpcServer.js → TemporaryConnectionRpcLocal.js} +6 -6
- package/dist/src/logic/temporary-connection/TemporaryConnectionRpcLocal.js.map +1 -0
- package/dist/src/logic/temporary-connection/{RemoteTemporaryConnectionRpcServer.d.ts → TemporaryConnectionRpcRemote.d.ts} +1 -1
- package/dist/src/logic/temporary-connection/{RemoteTemporaryConnectionRpcServer.js → TemporaryConnectionRpcRemote.js} +4 -4
- package/dist/src/logic/temporary-connection/TemporaryConnectionRpcRemote.js.map +1 -0
- package/dist/src/proto/packages/dht/protos/DhtRpc.d.ts +0 -4
- package/dist/src/proto/packages/dht/protos/DhtRpc.js +1 -2
- package/dist/src/proto/packages/dht/protos/DhtRpc.js.map +1 -1
- package/dist/src/proto/packages/trackerless-network/protos/NetworkRpc.client.d.ts +4 -4
- package/dist/src/proto/packages/trackerless-network/protos/NetworkRpc.client.js +7 -7
- package/dist/src/proto/packages/trackerless-network/protos/NetworkRpc.client.js.map +1 -1
- package/dist/src/proto/packages/trackerless-network/protos/NetworkRpc.d.ts +10 -10
- package/dist/src/proto/packages/trackerless-network/protos/NetworkRpc.js +7 -7
- package/dist/src/proto/packages/trackerless-network/protos/NetworkRpc.js.map +1 -1
- package/dist/src/proto/packages/trackerless-network/protos/NetworkRpc.server.d.ts +2 -2
- package/dist/test/benchmark/first-message.js +10 -13
- package/dist/test/benchmark/first-message.js.map +1 -1
- package/dist/test/utils/utils.d.ts +5 -5
- package/dist/test/utils/utils.js +14 -14
- package/dist/test/utils/utils.js.map +1 -1
- package/package.json +10 -8
- package/protos/NetworkRpc.proto +5 -5
- package/src/NetworkNode.ts +1 -1
- package/src/NetworkStack.ts +20 -62
- package/src/identifiers.ts +3 -3
- package/src/logic/{StreamNodeServer.ts → DeliveryRpcLocal.ts} +8 -7
- package/src/logic/{RemoteRandomGraphNode.ts → DeliveryRpcRemote.ts} +3 -3
- package/src/logic/EntryPointDiscovery.ts +181 -0
- package/src/logic/ILayer0.ts +3 -6
- package/src/logic/ILayer1.ts +2 -5
- package/src/logic/NodeList.ts +12 -12
- package/src/logic/RandomGraphNode.ts +67 -69
- package/src/logic/StreamrNode.ts +78 -90
- package/src/logic/createRandomGraphNode.ts +28 -26
- package/src/logic/formStreamPartDeliveryServiceId.ts +5 -0
- package/src/logic/inspect/Inspector.ts +8 -7
- package/src/logic/neighbor-discovery/{HandshakerServer.ts → HandshakeRpcLocal.ts} +20 -20
- package/src/logic/neighbor-discovery/{RemoteHandshaker.ts → HandshakeRpcRemote.ts} +6 -5
- package/src/logic/neighbor-discovery/Handshaker.ts +38 -38
- package/src/logic/neighbor-discovery/NeighborFinder.ts +6 -6
- package/src/logic/neighbor-discovery/NeighborUpdateManager.ts +15 -12
- package/src/logic/neighbor-discovery/{NeighborUpdateManagerServer.ts → NeighborUpdateRpcLocal.ts} +17 -17
- package/src/logic/neighbor-discovery/{RemoteNeighborUpdateManager.ts → NeighborUpdateRpcRemote.ts} +2 -2
- package/src/logic/propagation/Propagation.ts +2 -2
- package/src/logic/proxy/{ProxyStreamConnectionClient.ts → ProxyClient.ts} +33 -37
- package/src/logic/proxy/{ProxyStreamConnectionServer.ts → ProxyConnectionRpcLocal.ts} +10 -19
- package/src/logic/proxy/{RemoteProxyServer.ts → ProxyConnectionRpcRemote.ts} +1 -1
- package/src/logic/temporary-connection/{TemporaryConnectionRpcServer.ts → TemporaryConnectionRpcLocal.ts} +11 -10
- package/src/logic/temporary-connection/{RemoteTemporaryConnectionRpcServer.ts → TemporaryConnectionRpcRemote.ts} +1 -1
- package/src/proto/packages/dht/protos/DhtRpc.ts +1 -6
- package/src/proto/packages/trackerless-network/protos/NetworkRpc.client.ts +8 -8
- package/src/proto/packages/trackerless-network/protos/NetworkRpc.server.ts +2 -2
- package/src/proto/packages/trackerless-network/protos/NetworkRpc.ts +14 -14
- package/test/benchmark/first-message.ts +10 -13
- package/test/end-to-end/inspect.test.ts +12 -12
- package/test/end-to-end/proxy-and-full-node.test.ts +13 -14
- package/test/end-to-end/proxy-connections.test.ts +10 -12
- package/test/end-to-end/proxy-key-exchange.test.ts +12 -13
- package/test/end-to-end/random-graph-with-real-connections.test.ts +7 -7
- package/test/end-to-end/webrtc-full-node-network.test.ts +8 -8
- package/test/end-to-end/websocket-full-node-network.test.ts +8 -10
- package/test/integration/{RemoteRandomGraphNode.test.ts → DeliveryRpcRemote.test.ts} +17 -14
- package/test/integration/{RemoteHandshaker.test.ts → HandshakeRpcRemote.test.ts} +10 -9
- package/test/integration/Handshakes.test.ts +23 -20
- package/test/integration/Inspect.test.ts +3 -2
- package/test/integration/{RemoteNeighborUpdateManager.test.ts → NeighborUpdateRpcRemote.test.ts} +12 -10
- package/test/integration/NetworkNode.test.ts +9 -8
- package/test/integration/NetworkRpc.test.ts +5 -7
- package/test/integration/NetworkStack.test.ts +13 -15
- package/test/integration/Propagation.test.ts +2 -2
- package/test/integration/RandomGraphNode-Layer1Node-Latencies.test.ts +10 -8
- package/test/integration/RandomGraphNode-Layer1Node.test.ts +17 -17
- package/test/integration/StreamrNode.test.ts +5 -3
- package/test/integration/joining-streams-on-offline-peers.test.ts +16 -18
- package/test/integration/stream-without-default-entrypoints.test.ts +11 -13
- package/test/unit/{StreamNodeServer.test.ts → DeliveryRpcLocal.test.ts} +8 -8
- package/test/unit/EntrypointDiscovery.test.ts +132 -0
- package/test/unit/{HandshakerServer.test.ts → HandshakeRpcLocal.test.ts} +26 -24
- package/test/unit/Handshaker.test.ts +10 -8
- package/test/unit/Inspector.test.ts +4 -3
- package/test/unit/NeighborFinder.test.ts +5 -5
- package/test/unit/NodeList.test.ts +22 -13
- package/test/unit/{RemoteProxyServer.test.ts → ProxyConnectionRpcRemote.test.ts} +4 -4
- package/test/unit/RandomGraphNode.test.ts +12 -11
- package/test/unit/StreamMessageTranslator.test.ts +10 -9
- package/test/unit/StreamrNode.test.ts +8 -8
- package/test/utils/mock/MockLayer0.ts +7 -26
- package/test/utils/mock/MockLayer1.ts +6 -13
- package/test/utils/mock/MockNeighborFinder.ts +1 -2
- package/test/utils/mock/MockNeighborUpdateManager.ts +1 -2
- package/test/utils/mock/Transport.ts +2 -2
- package/test/utils/utils.ts +13 -13
- package/dist/src/logic/RemoteRandomGraphNode.js.map +0 -1
- package/dist/src/logic/StreamPartEntryPointDiscovery.d.ts +0 -39
- package/dist/src/logic/StreamPartEntryPointDiscovery.js +0 -194
- package/dist/src/logic/StreamPartEntryPointDiscovery.js.map +0 -1
- package/dist/src/logic/neighbor-discovery/HandshakerServer.js.map +0 -1
- package/dist/src/logic/neighbor-discovery/NeighborUpdateManagerServer.js.map +0 -1
- package/dist/src/logic/neighbor-discovery/RemoteHandshaker.js.map +0 -1
- package/dist/src/logic/neighbor-discovery/RemoteNeighborUpdateManager.js.map +0 -1
- package/dist/src/logic/proxy/ProxyStreamConnectionClient.js.map +0 -1
- package/dist/src/logic/proxy/ProxyStreamConnectionServer.js.map +0 -1
- package/dist/src/logic/proxy/RemoteProxyServer.js.map +0 -1
- package/dist/src/logic/temporary-connection/RemoteTemporaryConnectionRpcServer.js.map +0 -1
- package/dist/src/logic/temporary-connection/TemporaryConnectionRpcServer.js.map +0 -1
- package/src/logic/StreamPartEntryPointDiscovery.ts +0 -240
- package/test/unit/StreamPartEntrypointDiscovery.test.ts +0 -164
|
@@ -1,240 +0,0 @@
|
|
|
1
|
-
import { createHash } from 'crypto'
|
|
2
|
-
import {
|
|
3
|
-
isSamePeerDescriptor,
|
|
4
|
-
PeerDescriptor,
|
|
5
|
-
RecursiveFindResult,
|
|
6
|
-
DataEntry
|
|
7
|
-
} from '@streamr/dht'
|
|
8
|
-
import { Any } from '../proto/google/protobuf/any'
|
|
9
|
-
import { Logger, setAbortableTimeout, wait } from '@streamr/utils'
|
|
10
|
-
import { StreamPartDelivery } from './StreamrNode'
|
|
11
|
-
import { StreamPartID } from '@streamr/protocol'
|
|
12
|
-
import { NodeID, getNodeIdFromPeerDescriptor } from '../identifiers'
|
|
13
|
-
import { ILayer1 } from './ILayer1'
|
|
14
|
-
|
|
15
|
-
export const streamPartIdToDataKey = (streamPartId: StreamPartID): Uint8Array => {
|
|
16
|
-
return new Uint8Array(createHash('md5').update(streamPartId).digest())
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const parseEntryPointData = (dataEntries: DataEntry[]): PeerDescriptor[] => {
|
|
20
|
-
return dataEntries.filter((entry) => !entry.deleted).map((entry) => Any.unpack(entry.data!, PeerDescriptor))
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
interface FindEntryPointsResult {
|
|
24
|
-
entryPointsFromDht: boolean
|
|
25
|
-
discoveredEntryPoints: PeerDescriptor[]
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
const exponentialRunOff = async (
|
|
29
|
-
task: () => Promise<void>,
|
|
30
|
-
description: string,
|
|
31
|
-
abortSignal: AbortSignal,
|
|
32
|
-
baseDelay = 500,
|
|
33
|
-
maxAttempts = 6
|
|
34
|
-
): Promise<void> => {
|
|
35
|
-
for (let i = 1; i <= maxAttempts; i++) {
|
|
36
|
-
if (abortSignal.aborted) {
|
|
37
|
-
return
|
|
38
|
-
}
|
|
39
|
-
const factor = 2 ** i
|
|
40
|
-
const delay = baseDelay * factor
|
|
41
|
-
try {
|
|
42
|
-
await task()
|
|
43
|
-
} catch (e: any) {
|
|
44
|
-
logger.trace(`${description} failed, retrying in ${delay} ms`)
|
|
45
|
-
}
|
|
46
|
-
try { // Abort controller throws unexpected errors in destroy?
|
|
47
|
-
await wait(delay, abortSignal)
|
|
48
|
-
} catch (err) {
|
|
49
|
-
logger.trace(`${err}`)
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
const logger = new Logger(module)
|
|
55
|
-
|
|
56
|
-
const ENTRYPOINT_STORE_LIMIT = 8
|
|
57
|
-
export const NETWORK_SPLIT_AVOIDANCE_LIMIT = 4
|
|
58
|
-
|
|
59
|
-
interface StreamPartEntryPointDiscoveryConfig {
|
|
60
|
-
streamParts: Map<string, StreamPartDelivery>
|
|
61
|
-
ownPeerDescriptor: PeerDescriptor
|
|
62
|
-
getEntryPointData: (key: Uint8Array) => Promise<RecursiveFindResult>
|
|
63
|
-
getEntryPointDataViaNode: (key: Uint8Array, node: PeerDescriptor) => Promise<DataEntry[]>
|
|
64
|
-
storeEntryPointData: (key: Uint8Array, data: Any) => Promise<PeerDescriptor[]>
|
|
65
|
-
deleteEntryPointData: (key: Uint8Array) => Promise<void>
|
|
66
|
-
cacheInterval?: number
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
export class StreamPartEntryPointDiscovery {
|
|
70
|
-
private readonly abortController: AbortController
|
|
71
|
-
private readonly config: StreamPartEntryPointDiscoveryConfig
|
|
72
|
-
private readonly servicedStreamParts: Map<StreamPartID, NodeJS.Timeout>
|
|
73
|
-
private readonly cacheInterval: number
|
|
74
|
-
private readonly networkSplitAvoidedNodes: Map<StreamPartID, Set<NodeID>> = new Map()
|
|
75
|
-
|
|
76
|
-
constructor(config: StreamPartEntryPointDiscoveryConfig) {
|
|
77
|
-
this.config = config
|
|
78
|
-
this.abortController = new AbortController()
|
|
79
|
-
this.cacheInterval = this.config.cacheInterval ?? 60000
|
|
80
|
-
this.servicedStreamParts = new Map()
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
async discoverEntryPointsFromDht(
|
|
84
|
-
streamPartId: StreamPartID,
|
|
85
|
-
knownEntryPointCount: number,
|
|
86
|
-
forwardingNode?: PeerDescriptor
|
|
87
|
-
): Promise<FindEntryPointsResult> {
|
|
88
|
-
if (knownEntryPointCount > 0) {
|
|
89
|
-
return {
|
|
90
|
-
entryPointsFromDht: false,
|
|
91
|
-
discoveredEntryPoints: []
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
const discoveredEntryPoints = await this.discoverEntryPoints(streamPartId, forwardingNode)
|
|
95
|
-
if (discoveredEntryPoints.length === 0) {
|
|
96
|
-
discoveredEntryPoints.push(this.config.ownPeerDescriptor)
|
|
97
|
-
}
|
|
98
|
-
return {
|
|
99
|
-
discoveredEntryPoints,
|
|
100
|
-
entryPointsFromDht: true
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
private async discoverEntryPoints(streamPartId: StreamPartID, forwardingNode?: PeerDescriptor): Promise<PeerDescriptor[]> {
|
|
105
|
-
const dataKey = streamPartIdToDataKey(streamPartId)
|
|
106
|
-
let discoveredEntryPoints = forwardingNode ?
|
|
107
|
-
await this.queryEntryPointsViaNode(dataKey, forwardingNode) : await this.queryEntrypoints(dataKey)
|
|
108
|
-
|
|
109
|
-
if (this.networkSplitAvoidedNodes.has(streamPartId)) {
|
|
110
|
-
const filtered = discoveredEntryPoints.filter((node) =>
|
|
111
|
-
!this.networkSplitAvoidedNodes.get(streamPartId)!.has(getNodeIdFromPeerDescriptor(node)))
|
|
112
|
-
// If all discovered entry points have previously beed detected as offline, try again
|
|
113
|
-
if (filtered.length > 0) {
|
|
114
|
-
discoveredEntryPoints = filtered
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
return discoveredEntryPoints
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
private async queryEntrypoints(key: Uint8Array): Promise<PeerDescriptor[]> {
|
|
121
|
-
logger.trace(`Finding data from dht node ${this.config.ownPeerDescriptor.nodeName}`)
|
|
122
|
-
try {
|
|
123
|
-
const results = await this.config.getEntryPointData(key)
|
|
124
|
-
if (results.dataEntries) {
|
|
125
|
-
return parseEntryPointData(results.dataEntries)
|
|
126
|
-
} else {
|
|
127
|
-
return []
|
|
128
|
-
}
|
|
129
|
-
} catch (err) {
|
|
130
|
-
return []
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
private async queryEntryPointsViaNode(key: Uint8Array, node: PeerDescriptor): Promise<PeerDescriptor[]> {
|
|
135
|
-
logger.trace(`Finding data via node ${this.config.ownPeerDescriptor.nodeName}`)
|
|
136
|
-
try {
|
|
137
|
-
const results = await this.config.getEntryPointDataViaNode(key, node)
|
|
138
|
-
if (results) {
|
|
139
|
-
return parseEntryPointData(results)
|
|
140
|
-
} else {
|
|
141
|
-
return []
|
|
142
|
-
}
|
|
143
|
-
} catch (err) {
|
|
144
|
-
return []
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
async storeSelfAsEntryPointIfNecessary(
|
|
149
|
-
streamPartId: StreamPartID,
|
|
150
|
-
entryPointsFromDht: boolean,
|
|
151
|
-
currentEntrypointCount: number
|
|
152
|
-
): Promise<void> {
|
|
153
|
-
if (!this.config.streamParts.has(streamPartId) || !entryPointsFromDht) {
|
|
154
|
-
return
|
|
155
|
-
}
|
|
156
|
-
if ((this.config.streamParts.get(streamPartId)! as { layer1: ILayer1 }).layer1!.getBucketSize() < NETWORK_SPLIT_AVOIDANCE_LIMIT) {
|
|
157
|
-
await this.storeSelfAsEntryPoint(streamPartId)
|
|
158
|
-
setImmediate(() => this.avoidNetworkSplit(streamPartId))
|
|
159
|
-
} else if (currentEntrypointCount < ENTRYPOINT_STORE_LIMIT) {
|
|
160
|
-
await this.storeSelfAsEntryPoint(streamPartId)
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
private async storeSelfAsEntryPoint(streamPartId: StreamPartID): Promise<void> {
|
|
165
|
-
const ownPeerDescriptor = this.config.ownPeerDescriptor
|
|
166
|
-
const dataToStore = Any.pack(ownPeerDescriptor, PeerDescriptor)
|
|
167
|
-
try {
|
|
168
|
-
await this.config.storeEntryPointData(streamPartIdToDataKey(streamPartId), dataToStore)
|
|
169
|
-
this.keepSelfAsEntryPoint(streamPartId)
|
|
170
|
-
} catch (err) {
|
|
171
|
-
logger.warn(`Failed to store self as entrypoint for ${streamPartId}`)
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
private keepSelfAsEntryPoint(streamPartId: StreamPartID): void {
|
|
176
|
-
if (!this.config.streamParts.has(streamPartId) || this.servicedStreamParts.has(streamPartId)) {
|
|
177
|
-
return
|
|
178
|
-
}
|
|
179
|
-
this.servicedStreamParts.set(streamPartId, setTimeout(async () => {
|
|
180
|
-
if (!this.config.streamParts.has(streamPartId)) {
|
|
181
|
-
this.servicedStreamParts.delete(streamPartId)
|
|
182
|
-
return
|
|
183
|
-
}
|
|
184
|
-
logger.trace(`Attempting to keep self as entrypoint for ${streamPartId}`)
|
|
185
|
-
try {
|
|
186
|
-
const discovered = await this.discoverEntryPoints(streamPartId)
|
|
187
|
-
if (discovered.length < ENTRYPOINT_STORE_LIMIT
|
|
188
|
-
|| discovered.some((peerDescriptor) => isSamePeerDescriptor(peerDescriptor, this.config.ownPeerDescriptor))) {
|
|
189
|
-
await this.storeSelfAsEntryPoint(streamPartId)
|
|
190
|
-
this.servicedStreamParts.delete(streamPartId)
|
|
191
|
-
this.keepSelfAsEntryPoint(streamPartId)
|
|
192
|
-
} else {
|
|
193
|
-
this.servicedStreamParts.delete(streamPartId)
|
|
194
|
-
}
|
|
195
|
-
} catch (err) {
|
|
196
|
-
logger.debug(`Failed to keep self as entrypoint for ${streamPartId}`)
|
|
197
|
-
}
|
|
198
|
-
}, this.cacheInterval))
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
private async avoidNetworkSplit(streamPartId: StreamPartID): Promise<void> {
|
|
202
|
-
await exponentialRunOff(async () => {
|
|
203
|
-
if (this.config.streamParts.has(streamPartId)) {
|
|
204
|
-
const stream = this.config.streamParts.get(streamPartId)! as { layer1: ILayer1 }
|
|
205
|
-
const rediscoveredEntrypoints = await this.discoverEntryPoints(streamPartId)
|
|
206
|
-
await stream.layer1!.joinDht(rediscoveredEntrypoints, false, false)
|
|
207
|
-
if (stream.layer1!.getBucketSize() < NETWORK_SPLIT_AVOIDANCE_LIMIT) {
|
|
208
|
-
// Filter out nodes that are not in the k-bucket, assumed to be offline
|
|
209
|
-
const nodesToAvoid = rediscoveredEntrypoints.filter((peer) => !stream.layer1!.getKBucketPeers().includes(peer))
|
|
210
|
-
this.addAvoidedNodes(streamPartId, nodesToAvoid)
|
|
211
|
-
throw new Error(`Network split is still possible`)
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
}, 'avoid network split', this.abortController.signal)
|
|
215
|
-
this.networkSplitAvoidedNodes.delete(streamPartId)
|
|
216
|
-
logger.trace(`Network split avoided`)
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
private addAvoidedNodes(streamPartId: StreamPartID, nodesToAvoid: PeerDescriptor[]): void {
|
|
220
|
-
if (!this.networkSplitAvoidedNodes.has(streamPartId)) {
|
|
221
|
-
this.networkSplitAvoidedNodes.set(streamPartId, new Set())
|
|
222
|
-
}
|
|
223
|
-
nodesToAvoid.forEach((node) => this.networkSplitAvoidedNodes.get(streamPartId)!.add(getNodeIdFromPeerDescriptor(node)))
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
removeSelfAsEntryPoint(streamPartId: StreamPartID): void {
|
|
227
|
-
if (this.servicedStreamParts.has(streamPartId)) {
|
|
228
|
-
setAbortableTimeout(() => this.config.deleteEntryPointData(streamPartIdToDataKey(streamPartId)), 0, this.abortController.signal)
|
|
229
|
-
clearTimeout(this.servicedStreamParts.get(streamPartId))
|
|
230
|
-
this.servicedStreamParts.delete(streamPartId)
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
async destroy(): Promise<void> {
|
|
235
|
-
this.servicedStreamParts.forEach((_, streamPartId) => this.removeSelfAsEntryPoint(streamPartId))
|
|
236
|
-
this.servicedStreamParts.clear()
|
|
237
|
-
this.abortController.abort()
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
}
|
|
@@ -1,164 +0,0 @@
|
|
|
1
|
-
import { PeerDescriptor, RecursiveFindResult, isSamePeerDescriptor } from '@streamr/dht'
|
|
2
|
-
import { StreamPartIDUtils } from '@streamr/protocol'
|
|
3
|
-
import { wait } from '@streamr/utils'
|
|
4
|
-
import { range } from 'lodash'
|
|
5
|
-
import { getNodeIdFromPeerDescriptor } from '../../src/identifiers'
|
|
6
|
-
import { StreamPartEntryPointDiscovery } from '../../src/logic/StreamPartEntryPointDiscovery'
|
|
7
|
-
import { StreamPartDelivery } from '../../src/logic/StreamrNode'
|
|
8
|
-
import { Any } from '../../src/proto/google/protobuf/any'
|
|
9
|
-
import { DataEntry } from '../../src/proto/packages/dht/protos/DhtRpc'
|
|
10
|
-
import { MockLayer1 } from '../utils/mock/MockLayer1'
|
|
11
|
-
import { createMockPeerDescriptor } from '../utils/utils'
|
|
12
|
-
|
|
13
|
-
describe('StreamPartEntryPointDiscovery', () => {
|
|
14
|
-
|
|
15
|
-
let entryPointDiscoveryWithData: StreamPartEntryPointDiscovery
|
|
16
|
-
let entryPointDiscoveryWithoutData: StreamPartEntryPointDiscovery
|
|
17
|
-
let storeCalled: number
|
|
18
|
-
let streamParts = new Map<string, StreamPartDelivery>()
|
|
19
|
-
|
|
20
|
-
const peerDescriptor = createMockPeerDescriptor({
|
|
21
|
-
nodeName: 'fake'
|
|
22
|
-
})
|
|
23
|
-
const deletedPeerDescriptor = createMockPeerDescriptor({
|
|
24
|
-
nodeName: 'deleted'
|
|
25
|
-
})
|
|
26
|
-
|
|
27
|
-
const fakeData: DataEntry = {
|
|
28
|
-
data: Any.pack(peerDescriptor, PeerDescriptor),
|
|
29
|
-
ttl: 1000,
|
|
30
|
-
storer: peerDescriptor,
|
|
31
|
-
kademliaId: Uint8Array.from([1, 2, 3]),
|
|
32
|
-
stale: false,
|
|
33
|
-
deleted: false
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
const fakeDeletedData: DataEntry = {
|
|
37
|
-
data: Any.pack(deletedPeerDescriptor, PeerDescriptor),
|
|
38
|
-
ttl: 1000,
|
|
39
|
-
storer: deletedPeerDescriptor,
|
|
40
|
-
kademliaId: Uint8Array.from([1, 2, 3]),
|
|
41
|
-
stale: false,
|
|
42
|
-
deleted: true
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
const streamPartId = StreamPartIDUtils.parse('stream#0')
|
|
46
|
-
|
|
47
|
-
const fakeGetEntryPointData = async (_key: Uint8Array): Promise<RecursiveFindResult> => {
|
|
48
|
-
return {
|
|
49
|
-
closestNodes: [peerDescriptor],
|
|
50
|
-
dataEntries: [fakeData, fakeDeletedData]
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
const fakegetEntryPointDataViaNode = async (_key: Uint8Array, _node: PeerDescriptor): Promise<DataEntry[]> => {
|
|
55
|
-
return [fakeData]
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
const fakeStoreEntryPointData = async (_key: Uint8Array, _data: Any): Promise<PeerDescriptor[]> => {
|
|
59
|
-
storeCalled++
|
|
60
|
-
return [peerDescriptor]
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
const fakeEmptyGetEntryPointData = async (_key: Uint8Array): Promise<RecursiveFindResult> => {
|
|
64
|
-
return {
|
|
65
|
-
closestNodes: [],
|
|
66
|
-
dataEntries: []
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
const fakeDeleteEntryPointData = async (_key: Uint8Array): Promise<void> => {}
|
|
71
|
-
|
|
72
|
-
const addNodesToStream = (layer1: MockLayer1, count: number) => {
|
|
73
|
-
range(count).forEach(() => {
|
|
74
|
-
layer1.addNewRandomPeerToKBucket()
|
|
75
|
-
layer1.addNewRandomPeerToKBucket()
|
|
76
|
-
layer1.addNewRandomPeerToKBucket()
|
|
77
|
-
layer1.addNewRandomPeerToKBucket()
|
|
78
|
-
})
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
let layer1: MockLayer1
|
|
82
|
-
|
|
83
|
-
beforeEach(() => {
|
|
84
|
-
storeCalled = 0
|
|
85
|
-
streamParts = new Map()
|
|
86
|
-
layer1 = new MockLayer1(getNodeIdFromPeerDescriptor(peerDescriptor))
|
|
87
|
-
streamParts.set(streamPartId, { layer1 } as any)
|
|
88
|
-
entryPointDiscoveryWithData = new StreamPartEntryPointDiscovery({
|
|
89
|
-
ownPeerDescriptor: peerDescriptor,
|
|
90
|
-
streamParts: streamParts,
|
|
91
|
-
getEntryPointData: fakeGetEntryPointData,
|
|
92
|
-
getEntryPointDataViaNode: fakegetEntryPointDataViaNode,
|
|
93
|
-
storeEntryPointData: fakeStoreEntryPointData,
|
|
94
|
-
deleteEntryPointData: fakeDeleteEntryPointData,
|
|
95
|
-
cacheInterval: 2000
|
|
96
|
-
})
|
|
97
|
-
entryPointDiscoveryWithoutData = new StreamPartEntryPointDiscovery({
|
|
98
|
-
ownPeerDescriptor: peerDescriptor,
|
|
99
|
-
streamParts: new Map<string, StreamPartDelivery>(),
|
|
100
|
-
getEntryPointData: fakeEmptyGetEntryPointData,
|
|
101
|
-
getEntryPointDataViaNode: fakegetEntryPointDataViaNode,
|
|
102
|
-
storeEntryPointData: fakeStoreEntryPointData,
|
|
103
|
-
deleteEntryPointData: fakeDeleteEntryPointData,
|
|
104
|
-
cacheInterval: 2000
|
|
105
|
-
})
|
|
106
|
-
})
|
|
107
|
-
|
|
108
|
-
afterEach(() => {
|
|
109
|
-
entryPointDiscoveryWithData.destroy()
|
|
110
|
-
})
|
|
111
|
-
|
|
112
|
-
it('discoverEntryPointsFromDht has known entrypoints', async () => {
|
|
113
|
-
const res = await entryPointDiscoveryWithData.discoverEntryPointsFromDht(streamPartId, 1)
|
|
114
|
-
expect(res.entryPointsFromDht).toEqual(false)
|
|
115
|
-
expect(res.discoveredEntryPoints).toEqual([])
|
|
116
|
-
})
|
|
117
|
-
|
|
118
|
-
it('discoverEntryPointsFromDht does not have known entrypoints', async () => {
|
|
119
|
-
const res = await entryPointDiscoveryWithData.discoverEntryPointsFromDht(streamPartId, 0)
|
|
120
|
-
expect(res.discoveredEntryPoints.length).toBe(1)
|
|
121
|
-
expect(isSamePeerDescriptor(res.discoveredEntryPoints[0], peerDescriptor)).toBe(true)
|
|
122
|
-
})
|
|
123
|
-
|
|
124
|
-
it('discoverEntryPointsfromDht on an empty stream', async () => {
|
|
125
|
-
const res = await entryPointDiscoveryWithoutData.discoverEntryPointsFromDht(streamPartId, 0)
|
|
126
|
-
expect(res.entryPointsFromDht).toEqual(true)
|
|
127
|
-
expect(res.discoveredEntryPoints.length).toBe(1)
|
|
128
|
-
expect(isSamePeerDescriptor(res.discoveredEntryPoints[0], peerDescriptor)).toBe(true) // ownPeerDescriptor
|
|
129
|
-
})
|
|
130
|
-
|
|
131
|
-
it('store on empty stream', async () => {
|
|
132
|
-
await entryPointDiscoveryWithData.storeSelfAsEntryPointIfNecessary(streamPartId, true, 0)
|
|
133
|
-
expect(storeCalled).toEqual(1)
|
|
134
|
-
})
|
|
135
|
-
|
|
136
|
-
it('store on non-empty stream without known entry points', async () => {
|
|
137
|
-
addNodesToStream(layer1, 4)
|
|
138
|
-
await entryPointDiscoveryWithData.storeSelfAsEntryPointIfNecessary(streamPartId, false, 0)
|
|
139
|
-
expect(storeCalled).toEqual(0)
|
|
140
|
-
})
|
|
141
|
-
|
|
142
|
-
it('store on stream without saturated entrypoint count', async () => {
|
|
143
|
-
addNodesToStream(layer1, 4)
|
|
144
|
-
await entryPointDiscoveryWithData.storeSelfAsEntryPointIfNecessary(streamPartId, true, 0)
|
|
145
|
-
expect(storeCalled).toEqual(1)
|
|
146
|
-
})
|
|
147
|
-
|
|
148
|
-
it('will keep recaching until stream stopped', async () => {
|
|
149
|
-
await entryPointDiscoveryWithData.storeSelfAsEntryPointIfNecessary(streamPartId, true, 0)
|
|
150
|
-
expect(storeCalled).toEqual(1)
|
|
151
|
-
await wait(4500)
|
|
152
|
-
entryPointDiscoveryWithData.removeSelfAsEntryPoint(streamPartId)
|
|
153
|
-
expect(storeCalled).toEqual(3)
|
|
154
|
-
})
|
|
155
|
-
|
|
156
|
-
it('will stop recaching is stream is left', async () => {
|
|
157
|
-
await entryPointDiscoveryWithData.storeSelfAsEntryPointIfNecessary(streamPartId, true, 0)
|
|
158
|
-
expect(storeCalled).toEqual(1)
|
|
159
|
-
streamParts.delete(streamPartId)
|
|
160
|
-
await wait(4500)
|
|
161
|
-
expect(storeCalled).toEqual(1)
|
|
162
|
-
})
|
|
163
|
-
|
|
164
|
-
})
|