Adopts ListenBrainz-inspired patterns to speed up imports from ~24h to
under 30 minutes for 49k scrobbles.
Phase 1 - track_lookup cache table:
- New migration (000006) adds persistent entity lookup cache
- Maps normalized (artist, track, album) → (artist_id, album_id, track_id)
- SubmitListen fast path: cache hit skips 18 DB queries → 2 queries
- Cache populated after entity resolution, invalidated on merge/delete
- Benefits both live scrobbles and imports
Phase 2 - SaveListensBatch:
- New batch listen insert using pgx CopyFrom → temp table → INSERT ON CONFLICT
- Thousands of inserts per second vs one-at-a-time
Phase 3 - BulkSubmitter:
- Reusable import accelerator for all importers
- Pre-deduplicates scrobbles by (artist, track, album) in memory
- Worker pool (4 goroutines) for parallel entity creation on cache miss
- Batch listen insertion via SaveListensBatch
Phase 4 - Migrate importers:
- Maloja, Spotify, LastFM, ListenBrainz importers use BulkSubmitter
- Koito importer left as-is (already fast with pre-resolved IDs)
Phase 5 - Skip image lookups during import:
- GetArtistImage/GetAlbumImage calls fully skipped when SkipCacheImage=true
- Background tasks (FetchMissingArtistImages/FetchMissingAlbumImages) backfill
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* add dev branch container to workflow
* correctly set the default range of ActivityGrid
* fix: set name/short_name to koito (#61)
* fix dev container push workflow
* fix: race condition with using getComputedStyle primary color for dynamic activity grid darkening (#76)
* Fix race condition with using getComputedStyle primary color for dynamic activity grid darkening
Instead just use the color from the current theme directly. Tested works on initial load and theme changes.
Fixes https://github.com/gabehf/Koito/issues/75
* Rework theme provider to provide the actual Theme object throughtout the app, in addition to the name
Split name out of the Theme struct to simplify custom theme saving/reading
* fix: set first artist listed as primary by default (#81)
* feat: add server-side configuration with default theme (#90)
* docs: add example for usage of the main listenbrainz instance (#71)
* docs: add example for usage of the main listenbrainz instance
* Update scrobbler.md
---------
Co-authored-by: Gabe Farrell <90876006+gabehf@users.noreply.github.com>
* feat: add server-side cfg and default theme
* fix: repair custom theme
---------
Co-authored-by: m0d3rnX <jesper@posteo.de>
* docs: add default theme cfg option to docs
* feat: add ability to manually scrobble track (#91)
* feat: add button to manually scrobble from ui
* fix: ensure timestamp is in the past, log fix
* test: add integration test
* feat: add first listened to dates for media items (#92)
* fix: ensure error checks for ErrNoRows
* feat: add now playing endpoint and ui (#93)
* wip
* feat: add now playing
* fix: set default theme when config is not set
* feat: fetch images from subsonic server (#94)
* fix: useQuery instead of useEffect for now playing
* feat: custom artist separator regex (#95)
* Fix race condition with using getComputedStyle primary color for dynamic activity grid darkening
Instead just use the color from the current theme directly. Tested works on initial load and theme changes.
Fixes https://github.com/gabehf/Koito/issues/75
* Rework theme provider to provide the actual Theme object throughtout the app, in addition to the name
Split name out of the Theme struct to simplify custom theme saving/reading
* feat: add server-side configuration with default theme (#90)
* docs: add example for usage of the main listenbrainz instance (#71)
* docs: add example for usage of the main listenbrainz instance
* Update scrobbler.md
---------
Co-authored-by: Gabe Farrell <90876006+gabehf@users.noreply.github.com>
* feat: add server-side cfg and default theme
* fix: repair custom theme
---------
Co-authored-by: m0d3rnX <jesper@posteo.de>
* fix: rebase errors
---------
Co-authored-by: pet <128837728+againstpetra@users.noreply.github.com>
Co-authored-by: mlandry <mike.landry@gmail.com>
Co-authored-by: m0d3rnX <jesper@posteo.de>
* feat: single SOT for themes + basic custom support
* fix: adjust colors for yuu theme
* feat: Allow loading of environment variables from file (#20)
* feat: allow loading of environment variables from file
* Panic if a file for an environment variable cannot be read
* Use log.Fatalf + os.Exit instead of panic
* fix: remove supurfluous call to os.Exit()
---------
Co-authored-by: adaexec <nixos-git.s1pht@simplelogin.com>
Co-authored-by: Gabe Farrell <90876006+gabehf@users.noreply.github.com>
* chore: add pr test workflow
* chore: changelog
* feat: make all activity grids configurable
* fix: adjust activity grid style
* fix: make background gradient consistent size
* revert: remove year from activity grid opts
* style: adjust top item list min size to 200px
* feat: add support for custom themes
* fix: stabilized the order of top items
* chore: update changelog
* feat: native import & export
* fix: use correct request body for alias requests
* fix: clear input when closing edit modal
* chore: changelog
* docs: make endpoint clearer for some apps
* feat: add ui and handler for export
* fix: fix pr test workflow
---------
Co-authored-by: adaexec <78047743+adaexec@users.noreply.github.com>
Co-authored-by: adaexec <nixos-git.s1pht@simplelogin.com>