@streamr/dht 100.0.0-pretestnet.6 → 100.0.0-testnet-one.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/dist/src/connection/ConnectionLockHandler.js +2 -2
- package/dist/src/connection/ConnectionLockHandler.js.map +1 -1
- package/dist/src/connection/ConnectionLockRpcRemote.d.ts +2 -2
- package/dist/src/connection/ConnectionLockRpcRemote.js +2 -2
- package/dist/src/connection/ConnectionLockRpcRemote.js.map +1 -1
- package/dist/src/connection/ConnectionManager.js +4 -1
- package/dist/src/connection/ConnectionManager.js.map +1 -1
- package/dist/src/connection/ConnectorFacade.js.map +1 -1
- package/dist/src/connection/ManagedConnection.js +1 -0
- package/dist/src/connection/ManagedConnection.js.map +1 -1
- package/dist/src/connection/connectivityChecker.d.ts +9 -0
- package/dist/src/connection/connectivityChecker.js +121 -0
- package/dist/src/connection/connectivityChecker.js.map +1 -0
- package/dist/src/connection/connectivityRequestHandler.d.ts +2 -0
- package/dist/src/connection/connectivityRequestHandler.js +79 -0
- package/dist/src/connection/connectivityRequestHandler.js.map +1 -0
- package/dist/src/connection/simulator/Simulator.js +3 -2
- package/dist/src/connection/simulator/Simulator.js.map +1 -1
- package/dist/src/connection/simulator/SimulatorConnection.js +1 -1
- package/dist/src/connection/simulator/SimulatorConnection.js.map +1 -1
- package/dist/src/connection/webrtc/NodeWebrtcConnection.js +1 -1
- package/dist/src/connection/webrtc/NodeWebrtcConnection.js.map +1 -1
- package/dist/src/connection/webrtc/WebrtcConnector.js +1 -1
- package/dist/src/connection/webrtc/WebrtcConnector.js.map +1 -1
- package/dist/src/connection/webrtc/WebrtcConnectorRpcLocal.js +1 -1
- package/dist/src/connection/webrtc/WebrtcConnectorRpcLocal.js.map +1 -1
- package/dist/src/connection/webrtc/WebrtcConnectorRpcRemote.d.ts +2 -2
- package/dist/src/connection/webrtc/WebrtcConnectorRpcRemote.js +2 -2
- package/dist/src/connection/webrtc/WebrtcConnectorRpcRemote.js.map +1 -1
- package/dist/src/connection/webrtc/iceServerAsString.js +1 -1
- package/dist/src/connection/webrtc/iceServerAsString.js.map +1 -1
- package/dist/src/connection/websocket/ClientWebsocket.js +1 -0
- package/dist/src/connection/websocket/ClientWebsocket.js.map +1 -1
- package/dist/src/connection/websocket/WebsocketConnector.d.ts +0 -1
- package/dist/src/connection/websocket/WebsocketConnector.js +41 -7
- package/dist/src/connection/websocket/WebsocketConnector.js.map +1 -1
- package/dist/src/connection/websocket/WebsocketConnectorRpcRemote.d.ts +2 -2
- package/dist/src/connection/websocket/WebsocketConnectorRpcRemote.js +2 -2
- package/dist/src/connection/websocket/WebsocketConnectorRpcRemote.js.map +1 -1
- package/dist/src/dht/DhtNode.d.ts +9 -19
- package/dist/src/dht/DhtNode.js +76 -216
- package/dist/src/dht/DhtNode.js.map +1 -1
- package/dist/src/dht/DhtNodeRpcLocal.js +3 -3
- package/dist/src/dht/DhtNodeRpcLocal.js.map +1 -1
- package/dist/src/dht/DhtNodeRpcRemote.d.ts +3 -3
- package/dist/src/dht/DhtNodeRpcRemote.js +4 -4
- package/dist/src/dht/DhtNodeRpcRemote.js.map +1 -1
- package/dist/src/dht/ExternalApiRpcLocal.d.ts +4 -4
- package/dist/src/dht/ExternalApiRpcLocal.js +5 -12
- package/dist/src/dht/ExternalApiRpcLocal.js.map +1 -1
- package/dist/src/dht/ExternalApiRpcRemote.d.ts +3 -3
- package/dist/src/dht/ExternalApiRpcRemote.js +5 -5
- package/dist/src/dht/ExternalApiRpcRemote.js.map +1 -1
- package/dist/src/dht/PeerManager.d.ts +48 -0
- package/dist/src/dht/PeerManager.js +208 -0
- package/dist/src/dht/PeerManager.js.map +1 -0
- package/dist/src/dht/contact/ContactList.d.ts +1 -1
- package/dist/src/dht/contact/ContactList.js +1 -0
- package/dist/src/dht/contact/ContactList.js.map +1 -1
- package/dist/src/dht/contact/{Remote.d.ts → RpcRemote.d.ts} +3 -3
- package/dist/src/dht/contact/{Remote.js → RpcRemote.js} +8 -8
- package/dist/src/dht/contact/RpcRemote.js.map +1 -0
- package/dist/src/dht/discovery/DiscoverySession.d.ts +2 -9
- package/dist/src/dht/discovery/DiscoverySession.js +12 -26
- package/dist/src/dht/discovery/DiscoverySession.js.map +1 -1
- package/dist/src/dht/discovery/PeerDiscovery.d.ts +2 -9
- package/dist/src/dht/discovery/PeerDiscovery.js +13 -15
- package/dist/src/dht/discovery/PeerDiscovery.js.map +1 -1
- package/dist/src/dht/find/FindRpcLocal.js +2 -1
- package/dist/src/dht/find/FindRpcLocal.js.map +1 -1
- package/dist/src/dht/find/FindSession.d.ts +6 -6
- package/dist/src/dht/find/FindSession.js +13 -13
- package/dist/src/dht/find/FindSession.js.map +1 -1
- package/dist/src/dht/find/FindSessionRpcLocal.d.ts +1 -1
- package/dist/src/dht/find/FindSessionRpcRemote.d.ts +2 -2
- package/dist/src/dht/find/FindSessionRpcRemote.js +2 -2
- package/dist/src/dht/find/FindSessionRpcRemote.js.map +1 -1
- package/dist/src/dht/find/Finder.d.ts +4 -4
- package/dist/src/dht/find/Finder.js +50 -42
- package/dist/src/dht/find/Finder.js.map +1 -1
- package/dist/src/dht/routing/FindRpcRemote.d.ts +2 -2
- package/dist/src/dht/routing/FindRpcRemote.js +7 -5
- package/dist/src/dht/routing/FindRpcRemote.js.map +1 -1
- package/dist/src/dht/routing/Router.d.ts +2 -6
- package/dist/src/dht/routing/Router.js +21 -18
- package/dist/src/dht/routing/Router.js.map +1 -1
- package/dist/src/dht/routing/RouterRpcLocal.d.ts +2 -2
- package/dist/src/dht/routing/RouterRpcLocal.js +4 -3
- package/dist/src/dht/routing/RouterRpcLocal.js.map +1 -1
- package/dist/src/dht/routing/RouterRpcRemote.d.ts +2 -2
- package/dist/src/dht/routing/RouterRpcRemote.js +13 -8
- package/dist/src/dht/routing/RouterRpcRemote.js.map +1 -1
- package/dist/src/dht/routing/RoutingSession.d.ts +1 -1
- package/dist/src/dht/routing/RoutingSession.js +16 -11
- package/dist/src/dht/routing/RoutingSession.js.map +1 -1
- package/dist/src/dht/routing/getPreviousPeer.js.map +1 -1
- package/dist/src/dht/store/LocalDataStore.d.ts +3 -3
- package/dist/src/dht/store/LocalDataStore.js +18 -17
- package/dist/src/dht/store/LocalDataStore.js.map +1 -1
- package/dist/src/dht/store/StoreRpcLocal.d.ts +10 -9
- package/dist/src/dht/store/StoreRpcLocal.js +91 -99
- package/dist/src/dht/store/StoreRpcLocal.js.map +1 -1
- package/dist/src/dht/store/StoreRpcRemote.d.ts +4 -5
- package/dist/src/dht/store/StoreRpcRemote.js +6 -15
- package/dist/src/dht/store/StoreRpcRemote.js.map +1 -1
- package/dist/src/exports.d.ts +1 -1
- package/dist/src/exports.js +4 -4
- package/dist/src/exports.js.map +1 -1
- package/dist/src/helpers/PeerID.js +2 -2
- package/dist/src/helpers/PeerID.js.map +1 -1
- package/dist/src/helpers/UUID.js +1 -1
- package/dist/src/helpers/UUID.js.map +1 -1
- package/dist/src/helpers/nodeId.d.ts +1 -0
- package/dist/src/helpers/{kademliaId.js → nodeId.js} +4 -4
- package/dist/src/helpers/nodeId.js.map +1 -0
- package/dist/src/helpers/peerIdFromPeerDescriptor.js +3 -3
- package/dist/src/helpers/peerIdFromPeerDescriptor.js.map +1 -1
- package/dist/src/proto/packages/dht/protos/DhtRpc.client.d.ts +5 -16
- package/dist/src/proto/packages/dht/protos/DhtRpc.client.js +2 -9
- package/dist/src/proto/packages/dht/protos/DhtRpc.client.js.map +1 -1
- package/dist/src/proto/packages/dht/protos/DhtRpc.d.ts +80 -95
- package/dist/src/proto/packages/dht/protos/DhtRpc.js +67 -66
- package/dist/src/proto/packages/dht/protos/DhtRpc.js.map +1 -1
- package/dist/src/proto/packages/dht/protos/DhtRpc.server.d.ts +3 -10
- package/dist/src/transport/RoutingRpcCommunicator.js +2 -0
- package/dist/src/transport/RoutingRpcCommunicator.js.map +1 -1
- package/karma.config.js +2 -2
- package/package.json +5 -5
- package/protos/DhtRpc.proto +36 -36
- package/src/connection/ConnectionLockHandler.ts +2 -2
- package/src/connection/ConnectionLockRpcRemote.ts +2 -2
- package/src/connection/ConnectionManager.ts +4 -1
- package/src/connection/ConnectorFacade.ts +5 -4
- package/src/connection/ManagedConnection.ts +1 -0
- package/src/connection/connectivityChecker.ts +101 -0
- package/src/connection/connectivityRequestHandler.ts +79 -0
- package/src/connection/simulator/Simulator.ts +3 -2
- package/src/connection/simulator/SimulatorConnection.ts +1 -1
- package/src/connection/webrtc/BrowserWebrtcConnection.ts +10 -10
- package/src/connection/webrtc/NodeWebrtcConnection.ts +1 -1
- package/src/connection/webrtc/WebrtcConnector.ts +1 -1
- package/src/connection/webrtc/WebrtcConnectorRpcLocal.ts +1 -1
- package/src/connection/webrtc/WebrtcConnectorRpcRemote.ts +2 -2
- package/src/connection/webrtc/iceServerAsString.ts +1 -1
- package/src/connection/websocket/ClientWebsocket.ts +1 -0
- package/src/connection/websocket/WebsocketConnector.ts +22 -12
- package/src/connection/websocket/WebsocketConnectorRpcRemote.ts +2 -2
- package/src/dht/DhtNode.ts +102 -269
- package/src/dht/DhtNodeRpcLocal.ts +3 -3
- package/src/dht/DhtNodeRpcRemote.ts +4 -4
- package/src/dht/ExternalApiRpcLocal.ts +8 -13
- package/src/dht/ExternalApiRpcRemote.ts +5 -5
- package/src/dht/PeerManager.ts +256 -0
- package/src/dht/contact/ContactList.ts +3 -2
- package/src/dht/contact/{Remote.ts → RpcRemote.ts} +7 -6
- package/src/dht/discovery/DiscoverySession.ts +15 -40
- package/src/dht/discovery/PeerDiscovery.ts +18 -23
- package/src/dht/find/FindRpcLocal.ts +2 -2
- package/src/dht/find/FindSession.ts +20 -20
- package/src/dht/find/FindSessionRpcLocal.ts +1 -1
- package/src/dht/find/FindSessionRpcRemote.ts +2 -2
- package/src/dht/find/Finder.ts +79 -58
- package/src/dht/routing/FindRpcRemote.ts +7 -5
- package/src/dht/routing/Router.ts +22 -21
- package/src/dht/routing/RouterRpcLocal.ts +5 -5
- package/src/dht/routing/RouterRpcRemote.ts +13 -10
- package/src/dht/routing/RoutingSession.ts +15 -10
- package/src/dht/routing/getPreviousPeer.ts +1 -1
- package/src/dht/store/LocalDataStore.ts +18 -17
- package/src/dht/store/StoreRpcLocal.ts +101 -108
- package/src/dht/store/StoreRpcRemote.ts +7 -23
- package/src/exports.ts +1 -1
- package/src/helpers/PeerID.ts +2 -2
- package/src/helpers/UUID.ts +1 -1
- package/src/helpers/{kademliaId.ts → nodeId.ts} +1 -1
- package/src/helpers/peerIdFromPeerDescriptor.ts +3 -3
- package/src/proto/packages/dht/protos/DhtRpc.client.ts +6 -20
- package/src/proto/packages/dht/protos/DhtRpc.server.ts +3 -10
- package/src/proto/packages/dht/protos/DhtRpc.ts +103 -135
- package/src/transport/RoutingRpcCommunicator.ts +2 -0
- package/test/benchmark/Find.test.ts +4 -4
- package/test/benchmark/KademliaCorrectness.test.ts +2 -2
- package/test/benchmark/kademlia-simulation/Contact.ts +1 -1
- package/test/benchmark/kademlia-simulation/KademliaSimulation.ts +1 -1
- package/test/end-to-end/Layer0-Layer1.test.ts +1 -1
- package/test/end-to-end/Layer0MixedConnectionTypes.test.ts +1 -1
- package/test/end-to-end/Layer0Webrtc-Layer1.test.ts +2 -2
- package/test/end-to-end/Layer0Webrtc.test.ts +2 -2
- package/test/end-to-end/Layer1-Scale-WebSocket.test.ts +1 -1
- package/test/end-to-end/Layer1-Scale-Webrtc.test.ts +1 -1
- package/test/end-to-end/WebsocketConnectionRequest.test.ts +1 -1
- package/test/end-to-end/memory-leak.test.ts +8 -12
- package/test/integration/ConnectionLocking.test.ts +2 -2
- package/test/integration/ConnectionManager.test.ts +14 -14
- package/test/integration/DhtJoinPeerDiscovery.test.ts +1 -1
- package/test/integration/DhtNodeExternalAPI.test.ts +10 -7
- package/test/integration/DhtNodeRpcRemote.test.ts +4 -4
- package/test/integration/DhtRpc.test.ts +6 -6
- package/test/integration/Find.test.ts +3 -3
- package/test/integration/Layer1-scale.test.ts +2 -2
- package/test/integration/Mock-Layer1-Layer0.test.ts +1 -1
- package/test/integration/{MigrateData.test.ts → ReplicateData.test.ts} +9 -9
- package/test/integration/RouteMessage.test.ts +2 -2
- package/test/integration/RouterRpcRemote.test.ts +2 -2
- package/test/integration/RpcErrors.test.ts +2 -2
- package/test/integration/ScaleDownDht.test.ts +4 -2
- package/test/integration/SimultaneousConnections.test.ts +8 -8
- package/test/integration/Store.test.ts +33 -13
- package/test/integration/StoreAndDelete.test.ts +19 -17
- package/test/integration/StoreOnDhtWithTwoNodes.test.ts +20 -20
- package/test/integration/StoreRpcRemote.test.ts +3 -3
- package/test/integration/WebrtcConnectionManagement.test.ts +2 -2
- package/test/integration/WebrtcConnectorRpc.test.ts +1 -1
- package/test/integration/WebsocketConnectionManagement.test.ts +2 -2
- package/test/integration/WebsocketConnectorRpc.test.ts +2 -2
- package/test/unit/ConnectivityHelpers.test.ts +4 -4
- package/test/unit/Finder.test.ts +69 -23
- package/test/unit/LocalDataStore.test.ts +60 -43
- package/test/unit/RandomContactList.test.ts +2 -2
- package/test/unit/Router.test.ts +19 -11
- package/test/unit/RoutingSession.test.ts +76 -0
- package/test/unit/SortedContactList.test.ts +2 -2
- package/test/unit/WebsocketConnector.test.ts +1 -1
- package/test/unit/connectivityRequestHandler.test.ts +71 -0
- package/test/utils/mock/Router.ts +1 -1
- package/test/utils/utils.ts +24 -22
- package/dist/src/connection/ConnectivityChecker.d.ts +0 -17
- package/dist/src/connection/ConnectivityChecker.js +0 -208
- package/dist/src/connection/ConnectivityChecker.js.map +0 -1
- package/dist/src/dht/contact/Remote.js.map +0 -1
- package/dist/src/helpers/kademliaId.d.ts +0 -1
- package/dist/src/helpers/kademliaId.js.map +0 -1
- package/src/connection/ConnectivityChecker.ts +0 -199
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { DhtNodeRpcRemote } from '../DhtNodeRpcRemote'
|
|
2
2
|
import { SortedContactList } from '../contact/SortedContactList'
|
|
3
3
|
import { PeerID, PeerIDKey } from '../../helpers/PeerID'
|
|
4
|
-
import { getNodeIdFromPeerDescriptor } from '../../helpers/peerIdFromPeerDescriptor'
|
|
4
|
+
import { getNodeIdFromPeerDescriptor, peerIdFromPeerDescriptor } from '../../helpers/peerIdFromPeerDescriptor'
|
|
5
5
|
import { Logger } from '@streamr/utils'
|
|
6
6
|
import EventEmitter from 'eventemitter3'
|
|
7
7
|
import { v4 } from 'uuid'
|
|
@@ -12,7 +12,7 @@ import { FindRpcClient, RouterRpcClient } from '../../proto/packages/dht/protos/
|
|
|
12
12
|
import { toProtoRpcClient } from '@streamr/proto-rpc'
|
|
13
13
|
import { Contact } from '../contact/Contact'
|
|
14
14
|
import { FindRpcRemote } from './FindRpcRemote'
|
|
15
|
-
import { EXISTING_CONNECTION_TIMEOUT } from '../contact/
|
|
15
|
+
import { EXISTING_CONNECTION_TIMEOUT } from '../contact/RpcRemote'
|
|
16
16
|
import { getPreviousPeer } from './getPreviousPeer'
|
|
17
17
|
|
|
18
18
|
const logger = new Logger(module)
|
|
@@ -97,9 +97,9 @@ export class RoutingSession extends EventEmitter<RoutingSessionEvents> {
|
|
|
97
97
|
this.parallelism = parallelism
|
|
98
98
|
this.mode = mode
|
|
99
99
|
const previousPeer = getPreviousPeer(messageToRoute)
|
|
100
|
-
const previousId = previousPeer ? PeerID.fromValue(previousPeer.
|
|
100
|
+
const previousId = previousPeer ? PeerID.fromValue(previousPeer.nodeId) : undefined
|
|
101
101
|
this.contactList = new SortedContactList(
|
|
102
|
-
PeerID.fromValue(this.messageToRoute.destinationPeer!.
|
|
102
|
+
PeerID.fromValue(this.messageToRoute.destinationPeer!.nodeId),
|
|
103
103
|
10000,
|
|
104
104
|
undefined,
|
|
105
105
|
true,
|
|
@@ -116,7 +116,7 @@ export class RoutingSession extends EventEmitter<RoutingSessionEvents> {
|
|
|
116
116
|
if (this.ongoingRequests.has(peerId.toKey())) {
|
|
117
117
|
this.ongoingRequests.delete(peerId.toKey())
|
|
118
118
|
}
|
|
119
|
-
const contacts = this.
|
|
119
|
+
const contacts = this.updateAndGetRoutablePeers()
|
|
120
120
|
if (contacts.length === 0 && this.ongoingRequests.size === 0) {
|
|
121
121
|
logger.trace('routing failed, emitting routingFailed sessionId: ' + this.sessionId)
|
|
122
122
|
// TODO should call this.stop() so that we do cleanup? (after the emitFailure call)
|
|
@@ -143,7 +143,7 @@ export class RoutingSession extends EventEmitter<RoutingSessionEvents> {
|
|
|
143
143
|
return
|
|
144
144
|
}
|
|
145
145
|
this.successfulHopCounter += 1
|
|
146
|
-
const contacts = this.
|
|
146
|
+
const contacts = this.updateAndGetRoutablePeers()
|
|
147
147
|
if (this.successfulHopCounter >= this.parallelism || contacts.length === 0) {
|
|
148
148
|
// TODO should call this.stop() so that we do cleanup? (after the routingSucceeded call)
|
|
149
149
|
this.stopped = true
|
|
@@ -170,10 +170,15 @@ export class RoutingSession extends EventEmitter<RoutingSessionEvents> {
|
|
|
170
170
|
}
|
|
171
171
|
}
|
|
172
172
|
|
|
173
|
-
|
|
174
|
-
logger.trace('
|
|
175
|
-
//
|
|
176
|
-
|
|
173
|
+
updateAndGetRoutablePeers(): RemoteContact[] {
|
|
174
|
+
logger.trace('getRoutablePeers() sessionId: ' + this.sessionId)
|
|
175
|
+
// Remove stale contacts that may have been removed from connections
|
|
176
|
+
this.contactList.getAllContacts().forEach((contact) => {
|
|
177
|
+
const peerId = peerIdFromPeerDescriptor(contact.getPeerDescriptor())
|
|
178
|
+
if (this.connections.has(peerId.toKey()) === false) {
|
|
179
|
+
this.contactList.removeContact(peerId)
|
|
180
|
+
}
|
|
181
|
+
})
|
|
177
182
|
const contacts = Array.from(this.connections.values())
|
|
178
183
|
.map((peer) => new RemoteContact(peer, this.localPeerDescriptor, this.rpcCommunicator))
|
|
179
184
|
this.contactList.addContacts(contacts)
|
|
@@ -2,5 +2,5 @@ import { last } from 'lodash'
|
|
|
2
2
|
import { PeerDescriptor, RouteMessageWrapper } from '../../proto/packages/dht/protos/DhtRpc'
|
|
3
3
|
|
|
4
4
|
export const getPreviousPeer = (routeMessage: RouteMessageWrapper): PeerDescriptor | undefined => {
|
|
5
|
-
return last(routeMessage.routingPath
|
|
5
|
+
return last(routeMessage.routingPath)
|
|
6
6
|
}
|
|
@@ -23,23 +23,23 @@ interface LocalDataEntry {
|
|
|
23
23
|
export class LocalDataStore {
|
|
24
24
|
// A map into which each node can store one value per data key
|
|
25
25
|
// The first key is the key of the data, the second key is the
|
|
26
|
-
// PeerID of the
|
|
26
|
+
// PeerID of the creator of the data
|
|
27
27
|
private store: Map<PeerIDKey, Map<PeerIDKey, LocalDataEntry>> = new Map()
|
|
28
28
|
|
|
29
29
|
public storeEntry(dataEntry: DataEntry): boolean {
|
|
30
|
-
const publisherKey = PeerID.fromValue(dataEntry.
|
|
31
|
-
const dataKey = PeerID.fromValue(dataEntry.
|
|
30
|
+
const publisherKey = PeerID.fromValue(dataEntry.creator!.nodeId).toKey()
|
|
31
|
+
const dataKey = PeerID.fromValue(dataEntry.key).toKey()
|
|
32
32
|
|
|
33
33
|
if (!this.store.has(dataKey)) {
|
|
34
34
|
this.store.set(dataKey, new Map())
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
if (this.store.get(dataKey)!.has(publisherKey)) {
|
|
38
|
-
const storedMillis = (dataEntry.
|
|
38
|
+
const storedMillis = (dataEntry.createdAt!.seconds * 1000) + (dataEntry.createdAt!.nanos / 1000000)
|
|
39
39
|
const oldLocalEntry = this.store.get(dataKey)!.get(publisherKey)!
|
|
40
|
-
const oldStoredMillis = (oldLocalEntry.dataEntry.
|
|
40
|
+
const oldStoredMillis = (oldLocalEntry.dataEntry.createdAt!.seconds * 1000) + (oldLocalEntry.dataEntry.createdAt!.nanos / 1000000)
|
|
41
41
|
|
|
42
|
-
// do nothing if old entry is newer than the one being
|
|
42
|
+
// do nothing if old entry is newer than the one being replicated
|
|
43
43
|
if (oldStoredMillis >= storedMillis) {
|
|
44
44
|
return false
|
|
45
45
|
} else {
|
|
@@ -49,18 +49,19 @@ export class LocalDataStore {
|
|
|
49
49
|
this.store.get(dataKey)!.set(publisherKey, {
|
|
50
50
|
dataEntry,
|
|
51
51
|
ttlTimeout: setTimeout(() => {
|
|
52
|
-
this.deleteEntry(PeerID.fromValue(dataEntry.
|
|
52
|
+
this.deleteEntry(PeerID.fromValue(dataEntry.key), dataEntry.creator!)
|
|
53
53
|
}, createTtlValue(dataEntry.ttl))
|
|
54
54
|
})
|
|
55
55
|
return true
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
public markAsDeleted(id: Uint8Array,
|
|
58
|
+
public markAsDeleted(id: Uint8Array, creator: PeerID): boolean {
|
|
59
59
|
const dataKey = PeerID.fromValue(id).toKey()
|
|
60
|
-
|
|
60
|
+
const item = this.store.get(dataKey)
|
|
61
|
+
if ((item === undefined) || !item.has(creator.toKey())) {
|
|
61
62
|
return false
|
|
62
63
|
}
|
|
63
|
-
const storedEntry =
|
|
64
|
+
const storedEntry = item.get(creator.toKey())
|
|
64
65
|
storedEntry!.dataEntry.deleted = true
|
|
65
66
|
return true
|
|
66
67
|
}
|
|
@@ -77,9 +78,9 @@ export class LocalDataStore {
|
|
|
77
78
|
return dataEntries
|
|
78
79
|
}
|
|
79
80
|
|
|
80
|
-
public setStale(key: PeerID,
|
|
81
|
-
const
|
|
82
|
-
const storedEntry = this.store.get(key.toKey())?.get(
|
|
81
|
+
public setStale(key: PeerID, creator: PeerDescriptor, stale: boolean): void {
|
|
82
|
+
const creatorKey = keyFromPeerDescriptor(creator)
|
|
83
|
+
const storedEntry = this.store.get(key.toKey())?.get(creatorKey)
|
|
83
84
|
if (storedEntry) {
|
|
84
85
|
storedEntry.dataEntry.stale = stale
|
|
85
86
|
}
|
|
@@ -91,12 +92,12 @@ export class LocalDataStore {
|
|
|
91
92
|
})
|
|
92
93
|
}
|
|
93
94
|
|
|
94
|
-
public deleteEntry(key: PeerID,
|
|
95
|
-
const
|
|
96
|
-
const storedEntry = this.store.get(key.toKey())?.get(
|
|
95
|
+
public deleteEntry(key: PeerID, creator: PeerDescriptor): void {
|
|
96
|
+
const creatorKey = keyFromPeerDescriptor(creator)
|
|
97
|
+
const storedEntry = this.store.get(key.toKey())?.get(creatorKey)
|
|
97
98
|
if (storedEntry) {
|
|
98
99
|
clearTimeout(storedEntry.ttlTimeout)
|
|
99
|
-
this.store.get(key.toKey())?.delete(
|
|
100
|
+
this.store.get(key.toKey())?.delete(creatorKey)
|
|
100
101
|
if (this.store.get(key.toKey())?.size === 0) {
|
|
101
102
|
this.store.delete(key.toKey())
|
|
102
103
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
-
DataEntry,
|
|
2
|
+
DataEntry, ReplicateDataRequest, PeerDescriptor,
|
|
3
3
|
StoreDataRequest, StoreDataResponse
|
|
4
4
|
} from '../../proto/packages/dht/protos/DhtRpc'
|
|
5
5
|
import { PeerID } from '../../helpers/PeerID'
|
|
@@ -10,7 +10,7 @@ import { toProtoRpcClient } from '@streamr/proto-rpc'
|
|
|
10
10
|
import { StoreRpcClient } from '../../proto/packages/dht/protos/DhtRpc.client'
|
|
11
11
|
import { RoutingRpcCommunicator } from '../../transport/RoutingRpcCommunicator'
|
|
12
12
|
import { IFinder } from '../find/Finder'
|
|
13
|
-
import { areEqualPeerDescriptors
|
|
13
|
+
import { areEqualPeerDescriptors } from '../../helpers/peerIdFromPeerDescriptor'
|
|
14
14
|
import { Logger } from '@streamr/utils'
|
|
15
15
|
import { LocalDataStore } from './LocalDataStore'
|
|
16
16
|
import { IStoreRpc } from '../../proto/packages/dht/protos/DhtRpc.server'
|
|
@@ -22,6 +22,7 @@ import { SortedContactList } from '../contact/SortedContactList'
|
|
|
22
22
|
import { Contact } from '../contact/Contact'
|
|
23
23
|
import { DhtNodeRpcRemote } from '../DhtNodeRpcRemote'
|
|
24
24
|
import { ServiceID } from '../../types/ServiceID'
|
|
25
|
+
import { Empty } from '../../proto/google/protobuf/empty'
|
|
25
26
|
|
|
26
27
|
interface DataStoreConfig {
|
|
27
28
|
rpcCommunicator: RoutingRpcCommunicator
|
|
@@ -66,46 +67,48 @@ export class StoreRpcLocal implements IStoreRpc {
|
|
|
66
67
|
this.rpcRequestTimeout = config.rpcRequestTimeout
|
|
67
68
|
this.getNodesClosestToIdFromBucket = config.getNodesClosestToIdFromBucket
|
|
68
69
|
this.rpcCommunicator.registerRpcMethod(StoreDataRequest, StoreDataResponse, 'storeData',
|
|
69
|
-
(request: StoreDataRequest
|
|
70
|
-
this.rpcCommunicator.
|
|
71
|
-
(request:
|
|
72
|
-
this.rpcCommunicator.registerRpcMethod(DeleteDataRequest, DeleteDataResponse, 'deleteData',
|
|
73
|
-
(request: DeleteDataRequest, context: ServerCallContext) => this.deleteData(request, context))
|
|
70
|
+
(request: StoreDataRequest) => this.storeData(request))
|
|
71
|
+
this.rpcCommunicator.registerRpcNotification(ReplicateDataRequest, 'replicateData',
|
|
72
|
+
(request: ReplicateDataRequest, context: ServerCallContext) => this.replicateData(request, context))
|
|
74
73
|
|
|
75
74
|
this.dhtNodeEmitter.on('newContact', (peerDescriptor: PeerDescriptor) => {
|
|
76
75
|
this.localDataStore.getStore().forEach((dataMap, _dataKey) => {
|
|
77
|
-
dataMap.forEach((dataEntry) => {
|
|
78
|
-
if (this.
|
|
79
|
-
|
|
76
|
+
dataMap.forEach(async (dataEntry) => {
|
|
77
|
+
if (this.shouldReplicateDataToNewNode(dataEntry.dataEntry, peerDescriptor)) {
|
|
78
|
+
try {
|
|
79
|
+
await this.replicateDataToContact(dataEntry.dataEntry, peerDescriptor)
|
|
80
|
+
} catch (e) {
|
|
81
|
+
logger.trace('replicateDataToContact() failed', { error: e })
|
|
82
|
+
}
|
|
80
83
|
}
|
|
81
84
|
})
|
|
82
85
|
})
|
|
83
86
|
})
|
|
84
87
|
}
|
|
85
88
|
|
|
86
|
-
private
|
|
89
|
+
private shouldReplicateDataToNewNode(dataEntry: DataEntry, newNode: PeerDescriptor): boolean {
|
|
87
90
|
|
|
88
|
-
const dataId = PeerID.fromValue(dataEntry.
|
|
89
|
-
const newNodeId = PeerID.fromValue(newNode.
|
|
90
|
-
const localPeerId = PeerID.fromValue(this.localPeerDescriptor.
|
|
91
|
+
const dataId = PeerID.fromValue(dataEntry.key)
|
|
92
|
+
const newNodeId = PeerID.fromValue(newNode.nodeId)
|
|
93
|
+
const localPeerId = PeerID.fromValue(this.localPeerDescriptor.nodeId)
|
|
91
94
|
|
|
92
|
-
const closestToData = this.getNodesClosestToIdFromBucket(dataEntry.
|
|
95
|
+
const closestToData = this.getNodesClosestToIdFromBucket(dataEntry.key, 10)
|
|
93
96
|
|
|
94
97
|
const sortedList = new SortedContactList<Contact>(dataId, 20, undefined, true)
|
|
95
98
|
sortedList.addContact(new Contact(this.localPeerDescriptor))
|
|
96
99
|
|
|
97
100
|
closestToData.forEach((con) => {
|
|
98
|
-
if (!newNodeId.equals(PeerID.fromValue(con.getPeerDescriptor().
|
|
101
|
+
if (!newNodeId.equals(PeerID.fromValue(con.getPeerDescriptor().nodeId))) {
|
|
99
102
|
sortedList.addContact(new Contact(con.getPeerDescriptor()))
|
|
100
103
|
}
|
|
101
104
|
})
|
|
102
105
|
|
|
103
106
|
if (!sortedList.getAllContacts()[0].getPeerId().equals(localPeerId)) {
|
|
104
|
-
// If we are not the closes node to the data, do not
|
|
107
|
+
// If we are not the closes node to the data, do not replicate
|
|
105
108
|
return false
|
|
106
109
|
}
|
|
107
110
|
|
|
108
|
-
const newPeerId = PeerID.fromValue(newNode.
|
|
111
|
+
const newPeerId = PeerID.fromValue(newNode.nodeId)
|
|
109
112
|
sortedList.addContact(new Contact(newNode))
|
|
110
113
|
|
|
111
114
|
const sorted = sortedList.getAllContacts()
|
|
@@ -119,18 +122,18 @@ export class StoreRpcLocal implements IStoreRpc {
|
|
|
119
122
|
}
|
|
120
123
|
|
|
121
124
|
// if new node is within the storageRedundancyFactor closest nodes to the data
|
|
122
|
-
// do
|
|
125
|
+
// do replicate data to it
|
|
123
126
|
|
|
124
127
|
if (index < this.redundancyFactor) {
|
|
125
|
-
this.localDataStore.setStale(dataId, dataEntry.
|
|
128
|
+
this.localDataStore.setStale(dataId, dataEntry.creator!, false)
|
|
126
129
|
return true
|
|
127
130
|
} else {
|
|
128
|
-
this.localDataStore.setStale(dataId, dataEntry.
|
|
131
|
+
this.localDataStore.setStale(dataId, dataEntry.creator!, true)
|
|
129
132
|
return false
|
|
130
133
|
}
|
|
131
134
|
}
|
|
132
135
|
|
|
133
|
-
private async
|
|
136
|
+
private async replicateDataToContact(dataEntry: DataEntry, contact: PeerDescriptor, doNotConnect: boolean = false): Promise<void> {
|
|
134
137
|
const rpcRemote = new StoreRpcRemote(
|
|
135
138
|
this.localPeerDescriptor,
|
|
136
139
|
contact,
|
|
@@ -139,33 +142,30 @@ export class StoreRpcLocal implements IStoreRpc {
|
|
|
139
142
|
this.rpcRequestTimeout
|
|
140
143
|
)
|
|
141
144
|
try {
|
|
142
|
-
|
|
143
|
-
if (response.error) {
|
|
144
|
-
logger.trace('migrateData() returned error: ' + response.error)
|
|
145
|
-
}
|
|
145
|
+
await rpcRemote.replicateData({ entry: dataEntry }, doNotConnect)
|
|
146
146
|
} catch (e) {
|
|
147
|
-
logger.trace('
|
|
147
|
+
logger.trace('replicateData() threw an exception ' + e)
|
|
148
148
|
}
|
|
149
149
|
}
|
|
150
150
|
|
|
151
|
-
public async storeDataToDht(key: Uint8Array, data: Any): Promise<PeerDescriptor[]> {
|
|
151
|
+
public async storeDataToDht(key: Uint8Array, data: Any, creator: PeerDescriptor): Promise<PeerDescriptor[]> {
|
|
152
152
|
logger.debug(`Storing data to DHT ${this.serviceId}`)
|
|
153
153
|
const result = await this.finder.startFind(key)
|
|
154
154
|
const closestNodes = result.closestNodes
|
|
155
155
|
const successfulNodes: PeerDescriptor[] = []
|
|
156
156
|
const ttl = this.highestTtl // ToDo: make TTL decrease according to some nice curve
|
|
157
|
-
const
|
|
157
|
+
const createdAt = Timestamp.now()
|
|
158
158
|
for (let i = 0; i < closestNodes.length && successfulNodes.length < this.redundancyFactor; i++) {
|
|
159
159
|
if (areEqualPeerDescriptors(this.localPeerDescriptor, closestNodes[i])) {
|
|
160
160
|
this.localDataStore.storeEntry({
|
|
161
|
-
|
|
162
|
-
storer: this.localPeerDescriptor,
|
|
163
|
-
ttl,
|
|
164
|
-
storedAt: Timestamp.now(),
|
|
161
|
+
key,
|
|
165
162
|
data,
|
|
163
|
+
creator,
|
|
164
|
+
createdAt,
|
|
165
|
+
storedAt: Timestamp.now(),
|
|
166
|
+
ttl,
|
|
166
167
|
stale: false,
|
|
167
168
|
deleted: false,
|
|
168
|
-
storerTime
|
|
169
169
|
})
|
|
170
170
|
successfulNodes.push(closestNodes[i])
|
|
171
171
|
continue
|
|
@@ -178,7 +178,13 @@ export class StoreRpcLocal implements IStoreRpc {
|
|
|
178
178
|
this.rpcRequestTimeout
|
|
179
179
|
)
|
|
180
180
|
try {
|
|
181
|
-
const response = await rpcRemote.storeData({
|
|
181
|
+
const response = await rpcRemote.storeData({
|
|
182
|
+
key,
|
|
183
|
+
data,
|
|
184
|
+
creator,
|
|
185
|
+
createdAt,
|
|
186
|
+
ttl
|
|
187
|
+
})
|
|
182
188
|
if (!response.error) {
|
|
183
189
|
successfulNodes.push(closestNodes[i])
|
|
184
190
|
logger.trace('remote.storeData() returned success')
|
|
@@ -193,7 +199,7 @@ export class StoreRpcLocal implements IStoreRpc {
|
|
|
193
199
|
}
|
|
194
200
|
|
|
195
201
|
private selfIsOneOfClosestPeers(dataId: Uint8Array): boolean {
|
|
196
|
-
const localPeerId = PeerID.fromValue(this.localPeerDescriptor.
|
|
202
|
+
const localPeerId = PeerID.fromValue(this.localPeerDescriptor.nodeId)
|
|
197
203
|
const closestPeers = this.getNodesClosestToIdFromBucket(dataId, this.redundancyFactor)
|
|
198
204
|
const sortedList = new SortedContactList<Contact>(localPeerId, this.redundancyFactor, undefined, true)
|
|
199
205
|
sortedList.addContact(new Contact(this.localPeerDescriptor))
|
|
@@ -201,94 +207,81 @@ export class StoreRpcLocal implements IStoreRpc {
|
|
|
201
207
|
return sortedList.getClosestContacts().some((node) => node.getPeerId().equals(localPeerId))
|
|
202
208
|
}
|
|
203
209
|
|
|
204
|
-
public async deleteDataFromDht(key: Uint8Array): Promise<void> {
|
|
205
|
-
logger.debug(`Deleting data from DHT ${this.serviceId}`)
|
|
206
|
-
const result = await this.finder.startFind(key)
|
|
207
|
-
const closestNodes = result.closestNodes
|
|
208
|
-
const successfulNodes: PeerDescriptor[] = []
|
|
209
|
-
for (let i = 0; i < closestNodes.length && successfulNodes.length < this.redundancyFactor; i++) {
|
|
210
|
-
if (areEqualPeerDescriptors(this.localPeerDescriptor, closestNodes[i])) {
|
|
211
|
-
this.localDataStore.markAsDeleted(key, peerIdFromPeerDescriptor(this.localPeerDescriptor))
|
|
212
|
-
successfulNodes.push(closestNodes[i])
|
|
213
|
-
continue
|
|
214
|
-
}
|
|
215
|
-
const rpcRemote = new StoreRpcRemote(
|
|
216
|
-
this.localPeerDescriptor,
|
|
217
|
-
closestNodes[i],
|
|
218
|
-
this.serviceId,
|
|
219
|
-
toProtoRpcClient(new StoreRpcClient(this.rpcCommunicator.getRpcClientTransport())),
|
|
220
|
-
this.rpcRequestTimeout
|
|
221
|
-
)
|
|
222
|
-
try {
|
|
223
|
-
const response = await rpcRemote.deleteData({ kademliaId: key })
|
|
224
|
-
if (response.deleted) {
|
|
225
|
-
logger.trace('remote.deleteData() returned success')
|
|
226
|
-
} else {
|
|
227
|
-
logger.trace('could not delete data from ' + getNodeIdFromPeerDescriptor(closestNodes[i]))
|
|
228
|
-
}
|
|
229
|
-
successfulNodes.push(closestNodes[i])
|
|
230
|
-
} catch (e) {
|
|
231
|
-
logger.trace('remote.deleteData() threw an exception ' + e)
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
|
|
236
210
|
// RPC service implementation
|
|
237
|
-
async storeData(request: StoreDataRequest
|
|
211
|
+
async storeData(request: StoreDataRequest): Promise<StoreDataResponse> {
|
|
238
212
|
const ttl = Math.min(request.ttl, this.maxTtl)
|
|
239
|
-
const {
|
|
240
|
-
const { kademliaId, data, storerTime } = request
|
|
213
|
+
const { key, data, createdAt, creator } = request
|
|
241
214
|
this.localDataStore.storeEntry({
|
|
242
|
-
|
|
243
|
-
storer: incomingSourceDescriptor!,
|
|
244
|
-
ttl,
|
|
245
|
-
storedAt: Timestamp.now(),
|
|
246
|
-
storerTime,
|
|
215
|
+
key,
|
|
247
216
|
data,
|
|
248
|
-
|
|
217
|
+
creator,
|
|
218
|
+
createdAt,
|
|
219
|
+
storedAt: Timestamp.now(),
|
|
220
|
+
ttl,
|
|
221
|
+
stale: !this.selfIsOneOfClosestPeers(key),
|
|
249
222
|
deleted: false
|
|
250
223
|
})
|
|
251
224
|
|
|
252
|
-
if (!this.selfIsOneOfClosestPeers(
|
|
253
|
-
this.localDataStore.setAllEntriesAsStale(PeerID.fromValue(
|
|
225
|
+
if (!this.selfIsOneOfClosestPeers(key)) {
|
|
226
|
+
this.localDataStore.setAllEntriesAsStale(PeerID.fromValue(key))
|
|
254
227
|
}
|
|
255
228
|
|
|
256
229
|
logger.trace('storeData()')
|
|
257
230
|
return StoreDataResponse.create()
|
|
258
231
|
}
|
|
259
232
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
233
|
+
async destroy(): Promise<void> {
|
|
234
|
+
await this.replicateDataToClosestNodes()
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
private async replicateDataToClosestNodes(): Promise<void> {
|
|
238
|
+
const dataEntries = Array.from(this.localDataStore.getStore().values())
|
|
239
|
+
.flatMap((dataMap) => Array.from(dataMap.values()))
|
|
240
|
+
.map((localData) => localData.dataEntry)
|
|
241
|
+
|
|
242
|
+
await Promise.all(dataEntries.map(async (dataEntry) => {
|
|
243
|
+
const dhtNodeRemotes = this.getNodesClosestToIdFromBucket(dataEntry.key, this.redundancyFactor)
|
|
244
|
+
await Promise.all(dhtNodeRemotes.map(async (remoteDhtNode) => {
|
|
245
|
+
const rpcRemote = new StoreRpcRemote(
|
|
246
|
+
this.localPeerDescriptor,
|
|
247
|
+
remoteDhtNode.getPeerDescriptor(),
|
|
248
|
+
this.serviceId,
|
|
249
|
+
toProtoRpcClient(new StoreRpcClient(this.rpcCommunicator.getRpcClientTransport())),
|
|
250
|
+
this.rpcRequestTimeout
|
|
251
|
+
)
|
|
252
|
+
try {
|
|
253
|
+
await rpcRemote.replicateData({ entry: dataEntry })
|
|
254
|
+
} catch (err) {
|
|
255
|
+
logger.trace('Failed to replicate data in replicateDataToClosestNodes', { error: err })
|
|
256
|
+
}
|
|
257
|
+
}))
|
|
258
|
+
}))
|
|
266
259
|
}
|
|
267
260
|
|
|
268
261
|
// RPC service implementation
|
|
269
|
-
public async
|
|
270
|
-
logger.trace('server-side
|
|
271
|
-
const dataEntry = request.
|
|
262
|
+
public async replicateData(request: ReplicateDataRequest, context: ServerCallContext): Promise<Empty> {
|
|
263
|
+
logger.trace('server-side replicateData()')
|
|
264
|
+
const dataEntry = request.entry!
|
|
272
265
|
|
|
273
266
|
const wasStored = this.localDataStore.storeEntry(dataEntry)
|
|
274
267
|
|
|
275
268
|
if (wasStored) {
|
|
276
|
-
this.
|
|
269
|
+
this.replicateDataToNeighborsIfNeeded((context as DhtCallContext).incomingSourceDescriptor!, request.entry!)
|
|
277
270
|
}
|
|
278
|
-
if (!this.selfIsOneOfClosestPeers(dataEntry.
|
|
279
|
-
this.localDataStore.setAllEntriesAsStale(PeerID.fromValue(dataEntry.
|
|
271
|
+
if (!this.selfIsOneOfClosestPeers(dataEntry.key)) {
|
|
272
|
+
this.localDataStore.setAllEntriesAsStale(PeerID.fromValue(dataEntry.key))
|
|
280
273
|
}
|
|
281
|
-
logger.trace('server-side
|
|
282
|
-
return
|
|
274
|
+
logger.trace('server-side replicateData() at end')
|
|
275
|
+
return {}
|
|
283
276
|
}
|
|
284
277
|
|
|
285
|
-
private
|
|
278
|
+
private replicateDataToNeighborsIfNeeded(incomingPeer: PeerDescriptor, dataEntry: DataEntry): void {
|
|
286
279
|
|
|
287
280
|
// sort own contact list according to data id
|
|
288
|
-
const localPeerId = PeerID.fromValue(this.localPeerDescriptor.
|
|
289
|
-
const dataId = PeerID.fromValue(dataEntry.
|
|
290
|
-
const incomingPeerId = PeerID.fromValue(incomingPeer.
|
|
291
|
-
const closestToData = this.getNodesClosestToIdFromBucket(dataEntry.
|
|
281
|
+
const localPeerId = PeerID.fromValue(this.localPeerDescriptor.nodeId)
|
|
282
|
+
const dataId = PeerID.fromValue(dataEntry.key)
|
|
283
|
+
const incomingPeerId = PeerID.fromValue(incomingPeer.nodeId)
|
|
284
|
+
const closestToData = this.getNodesClosestToIdFromBucket(dataEntry.key, 10)
|
|
292
285
|
|
|
293
286
|
const sortedList = new SortedContactList<Contact>(dataId, this.redundancyFactor, undefined, true)
|
|
294
287
|
sortedList.addContact(new Contact(this.localPeerDescriptor))
|
|
@@ -298,33 +291,33 @@ export class StoreRpcLocal implements IStoreRpc {
|
|
|
298
291
|
})
|
|
299
292
|
|
|
300
293
|
if (!sortedList.getAllContacts()[0].getPeerId().equals(localPeerId)) {
|
|
301
|
-
// If we are not the closest node to the data,
|
|
294
|
+
// If we are not the closest node to the data, replicate only to the
|
|
302
295
|
// closest one to the data
|
|
303
296
|
|
|
304
297
|
const contact = sortedList.getAllContacts()[0]
|
|
305
|
-
const contactPeerId = PeerID.fromValue(contact.getPeerDescriptor().
|
|
298
|
+
const contactPeerId = PeerID.fromValue(contact.getPeerDescriptor().nodeId)
|
|
306
299
|
if (!incomingPeerId.equals(contactPeerId) && !localPeerId.equals(contactPeerId)) {
|
|
307
300
|
setImmediate(async () => {
|
|
308
301
|
try {
|
|
309
|
-
await this.
|
|
310
|
-
logger.trace('
|
|
302
|
+
await this.replicateDataToContact(dataEntry, contact.getPeerDescriptor())
|
|
303
|
+
logger.trace('replicateDataToContact() returned when migrating to only the closest contact')
|
|
311
304
|
} catch (e) {
|
|
312
|
-
logger.error('
|
|
305
|
+
logger.error('replicating data to only the closest contact failed ' + e)
|
|
313
306
|
}
|
|
314
307
|
})
|
|
315
308
|
}
|
|
316
309
|
} else {
|
|
317
|
-
// if we are the closest to the data,
|
|
310
|
+
// if we are the closest to the data, replicate to all storageRedundancyFactor nearest
|
|
318
311
|
sortedList.getAllContacts().forEach((contact) => {
|
|
319
|
-
const contactPeerId = PeerID.fromValue(contact.getPeerDescriptor().
|
|
312
|
+
const contactPeerId = PeerID.fromValue(contact.getPeerDescriptor().nodeId)
|
|
320
313
|
if (!incomingPeerId.equals(contactPeerId) && !localPeerId.equals(contactPeerId)) {
|
|
321
314
|
if (!incomingPeerId.equals(contactPeerId) && !localPeerId.equals(contactPeerId)) {
|
|
322
315
|
setImmediate(async () => {
|
|
323
316
|
try {
|
|
324
|
-
await this.
|
|
325
|
-
logger.trace('
|
|
317
|
+
await this.replicateDataToContact(dataEntry, contact.getPeerDescriptor())
|
|
318
|
+
logger.trace('replicateDataToContact() returned')
|
|
326
319
|
} catch (e) {
|
|
327
|
-
logger.error('
|
|
320
|
+
logger.error('replicating data to one of the closest contacts failed ' + e)
|
|
328
321
|
}
|
|
329
322
|
})
|
|
330
323
|
}
|
|
@@ -1,16 +1,13 @@
|
|
|
1
|
-
import { EXISTING_CONNECTION_TIMEOUT,
|
|
1
|
+
import { EXISTING_CONNECTION_TIMEOUT, RpcRemote } from '../contact/RpcRemote'
|
|
2
2
|
import { IStoreRpcClient } from '../../proto/packages/dht/protos/DhtRpc.client'
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
DeleteDataResponse,
|
|
6
|
-
MigrateDataRequest,
|
|
7
|
-
MigrateDataResponse,
|
|
3
|
+
import {
|
|
4
|
+
ReplicateDataRequest,
|
|
8
5
|
StoreDataRequest,
|
|
9
6
|
StoreDataResponse
|
|
10
7
|
} from '../../proto/packages/dht/protos/DhtRpc'
|
|
11
8
|
import { getNodeIdFromPeerDescriptor } from '../../helpers/peerIdFromPeerDescriptor'
|
|
12
9
|
|
|
13
|
-
export class StoreRpcRemote extends
|
|
10
|
+
export class StoreRpcRemote extends RpcRemote<IStoreRpcClient> {
|
|
14
11
|
|
|
15
12
|
async storeData(request: StoreDataRequest): Promise<StoreDataResponse> {
|
|
16
13
|
const options = this.formDhtRpcOptions()
|
|
@@ -19,29 +16,16 @@ export class StoreRpcRemote extends Remote<IStoreRpcClient> {
|
|
|
19
16
|
} catch (err) {
|
|
20
17
|
const to = getNodeIdFromPeerDescriptor(this.getPeerDescriptor())
|
|
21
18
|
const from = getNodeIdFromPeerDescriptor(this.getLocalPeerDescriptor())
|
|
22
|
-
throw Error(
|
|
23
|
-
`Could not store data to ${to} from ${from} ${err}`
|
|
24
|
-
)
|
|
19
|
+
throw new Error(`Could not store data to ${to} from ${from} ${err}`)
|
|
25
20
|
}
|
|
26
21
|
}
|
|
27
22
|
|
|
28
|
-
async
|
|
29
|
-
const options = this.formDhtRpcOptions()
|
|
30
|
-
try {
|
|
31
|
-
return await this.getClient().deleteData(request, options)
|
|
32
|
-
} catch (err) {
|
|
33
|
-
throw Error(
|
|
34
|
-
`Could not call delete data to ${getNodeIdFromPeerDescriptor(this.getPeerDescriptor())} ${err}`
|
|
35
|
-
)
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
async migrateData(request: MigrateDataRequest, doNotConnect: boolean = false): Promise<MigrateDataResponse> {
|
|
23
|
+
async replicateData(request: ReplicateDataRequest, doNotConnect: boolean = false): Promise<void> {
|
|
40
24
|
const options = this.formDhtRpcOptions({
|
|
41
25
|
timeout: EXISTING_CONNECTION_TIMEOUT,
|
|
42
26
|
doNotConnect
|
|
43
27
|
})
|
|
44
|
-
return this.getClient().
|
|
28
|
+
return this.getClient().replicateData(request, options)
|
|
45
29
|
}
|
|
46
30
|
|
|
47
31
|
}
|
package/src/exports.ts
CHANGED
|
@@ -9,7 +9,7 @@ export { ITransport } from './transport/ITransport'
|
|
|
9
9
|
export { ConnectionManager, ConnectionLocker, PortRange, TlsCertificate } from './connection/ConnectionManager'
|
|
10
10
|
export { DefaultConnectorFacade } from './connection/ConnectorFacade'
|
|
11
11
|
export { DhtRpcOptions } from './rpc-protocol/DhtRpcOptions'
|
|
12
|
-
export {
|
|
12
|
+
export { RpcRemote, EXISTING_CONNECTION_TIMEOUT } from './dht/contact/RpcRemote'
|
|
13
13
|
export { areEqualPeerDescriptors } from './helpers/peerIdFromPeerDescriptor'
|
|
14
14
|
export { IceServer } from './connection/webrtc/WebrtcConnector'
|
|
15
15
|
export { DhtCallContext } from './rpc-protocol/DhtCallContext'
|
package/src/helpers/PeerID.ts
CHANGED
|
@@ -14,7 +14,7 @@ export class PeerID {
|
|
|
14
14
|
private readonly key: PeerIDKey // precompute often-used form of data
|
|
15
15
|
|
|
16
16
|
protected constructor({ ip, value, stringValue }: { ip?: string, value?: Uint8Array, stringValue?: string } = {}) {
|
|
17
|
-
if (ip) {
|
|
17
|
+
if (ip !== undefined) {
|
|
18
18
|
this.data = new Uint8Array(20)
|
|
19
19
|
const ipNum = this.ip2Int(ip)
|
|
20
20
|
const view = new DataView(this.data.buffer)
|
|
@@ -23,7 +23,7 @@ export class PeerID {
|
|
|
23
23
|
this.data.set((new UUID()).value, 4)
|
|
24
24
|
} else if (value) {
|
|
25
25
|
this.data = new Uint8Array(value.slice(0))
|
|
26
|
-
} else if (stringValue) {
|
|
26
|
+
} else if (stringValue !== undefined) {
|
|
27
27
|
const ab = PeerID.textEncoder.encode(stringValue) //toUTF8Array(stringValue)
|
|
28
28
|
this.data = ab
|
|
29
29
|
} else {
|
package/src/helpers/UUID.ts
CHANGED
|
@@ -3,6 +3,6 @@ import crypto from 'crypto'
|
|
|
3
3
|
// https://www.scs.stanford.edu/~dm/home/papers/kpos.pdf
|
|
4
4
|
const KADEMLIA_ID_LENGTH_IN_BYTES = 20
|
|
5
5
|
|
|
6
|
-
export const
|
|
6
|
+
export const createRandomNodeId = (): Uint8Array => {
|
|
7
7
|
return crypto.randomBytes(KADEMLIA_ID_LENGTH_IN_BYTES)
|
|
8
8
|
}
|
|
@@ -3,16 +3,16 @@ import { PeerDescriptor } from '../proto/packages/dht/protos/DhtRpc'
|
|
|
3
3
|
import { PeerID, PeerIDKey } from './PeerID'
|
|
4
4
|
|
|
5
5
|
export const peerIdFromPeerDescriptor = (peerDescriptor: PeerDescriptor): PeerID => {
|
|
6
|
-
return PeerID.fromValue(peerDescriptor.
|
|
6
|
+
return PeerID.fromValue(peerDescriptor.nodeId)
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
// TODO could move getNodeIdFromPeerDescriptor (and NodeID) from trackerless-network
|
|
10
10
|
export const getNodeIdFromPeerDescriptor = (peerDescriptor: PeerDescriptor): string => {
|
|
11
|
-
return binaryToHex(peerDescriptor.
|
|
11
|
+
return binaryToHex(peerDescriptor.nodeId)
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
export const keyFromPeerDescriptor = (peerDescriptor: PeerDescriptor): PeerIDKey => {
|
|
15
|
-
return PeerID.fromValue(peerDescriptor.
|
|
15
|
+
return PeerID.fromValue(peerDescriptor.nodeId).toKey()
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
export const areEqualPeerDescriptors = (peerDescriptor1: PeerDescriptor, peerDescriptor2: PeerDescriptor): boolean => {
|