Comparing version 1.3.2 to 2.0.0
232
cache.js
@@ -5,135 +5,137 @@ // taken from https://github.com/tiborv/memory-cache-ttl | ||
var options = {}; | ||
var cache = {}; | ||
var ttlQueue = []; | ||
var ttlExtend = new Set(); | ||
module.exports = function () { | ||
var genExpire = function genExpire(seconds) { | ||
var t = new Date(); | ||
t.setSeconds(t.getSeconds() + seconds); | ||
return t; | ||
}; | ||
var options = {}; | ||
var cache = {}; | ||
var ttlQueue = []; | ||
var ttlExtend = new Set(); | ||
var binarySearch = function binarySearch(value) { | ||
var low = 0; | ||
var high = ttlQueue.length; | ||
var genExpire = function genExpire(seconds) { | ||
var t = new Date(); | ||
t.setSeconds(t.getSeconds() + seconds); | ||
return t; | ||
}; | ||
while (low < high) { | ||
var mid = low + high >>> 1; // eslint-disable-line no-bitwise | ||
if (ttlQueue[mid].expires.getTime() < value) low = mid + 1;else high = mid; | ||
} | ||
return low; | ||
}; | ||
var binarySearch = function binarySearch(value) { | ||
var low = 0; | ||
var high = ttlQueue.length; | ||
var addToTTLQueue = function addToTTLQueue(ttl) { | ||
ttlQueue = ttlQueue.filter(function (e) { | ||
return e.id !== ttl.id; | ||
}); | ||
ttlQueue.splice(binarySearch(ttl.expires.getTime()), 0, ttl); | ||
}; | ||
while (low < high) { | ||
var mid = low + high >>> 1; // eslint-disable-line no-bitwise | ||
if (ttlQueue[mid].expires.getTime() < value) low = mid + 1;else high = mid; | ||
} | ||
return low; | ||
}; | ||
var cleanExpired = function cleanExpired() { | ||
if (ttlQueue.length === 0) return; | ||
var now = new Date().getTime(); | ||
if (ttlQueue[0].expires.getTime() > now) return; | ||
var expiredIndex = binarySearch(now); | ||
ttlQueue.slice(0, expiredIndex).map(function (ttl) { | ||
return delete cache[ttl.id]; | ||
}); | ||
ttlQueue = ttlQueue.slice(expiredIndex, ttlQueue.length); | ||
}; | ||
var addToTTLQueue = function addToTTLQueue(ttl) { | ||
ttlQueue = ttlQueue.filter(function (e) { | ||
return e.id !== ttl.id; | ||
}); | ||
ttlQueue.splice(binarySearch(ttl.expires.getTime()), 0, ttl); | ||
}; | ||
var set = function set(id, value, ttl) { | ||
if (!ttl && !options.ttl) throw new Error('Global or local TTL needs to be set'); | ||
cache[id] = value; | ||
if (ttl) return addToTTLQueue({ id: id, expires: genExpire(ttl) }); | ||
addToTTLQueue({ | ||
id: id, | ||
expires: options.randomize ? genExpire(Math.ceil(Math.random() * options.ttl)) : genExpire(options.ttl) | ||
}); | ||
}; | ||
var cleanExpired = function cleanExpired() { | ||
if (ttlQueue.length === 0) return; | ||
var now = new Date().getTime(); | ||
if (ttlQueue[0].expires.getTime() > now) return; | ||
var expiredIndex = binarySearch(now); | ||
ttlQueue.slice(0, expiredIndex).map(function (ttl) { | ||
return delete cache[ttl.id]; | ||
}); | ||
ttlQueue = ttlQueue.slice(expiredIndex, ttlQueue.length); | ||
}; | ||
var check = function check(id) { | ||
return id in cache; | ||
}; | ||
var set = function set(id, value, ttl) { | ||
if (!ttl && !options.ttl) throw new Error('Global or local TTL needs to be set'); | ||
cache[id] = value; | ||
if (ttl) return addToTTLQueue({ id: id, expires: genExpire(ttl) }); | ||
addToTTLQueue({ | ||
id: id, | ||
expires: options.randomize ? genExpire(Math.ceil(Math.random() * options.ttl)) : genExpire(options.ttl) | ||
}); | ||
}; | ||
var get = function get(id) { | ||
if (options.extendOnHit) ttlExtend.add(id); | ||
return cache[id]; | ||
}; | ||
var check = function check(id) { | ||
return id in cache; | ||
}; | ||
var del = function del(id) { | ||
delete cache[id]; | ||
ttlQueue = ttlQueue.filter(function (t) { | ||
return t.id !== id; | ||
}); | ||
}; | ||
var get = function get(id) { | ||
if (options.extendOnHit) ttlExtend.add(id); | ||
return cache[id]; | ||
}; | ||
var list = function list() { | ||
return cache; | ||
}; | ||
var del = function del(id) { | ||
delete cache[id]; | ||
ttlQueue = ttlQueue.filter(function (t) { | ||
return t.id !== id; | ||
}); | ||
}; | ||
var flush = function flush() { | ||
cache = {}; | ||
ttlQueue = []; | ||
}; | ||
var list = function list() { | ||
return cache; | ||
}; | ||
var onInterval = function onInterval() { | ||
if (ttlQueue.length === 0) return; | ||
ttlQueue.forEach(function (ttl) { | ||
options.onInterval(ttl.id).then(function () { | ||
var newValue = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : cache[ttl.id]; | ||
var flush = function flush() { | ||
cache = {}; | ||
ttlQueue = []; | ||
}; | ||
cache[ttl.id] = newValue; | ||
var onInterval = function onInterval() { | ||
if (ttlQueue.length === 0) return; | ||
ttlQueue.forEach(function (ttl) { | ||
options.onInterval(ttl.id).then(function () { | ||
var newValue = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : cache[ttl.id]; | ||
cache[ttl.id] = newValue; | ||
}); | ||
}); | ||
}); | ||
}; | ||
}; | ||
var extendOnHit = function extendOnHit() { | ||
if (ttlExtend.size === 0) return; | ||
ttlExtend.forEach(function (id) { | ||
return set(id, cache[id]); | ||
}); | ||
ttlExtend = new Set(); | ||
}; | ||
var extendOnHit = function extendOnHit() { | ||
if (ttlExtend.size === 0) return; | ||
ttlExtend.forEach(function (id) { | ||
return set(id, cache[id]); | ||
}); | ||
ttlExtend = new Set(); | ||
}; | ||
var runningProcess = void 0; | ||
var runTasks = function runTasks() { | ||
if (runningProcess) clearInterval(runningProcess); | ||
runningProcess = setInterval(function () { | ||
if (options.extendOnHit) extendOnHit(); | ||
cleanExpired(); | ||
if (options.onInterval) onInterval(); | ||
}, options.interval * 1000); | ||
}; | ||
var runningProcess = void 0; | ||
var runTasks = function runTasks() { | ||
if (runningProcess) clearInterval(runningProcess); | ||
runningProcess = setInterval(function () { | ||
if (options.extendOnHit) extendOnHit(); | ||
cleanExpired(); | ||
if (options.onInterval) onInterval(); | ||
}, options.interval * 1000); | ||
}; | ||
var init = function init() { | ||
var o = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : { interval: 1 }; | ||
var init = function init() { | ||
var o = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : { interval: 1 }; | ||
options = o; | ||
if (o.onInterval && typeof o.onInterval !== 'function') { | ||
throw new Error('onInterval needs to be a Promise/function'); | ||
} | ||
runTasks(); | ||
}; | ||
options = o; | ||
if (o.onInterval && typeof o.onInterval !== 'function') { | ||
throw new Error('onInterval needs to be a Promise/function'); | ||
} | ||
runTasks(); | ||
}; | ||
exports.default = { | ||
init: init, | ||
set: set, | ||
get: get, | ||
check: check, | ||
del: del, | ||
list: list, | ||
flush: flush, | ||
__ttlQueue: function __ttlQueue() { | ||
return ttlQueue; | ||
}, | ||
stats: function stats() { | ||
return { | ||
cacheEntries: Object.keys(cache).length, | ||
ttlQueueEntries: ttlQueue.length, | ||
ttlExtendEntries: ttlExtend.size | ||
}; | ||
} | ||
}; | ||
module.exports = exports['default']; | ||
return { | ||
init: init, | ||
set: set, | ||
get: get, | ||
check: check, | ||
del: del, | ||
list: list, | ||
flush: flush, | ||
__ttlQueue: function __ttlQueue() { | ||
return ttlQueue; | ||
}, | ||
stats: function stats() { | ||
return { | ||
cacheEntries: Object.keys(cache).length, | ||
ttlQueueEntries: ttlQueue.length, | ||
ttlExtendEntries: ttlExtend.size | ||
}; | ||
} | ||
}; | ||
} |
31
index.js
@@ -5,3 +5,3 @@ var debug = require('debug')('dat') | ||
var https = require('https') | ||
var cache = require('./cache') | ||
var memoryCache = require('./cache') | ||
var maybe = require('call-me-maybe') | ||
@@ -15,3 +15,7 @@ var concat = require('concat-stream') | ||
module.exports = function () { | ||
module.exports = function (datDnsOpts) { | ||
datDnsOpts = datDnsOpts || {} | ||
var pCache = datDnsOpts.persistentCache | ||
var mCache = memoryCache() | ||
function resolveName (name, opts, cb) { | ||
@@ -24,3 +28,3 @@ if (typeof opts === 'function') { | ||
var ignoreCachedMiss = opts && opts.ignoreCachedMiss | ||
return maybe(cb, new Promise(function (resolve, reject) { | ||
var promise = new Promise(function (resolve, reject) { | ||
// parse the name as needed | ||
@@ -40,3 +44,3 @@ var nameParsed = url.parse(name) | ||
if (!ignoreCache) { | ||
const cachedKey = cache.get(name) | ||
const cachedKey = mCache.get(name) | ||
if (typeof cachedKey !== 'undefined') { | ||
@@ -53,3 +57,11 @@ if (cachedKey || (!cachedKey && !ignoreCachedMiss)) { | ||
requestRecord(name, resolve, reject) | ||
})) | ||
}) | ||
// read from persistent cache on failure | ||
if (pCache) { | ||
promise = promise.catch(function (err) { return pCache.read(name, err) }) | ||
} | ||
maybe(cb, promise) | ||
return promise | ||
} | ||
@@ -70,3 +82,3 @@ | ||
debug('DNS-over-HTTPS lookup failed for name:', name, err) | ||
cache.set(name, false, 60) // cache the miss for a minute | ||
mCache.set(name, false, 60) // cache the miss for a minute | ||
reject(new Error('DNS record not found')) | ||
@@ -109,4 +121,5 @@ }) | ||
if (ttl !== 0) { | ||
cache.set(name, key, ttl) | ||
mCache.set(name, key, ttl) | ||
} | ||
if (pCache) pCache.write(name, key, ttl) | ||
debug('DNS-over-HTTPS resolved', name, 'to', key) | ||
@@ -117,7 +130,7 @@ resolve(key) | ||
function listCache () { | ||
return cache.list() | ||
return mCache.list() | ||
} | ||
function flushCache () { | ||
cache.flush() | ||
mCache.flush() | ||
} | ||
@@ -124,0 +137,0 @@ |
{ | ||
"name": "dat-dns", | ||
"version": "1.3.2", | ||
"version": "2.0.0", | ||
"description": "Issue DNS lookups for Dat archives using HTTPS requests to the target host.", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -25,2 +25,17 @@ # dat-dns | ||
datDns.flushCache() | ||
// use a persistent fallback cache | ||
// (this is handy for persistent dns data when offline) | ||
var datDns = require('dat-dns')({ | ||
persistentCache: { | ||
read: async (name, err) => { | ||
// try lookup | ||
// if failed, you can throw the original error: | ||
throw err | ||
}, | ||
write: async (name, key, ttl) => { | ||
// write to your cache | ||
} | ||
} | ||
}) | ||
``` | ||
@@ -27,0 +42,0 @@ |
34
test.js
@@ -87,1 +87,35 @@ var tape = require('tape') | ||
}) | ||
tape('Persistent fallback cache', function (t) { | ||
t.plan(8) | ||
var persistentCache = { | ||
read: function (name, err) { | ||
if (name === 'foo') return '40a7f6b6147ae695bcbcff432f684c7bb5291ea339c28c1755896cdeb80bd2f9' | ||
throw err | ||
}, | ||
write: function (name, key, ttl) { | ||
t.deepEqual(name, 'pfrazee.hashbase.io') | ||
t.ok(/[0-9a-f]{64}/.test(key)) | ||
} | ||
} | ||
var datDns = require('./index')({persistentCache}) | ||
datDns.resolveName('pfrazee.hashbase.io', function (err, key) { | ||
t.error(err) | ||
t.ok(/[0-9a-f]{64}/.test(key)) | ||
datDns.resolveName('foo', function (err, key) { | ||
t.error(err) | ||
t.deepEqual(key, '40a7f6b6147ae695bcbcff432f684c7bb5291ea339c28c1755896cdeb80bd2f9') | ||
datDns.resolveName('bar', function (err, key) { | ||
t.ok(err) | ||
t.notOk(key) | ||
t.end() | ||
}) | ||
}) | ||
}) | ||
}) |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
13145
333
66