novela/docs/TECHNICAL.md

5.7 KiB

Novela 2.0 - Technical Status (Develop)

Scope

Dit document beschrijft de actuele technische status van de develop codebase. Dit document is de primaire technische documentatie voor de huidige codebase.

Architecture

  • Stack: FastAPI, Jinja2 templates, plain JS, PostgreSQL 16, Docker.
  • Startup lifecycle (main.py):
    1. init_pool()
    2. run_migrations()
    3. start_backup_scheduler()
    4. routers mounten
  • Shutdown lifecycle:
    1. stop_backup_scheduler()
    2. close_pool()
  • Source-of-truth regel: bestand op schijf leidend, database als index/cache.

Router Status

routers/library.py

  • GET /library
  • GET /api/library
  • POST /library/rescan
  • POST /library/import (EPUB/PDF/CBR/CBZ)
  • DELETE /library/file/{filename}
  • GET /library/cover/{filename}
  • GET /library/cover-cached/{filename}
  • POST /library/cover/{filename} (EPUB)
  • POST /library/want-to-read/{filename}
  • POST /library/archive/{filename}
  • POST /library/new/mark-reviewed (bulk needs_review=false)
  • GET /home
  • GET /api/home
  • GET /stats
  • GET /api/stats
  • GET /library/list (compat)

GET /api/library draait standaard in fast-path (DB-only, geen full disk rescan). Voor geforceerde sync: GET /api/library?rescan=true of POST /library/rescan. include_file_info=true is optioneel voor bestandsgrootte/mtime verrijking.

/api/home levert:

  • continue_reading
  • shorts_unread
  • novels_unread
  • shorts_read
  • novels_read

/api/stats levert naast totals ook chart- en history-data voor stats.html:

  • reads_by_month, reads_by_dow, reads_by_hour
  • genre_counts, publisher_counts, fav_genre, fav_publisher
  • top_books, history

Home-secties filteren series uit met:

  • COALESCE(series, '') = ''
  • filename NOT LIKE '%/Series/%'

Read-secties op Home zijn gesorteerd op oudste eerst:

  • shorts_read: ORDER BY MAX(read_at) ASC
  • novels_read: ORDER BY MAX(read_at) ASC

routers/reader.py

  • Epub serving/chapters/images
  • Reader pagina + book detail
  • Metadata patch (PATCH /library/book/{filename})
  • Progress read/write/delete
  • Mark-as-read
  • PDF render endpoint
  • CBR/CBZ page endpoint
  • Genres endpoint

routers/editor.py

  • Editor pagina
  • Chapter get/save
  • Chapter add
  • Chapter delete

routers/grabber.py

  • Grabber pagina + convert/debug flows
  • SSE events
  • Credentials beheer voor scraper-sites
  • Credentials manager UI (/credentials-manager)

routers/backup.py

  • GET /backup
  • GET/POST/DELETE /api/backup/credentials
  • GET /api/backup/health
  • GET /api/backup/status
  • GET /api/backup/history
  • POST /api/backup/run

Backup & Security

  • Dropbox token encrypted-at-rest in credentials (site='dropbox').
  • Dropbox backup root encrypted opgeslagen in credentials (site='dropbox_backup_root').
  • Retentie (snapshots to keep) encrypted opgeslagen in credentials (site='dropbox_backup_retention').
  • Backup schedule (enabled + interval_hours) encrypted opgeslagen in credentials (site='dropbox_backup_schedule').
  • Encryptie via NOVELA_MASTER_KEY (Fernet).

Implementatie:

  • Versie-gebaseerde backups met deduplicatie:
    • bestandsobjecten in Dropbox: library_objects/{sha256_prefix}/{sha256}
    • snapshots in Dropbox: library_snapshots/snapshot-YYYYMMDD-HHMMSS.json
  • Elke run maakt een nieuwe snapshot (versie) en uploadt alleen ontbrekende objecten.
  • Retentie verwijdert oude snapshots boven de ingestelde limiet.
  • Orphan object-prune verwijdert objecten die niet meer door retained snapshots worden gerefereerd.
  • Lokale manifestcache (config/backup_manifest.json) versnelt changeddetectie.
  • Database backup via pg_dump naar Dropbox postgres/.
  • POST /api/backup/run start altijd als background task en geeft direct status terug.
  • Scheduler draait in achtergrond (start_backup_scheduler) en triggert op interval als backup aanstaat.
  • Concurrentierestrictie: slechts 1 backup tegelijk.
  • Bij container restart/crash worden stale running logs automatisch gemarkeerd als interrupted/error.

Environment

stack/novela.env bevat nu minimaal:

  • POSTGRES_DB
  • POSTGRES_USER
  • POSTGRES_PASSWORD
  • NOVELA_MASTER_KEY
  • CONFIG_DIR

Dropbox settings verlopen via webinterface op /backup.

UI Notes

  • Library import accepteert: EPUB/PDF/CBR/CBZ.
  • Home heeft dezelfde importmogelijkheden.
  • Home heeft zoekfunctionaliteit.
  • Home header/dropzone uitlijning gelijkgetrokken met Library (zoek rechtsboven, dropzone eronder).
  • New view ondersteunt Grid en List mode.
  • Bulk selectie + Remove from New werkt alleen in List mode.
  • List mode heeft kolomfilter (aan/uit) met kolommen:
    • Publisher
    • Author
    • Series
    • Volume
    • Title
    • Has cover
    • Updated
    • Genres
    • Sub-genres
    • Tags
    • Status
  • List mode ondersteunt multi-select met Shift+klik range-select op checkboxes.
  • Grid mode toont geen selectie-checkboxes of bulkacties.
  • Backup pagina ondersteunt:
    • handmatige run en dry-run
    • instellingen voor Dropbox root
    • retentie-aantal snapshots
    • geplande backup (aan/uit + interval in uren)
    • status + history overzicht

Known Conventions

  • Verwijderen boek: bestand verwijderen, lege mappen prunen, daarna DELETE FROM library (cascade op child-tabellen).
  • Cover strategie:
    • EPUB: cover uit bestand + cache
    • PDF/CBR: thumbnail via cover cache

Performance Notes

  • Library-load geoptimaliseerd voor grote datasets:
    • list_library_json() gebruikt pre-aggregatie voor reading_sessions.
    • has_cached_cover komt direct uit SQL join i.p.v. losse volledige cache-fetch.
  • Nieuwe migrations-indexen:
    • idx_library_sort_coalesce
    • idx_library_needs_review
    • idx_library_archived
    • idx_reading_sessions_filename_readat
    • idx_book_tags_filename_tag