Skip to content

Update the docs cache as a whole - #1350

Merged
clauderic merged 1 commit into
graph-rebuild-after-errorfrom
docs-cache-atomic-writes
Oct 20, 2026
Merged

clauderic merged 1 commit into
graph-rebuild-after-errorfrom
docs-cache-atomic-writes

Conversation

@clauderic

@clauderic clauderic commented Oct 20, 2026 •

Copy link
Copy Markdown
Member

Stacked on #1349. Review that one first; this PR's base moves down the stack as the PRs below it merge.

What are you adding in this PR?

The docs cache is now updated as a whole, as one folder swap, instead of one file at a time.

Updating it file by file had four problems:

  • setup wrote the new latest.json before the other files. If a later download failed, the cache had the new revision but a mix of old and new files, and no run fixed it until the next revision.
  • A file removed upstream stayed in the cache forever.
  • A run reading the cache while another wrote it could read a truncated file, since fs.writeFile truncates first.
  • download didn't check the response status, so an HTTP error page was cached as if it were the file.

Now:

  • setup reads the remote revision without writing it.
  • When the revision changed, replaceThemeLiquidDocs downloads every file into a new folder next to the cache, then swaps it in with two renames: the old folder out, the new one in.
  • So the cache is always one complete set. A failed update leaves it as it was, and the next run retries.
  • A download that isn't 2xx fails.

The swap isn't atomic: between the two renames there's no cache folder. A reader in that moment falls back to the bundled docs, as it already does when the cache is missing. Two runs that update at once each stage a complete folder, and the cache ends up as one of them. A rename that loses the race fails, and that run keeps its old docs.

downloadThemeLiquidDocs(dir) is unchanged, since the CLI and the build use it to download into a folder of their choice.

The manager's tests mock node:fs/promises. In the shared vitest project that mock leaked into the new downloader tests, so the manager's tests now run isolated, like the other files in isolatedTests.

What's next? Any followup issues?

None.

Tophatting

  • npx vitest run packages/theme-check-docs-updater. The downloader tests swap a real temporary folder: a complete download replaces it and drops a file that's gone upstream, and a failed one leaves it as it was. Both fail with the old file-by-file writes. The manager tests check that setup replaces the docs only when the revision changed.
  • End to end, with a throwaway HOME so your own cache is untouched: build the package, then call new ThemeLiquidDocsManager(console.error).tags() twice. The first run downloads into a staging folder and swaps it in, and the second reads the cache without downloading. Only the cache folder is left in $HOME/Library/Caches.

Before you deploy

  • I included a patch bump changeset
  • My feature is backward compatible

🤖 Generated with Claude Code

@clauderic
clauderic requested a review from a team as a code owner October 20, 2026 13:14
@clauderic clauderic mentioned this pull request Oct 20, 2026
2 tasks done
@clauderic
clauderic added this pull request to stack #1353 October 20, 2026 13:15
Updating the docs cache rewrote it one file at a time:
- setup wrote the new latest.json first. If a later download failed,
  the cache had the new revision but a mix of old and new files, and
  no run fixed it until the next revision.
- A file removed upstream stayed in the cache forever.
- A run reading the cache while another wrote it could read a
  truncated file.
- An HTTP error page was cached as if it were the file.

setup now reads the remote revision without writing it. When it
changed, replaceThemeLiquidDocs downloads every file into a new folder
and swaps it in with two renames. So the cache is always one complete
set, and a failed update leaves it as it was, to be retried on the
next run. A download that isn't 2xx now fails.

The manager's tests mock node:fs/promises, which leaked into the new
downloader tests in the shared vitest project, so they now run
isolated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@clauderic clauderic changed the title Write the docs cache atomically Update the docs cache as a whole Oct 20, 2026
@clauderic
clauderic force-pushed the docs-cache-atomic-writes branch from 252bb9d to fca4a62 Compare October 20, 2026 13:47
@clauderic
clauderic merged commit 20f8edf into main Oct 20, 2026
8 checks passed
@clauderic
clauderic deleted the docs-cache-atomic-writes branch October 20, 2026 16:28
@clauderic clauderic mentioned this pull request Oct 20, 2026
1 task done
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.

3 participants