@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.
Files changed (177) hide show
  1. package/dist/package.json +10 -8
  2. package/dist/src/NetworkNode.js +1 -1
  3. package/dist/src/NetworkNode.js.map +1 -1
  4. package/dist/src/NetworkStack.d.ts +1 -3
  5. package/dist/src/NetworkStack.js +18 -47
  6. package/dist/src/NetworkStack.js.map +1 -1
  7. package/dist/src/identifiers.js +2 -2
  8. package/dist/src/identifiers.js.map +1 -1
  9. package/dist/src/logic/{StreamNodeServer.d.ts → DeliveryRpcLocal.d.ts} +6 -5
  10. package/dist/src/logic/{StreamNodeServer.js → DeliveryRpcLocal.js} +5 -5
  11. package/dist/src/logic/{StreamNodeServer.js.map → DeliveryRpcLocal.js.map} +1 -1
  12. package/dist/src/logic/{RemoteRandomGraphNode.d.ts → DeliveryRpcRemote.d.ts} +2 -2
  13. package/dist/src/logic/{RemoteRandomGraphNode.js → DeliveryRpcRemote.js} +5 -5
  14. package/dist/src/logic/DeliveryRpcRemote.js.map +1 -0
  15. package/dist/src/logic/EntryPointDiscovery.d.ts +35 -0
  16. package/dist/src/logic/EntryPointDiscovery.js +145 -0
  17. package/dist/src/logic/EntryPointDiscovery.js.map +1 -0
  18. package/dist/src/logic/ILayer0.d.ts +3 -6
  19. package/dist/src/logic/ILayer1.d.ts +2 -2
  20. package/dist/src/logic/NodeList.d.ts +10 -10
  21. package/dist/src/logic/NodeList.js +2 -2
  22. package/dist/src/logic/NodeList.js.map +1 -1
  23. package/dist/src/logic/RandomGraphNode.d.ts +8 -12
  24. package/dist/src/logic/RandomGraphNode.js +47 -46
  25. package/dist/src/logic/RandomGraphNode.js.map +1 -1
  26. package/dist/src/logic/StreamrNode.d.ts +9 -11
  27. package/dist/src/logic/StreamrNode.js +72 -75
  28. package/dist/src/logic/StreamrNode.js.map +1 -1
  29. package/dist/src/logic/createRandomGraphNode.d.ts +6 -1
  30. package/dist/src/logic/createRandomGraphNode.js +17 -23
  31. package/dist/src/logic/createRandomGraphNode.js.map +1 -1
  32. package/dist/src/logic/formStreamPartDeliveryServiceId.d.ts +2 -0
  33. package/dist/src/logic/formStreamPartDeliveryServiceId.js +8 -0
  34. package/dist/src/logic/formStreamPartDeliveryServiceId.js.map +1 -0
  35. package/dist/src/logic/inspect/Inspector.d.ts +3 -2
  36. package/dist/src/logic/inspect/Inspector.js +5 -5
  37. package/dist/src/logic/inspect/Inspector.js.map +1 -1
  38. package/dist/src/logic/neighbor-discovery/{HandshakerServer.d.ts → HandshakeRpcLocal.d.ts} +10 -10
  39. package/dist/src/logic/neighbor-discovery/{HandshakerServer.js → HandshakeRpcLocal.js} +13 -13
  40. package/dist/src/logic/neighbor-discovery/HandshakeRpcLocal.js.map +1 -0
  41. package/dist/src/logic/neighbor-discovery/{RemoteHandshaker.d.ts → HandshakeRpcRemote.d.ts} +1 -1
  42. package/dist/src/logic/neighbor-discovery/{RemoteHandshaker.js → HandshakeRpcRemote.js} +8 -7
  43. package/dist/src/logic/neighbor-discovery/HandshakeRpcRemote.js.map +1 -0
  44. package/dist/src/logic/neighbor-discovery/Handshaker.d.ts +8 -7
  45. package/dist/src/logic/neighbor-discovery/Handshaker.js +23 -24
  46. package/dist/src/logic/neighbor-discovery/Handshaker.js.map +1 -1
  47. package/dist/src/logic/neighbor-discovery/NeighborFinder.d.ts +1 -1
  48. package/dist/src/logic/neighbor-discovery/NeighborFinder.js +5 -5
  49. package/dist/src/logic/neighbor-discovery/NeighborFinder.js.map +1 -1
  50. package/dist/src/logic/neighbor-discovery/NeighborUpdateManager.d.ts +3 -2
  51. package/dist/src/logic/neighbor-discovery/NeighborUpdateManager.js +7 -7
  52. package/dist/src/logic/neighbor-discovery/NeighborUpdateManager.js.map +1 -1
  53. package/dist/src/logic/neighbor-discovery/{NeighborUpdateManagerServer.d.ts → NeighborUpdateRpcLocal.d.ts} +6 -6
  54. package/dist/src/logic/neighbor-discovery/{NeighborUpdateManagerServer.js → NeighborUpdateRpcLocal.js} +11 -11
  55. package/dist/src/logic/neighbor-discovery/NeighborUpdateRpcLocal.js.map +1 -0
  56. package/dist/src/logic/neighbor-discovery/{RemoteNeighborUpdateManager.d.ts → NeighborUpdateRpcRemote.d.ts} +1 -1
  57. package/dist/src/logic/neighbor-discovery/{RemoteNeighborUpdateManager.js → NeighborUpdateRpcRemote.js} +5 -5
  58. package/dist/src/logic/neighbor-discovery/NeighborUpdateRpcRemote.js.map +1 -0
  59. package/dist/src/logic/propagation/Propagation.js +2 -2
  60. package/dist/src/logic/propagation/Propagation.js.map +1 -1
  61. package/dist/src/logic/proxy/{ProxyStreamConnectionClient.d.ts → ProxyClient.d.ts} +8 -12
  62. package/dist/src/logic/proxy/{ProxyStreamConnectionClient.js → ProxyClient.js} +28 -29
  63. package/dist/src/logic/proxy/ProxyClient.js.map +1 -0
  64. package/dist/src/logic/proxy/{ProxyStreamConnectionServer.d.ts → ProxyConnectionRpcLocal.d.ts} +5 -7
  65. package/dist/src/logic/proxy/{ProxyStreamConnectionServer.js → ProxyConnectionRpcLocal.js} +6 -12
  66. package/dist/src/logic/proxy/ProxyConnectionRpcLocal.js.map +1 -0
  67. package/dist/src/logic/proxy/{RemoteProxyServer.d.ts → ProxyConnectionRpcRemote.d.ts} +1 -1
  68. package/dist/src/logic/proxy/{RemoteProxyServer.js → ProxyConnectionRpcRemote.js} +4 -4
  69. package/dist/src/logic/proxy/ProxyConnectionRpcRemote.js.map +1 -0
  70. package/dist/src/logic/temporary-connection/{TemporaryConnectionRpcServer.d.ts → TemporaryConnectionRpcLocal.d.ts} +5 -4
  71. package/dist/src/logic/temporary-connection/{TemporaryConnectionRpcServer.js → TemporaryConnectionRpcLocal.js} +6 -6
  72. package/dist/src/logic/temporary-connection/TemporaryConnectionRpcLocal.js.map +1 -0
  73. package/dist/src/logic/temporary-connection/{RemoteTemporaryConnectionRpcServer.d.ts → TemporaryConnectionRpcRemote.d.ts} +1 -1
  74. package/dist/src/logic/temporary-connection/{RemoteTemporaryConnectionRpcServer.js → TemporaryConnectionRpcRemote.js} +4 -4
  75. package/dist/src/logic/temporary-connection/TemporaryConnectionRpcRemote.js.map +1 -0
  76. package/dist/src/proto/packages/dht/protos/DhtRpc.d.ts +0 -4
  77. package/dist/src/proto/packages/dht/protos/DhtRpc.js +1 -2
  78. package/dist/src/proto/packages/dht/protos/DhtRpc.js.map +1 -1
  79. package/dist/src/proto/packages/trackerless-network/protos/NetworkRpc.client.d.ts +4 -4
  80. package/dist/src/proto/packages/trackerless-network/protos/NetworkRpc.client.js +7 -7
  81. package/dist/src/proto/packages/trackerless-network/protos/NetworkRpc.client.js.map +1 -1
  82. package/dist/src/proto/packages/trackerless-network/protos/NetworkRpc.d.ts +10 -10
  83. package/dist/src/proto/packages/trackerless-network/protos/NetworkRpc.js +7 -7
  84. package/dist/src/proto/packages/trackerless-network/protos/NetworkRpc.js.map +1 -1
  85. package/dist/src/proto/packages/trackerless-network/protos/NetworkRpc.server.d.ts +2 -2
  86. package/dist/test/benchmark/first-message.js +10 -13
  87. package/dist/test/benchmark/first-message.js.map +1 -1
  88. package/dist/test/utils/utils.d.ts +5 -5
  89. package/dist/test/utils/utils.js +14 -14
  90. package/dist/test/utils/utils.js.map +1 -1
  91. package/package.json +10 -8
  92. package/protos/NetworkRpc.proto +5 -5
  93. package/src/NetworkNode.ts +1 -1
  94. package/src/NetworkStack.ts +20 -62
  95. package/src/identifiers.ts +3 -3
  96. package/src/logic/{StreamNodeServer.ts → DeliveryRpcLocal.ts} +8 -7
  97. package/src/logic/{RemoteRandomGraphNode.ts → DeliveryRpcRemote.ts} +3 -3
  98. package/src/logic/EntryPointDiscovery.ts +181 -0
  99. package/src/logic/ILayer0.ts +3 -6
  100. package/src/logic/ILayer1.ts +2 -5
  101. package/src/logic/NodeList.ts +12 -12
  102. package/src/logic/RandomGraphNode.ts +67 -69
  103. package/src/logic/StreamrNode.ts +78 -90
  104. package/src/logic/createRandomGraphNode.ts +28 -26
  105. package/src/logic/formStreamPartDeliveryServiceId.ts +5 -0
  106. package/src/logic/inspect/Inspector.ts +8 -7
  107. package/src/logic/neighbor-discovery/{HandshakerServer.ts → HandshakeRpcLocal.ts} +20 -20
  108. package/src/logic/neighbor-discovery/{RemoteHandshaker.ts → HandshakeRpcRemote.ts} +6 -5
  109. package/src/logic/neighbor-discovery/Handshaker.ts +38 -38
  110. package/src/logic/neighbor-discovery/NeighborFinder.ts +6 -6
  111. package/src/logic/neighbor-discovery/NeighborUpdateManager.ts +15 -12
  112. package/src/logic/neighbor-discovery/{NeighborUpdateManagerServer.ts → NeighborUpdateRpcLocal.ts} +17 -17
  113. package/src/logic/neighbor-discovery/{RemoteNeighborUpdateManager.ts → NeighborUpdateRpcRemote.ts} +2 -2
  114. package/src/logic/propagation/Propagation.ts +2 -2
  115. package/src/logic/proxy/{ProxyStreamConnectionClient.ts → ProxyClient.ts} +33 -37
  116. package/src/logic/proxy/{ProxyStreamConnectionServer.ts → ProxyConnectionRpcLocal.ts} +10 -19
  117. package/src/logic/proxy/{RemoteProxyServer.ts → ProxyConnectionRpcRemote.ts} +1 -1
  118. package/src/logic/temporary-connection/{TemporaryConnectionRpcServer.ts → TemporaryConnectionRpcLocal.ts} +11 -10
  119. package/src/logic/temporary-connection/{RemoteTemporaryConnectionRpcServer.ts → TemporaryConnectionRpcRemote.ts} +1 -1
  120. package/src/proto/packages/dht/protos/DhtRpc.ts +1 -6
  121. package/src/proto/packages/trackerless-network/protos/NetworkRpc.client.ts +8 -8
  122. package/src/proto/packages/trackerless-network/protos/NetworkRpc.server.ts +2 -2
  123. package/src/proto/packages/trackerless-network/protos/NetworkRpc.ts +14 -14
  124. package/test/benchmark/first-message.ts +10 -13
  125. package/test/end-to-end/inspect.test.ts +12 -12
  126. package/test/end-to-end/proxy-and-full-node.test.ts +13 -14
  127. package/test/end-to-end/proxy-connections.test.ts +10 -12
  128. package/test/end-to-end/proxy-key-exchange.test.ts +12 -13
  129. package/test/end-to-end/random-graph-with-real-connections.test.ts +7 -7
  130. package/test/end-to-end/webrtc-full-node-network.test.ts +8 -8
  131. package/test/end-to-end/websocket-full-node-network.test.ts +8 -10
  132. package/test/integration/{RemoteRandomGraphNode.test.ts → DeliveryRpcRemote.test.ts} +17 -14
  133. package/test/integration/{RemoteHandshaker.test.ts → HandshakeRpcRemote.test.ts} +10 -9
  134. package/test/integration/Handshakes.test.ts +23 -20
  135. package/test/integration/Inspect.test.ts +3 -2
  136. package/test/integration/{RemoteNeighborUpdateManager.test.ts → NeighborUpdateRpcRemote.test.ts} +12 -10
  137. package/test/integration/NetworkNode.test.ts +9 -8
  138. package/test/integration/NetworkRpc.test.ts +5 -7
  139. package/test/integration/NetworkStack.test.ts +13 -15
  140. package/test/integration/Propagation.test.ts +2 -2
  141. package/test/integration/RandomGraphNode-Layer1Node-Latencies.test.ts +10 -8
  142. package/test/integration/RandomGraphNode-Layer1Node.test.ts +17 -17
  143. package/test/integration/StreamrNode.test.ts +5 -3
  144. package/test/integration/joining-streams-on-offline-peers.test.ts +16 -18
  145. package/test/integration/stream-without-default-entrypoints.test.ts +11 -13
  146. package/test/unit/{StreamNodeServer.test.ts → DeliveryRpcLocal.test.ts} +8 -8
  147. package/test/unit/EntrypointDiscovery.test.ts +132 -0
  148. package/test/unit/{HandshakerServer.test.ts → HandshakeRpcLocal.test.ts} +26 -24
  149. package/test/unit/Handshaker.test.ts +10 -8
  150. package/test/unit/Inspector.test.ts +4 -3
  151. package/test/unit/NeighborFinder.test.ts +5 -5
  152. package/test/unit/NodeList.test.ts +22 -13
  153. package/test/unit/{RemoteProxyServer.test.ts → ProxyConnectionRpcRemote.test.ts} +4 -4
  154. package/test/unit/RandomGraphNode.test.ts +12 -11
  155. package/test/unit/StreamMessageTranslator.test.ts +10 -9
  156. package/test/unit/StreamrNode.test.ts +8 -8
  157. package/test/utils/mock/MockLayer0.ts +7 -26
  158. package/test/utils/mock/MockLayer1.ts +6 -13
  159. package/test/utils/mock/MockNeighborFinder.ts +1 -2
  160. package/test/utils/mock/MockNeighborUpdateManager.ts +1 -2
  161. package/test/utils/mock/Transport.ts +2 -2
  162. package/test/utils/utils.ts +13 -13
  163. package/dist/src/logic/RemoteRandomGraphNode.js.map +0 -1
  164. package/dist/src/logic/StreamPartEntryPointDiscovery.d.ts +0 -39
  165. package/dist/src/logic/StreamPartEntryPointDiscovery.js +0 -194
  166. package/dist/src/logic/StreamPartEntryPointDiscovery.js.map +0 -1
  167. package/dist/src/logic/neighbor-discovery/HandshakerServer.js.map +0 -1
  168. package/dist/src/logic/neighbor-discovery/NeighborUpdateManagerServer.js.map +0 -1
  169. package/dist/src/logic/neighbor-discovery/RemoteHandshaker.js.map +0 -1
  170. package/dist/src/logic/neighbor-discovery/RemoteNeighborUpdateManager.js.map +0 -1
  171. package/dist/src/logic/proxy/ProxyStreamConnectionClient.js.map +0 -1
  172. package/dist/src/logic/proxy/ProxyStreamConnectionServer.js.map +0 -1
  173. package/dist/src/logic/proxy/RemoteProxyServer.js.map +0 -1
  174. package/dist/src/logic/temporary-connection/RemoteTemporaryConnectionRpcServer.js.map +0 -1
  175. package/dist/src/logic/temporary-connection/TemporaryConnectionRpcServer.js.map +0 -1
  176. package/src/logic/StreamPartEntryPointDiscovery.ts +0 -240
  177. 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
- })