Skip to content

fix(core/xref-db): skip caching empty xref results#5260

Open
marcoscaceres wants to merge 5 commits into
speced:mainfrom
marcoscaceres:fix/5256-xref-cache-poisoning
Open

fix(core/xref-db): skip caching empty xref results#5260
marcoscaceres wants to merge 5 commits into
speced:mainfrom
marcoscaceres:fix/5256-xref-cache-poisoning

Conversation

@marcoscaceres
Copy link
Copy Markdown
Contributor

Closes #5256

When the xref API returns no result for a query, `cacheXrefData()` stored an empty array in IDB. On subsequent loads, the cache hit prevented re-fetching, permanently suppressing results for terms that were temporarily missing from the API.

Skips caching queries with no results so they are re-fetched next time.

When the xref API returns no result for a query, `cacheXrefData()` was
storing an empty array in IDB. On subsequent loads, the cache hit
prevented re-fetching, permanently suppressing results for terms that
were temporarily missing from the API.

Skip caching queries with no results so they are re-fetched next time.

Closes speced#5256
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes core/xref-db’s IndexedDB caching behavior so that “no results” responses from the xref API don’t get cached and block future refetches, addressing #5256.

Changes:

  • Stop writing entries to IDB when a query’s xref result is empty ([]).
  • Ensure missing/empty results will be re-fetched on subsequent runs instead of being treated as a cache hit.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/core/xref-db.js
Comment thread src/core/xref-db.js
Address Copilot feedback: resolveXrefCache now uses a readwrite
transaction that deletes empty-result entries it encounters, recovering
from previously cached empty arrays.
Two tests using real IDB:
1. Queries with empty results are not cached (write path)
2. Pre-existing empty cache entries are deleted on read (migration)

Address Copilot feedback requesting test coverage.
@marcoscaceres
Copy link
Copy Markdown
Contributor Author

@copilot Can you confirm all your feedback has been addressed? Can you fix anything that was not addressed?

1 similar comment
@marcoscaceres
Copy link
Copy Markdown
Contributor Author

@copilot Can you confirm all your feedback has been addressed? Can you fix anything that was not addressed?

@marcoscaceres marcoscaceres marked this pull request as ready for review May 4, 2026 14:05
@marcoscaceres marcoscaceres requested a review from sidvishnoi May 4, 2026 14:05
Comment thread src/core/xref-db.js Outdated
Comment on lines +41 to +53
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;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe these changes aren't really needed, if we skip storing these in the first place. For existing cached entries, we'll eventually bust the entire cache, iirc.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. Simplified in f76c548: removed the read-side cleanup entirely. Now the only change vs main is the write-side skip (if (!result?.length) continue). Existing stale entries get cleared by the version-based cache bust.

Per sidvishnoi: "Maybe these changes aren't really needed, if we
skip storing these in the first place."

The write-side fix (skip storing empty results) prevents the problem.
Existing stale entries will be cleared by the version-based cache bust.
No need for a readwrite transaction on the read path.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug: xref-db caches empty array for missing results, preventing future resolution

3 participants