Repository navigation
feat(providers): add Bazarr integration - #58
Conversation
|
Part of a set of integration PRs. Overview, merge order and design notes: #64 |
itz4blitz
left a comment
There was a problem hiding this comment.
Requesting changes. Registration, the client, and the log parser look solid. History sync drops events and will not retry them.
-
collectHistory(packages/provider-bazarr/src/bazarr.provider.ts) stops after 3 pages of 50 oncesinceis set, and the first poll (nosince) reads only one page.pollServerthen setslastActivitySyncto the max timestamp of the returned activities (ingestion.service.ts). That max is the newest row, so the next poll starts at the head again and the skipped tail is never stored. Health rows make this worse:normalizeHealthIssuestampsnew Date(), and one inserted history row beside a standing health issue moves the cursor to now. Page until the oldest parsed row is older than the cutoff, or when the cap hits, leavelastActivitySyncat the oldest fetched history time. Keep health timestamps out of that cursor. -
parseDateString(packages/provider-bazarr/src/bazarr.utils.ts) treats slash dates as month-first unless the first number is greater than 12. Bazarr'sparsed_timestampis Python%x %X. Day-first locales (en_GB,fr_FR) swap the day and month for days 1–12, the cutoff drops those rows, and paging can stop early. Dotted dates are already day-first. Add a day-first fixture (05/10/26as 5 October) and do not advance the cutoff from a timestamp that failed to parse.
Also, when you rebase: this PR conflicts with the other integration branches on the shared registration files. #57 and #60 are landing first.
Follow-ups, not blocking: Bazarr warn/error issues are stored as system because issue_source has no bazarr value (same gap as Whisparr). The new op:// refs in .env.tpl will fail op inject until those vault items exist.
Add @logarr/provider-bazarr, a standalone provider for Bazarr's /api. - X-API-KEY client with `data` envelope unwrapping; connection test via /api/system/status - Activity from episode and movie subtitle history (action labels from Bazarr's history_log codes), system health and failed jobs, with stable content-hash ids (the history API exposes no row id), since-filtering and bounded paging - File tailing of bazarr.log with a parser for Bazarr's pipe-delimited format, preserving `|` inside messages and unescaping inline tracebacks - Backend registration, env seeding (BAZARR_URL/BAZARR_API_KEY, /bazarr-logs), proxy path, Dockerfiles, compose, turbo env - Frontend: Bazarr integration flipped to available with truthful capability flags, provider icon and logs deep link - README updates, including a note about Bazarr's naive local timestamps
…ates History sync now pages until the oldest parseable row is older than the cutoff (40 page safety cap; 7 day window on the first poll). When the cap is hit, only rows at or before the oldest fetched history row may advance the sync cursor. Health, failed-job and unparsed rows never advance it (advancesSyncCursor: false). Slash dates are read per response: a number above 12 proves day-first or month-first, the order is remembered per server, and rows that stay ambiguous are treated as unparsed instead of guessed.
…d polls progress Locate the first row older than the cutoff by probing (exponential then binary search on start), then read pages oldest to newest with an overlap that detects rows inserted at the head mid-read. If the page cap is hit the rows are the oldest ones above the cutoff and the cursor advances only to the newest row read with certainty, so each poll gains ground until the backlog is caught up. History ids hash the raw timestamp text (independent of the inferred date order), the date order is inferred over every row of the poll before normalizing, a failing history source keeps the other source's rows off the cursor, rows never move the cursor backwards past since, and year-first dates (2026/10/05) are read as Y/M/D.
1503280 to
4f6ab79
Compare
|
Thanks for the review. I've rebased onto current master and pushed the changes.
Known limitation: a server with more than 50 subtitle events per day costs extra requests per poll. If one of the two history endpoints keeps failing, the cursor stays put. Happy to tighten either in a follow-up. |
Summary
Adds a Bazarr integration (
@logarr/provider-bazarr). Bazarr's API isn't an *arr v3 API (/api/...,X-API-KEY,{ data }envelope, pipe-delimited log format), so this is a standalone provider that depends only on@logarr/core.What it ingests
/api/system/healthissues, and failed jobs from/api/system/jobs.history_logcall sites in Bazarr's source.bazarr.log.ts|LEVEL|logger|message|format, keeps|characters inside messages, and unescapes inline'Traceback…'reprs intoexceptionandstackTrace.Wiring
IngestionServiceandServersService.BAZARR_URL,BAZARR_API_KEY,BAZARR_LOGS_PATH, mounted at/bazarr-logs./api, both Dockerfiles, compose files,turbo.jsonenv,.env.exampleand.env.tpl.bazarrintegration flips fromcoming_soontoavailable. Its capability flags match what is implemented: activity and real-time logs (file tailing, the same as Sonarr) yes; webhooks and metrics no.Notes and limitations
[bazarr] Failed to get …log line, and the poll fails only when every endpoint fails. Health activities use thehealth_warningtype, matching the *arr base.TZ). Because of this, the history window is widened by 24h, and duplicates are removed by the stable ids.issue_sourcehas nobazarrvalue, so issues fall back tosystem, the same as Plex, Emby and Whisparr today.Testing
@logarr/provider-bazarrhas 136 unit tests covering:sincefiltering, paging caps, and partial failure of individual endpoints;LogFileProcessorend to end.pnpm build,pnpm lint,pnpm typecheckandpnpm testall pass.pnpm install --frozen-lockfileis clean, and the lockfile diff only adds the new package.pnpm format:checkalready fails onmaster(pre-existing unformatted files, including one line inserver-seed.service.ts). All files added or changed here are prettier-clean.