Commit Graph
368 Commits
Author SHA1 Message Date
yonlu 3bf66ed125 perf(08-01): add queueMicrotask coalescing to library store and debounce search input
- Library store notify() coalesces multiple calls per microtask tick into one subscriber notification
- Search input debounces store propagation by 150ms while keeping instant visual feedback
- Empty search input clears immediately for responsive UX
2026-03-04 23:14:16 -05:00
yonlu 08793bf60d docs(08-frontend-performance-ux): create phase plan 2026-03-04 21:34:48 -05:00
yonlu 568a9aa090 docs(08): capture phase context 2026-03-04 21:26:58 -05:00
yonlu fbaa72da8f docs(phase-07): complete phase execution 2026-03-04 21:04:13 -05:00
yonlu 6f79c77b58 docs(07-01): complete queue persistence optimization plan
- SUMMARY.md with incremental persistence + Phase 2 dedup details
- STATE.md updated: Phase 7 complete (2/2 plans), decisions recorded
- ROADMAP.md updated: Phase 7 marked complete
- REQUIREMENTS.md: PERF-01, PERF-02 marked complete
2026-03-04 21:00:31 -05:00
yonlu ced58fe6a9 perf(07-01): eliminate redundant lookups in SetQueue Phase 2
- Add phase1Meta parameter to resolveRemainingTracks
- Filter out already-resolved paths before lookupTrackMetaBatch call
- Merge Phase 1 results into Phase 2 lookup map
- Pass batchMeta from SetQueue call site to resolveRemainingTracks
- For 1000-track queue with Phase 1 resolving 50, Phase 2 now queries 950 instead of 1000
2026-03-04 20:58:22 -05:00
yonlu cdd17db275 perf(07-01): add incremental persistence helpers for queue mutations
- Add persistAddTrack/persistAddTracks for O(1) append operations
- Add persistInsertTracks with variable-N position shift for insert-at operations
- Add persistRemoveTrack with single DELETE + position shift
- Wire AddTrack/AddTracks to use incremental INSERT (no full table rewrite)
- Wire InsertNext/InsertNextTracks/InsertTracksAt to use position shift + INSERT
- Wire RemoveTrack to use single DELETE + shift (no full table rewrite)
- RemoveTracks keeps full persistTracks rewrite (bulk operation per design)
- Preserve shuffle order regeneration in all mutation paths
2026-03-04 20:57:47 -05:00
yonlu cd98ad6dc8 perf(07-02): defer eagerFetch to after DOM ready for instant app shell
- Remove eagerFetch() call from LibraryStore constructor
- Add deferEagerFetch() that waits for DOMContentLoaded event
- App shell renders before backend data roundtrips begin
- All 4 data types (tracks, albums, artists, genres) still loaded eagerly
- invalidate() still calls eagerFetch() directly for post-scan refresh
2026-03-04 20:54:38 -05:00
yonlu 9f381e2a03 docs(07): create phase plan 2026-03-04 20:49:38 -05:00
yonlu 2ffcd6ea0e docs(07): capture phase context 2026-03-04 20:41:39 -05:00
yonlu c9626f4c9f docs(phase-06): complete phase execution 2026-03-04 19:38:35 -05:00
yonlu 0bd968ca19 docs(06-03): complete lookupChunk migration & SAFETY comments plan
- SUMMARY.md with execution results and self-check
- STATE.md updated: Phase 6 complete (3/3 plans), decisions recorded
- ROADMAP.md updated: Phase 6 marked Complete
- REQUIREMENTS.md: QUAL-03 and QUAL-04 marked complete
2026-03-04 19:36:00 -05:00
yonlu 7dfe003e63 docs(06-03): add SAFETY comments to all 12 hand-crafted SQL statements
- 7 SAFETY comments in search.go (FTS5 MATCH/INSERT/DELETE operations)
- 3 SAFETY comments in library.go (FTS5 INSERT/DELETE in commitNewAudioFile, updateAudioFileMetadata)
- 1 SAFETY comment in rescan.go (FTS5 DELETE in clearAllLibraryData)
- 1 SAFETY comment in persistence.go (variable-count multi-row INSERT)
- Cross-references link library.go/rescan.go back to search.go
- Two-part format: why sqlc can't handle it + what makes it safe
2026-03-04 19:33:55 -05:00
yonlu 2221a68459 feat(06-03): migrate lookupChunk to sqlc-generated LookupTrackMetaByPaths query
- Add LookupTrackMetaByPaths sqlc query using track_metadata VIEW with sqlc.slice()
- Replace hand-crafted fmt.Sprintf IN clause in lookupChunk with sqlc-generated call
- Preserve lookupTrackMetaBatch chunking at maxSQLiteVars (900)
- All queue tests pass with -race
2026-03-04 19:31:52 -05:00
yonlu 30579e950e docs(06-02): complete event codegen plan
- SUMMARY.md with codegen tool details and verification results
- STATE.md updated with position, decisions, session context
- ROADMAP.md progress: Phase 6 at 2/3 plans
- REQUIREMENTS.md: QUAL-02 marked complete
2026-03-04 19:25:57 -05:00
yonlu 48d1416e43 docs(06-01): complete track_metadata VIEW consolidation plan
- SUMMARY.md: 2 tasks, 4 files, 2min duration
- STATE.md: advance to Phase 6 plan 1/3
- ROADMAP.md: update progress for phases 3-6
- REQUIREMENTS.md: mark QUAL-01 complete
2026-03-04 19:25:53 -05:00
yonlu 9159b409dc refactor(06-01): consolidate search queries to use track_metadata VIEW
- SearchFTS uses JOIN track_metadata instead of 5-table inline JOIN
- SearchFTSByFilename uses JOIN track_metadata instead of 5-table inline JOIN
- SearchFTSTracks uses JOIN track_metadata instead of 6-table inline JOIN
- RebuildSearchIndex selects from track_metadata instead of inline JOIN
- All 15 database tests pass with -race
2026-03-04 19:23:11 -05:00
yonlu 3e9edd05e8 feat(06-02): create Go→TypeScript event constant codegen tool
- Add backend/events/cmd/genevents/main.go using go/ast for deterministic output
- Add //go:generate directive to backend/events/events.go
- Generate frontend/src/events.ts with all 21 constants including LibraryConfigChanged
- Atomic file writes via temp file + rename
- Comment groups preserved with trailing period stripping
2026-03-04 19:22:11 -05:00
yonlu 9c7e5a9634 feat(06-01): create track_metadata VIEW schema and migration 4
- Add track_metadata_view.sql for sqlc VIEW awareness
- Add migration4TrackMetadataView for existing databases
- sqlc generate produces TrackMetadatum model from VIEW
- migration2 inline JOIN preserved (runs before VIEW exists)
2026-03-04 19:21:58 -05:00
yonlu e8cca7c942 docs(06): create phase plan — 3 plans for SQL consolidation, event codegen, and SAFETY comments 2026-03-04 19:17:06 -05:00
yonlu 99484abf9e docs(phase-6): research SQL consolidation & code quality domain 2026-03-04 18:59:34 -05:00
yonlu a43257501a docs(06): capture phase context 2026-03-04 18:51:01 -05:00
yonlu 9298b4aead docs(phase-05): complete phase execution 2026-03-04 16:49:09 -05:00
yonlu 7804752d45 docs(05-01): complete FTS5 search tests plan
- SUMMARY.md: 15 tests, 9min duration, 2 deviations documented
- STATE.md: Phase 5 fully complete, 84 total tests
- REQUIREMENTS.md: TEST-03 marked complete
2026-03-04 16:45:25 -05:00
yonlu dd34569ac0 test(05-01): add FTS5 search tests for database package
- seedSearchData helper creates full entity graph (7 tracks, 4 artists, 7 albums)
- Pure helper tests: tokeniseForFTS, buildFTSQuery, stripExtForSearch
- FTS5 search tests: basic term, empty query, special characters (AC/DC),
  multi-word, diacritics (Beyonce→Beyoncé), ranking, filename search
