Skip to content

Extend catalog cascade to GET /library/query so modern Card Catalog sees matched_via#978

Merged
jakebromberg merged 2 commits into
mainfrom
bugfix/977-cascade-library-query
May 21, 2026
Merged

Extend catalog cascade to GET /library/query so modern Card Catalog sees matched_via#978
jakebromberg merged 2 commits into
mainfrom
bugfix/977-cascade-library-query

Conversation

@jakebromberg
Copy link
Copy Markdown
Member

Closes #977. Follow-up to #973 (which wired the cascade onto GET /library/).

The modern Card Catalog calls GET /library/query, which runs its own
field-aware ILIKE primary path in librarySearchService.searchLibrary
and never reaches the Track 1 (CTA) + Track 2 (LML /lookup) cascade
owned by libraryService.searchLibraryBothMode. So even though prod is
running with both CATALOG_TRACK_SEARCH_*_ENABLED=true, modern dj-site
showed no chips for vi scose poise while classic-experience search did.

Approach

After the primary db.execute(dataQuery) returns 0 rows AND the parsed
query is a single bareword (no artist: / album: / label: qualifier,
no quoted exact, no NOT), fall through to:

  1. searchLibraryByCTARaw(q, limit, on_streaming) — Track 1, gated by flags.ctaEnabled
  2. on Track 1 0-hit, searchLibraryByTrackRaw(q, limit) — Track 2, gated by flags.discogsEnabled

Both primitives already return TaggedLibraryViewEntry[] (LibraryArtistViewEntry + matched_via) and were introduced as reusable building blocks in #973. Genre/format/on_streaming filters and the requested sort + order apply to the bounded cascade list in-memory before serialization. Cascade fallback is single-page (page > 0 returns []) so the client doesn't paginate into a bounded list.

With both flags off (the default), the function path is byte-identical to today.

Trigger detection

Cascade fires when the parsed SearchCondition[] is exactly:

[{ field: 'all', exact: false, negated: false, ... }]

Field-qualified queries like artist:NonexistentFoo skip the cascade even on 0-hit — they signal a structured match intent, not a cross-table track lookup.

Test plan

  • npm run typecheck — clean
  • npm run lint — 0 errors on touched files
  • npm run format:check — clean
  • npm run test:unit — 1991 / 1991 pass
  • Integration (CI docker stack):
  • Once merged + deployed, smoke against prod: GET /library/query?q=vi+scose+poise should return { results: [{ id: …, matched_via: [{ source: "discogs_release" | "discogs_master", … }] }], total: 1, page: 0, totalPages: 1 }. Modern Card Catalog chip rendering should turn on automatically (component already wired at dj-site/src/components/experiences/modern/catalog/Results/Result.tsx:111).

Related

`searchLibraryQueryEndpoint` runs its own field-aware ILIKE primary path,
so the Track 1 (CTA) + Track 2 (LML `/lookup`) cascade owned by
`searchLibraryBothMode` was unreachable from the modern Card Catalog. That
left modern dj-site without `matched_via` chips even after BS#972/#973
wired the cascade onto the classic-experience `/library/` route.

When the primary query returns no rows AND the parsed query is a single
bareword (no `artist:`/`album:`/`label:` qualifier, no quoted exact, no
NOT), fall through to `searchLibraryByCTARaw` + `searchLibraryByTrackRaw`
under the existing `CATALOG_TRACK_SEARCH_CTA_ENABLED` /
`CATALOG_TRACK_SEARCH_DISCOGS_ENABLED` flags. Apply `genre` / `format` /
`on_streaming` filters and the requested `sort` + `order` over the
bounded fallback list in-memory before returning. Cascade fallback is
single-page (`page > 0` stays empty) so the client doesn't keep
scrolling into a bounded list.

Both flags default to `false`, so when the operator hasn't opted in the
function path is byte-identical to today.

Closes #977
Tightens the in-memory filter comment in runCascade so it accurately
describes which raw primitive applies which filter (CTA honors
on_streaming server-side; only Track 2 needs the in-memory pass).
Adds an inline comment in the BS#977 CTA test explaining why
'Bioluminescence' triggers the cascade and how the curated
track-to-album map produces the comp library row.
@jakebromberg jakebromberg merged commit b4ed817 into main May 21, 2026
5 checks passed
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.

Extend catalog cascade to GET /library/query so modern Card Catalog sees matched_via

1 participant