A file that appears is never noticed: there is no filesystem watcher #96
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
No crate in the workspace depends on
notifyor anything like it. A library is read at startup and when something asks for a scan; a file dropped into a watched directory is invisible until one of those happens.Upstream watches every library path (
LibraryMonitor), debounces, and refreshes the affected part of the tree — which is why a file copied into a Jellyfin library appears within seconds without a scan. That is the behaviour an operator expects from an install, and the reason a 12-hour scheduled scan is a backstop upstream rather than the only mechanism.There is a route that stands in for it today —
POST /Library/Media/Updatedand the four beside it, which is how something outside the server reports that a file arrived — so an external watcher is already possible. That is not a substitute for the server doing it.Related but distinct: the periodic scan itself is missing (see the scheduler issue), and a whole-library pass currently costs 42 s at 20,000 films with nothing changed (#92). A watcher makes the incremental case cheap and is the reason upstream can afford to be slow on the whole-library one.
Where to start
The scan is
crates/jellyfin-app/src/scan/, andchanges.rsis the changedetection a watcher would feed;
crates/jellyfin-server/src/main.rs:282,532iswhere a pass is started today. A watcher is an adapter, so the port goes in
jellyfin-coreand the implementation at the edge —ARCHITECTURE.mddecideswhich crate, and the rule that
jellyfin-coretouches no filesystem is notnegotiable.
Upstream is
Emby.Server.Implementations/IO/LibraryMonitor.cs. Read threethings out of it rather than inventing them: the debounce (it waits before
acting, and a burst of events must not be a burst of scans), the paths it
ignores, and how it decides a file has finished being written — a file still
copying must not be probed half-written, which is the failure mode that makes a
naive watcher worse than none.
How to know it is done
without any request being made, and its row is the row a scan would have
written — compare against a scan of the same tree rather than eyeballing it.
duplicated.
depend on timing luck.
House rules
CLAUDE.mdis the short version and these are the parts that bite: tests rununder
cargo nextest; upstream's source is the checkout inupstream/at thepin (
v12.0-rc5,6d501ba4) and not the clone beside the repository;generated files are regenerated rather than edited; a comment says what the code
does, not how it got there; and
Dnreferences stay out of code and comments.ARCHITECTURE.mddecides which crate a thing goes in and which dependency edgesare illegal,
DECISIONS.mdsays why a rule exists.The reference pair is
cargo xtask reference up(andreference provision,which is idempotent); a run is
cargo run -p jellyfin-harness -- replay --upstream URL --ours URL --scenario FILE --out DIR,with
diff-dbfor the two databases.crates/jellyfin-harness/README.mdsayswhat a diff means and what an ignore entry has to carry — every entry needs a
reason and an expiry milestone, and an adds-only history is the smell the risk
table names.