# Filter Flow Documentation This document explains how the `ignore_singles` and `ignore_compilations` settings propagate through the NaviWatcher system. ## Overview The application implements a dual-path filtering approach to balance storage efficiency with real-time responsiveness to user preference changes: 1. **MusicBrainz Sync Path (Store-time filtering)**: - Applies filtering when caching release groups from the MusicBrainz API - Stores only filtered results in the `external_releases` table - Reduces database size by excluding unwanted release types upfront 2. **Scanner Path (Read-time filtering)**: - Applies filtering when retrieving cached data for comparison - Ensures changes to `ignore_singles`/`ignore_compilations` take effect immediately - Provides real-time responsiveness without waiting for cache expiry ## Data Flow 1. **Artist Settings Storage**: - Navidrome artist sync populates the `artist_settings` table - Stores `ignore_singles` and `ignore_compilations` boolean flags per artist 2. **MusicBrainz Synchronization**: - `SyncArtistDiscography` retrieves artist settings via `getArtistFilterOptions` - Applies filtering using `ApplyTypeToggles` before storing in `external_releases` - On cache hits, re-applies filter to ensure freshness of user preferences 3. **Scanning Process**: - `ScanArtist settings via `GetArtistSettings` - Creates `TypeFilter` with current `ignore_singles`/`ignore_compilations` values - Applies filter during `FindMissingReleases` via `filter.suppressed()` check - Uses same `musicbrainz.ApplyTypeToggles` logic for consistency ## Implementation Details ### Shared Filtering Logic Both paths use the same underlying filtering logic: - `musicbrainz.ApplyTypeToggles` for ExternalRelease filtering - `musicbrainz.ApplyTypeTogglesToReleaseGroups` for ReleaseGroup filtering - Consistent criteria: - IgnoreSingles: Type == "Single" OR Type == "EP" OR SecondaryTypes contains "Single"/"EP" - IgnoreCompilations: Type == "Compilation" OR SecondaryTypes contains "Compilation" ### TypeFilter Structure ```go type TypeFilter struct { IgnoreSingles bool IgnoreCompilations bool } ``` ### Filter Application - **MusicBrainz Path**: `ApplyTypeToggles(releases, FilterOptions{IgnoreSingles: s.IgnoreSingles, IgnoreCompilations: s.IgnoreCompilations})` - **Scanner Path**: `filter.suppressed(ext)` which internally uses the same logic ## Benefits 1. **Storage Efficiency**: Only desired release types are cached in the database 2. **Immediate Responsiveness**: User preference changes take effect in real-time 3. **Consistent Behavior**: Both code paths produce identical filtering results 4. **Cache Efficiency**: Existing cached data remains useful when preferences change ## Related Files - `internal/scanner/diff.go`: TypeFilter definition and suppressed() method - `internal/scanner/scan.go`: ScanArtist and ScanAll functions - `internal/musicbrainz/sync.go`: SyncArtistDiscography and getArtistFilterOptions - `internal/musicbrainz/filter.go`: ApplyTypeToggles and related filtering functions - `internal/database/artist_settings.go`: GetArtistSettings and GetAllArtistSettings