feat: add delegated peer and content routing support (#242)

* feat: allow for configuring content and peer routing

* feat: support multiple peer and content routing modules

* docs: add delegated routing example
This commit is contained in:
Jacob Heun
2018-10-19 16:28:28 +02:00
committed by GitHub
parent 3226632d83
commit a95389a28e
18 changed files with 1155 additions and 147 deletions

View File

@ -1,20 +1,82 @@
'use strict'
const tryEach = require('async/tryEach')
const parallel = require('async/parallel')
const errCode = require('err-code')
module.exports = (node) => {
const routers = node._modules.contentRouting || []
// If we have the dht, make it first
if (node._dht) {
routers.unshift(node._dht)
}
return {
findProviders: (key, timeout, callback) => {
if (!node._dht) {
return callback(new Error('DHT is not available'))
/**
* 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
* @param {function(Error, Result<Array>)} callback
* @returns {void}
*/
findProviders: (key, options, callback) => {
if (!routers.length) {
return callback(errCode(new Error('No content routers available'), 'NO_ROUTERS_AVAILABLE'))
}
node._dht.findProviders(key, timeout, callback)
if (typeof options === 'function') {
callback = options
options = {}
} else if (typeof options === 'number') { // This can be deprecated in a future release
options = {
maxTimeout: options
}
}
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)
})
},
/**
* 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}
*/
provide: (key, callback) => {
if (!node._dht) {
return callback(new Error('DHT is not available'))
if (!routers.length) {
return callback(errCode(new Error('No content routers available'), 'NO_ROUTERS_AVAILABLE'))
}
node._dht.provide(key, callback)
parallel(routers.map((router) => {
return (cb) => router.provide(key, cb)
}), callback)
}
}
}