2018-02-07 07:48:37 +00:00
|
|
|
'use strict'
|
|
|
|
|
2018-10-19 16:28:28 +02:00
|
|
|
const tryEach = require('async/tryEach')
|
|
|
|
const parallel = require('async/parallel')
|
|
|
|
const errCode = require('err-code')
|
2019-07-29 14:40:40 +01:00
|
|
|
const promisify = require('promisify-es6')
|
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 || []
|
|
|
|
|
|
|
|
// If we have the dht, make it first
|
|
|
|
if (node._dht) {
|
|
|
|
routers.unshift(node._dht)
|
|
|
|
}
|
|
|
|
|
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
|
|
|
|
* @param {object} options
|
|
|
|
* @param {number} options.maxTimeout How long the query should run
|
2018-11-13 10:46:51 +00:00
|
|
|
* @param {number} options.maxNumProviders - maximum number of providers to find
|
2018-10-19 16:28:28 +02:00
|
|
|
* @param {function(Error, Result<Array>)} callback
|
|
|
|
* @returns {void}
|
|
|
|
*/
|
2019-07-29 14:40:40 +01:00
|
|
|
findProviders: promisify((key, options, callback) => {
|
2018-10-19 16:28:28 +02:00
|
|
|
if (typeof options === 'function') {
|
|
|
|
callback = options
|
|
|
|
options = {}
|
|
|
|
} else if (typeof options === 'number') { // This can be deprecated in a future release
|
|
|
|
options = {
|
|
|
|
maxTimeout: options
|
|
|
|
}
|
2018-02-07 07:48:37 +00:00
|
|
|
}
|
|
|
|
|
2018-11-05 13:56:45 +01:00
|
|
|
if (!routers.length) {
|
|
|
|
return callback(errCode(new Error('No content routers available'), 'NO_ROUTERS_AVAILABLE'))
|
|
|
|
}
|
|
|
|
|
2018-10-19 16:28:28 +02:00
|
|
|
const tasks = routers.map((router) => {
|
|
|
|
return (cb) => router.findProviders(key, options, (err, results) => {
|
|
|
|
if (err) {
|
|
|
|
return cb(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we don't have any results, we need to provide an error to keep trying
|
|
|
|
if (!results || Object.keys(results).length === 0) {
|
|
|
|
return cb(errCode(new Error('not found'), 'NOT_FOUND'), null)
|
|
|
|
}
|
|
|
|
|
|
|
|
cb(null, results)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
tryEach(tasks, (err, results) => {
|
|
|
|
if (err && err.code !== 'NOT_FOUND') {
|
|
|
|
return callback(err)
|
|
|
|
}
|
|
|
|
results = results || []
|
|
|
|
callback(null, results)
|
|
|
|
})
|
2019-07-29 14:40:40 +01:00
|
|
|
}),
|
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
|
|
|
|
* @param {function(Error)} callback
|
|
|
|
* @returns {void}
|
|
|
|
*/
|
2019-07-29 14:40:40 +01:00
|
|
|
provide: promisify((key, callback) => {
|
2018-10-19 16:28:28 +02:00
|
|
|
if (!routers.length) {
|
|
|
|
return callback(errCode(new Error('No content routers available'), 'NO_ROUTERS_AVAILABLE'))
|
2018-02-07 07:48:37 +00:00
|
|
|
}
|
|
|
|
|
2018-10-19 16:28:28 +02:00
|
|
|
parallel(routers.map((router) => {
|
|
|
|
return (cb) => router.provide(key, cb)
|
|
|
|
}), callback)
|
2019-07-29 14:40:40 +01:00
|
|
|
})
|
2018-02-07 07:48:37 +00:00
|
|
|
}
|
|
|
|
}
|