2018-02-07 07:48:37 +00:00
|
|
|
'use strict'
|
|
|
|
|
2018-10-19 16:28:28 +02:00
|
|
|
const errCode = require('err-code')
|
2019-12-01 22:54:59 +01:00
|
|
|
const { messages, codes } = require('./errors')
|
|
|
|
|
|
|
|
const all = require('async-iterator-all')
|
|
|
|
const pAny = require('p-any')
|
2018-10-19 16:28:28 +02:00
|
|
|
|
2018-02-07 07:48:37 +00:00
|
|
|
module.exports = (node) => {
|
2018-10-19 16:28:28 +02:00
|
|
|
const routers = node._modules.contentRouting || []
|
2019-12-01 22:54:59 +01:00
|
|
|
const dht = node._dht
|
2018-10-19 16:28:28 +02:00
|
|
|
|
|
|
|
// If we have the dht, make it first
|
2019-12-01 22:54:59 +01:00
|
|
|
if (dht) {
|
|
|
|
routers.unshift(dht)
|
2018-10-19 16:28:28 +02:00
|
|
|
}
|
|
|
|
|
2018-02-07 07:48:37 +00:00
|
|
|
return {
|
2018-10-19 16:28:28 +02:00
|
|
|
/**
|
|
|
|
* Iterates over all content routers in series to find providers of the given key.
|
|
|
|
* Once a content router succeeds, iteration will stop.
|
|
|
|
*
|
|
|
|
* @param {CID} key The CID key of the content to find
|
2019-12-01 22:54:59 +01:00
|
|
|
* @param {object} [options]
|
|
|
|
* @param {number} [options.timeout] How long the query should run
|
|
|
|
* @param {number} [options.maxNumProviders] - maximum number of providers to find
|
|
|
|
* @returns {AsyncIterable<PeerInfo>}
|
2018-10-19 16:28:28 +02:00
|
|
|
*/
|
2019-12-01 22:54:59 +01:00
|
|
|
async * findProviders (key, options) {
|
2018-11-05 13:56:45 +01:00
|
|
|
if (!routers.length) {
|
2019-12-01 22:54:59 +01:00
|
|
|
throw errCode(new Error('No content routers available'), 'NO_ROUTERS_AVAILABLE')
|
2018-11-05 13:56:45 +01:00
|
|
|
}
|
|
|
|
|
2019-12-01 22:54:59 +01:00
|
|
|
const result = await pAny(
|
|
|
|
routers.map(async (router) => {
|
|
|
|
const provs = await all(router.findProviders(key, options))
|
2018-10-19 16:28:28 +02:00
|
|
|
|
2019-12-01 22:54:59 +01:00
|
|
|
if (!provs || !provs.length) {
|
|
|
|
throw errCode(new Error('not found'), 'NOT_FOUND')
|
2018-10-19 16:28:28 +02:00
|
|
|
}
|
2019-12-01 22:54:59 +01:00
|
|
|
return provs
|
2018-10-19 16:28:28 +02:00
|
|
|
})
|
2019-12-01 22:54:59 +01:00
|
|
|
)
|
2018-10-19 16:28:28 +02:00
|
|
|
|
2019-12-01 22:54:59 +01:00
|
|
|
for (const pInfo of result) {
|
|
|
|
yield pInfo
|
|
|
|
}
|
|
|
|
},
|
2018-10-19 16:28:28 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Iterates over all content routers in parallel to notify it is
|
|
|
|
* a provider of the given key.
|
|
|
|
*
|
|
|
|
* @param {CID} key The CID key of the content to find
|
2019-12-01 22:54:59 +01:00
|
|
|
* @returns {Promise<void>}
|
2018-10-19 16:28:28 +02:00
|
|
|
*/
|
2019-12-01 22:54:59 +01:00
|
|
|
async provide (key) { // eslint-disable-line require-await
|
2018-10-19 16:28:28 +02:00
|
|
|
if (!routers.length) {
|
2019-12-01 22:54:59 +01:00
|
|
|
throw errCode(new Error('No content routers available'), 'NO_ROUTERS_AVAILABLE')
|
|
|
|
}
|
|
|
|
|
|
|
|
return Promise.all(routers.map((router) => router.provide(key)))
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Store the given key/value pair in the DHT.
|
|
|
|
* @param {Buffer} key
|
|
|
|
* @param {Buffer} value
|
|
|
|
* @param {Object} [options] - put options
|
|
|
|
* @param {number} [options.minPeers] - minimum number of peers required to successfully put
|
|
|
|
* @returns {Promise<void>}
|
|
|
|
*/
|
|
|
|
async put (key, value, options) { // eslint-disable-line require-await
|
|
|
|
if (!node.isStarted() || !dht.isStarted) {
|
|
|
|
throw errCode(new Error(messages.NOT_STARTED_YET), codes.DHT_NOT_STARTED)
|
|
|
|
}
|
|
|
|
|
|
|
|
return dht.put(key, value, options)
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the value to the given key.
|
|
|
|
* Times out after 1 minute by default.
|
|
|
|
* @param {Buffer} key
|
|
|
|
* @param {Object} [options] - get options
|
|
|
|
* @param {number} [options.timeout] - optional timeout (default: 60000)
|
|
|
|
* @returns {Promise<{from: PeerId, val: Buffer}>}
|
|
|
|
*/
|
|
|
|
async get (key, options) { // eslint-disable-line require-await
|
|
|
|
if (!node.isStarted() || !dht.isStarted) {
|
|
|
|
throw errCode(new Error(messages.NOT_STARTED_YET), codes.DHT_NOT_STARTED)
|
|
|
|
}
|
|
|
|
|
|
|
|
return dht.get(key, options)
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the `n` values to the given key without sorting.
|
|
|
|
* @param {Buffer} key
|
|
|
|
* @param {number} nVals
|
|
|
|
* @param {Object} [options] - get options
|
|
|
|
* @param {number} [options.timeout] - optional timeout (default: 60000)
|
|
|
|
* @returns {Promise<Array<{from: PeerId, val: Buffer}>>}
|
|
|
|
*/
|
|
|
|
async getMany (key, nVals, options) { // eslint-disable-line require-await
|
|
|
|
if (!node.isStarted() || !dht.isStarted) {
|
|
|
|
throw errCode(new Error(messages.NOT_STARTED_YET), codes.DHT_NOT_STARTED)
|
2018-02-07 07:48:37 +00:00
|
|
|
}
|
|
|
|
|
2019-12-01 22:54:59 +01:00
|
|
|
return dht.getMany(key, nVals, options)
|
|
|
|
}
|
2018-02-07 07:48:37 +00:00
|
|
|
}
|
|
|
|
}
|