Repository navigation
perf(daemon): refresh before each request from native file watcher events - #217
Open
sergej-koscejev wants to merge 5 commits into
Open
sergej-koscejev wants to merge 5 commits into
sergej-koscejev wants to merge 5 commits into
Conversation
…watcher # Conflicts: # docs/test-running-design.md
github-merge-queue
Bot
removed this pull request from the merge queue due to a conflict with the base branch
Nov 10, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #188
Before each request, the daemon now refreshes project and module folders from the native file watcher (
fsnotifier) events. It walks the folders only when it cannot trust the watcher.What it adds:
daemon-mps-plugin:HeadlessNativeFileWatcher, a secondpluggableFileWatcherwithisDisabled()limited toidea.filewatcher.disabled. It counts watch-root changes andfsnotifierstarts (myStartAttemptCount, via reflection). After aFile Watcher Messagesnotification (inotify limit, gave up, not executable), it reports itself as untrusted.FileWatcherExecutable: before MPS starts, the daemon copiesbin/<os>/fsnotifierinto<workspace>/fsnotifier/, sets the executable bit, and setsidea.filewatcher.executable.path. For Linux on aarch64 it usesbin/linux-aarch64. With no binary for the platform, it setsidea.filewatcher.disabled=true.MOPS_DAEMON_JAVA_OPTIONS=-Didea.filewatcher.disabled=trueturns the watcher off.FileWatcherFence: the fence from the issue. It hooksFileWatcher.myTestNotifierand watches its own root withaddRootToWatch.ProjectRequestGate: only readers queued before a refresh started share that refresh. Before this change, a reader that arrived during a refresh shared it and could miss a change made just before the reader arrived. The fence would not close that gap.Decisions (the issue left these open):
fsnotifier: the daemon copies it, not the CLI launcher. The daemon owns its workspace, and daemon tests (SharedMpsEnvironment) get the same watcher this way. The alternative is the launcher passing-D…executable.path.<config>/pluginsbeing watched by chance.Not done: making the class path
snapshot()event-driven (#189).Evidence
Fence test (
FileWatcherRefreshSemanticsTest): 20 times, rename a node in a model file, then refresh right away, then read the node. The test runs once for a project model and once for a library model outside the project folder. On macOS and on Linux x86-64 it also asserts that the refresh used watcher events.return true, both tests fail: the refresh misses the edit.Watcher off:
LibraryModelRefreshIntegrationTestruns the existing scenario once with the watcher and once with-Didea.filewatcher.disabled=truethrough the installed CLI. The second run checks that edits are visible, that the log saysa full walk because the file watcher is not operational, and that no refresh used watcher events. Both pass on 2026.1.1.Wider runs: the whole daemon suite passes on 2024.1.6 and 2025.1.4 with the watcher on. One
TestReportStoreTestfailure on 2025.1.4 was aNoClassDefFoundErrorfrom a jar I rebuilt during the run; it passed when I ran it again.ProjectRequestGateTesthas a new case: a reader that arrives during a refresh waits for its own refresh.Per-request cost: a copy of MPS-extensions with MPS 2024.1.6 (260 modules, 51,757 files, built), macOS arm64. The machine was busy with other builds, so wall times are noisy.
main/ watcher offmops list --depth 0, wall time, 25 runs, medianmain)main)mops daemon pingtakes 350–500 ms of CLI time and does not refresh. The first refresh walks every folder (261 ms) and loads the files the VFS has stored.Merge Danger
Blast Radius: daemon-wide
Every daemon now starts a
fsnotifierprocess. Whether a request sees external changes now depends on the fence and the trust checks. If a check is wrong, a request misses an external edit and nothing reports it. The test that asserts watcher use runs only on macOS and Linux x86-64. Not exercised at runtime:fsnotifierreports another case, the fence times out (2 s) and the refresh walks the folders.The new gate rule can split a reader batch into more refreshes when readers arrive while a refresh is running.