multi-library: per-library excluded_dirs
Adds a nullable comma-separated TEXT column to the libraries table.
Effective excludes for a walk = (env-var globals) ∪
(library.excluded_dirs). Empty / NULL = no library-specific
extras; the global env var still applies.
Migration (2026-05-01-110000_libraries_excluded_dirs)
ALTER TABLE libraries ADD COLUMN excluded_dirs TEXT. NULL on every
existing row — no behavior change on upgrade.
Library struct + helpers (libraries.rs)
- Library gains excluded_dirs: Vec<String>, parsed from the column
by parse_excluded_dirs_column (drops empties / whitespace,
matches the env-var parser).
- Library::effective_excluded_dirs(globals) returns the union.
- From<LibraryRow> hydrates the field on AppState construction so
/libraries surfaces it.
Watcher / walkers / memories
Every per-library walker now consults the effective set:
- process_new_files (file-watch ingest, RAW/EXIF/face)
- process_face_backlog (filter_excluded inherits)
- create_thumbnails (startup + new-file branch)
- update_media_counts (Prometheus gauge)
- cleanup_orphaned_playlists (per-library source-existence check)
- memories endpoint (PathExcluder)
Effective set is computed once per per-library iteration in the
watcher tick and threaded through; called functions retain their
flat &[String] signature (no per-library awareness needed inside
the walker primitives).
Use case: mount a parent directory while a sibling library covers
a child subtree, and exclude the child subtree from the parent so
the libraries don't double-walk / double-write image_exif. With
hash-keyed derived data (Branches B/C), the duplication-avoidance
is the only cost prevented — face / tag / insight sharing was
already correct via content_hash.
Tests: 228 pass (226 from previous + 2 new in libraries::tests:
parse_excluded_dirs_column edge cases,
effective_excluded_dirs_unions_global_and_per_library).
CLAUDE.md gains a "Per-library excludes" subsection of the
multi-library data model.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
-- Requires SQLite 3.35+ for ALTER TABLE DROP COLUMN.
|
||||
ALTER TABLE libraries DROP COLUMN excluded_dirs;
|
||||
14
migrations/2026-05-01-110000_libraries_excluded_dirs/up.sql
Normal file
14
migrations/2026-05-01-110000_libraries_excluded_dirs/up.sql
Normal file
@@ -0,0 +1,14 @@
|
||||
-- Per-library excluded directories.
|
||||
--
|
||||
-- The global EXCLUDED_DIRS env var is the right knob for excludes that
|
||||
-- every library shares (Synology @eaDir, .thumbnails, etc.). It's a
|
||||
-- poor fit for "exclude this subtree from THIS library only", which
|
||||
-- the natural use case for is mounting a parent directory while
|
||||
-- another library already covers a child subtree underneath.
|
||||
--
|
||||
-- This column is parsed comma-separated, same shape as the env var,
|
||||
-- and the watcher / memories / thumbnail walks each apply
|
||||
-- (env_globals ∪ library.excluded_dirs) when scanning the library.
|
||||
-- NULL = no extra excludes; the global env var still applies.
|
||||
|
||||
ALTER TABLE libraries ADD COLUMN excluded_dirs TEXT;
|
||||
Reference in New Issue
Block a user