@multiformats/dns
Version:
Resolve DNS queries with browser fallback
74 lines • 2.27 kB
JavaScript
import hashlru from 'hashlru';
import { RecordType } from '../index.js';
import { DEFAULT_TTL, toDNSResponse } from './to-dns-response.js';
/**
* Time Aware Least Recent Used Cache
*
* @see https://arxiv.org/pdf/1801.00390
*/
class CachedAnswers {
lru;
constructor(maxSize) {
this.lru = hashlru(maxSize);
}
get(fqdn, types) {
let foundAllAnswers = true;
const answers = [];
for (const type of types) {
const cached = this.getAnswers(fqdn, type);
if (cached.length === 0) {
foundAllAnswers = false;
break;
}
answers.push(...cached);
}
if (foundAllAnswers) {
return toDNSResponse({ answers });
}
}
getAnswers(domain, type) {
const key = `${domain.toLowerCase()}-${type}`;
const answers = this.lru.get(key);
if (answers != null) {
const cachedAnswers = answers
.filter((entry) => {
return entry.expires > Date.now();
})
.map(({ expires, value }) => ({
...value,
TTL: Math.round((expires - Date.now()) / 1000),
type: RecordType[value.type]
}));
if (cachedAnswers.length === 0) {
this.lru.remove(key);
}
// @ts-expect-error hashlru stringifies stored types which turns enums
// into strings, we convert back into enums above but tsc doesn't know
return cachedAnswers;
}
return [];
}
add(domain, answer) {
const key = `${domain.toLowerCase()}-${answer.type}`;
const answers = this.lru.get(key) ?? [];
answers.push({
expires: Date.now() + ((answer.TTL ?? DEFAULT_TTL) * 1000),
value: answer
});
this.lru.set(key, answers);
}
remove(domain, type) {
const key = `${domain.toLowerCase()}-${type}`;
this.lru.remove(key);
}
clear() {
this.lru.clear();
}
}
/**
* Avoid sending multiple queries for the same hostname by caching results
*/
export function cache(size) {
return new CachedAnswers(size);
}
//# sourceMappingURL=cache.js.map