- SearchFTSTracks verifies all 16 columns populated
- Index ops: insert, delete (documents contentless FTS5 limitation),
  rebuild, clear (documents contentless limitation)
- Migration test: user_version >= 3, UNIQUE index enforcement
- 15 tests, all passing with -race
2026-03-04 16:43:06 -05:00
yonlu efddad66df docs(05-02): complete library scan tests plan
- SUMMARY.md with 13 tests across entity cache, pure helpers, orphan cleanup
- STATE.md updated: Phase 5 in progress, decisions, metrics
- ROADMAP.md updated: plan progress for Phase 5
- REQUIREMENTS.md updated: TEST-06 marked complete
2026-03-04 16:40:26 -05:00
yonlu fa6c378e25 test(05-02): add entity cache and orphan cleanup tests with DB backing
- TestCachedUpsertArtistCredit: cache hit returns same ID on second call
- TestCachedLinkArtist: skips duplicate INSERT via linkedCredits cache
- TestCachedLinkArtist_MultiCredit: same artist linked to different credits
- TestCachedUpsertGenre: genre cache returns same ID on repeated calls
- TestResolveReleaseGroup: creates release group, updates cover art on cache hit
- TestResolveReleaseGroup_CacheHit: pre-populated cache returns cached ID
- TestOrphanDeletion: DeleteAudioFile removes row, documents contentless FTS5 limitation
- TestEntityCache_EmptyFields: empty artist name, empty album, AlbumArtist reuse
2026-03-04 16:37:48 -05:00
yonlu 6f96a9411f test(05-02): add pure helper tests for scan utility functions
- TestGetRecordingName: title present, fallback to filename sans extension
- TestToNullInt64: zero as null, positive/negative as valid
- TestToNullString: empty as null, non-empty as valid
- TestSplitGenres: empty/single/multiple genre splitting on || delimiter
- TestMapTrackRow: all 16 columns including string TrackLength, NullInt64 fields
2026-03-04 16:35:00 -05:00
yonlu 455e3f8e13 docs(05): create phase plan for database and library tests 2026-03-04 15:06:06 -05:00
yonlu 963a5b594b docs(05): capture phase context 2026-03-04 14:38:45 -05:00
yonlu 8a97e522cc docs(phase-04): complete phase execution 2026-03-03 17:08:07 -05:00
yonlu 7703297ebf docs(04-02): complete config and player tests plan
- SUMMARY: 27 test cases across 6 packages, all passing with -race
- STATE: Phase 4 complete, 14/26 requirements delivered
- ROADMAP: Phase 04 marked complete
- REQUIREMENTS: TEST-04, TEST-05 marked complete
2026-03-03 17:04:26 -05:00
yonlu 5513d47a4a docs(04-01): complete queue unit tests plan 2026-03-03 17:02:32 -05:00
yonlu 294b629877 test(04-02): add player volume conversion and state mapping tests
- ToVolume/ToUserVolume at all boundary values (0, 25, 50, 75, 100)
- Out-of-range behavior for both conversion directions
- Full roundtrip characterization (0-100) with ±1 tolerance
- clampVolume at and beyond both boundaries
- stateToMediaControls for all states including unknown fallback
2026-03-03 17:01:40 -05:00
yonlu 77cc993fec test(04-01): add queue persistence round-trip tests
- Full roundtrip: SaveState/RestoreState preserves all fields (tracks, index, shuffle, repeat, shuffleOrder)
- Edge cases: empty queue, single track, no prior save state
- Track order: 10-track order preservation verification
- Overwrite: second SaveState replaces first
- 6 tests all passing with -race
2026-03-03 17:00:38 -05:00
yonlu f9b2ad95b7 test(04-02): add config and sub-config validation tests
- Theme: hex color regex + background shade enum validation
- Tracklist: column ID recognition + duplicate detection
- Favorites: icon style enum validation
- Library: directory existence + scan concurrency mode validation
- Config: load/save roundtrip, missing file handling, composed errors, defaults
2026-03-03 17:00:12 -05:00
yonlu 8d60dc05ce test(04-01): add queue core operations and navigation tests
- Queue operations: SetQueue, AddTrack, InsertTracksAt, MoveQueueTracks, RemoveTrack, Clear, ToggleShuffle, CycleRepeat
- Navigation: nextIndex/previousIndex in all repeat modes (off/all/one)
- Shuffle: generateShuffleOrder properties (no duplicates, current at [0]), shuffle navigation
- Mock TrackLoader and seedAudioFiles helper for DB-backed tests
- 23 tests total (14 core + 9 navigation) all passing with -race
2026-03-03 16:59:45 -05:00
yonlu 5400df257c docs(04): create phase plan for queue, config & player tests 2026-03-03 13:32:55 -05:00
yonlu 6e3c95ea61 docs(04): capture phase context 2026-03-03 09:50:16 -05:00
yonlu 062d429513 docs(phase-03): complete phase execution 2026-03-02 22:10:35 -05:00
yonlu c3a6e1161f docs(03-01): complete test infrastructure plan 2026-03-02 22:07:40 -05:00
yonlu bae9d70d23 feat(03-01): create NewTestDB helper for in-memory SQLite test databases
- Add testhelper.go with exported NewTestDB(t *testing.T) *DB
- Opens :memory: SQLite with same connection params as production
- Shares applyPRAGMAs, schema application loop, and runMigrations
- Registers t.Cleanup for automatic DB close
- No orphan cleanup, no functional options, no error return
2026-03-02 22:05:39 -05:00
yonlu d34881530a feat(03-01): extract shared applyPRAGMAs and add production PRAGMAs to NewDB
- Extract inline foreign_keys PRAGMA into shared applyPRAGMAs function
- Add synchronous=NORMAL, cache_size=-8000, mmap_size=67108864 PRAGMAs
- NewDB now calls applyPRAGMAs instead of inline PRAGMA exec
- applyPRAGMAs will be reused by NewTestDB for production-mirroring tests
2026-03-02 22:04:49 -05:00
yonlu abaf46ef1f docs(03): create phase plan 2026-03-02 21:21:52 -05:00
yonlu b47b64b625 docs(03): capture phase context 2026-03-02 21:06:50 -05:00
yonlu b17ce5d0e4 docs(phase-02): complete phase execution 2026-03-02 19:24:27 -05:00
yonlu 1c9356b6ad docs(02-02): complete artist credit error checking & scan warnings plan
- SUMMARY.md with all task commits and self-check
- STATE.md advanced to Phase 2 complete (2/2 plans)
- ROADMAP.md updated with Phase 2 complete status
- REQUIREMENTS.md marked CORR-08, CORR-09 complete
2026-03-02 19:21:06 -05:00
yonlu e6866ded9d feat(02-02): add ScanWarning type and reclassify scan errors as warnings
- Add ScanWarning struct with FilePath/Phase/Err to ScanMetrics
- Add mutex-protected addWarning method for concurrent use
- Reclassify walk, extraction, commit, orphan, variant, FTS failures as warnings
- Update commitBatch to return only fatal tx.Commit errors
- Update cachedLinkArtist to check errors via database.IsUniqueViolation
- Update handleConfigUpdate to capture and log scan warning count
2026-03-02 19:18:11 -05:00
yonlu 0d5b76cb0f docs(02-01): complete error handling & config fixes plan
- SUMMARY.md with all task commits and self-check
- STATE.md advanced to Phase 2 Plan 1/2 complete
- ROADMAP.md updated with Phase 2 progress
- REQUIREMENTS.md marked CORR-05, CORR-06, CORR-07 complete
2026-03-02 18:42:28 -05:00
yonlu 0860b2fd4b fix(02-01): log MPRIS callback errors instead of discarding them
- OnPause, OnPlayPause, OnStop, OnSeek now check errors and log at Warn level
- All four MPRIS closures use yj.logger.Warn for non-fatal error reporting
- No more silently discarded player.Pause() / player.Seek() errors
2026-03-02 18:39:54 -05:00