fix: address code review findings

- Honor ignore_singles/ignore_compilations at scanner read time so toggles
  take effect immediately on the dashboard, artist page, and digest instead
  of waiting for the MusicBrainz cache to expire and prune rows.
- Run notifier notify synchronously in the scheduler loop to avoid overlapping
  read-send-mark runs double-sending the digest.
- Show artist name (with ID fallback) on the archive page instead of raw IDs.
- Select last_synced in GetAllArtistSettings for contract consistency.
- Fix stale startPeriodicSync comment and remove redundant error var.
- Remove dead ignored-branch from the artist template (never rendered).
- Add tests: CSRF sameOrigin, ArtistCacheFresh, secondary_types round-trip,
  and scanner type-toggle filtering.
- Update Specification.md schema/config to reflect mbid, last_synced,
  secondary_types, sync.interval, and server.public_url.
This commit is contained in:
2026-07-20 06:18:21 +03:00
parent f5b0034b4d
commit a8aa445d94
13 changed files with 402 additions and 31 deletions

View File

@@ -75,21 +75,24 @@ NaviWatcher взаимодействует с Navidrome через **Subsonic AP
### Таблица `artist_settings`
Хранит параметры мониторинга для каждого артиста из Navidrome.
* `id`: string (MBID или имя)
* `id`: string (Navidrome artist ID — Primary Key)
* `name`: string
* `mbid`: string (MusicBrainz Artist ID; разрешается лениво при первой синхронизации и кэшируется; миграция `008_add_mbid_to_artist_settings`). `NULL` до первого разрешения.
* `ignore_singles`: boolean (default: false)
* `ignore_compilations`: boolean (default: false)
* `monitored`: boolean (default: true)
* `last_synced`: datetime — время последней синхронизации дискографии; сигнал свежести кэша, чтобы пустые дискографии соблюдали TTL (миграция `009_add_last_synced_to_artist_settings`). `NULL` — ещё не синхронизировался.
### Таблица `external_releases`
Кэш релизов, найденных во внешнем мире.
* `rgid`: string (MusicBrainz Release Group ID) — Primary Key.
* `artist_id`: string (FK)
* `title`: string
* `type`: string (album/single/ep)
* `type`: string (album/single/ep/compilation)
* `release_date`: string
* `is_ignored`: boolean (флаг скрытия из списка новинок)
* `cached_at`: datetime — время последней синхронизации/кэширования из MusicBrainz; используется для проверки TTL кэша (см. миграцию `005_add_cached_at_to_external_releases`). Значение `NULL` означает отсутствие актуального кэша.
* `secondary_types`: text — вторичные типы Release Group (Single/EP/Compilation и т.д.), через запятую; используются для фильтрации по типам наряду с первичным `type` (миграция `006_add_secondary_types_to_external_releases`).
### Таблица `local_albums`
Локальные альбомы, синхронизированные из Navidrome через Subsonic API.
@@ -128,6 +131,9 @@ server:
# Basic Auth для доступа к веб-интерфейсу
username: "admin"
password: "password123"
# Внешний адрес веб-интерфейса для ссылок в Telegram-дайджестах.
# Если пусто, используется host:port (кроме 0.0.0.0 — тогда ссылка не формируется).
public_url: "https://naviwatcher.example.com"
navidrome:
url: "http://localhost:4533"
@@ -147,6 +153,10 @@ telegram:
scanner:
fuzzy_threshold: 0.85
# Периодический цикл sync+scan (длительность Go, напр. "6h", "30m"); по умолчанию 6h
sync:
interval: 6h
```