Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions src/core/xref-db.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,19 @@ export async function resolveXrefCache(queries) {
const requiredKeySet = new Set(queries.map(query => query.id));
try {
const cache = await getIdbCache();
let cursor = await cache.transaction(STORE_NAME).store.openCursor();
const tx = cache.transaction(STORE_NAME, "readwrite");
let cursor = await tx.store.openCursor();
while (cursor) {
if (requiredKeySet.has(cursor.key)) {
cachedData.set(cursor.key, cursor.value.result);
if (cursor.value.result?.length) {
cachedData.set(cursor.key, cursor.value.result);
} else {
cursor.delete();
}
}
cursor = await cursor.continue();
}
await tx.done;
} catch (err) {
console.error(err);
}
Expand Down Expand Up @@ -87,7 +93,8 @@ export async function cacheXrefData(queries, results) {
const cache = await getIdbCache();
const tx = cache.transaction(STORE_NAME, "readwrite");
for (const query of queries) {
const result = results.get(query.id) ?? [];
const result = results.get(query.id);
if (!result?.length) continue;
tx.objectStore(STORE_NAME).add({ query, result });
Comment thread
marcoscaceres marked this conversation as resolved.
Comment thread
marcoscaceres marked this conversation as resolved.
}
await tx.done;
Expand Down
71 changes: 70 additions & 1 deletion tests/spec/core/xref-spec.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
"use strict";

import {
cacheXrefData,
clearXrefData,
resolveXrefCache,
} from "../../../src/core/xref-db.js";
import {
errorFilters,
flushIframes,
makeDefaultBody,
makeRSDoc,
makeStandardOps,
} from "../SpecHelper.js";
import { clearXrefData } from "../../../src/core/xref-db.js";

describe("Core — xref", () => {
afterAll(flushIframes);
Expand Down Expand Up @@ -1118,3 +1122,68 @@ describe("Core — xref", () => {
);
});
});

describe("Core — xref-db caching", () => {
beforeEach(async () => {
await clearXrefData();
localStorage.setItem("XREF:LAST_VERSION_CHECK", Date.now().toString());
});

afterEach(async () => {
await clearXrefData();
});

it("does not cache queries with empty results", async () => {
const queries = [
{ id: "found-term", term: "found", types: ["dfn"] },
{ id: "missing-term", term: "missing", types: ["dfn"] },
];
const results = new Map();
results.set("found-term", [{ uri: "#found", shortname: "spec" }]);

await cacheXrefData(queries, results);
const cached = await resolveXrefCache(queries);

expect(cached.has("found-term")).toBeTrue();
expect(cached.has("missing-term")).toBeFalse();
});

it("cleans up pre-existing empty cache entries on read", async () => {
const queries = [{ id: "stale-term", term: "stale", types: ["dfn"] }];

const { promise: dbReady, resolve, reject } = Promise.withResolvers();
const req = indexedDB.open("xref", 2);
req.onsuccess = () => resolve(req.result);
req.onerror = () => reject(req.error);
const db = await dbReady;

const tx = db.transaction("xrefs", "readwrite");
tx.objectStore("xrefs").add({ query: queries[0], result: [] });
const { promise: txDone, resolve: txResolve } = Promise.withResolvers();
tx.oncomplete = txResolve;
await txDone;
db.close();

const cached = await resolveXrefCache(queries);
expect(cached.has("stale-term")).toBeFalse();

const {
promise: verifyDbReady,
resolve: resolveVerifyDb,
reject: rejectVerifyDb,
} = Promise.withResolvers();
const req2 = indexedDB.open("xref", 2);
req2.onsuccess = () => resolveVerifyDb(req2.result);
req2.onerror = () => rejectVerifyDb(req2.error);
const verifyDb = await verifyDbReady;

const verifyTx = verifyDb.transaction("xrefs", "readonly");
const getReq = verifyTx.objectStore("xrefs").get("stale-term");
const { promise: getReady, resolve: resolveGet } = Promise.withResolvers();
getReq.onsuccess = () => resolveGet(getReq.result);
const remaining = await getReady;
verifyDb.close();

expect(remaining).toBeUndefined();
});
});
Loading