Skip to content

Prevent stale 404s for files written by another realm-server instance - #5923

Draft
jurgenwerk wants to merge 2 commits into
mainfrom
cs-12032-peer-readdir-on-file-change
Draft

Prevent stale 404s for files written by another realm-server instance#5923
jurgenwerk wants to merge 2 commits into
mainfrom
cs-12032-peer-readdir-on-file-change

Conversation

@jurgenwerk

@jurgenwerk jurgenwerk commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

Prevent a realm-server task from returning 404 for a file another task just wrote.

Staging runs two tasks on one shared EFS volume. A task that looked up a path before the file existed keeps trusting that "not there" answer for up to a minute (measured: 50 s), because the kernel caches it. The AI assistant then sees its own new files as missing and re-creates them.

Fix: every write already sends NOTIFY realm_file_changes to the other task. The receiving task now also lists the directories leading to the path, which makes the kernel re-read them and drop the stale entry. On staging a directory listing made the 404s stop within 0.2 s. Listings are coalesced per directory, run asynchronously, and are covered by unit tests. Verify after deploy with the probe script on the ticket.

🤖 Generated with Claude Code

On a multi-instance realm-server sharing one EFS volume, a peer that had
looked up a path before it existed keeps answering 404 for it until the
kernel's directory attribute cache expires (~50s measured on staging).
Re-listing the parent directory when the write notification arrives makes
the kernel re-read the directory and drop the stale negative entry.

CS-12032

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

Host Test Results

    1 files  ±0      1 suites  ±0   2h 13m 7s ⏱️ - 1m 21s
4 591 tests ±0  4 577 ✅ ±0  14 💤 ±0  0 ❌ ±0 
4 610 runs  ±0  4 596 ✅ ±0  14 💤 ±0  0 ❌ ±0 

Results for commit 65b7292. ± Comparison against earlier commit bdd13a8.

Realm Server Test Results

    1 files  ±0      1 suites  ±0   18m 43s ⏱️ + 3m 20s
2 356 tests +4  2 356 ✅ +4  0 💤 ±0  0 ❌ ±0 
2 439 runs  +4  2 439 ✅ +4  0 💤 ±0  0 ❌ ±0 

Results for commit 65b7292. ± Comparison against earlier commit bdd13a8.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds cross-instance NFS directory-cache refreshes so peer realm servers can see newly written files promptly.

Changes:

  • Adds Realm.refreshDirectoryView().
  • Refreshes directories after per-path notifications.
  • Tests dispatch, wildcard exclusion, and failure handling.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

File Description
packages/runtime-common/realm.ts Adds directory refresh logic.
packages/realm-server/lib/realm-file-changes-listener.ts Triggers refreshes from notifications.
packages/realm-server/tests/realm-file-changes-listener-test.ts Tests listener behavior.

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread packages/runtime-common/realm.ts Outdated
async refreshDirectoryView(path: LocalPath): Promise<void> {
let separator = path.lastIndexOf('/');
let directory = separator === -1 ? '' : path.slice(0, separator);
for await (let _entry of this.#adapter.readdir(directory)) {

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.

[Claude Code 🤖] (Written by Claude on Matic's behalf.) Fixed: the refresh now lists every ancestor from the realm root down to the immediate parent (ancestorDirectories), so a parent directory the peer had cached as absent is refreshed before its children are looked up. Covered by the new directory-view-refresher-test.ts.

Comment on lines +108 to +110
// Fire-and-forget: the NOTIFY handler stays synchronous, and a failed
// directory listing only means the kernel cache expires on its own.
realm.refreshDirectoryView(parsed.path).catch((err: unknown) => {

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.

[Claude Code 🤖] (Written by Claude on Matic's behalf.) Fixed both parts: NodeAdapter.readdir now uses fs.promises-style readdir (the sync helper it used is removed), and the refresh logic moved into DirectoryViewRefresher, which coalesces per directory — while a listing is in flight, later requests share it and at most one follow-up is queued behind it. A batch write into one directory therefore costs a bounded number of listings instead of one per file; the test asserts listings never overlap and that five concurrent refreshes produce fewer listings than refreshes.

Comment thread packages/realm-server/tests/realm-file-changes-listener-test.ts Outdated
…ronously

Address review: a peer that cached a parent directory as absent needs the
ancestors re-listed too; batch writes emit one notification per file, so
listings of one directory are coalesced (one in flight, one queued);
NodeAdapter.readdir now uses the async fs API so the refresh and the request
path do not block the event loop on a network filesystem.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@jurgenwerk jurgenwerk changed the title Refresh a peer realm-server's directory view when another instance writes a file Prevent stale 404s for files written by another realm-server instance Aug 28, 2026
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.

2 participants