feat: Implement caching and rate limiting for API requests
This commit is contained in:
@@ -1,13 +1,18 @@
|
||||
import { readFile, writeFile, mkdir } from "node:fs/promises";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { parseWord, PARSER_VERSION } from "./parser.js";
|
||||
import { request } from "./source.js";
|
||||
import { request, MIN_REFRESH } from "./source.js";
|
||||
|
||||
const data = fileURLToPath(new URL("../.data/parsed/", import.meta.url));
|
||||
// When each document was last downloaded, and the downloads under way: a forced refresh
|
||||
// downloads a document at most once per MIN_REFRESH, and simultaneous ones share a download.
|
||||
const fetchedAt = new Map(),
|
||||
loading = new Map();
|
||||
|
||||
/** A parsed catalog document, from the disk cache while the file and parser are unchanged. */
|
||||
export async function scheduleFor(file, { refresh = false } = {}) {
|
||||
const cache = data + file.id + ".json";
|
||||
if (refresh && Date.now() - (fetchedAt.get(file.id) || 0) < MIN_REFRESH) refresh = false;
|
||||
if (!refresh)
|
||||
try {
|
||||
const cached = JSON.parse(await readFile(cache, "utf8"));
|
||||
@@ -17,7 +22,17 @@ export async function scheduleFor(file, { refresh = false } = {}) {
|
||||
)
|
||||
return cached;
|
||||
} catch {}
|
||||
if (!loading.has(file.id))
|
||||
loading.set(
|
||||
file.id,
|
||||
download(file, cache).finally(() => loading.delete(file.id)),
|
||||
);
|
||||
return loading.get(file.id);
|
||||
}
|
||||
|
||||
async function download(file, cache) {
|
||||
const buffer = await request(file.path);
|
||||
fetchedAt.set(file.id, Date.now());
|
||||
const parsed = await parseWord(buffer, {
|
||||
name: file.name,
|
||||
url: file.url,
|
||||
|
||||
Reference in New Issue
Block a user