-
released this
2026-06-16 19:14:33 +02:00 | 0 commits to master since this releasev2.0.0 — Two containers from one repo, standalone person updater & performance
⚠️ Breaking change: the repo now builds two containers instead of one. The deployment layout and environment variables have changed — see "Migration" below.
💥 Breaking / Architecture
- One repo, two images:
manga-mover-and-metadata-collector(Suwayomi → Kavita mover) andkavita-lightnovel-metadata-fetcher(LN metadata) now share the codebase. Common modules live insrc/, container-specific ones insrc/manga/andsrc/ln/. - Separate entry points
main_manga.py/main_ln.pyinstead ofmain.py. One Dockerfile (--build-arg APP=manga|ln), and a single build and release workflow for both images. - One shared
docker-compose.prod.ymlwith both services (container name = image name, separate/configvolumes and ports 8080 / 8081).
✨ New features
Standalone, global person updater
- No longer runs after every move (which ate ~50 % of move time); it now runs on its own cron schedule together with the volume/cover updater.
- Id-based instead of series-centric: walks every Kavita person, reads the tracker id from the name (
Rem (MAL 118737)), looks it up on MAL/AniList by id, and writes back the image, description and the id into the person record (when still empty). Persons without an id are skipped; conflicts are reported instead of overwritten. - Format-independent: a single run covers both manga and light novels. Triggerable by cron and via the Sync persons button in both web UIs.
Character disambiguation
- Character names now carry the tracker character id (
Name (MAL 12345)/(AL 12345)) so same-named characters stay separate, while the same character shares one Kavita person record across your manga and LN libraries. Authors/staff get no suffix.
Performance stats
- Per-step timing for the move, volume/cover updater and person updater — each with its own JSON file and web page (
/perf,/perf/volume,/perf/person). The person updater records the trigger source (web/ln/cron). Progress is saved after every series (crash-safe, observable live).
Cover cache
- Each cover is downloaded only once, no matter how many chapters share it. Optionally persistent (
COVER_CACHE_PATH) or temporary.
🚀 Performance optimizations
_determine_volume()is now resolved once per chapter instead of three times (memoization).- The MangaDex title search (
find_manga_id) is cached per series instead of per chapter. - Volume cover resolution (
/images+/works) now caches empty results too → no re-pagination per chapter. - The parent-series fetch (SeriesGroup) is cached per series.
🐛 Fixes
LocalizedSeriesnow uses the correct romanized title for the original language (manga → ja-Latn, manhwa → ko-Latn, manhua → zh-Latn).matches.json: case-insensitive keys +folderTitle(no more duplicates from capitalization differences).- Volume covers now come from the
/imagesendpoint with a/worksfallback.
🔧 Configuration
- Default updater cron:
0 10 * * 0(Sundays 10:00, local time — setTZ!). - New variables:
VOLUME_PERF_PATH,PERSON_PERF_PATH,LN_UPDATER_ENABLED.UPDATER_INTERVALis gone (onlyUPDATER_SCHEDULEnow).
📋 Migrating from 1.x
- Adopt the new
docker-compose.prod.yml+.env.example(two services). - Add to
.env:HOST_MANGA_CONFIG_PATH,HOST_LN_CONFIG_PATH,LN_LIBRARY_IDS,LN_WEB_PORT,TZ. - Person sync now runs on cron — the first run links existing characters via the id in their name.
🤖 Generated with Claude Code
What's Changed
- Performance and Person Updater Improvements in #7
Contributors
New Contributors
- @johannesbot made their first contribution in #7
Full Changelog: v1.1.0...v2.0.0
Downloads
- One repo, two images: