mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-16 22:26:16 -08:00
perf(tmdb): send catalog title matches in small requests (#1891)
CatalogTitleMatchService.matchTitles sent a caller's whole batch as one DB_MATCH_TITLES request, and the DB worker answers one request at a time: a recommendations batch held every other read for 95 s on a 3.9M-title library. The service now deduplicates the titles, keeps the 200-title cap, and sends requests of five titles one after another, concatenating the answers in order. The answer stays all-or-nothing: a failed request returns no matches, a lock that starts withholding everything stops the batch, and a batch starts over when ParentalLockService.version() changes between requests (no matches after three changing attempts). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
43358e10f2
commit
dd815676b4
7 files changed
+287
-20
No files matched your search
@@ -208,7 +208,8 @@ component for detail→detail navigation.
|
||||
|
||||
`CrossPortalSimilarService` (`libs/services`) extends the rail across
|
||||
portals: recommendations are matched against ALL imported Xtream
|
||||
playlists with one batched `DB_MATCH_TITLES` request (Electron only,
|
||||
playlists with one batched match (`DB_MATCH_TITLES`, sent in small
|
||||
requests, see "Sending a batched match"; Electron only,
|
||||
same two-tier + year rule). Stalker detail views — where the local
|
||||
catalog is server-paginated and unmatchable — get their "Similar" rail
|
||||
purely from these cross-portal matches (shared `VodDetailsComponent` for
|
||||
@@ -353,7 +354,8 @@ Filmography has two scopes:
|
||||
rest open the portal search prefilled with the title (`?q=`). Stalker
|
||||
has no local catalog, so every title goes through the portal search.
|
||||
- **All portals** (Electron only, toggle hidden in the PWA): one batched
|
||||
`DB_MATCH_TITLES` worker request runs a trigram-FTS lookup per title
|
||||
match (`DB_MATCH_TITLES` worker requests of five titles, see "Sending a
|
||||
batched match") runs a trigram-FTS lookup per title
|
||||
over ALL imported Xtream playlists
|
||||
(`operations/title-match.operations.ts`), confirming candidates with
|
||||
the same two-tier normalized-title matching the renderer uses
|
||||
@@ -363,6 +365,24 @@ Filmography has two scopes:
|
||||
This also works from Stalker actor pages — the one place the Stalker
|
||||
catalog limitation is lifted.
|
||||
|
||||
### Sending a batched match
|
||||
|
||||
`CatalogTitleMatchService.matchTitles` deduplicates the titles, keeps the
|
||||
first `TITLE_MATCH_TITLE_LIMIT` (200, the worker's own cap) and sends them
|
||||
in `DB_MATCH_TITLES` requests of `TITLE_MATCH_REQUEST_SIZE` (5), one after
|
||||
another, concatenating the answers in order. The DB worker answers one
|
||||
request at a time, so a whole rail's batch in one request held every other
|
||||
read behind it: on a 3.9M-title library one recommendations batch took
|
||||
95 s cold and kept the dashboard's playback positions (and with them the
|
||||
Continue Watching rail) waiting; now other reads wait for five titles at
|
||||
most. The answer stays all-or-nothing: a failed
|
||||
request, or a parental lock that starts withholding everything midway,
|
||||
returns no matches, as one failed request did before. One request ran
|
||||
under one parental-lock state, so a batch does too: when
|
||||
`ParentalLockService.version()` changes between requests (a relock, an
|
||||
unlock, a changed lock list) the batch starts over, and after
|
||||
`TITLE_MATCH_LOCK_ATTEMPTS` (3) changing attempts it returns no matches.
|
||||
|
||||
### Resolving a batched match
|
||||
|
||||
Every `DB_MATCH_TITLES` consumer — the Trending rail, the "Because you
|
||||
@@ -645,7 +665,8 @@ since shipped.)
|
||||
toggle): `DashboardTrendingService`
|
||||
(`libs/workspace/dashboard/data-access`) pulls the weekly TMDB trending
|
||||
lists (cached one day per language) and runs ONE batched
|
||||
`CatalogTitleMatchService.matchTitles` request against the imported
|
||||
`CatalogTitleMatchService.matchTitles` call (worker requests of five
|
||||
titles, see "Sending a batched match") against the imported
|
||||
Xtream playlists — matched cards navigate straight to their detail view
|
||||
and show the playlist name; unmatched cards open the global search
|
||||
prefilled. Requires both the TMDB opt-in and the Electron DB worker
|
||||
@@ -665,7 +686,8 @@ since shipped.)
|
||||
interleaved round-robin, deduplicated by TMDB id, stripped of anything
|
||||
already watched or favorited, and matched against
|
||||
the imported libraries with ONE batched
|
||||
`CatalogTitleMatchService.matchTitles` request. The watched/favorited
|
||||
`CatalogTitleMatchService.matchTitles` call (worker requests of five
|
||||
titles). The watched/favorited
|
||||
exclusion index is built through the same lookup-attempt builder the
|
||||
seeds use, so an activity row is indexed under more than its display
|
||||
title: under the media type the detail view enriched with (a Stalker
|
||||
@@ -719,7 +741,7 @@ since shipped.)
|
||||
on its behalf would drop its recommendations for the session; a seed
|
||||
that has no TMDB match never resolves either, so that user's rail
|
||||
re-runs each visit, which is bounded work (cached enrichment misses
|
||||
plus one batched worker call). Latched loads are keyed by the TMDB language
|
||||
plus one batched title match). Latched loads are keyed by the TMDB language
|
||||
(payloads are localized; the facade exposes `language()` for this), the
|
||||
seed set, the watched/favorited exclusion set AND the imported-playlist
|
||||
id set — watching something new re-seeds on the next dashboard visit,
|
||||
|
||||
Reference in new issue
Block a user