Skip to content

Elasticsearch dual-write sync, bulk reindex, and reindex endpoint#232

Open
jakebromberg wants to merge 4 commits intofeature/elasticsearch-searchfrom
feature/elasticsearch-sync
Open

Elasticsearch dual-write sync, bulk reindex, and reindex endpoint#232
jakebromberg wants to merge 4 commits intofeature/elasticsearch-searchfrom
feature/elasticsearch-sync

Conversation

@jakebromberg
Copy link
Member

@jakebromberg jakebromberg commented Mar 11, 2026

Summary

  • Implement dual-write sync: insertAlbum, addToRotation, and killRotationInDB fire-and-forget index updates to ES
  • Add bulkIndexLibrary() for full reindex in batches of 500, with error counting for observability
  • Add POST /library/reindex endpoint (requires catalog: ['write'])
  • Add removeLibraryDocument() with 404 tolerance
  • Add label_id to ES index mapping, sync serialization, and hit deserialization (from main's labels feature)
  • Fix Drizzle column name mismatch by using raw SQL for view queries
  • Rename album_title query param to album_name to match API spec

Closes #252

Test plan

  • 15 unit tests for elasticsearch.sync.ts (indexing, removal, bulk, chunking, error handling, null client)
  • 10 unit tests for library.service.ts (dual-write calls, error isolation)
  • npm run typecheck clean
  • npm run lint 0 errors
  • Manual: POST /library/reindex with ES running
  • Manual: POST /library then search — dual-write works
  • Manual: Without ELASTICSEARCH_URL — graceful degradation

@jakebromberg jakebromberg marked this pull request as draft March 11, 2026 17:37
@jakebromberg jakebromberg marked this pull request as ready for review March 21, 2026 18:12
Jake Bromberg added 4 commits March 21, 2026 11:25
…dex endpoint

Wire Elasticsearch sync into the library service layer so album inserts, rotation adds, and rotation kills are dual-written to ES as fire-and-forget operations. Errors are logged but never propagated, so library operations succeed even when ES is unavailable.

Add POST /library/reindex endpoint (requires catalog write permission) that bulk-indexes all library_artist_view rows into ES in batches of 500.

Add unit tests for all sync functions and verify dual-write calls from library service functions.
Drizzle ORM references underlying table column names (e.g. artist_genre_code) instead of view column aliases (e.g. code_artist_number) when using db.select().from(view). Switch to raw SQL with db.execute() for library_artist_view queries.

Also fix add_date serialization: postgres-js returns timestamp strings (not Date objects) from raw queries, so parse through new Date() to produce valid ISO strings for ES.
The GET /library endpoint accepted album_title as a query parameter, but
the OpenAPI spec (CatalogSearchParams) and the dj-site frontend both
send album_name. This caused album searches to be silently ignored.

Closes #233
After rebasing on main, the LibraryArtistViewEntry type gained a label_id
field from the labels table feature. Update the ES index mapping,
document serialization, hit deserialization, and test fixtures to include it.
@jakebromberg jakebromberg force-pushed the feature/elasticsearch-sync branch from 2a94a21 to b639450 Compare March 21, 2026 18:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants