Skip to content
This repository has been archived by the owner on Jul 21, 2023. It is now read-only.

Limit scope of queries to k closest peers #97

Merged
merged 7 commits into from
Apr 17, 2019
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ exports.READ_MESSAGE_TIMEOUT = minute
// The number of records that will be retrieved on a call to getMany()
exports.GET_MANY_RECORD_COUNT = 16

// K is the maximum number of requests to perform before returning failue
// K is the maximum number of requests to perform before returning failure
exports.K = 20

// Alpha is the concurrency for asynchronous requests
Expand Down
101 changes: 101 additions & 0 deletions src/peer-distance-list.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
'use strict'

const distance = require('xor-distance')
const utils = require('./utils')
const map = require('async/map')

/**
* Maintains a list of peerIds sorted by distance from a DHT key.
*/
class PeerDistanceList {
/**
* Creates a new PeerDistanceList.
*
* @param {Buffer} originDhtKey - the DHT key from which distance is calculated
* @param {number} capacity - the maximum size of the list
*/
constructor (originDhtKey, capacity) {
this.originDhtKey = originDhtKey
this.capacity = capacity
this.peerDistances = []
}

/**
* The length of the list
*/
get length () {
return this.peerDistances.length
}

/**
* The peerIds in the list, in order of distance from the origin key
*/
get peers () {
return this.peerDistances.map(pd => pd.peerId)
}

/**
* Add a peerId to the list.
*
* @param {PeerId} peerId
* @param {function(Error)} callback
* @returns {void}
*/
add (peerId, callback) {
if (this.peerDistances.find(pd => pd.peerId.id.equals(peerId.id))) {
return callback()
}

utils.convertPeerId(peerId, (err, dhtKey) => {
if (err) {
return callback(err)
}

const el = {
peerId,
distance: distance(this.originDhtKey, dhtKey)
}

this.peerDistances.push(el)
this.peerDistances.sort((a, b) => distance.compare(a.distance, b.distance))
this.peerDistances = this.peerDistances.slice(0, this.capacity)

callback()
})
}

/**
* Indicates whether any of the peerIds passed as a parameter are closer
* to the origin key than the furthest peerId in the PeerDistanceList.
*
* @param {Array<PeerId>} peerIds
* @param {function(Error, Boolean)} callback
* @returns {void}
*/
anyCloser (peerIds, callback) {
if (!peerIds.length) {
return callback(null, false)
}

if (!this.length) {
return callback(null, true)
}

map(peerIds, (peerId, cb) => utils.convertPeerId(peerId, cb), (err, dhtKeys) => {
if (err) {
return callback(err)
}

const furthestDistance = this.peerDistances[this.peerDistances.length - 1].distance
for (const dhtKey of dhtKeys) {
const keyDistance = distance(this.originDhtKey, dhtKey)
if (distance.compare(keyDistance, furthestDistance) < 0) {
return callback(null, true)
}
}
return callback(null, false)
})
}
}

module.exports = PeerDistanceList
Loading