Skip to content

feat(providers): add Readarr integration - #61

Merged
itz4blitz merged 4 commits into
itz4blitz:masterfrom
vbrzezina:feat/readarr-integration
Oct 16, 2026
Merged

itz4blitz merged 4 commits into
itz4blitz:masterfrom
vbrzezina:feat/readarr-integration

Conversation

@vbrzezina

@vbrzezina vbrzezina commented Oct 10, 2026 •

Copy link
Copy Markdown
Contributor

Stacked on #57. That PR fixes *arr log-file ingestion, which this integration relies on. Only the last commit, feat(providers): add Readarr integration, belongs to this PR. Please merge #57 first.

Summary

Adds a Readarr integration (@logarr/provider-readarr) on the shared provider-arr base, using Readarr's v1 API.

⚠️ Readarr was retired upstream in June 2025 (archived; last release v0.4.18). It is supported on a best-effort basis, and the integration description and README say so.

  • v1 history: an ArrClient subclass for the v1 API reads history and history/since with includeAuthor and includeBook.
  • Shared helpers: event resolution, severity and item ids use the shared provider-arr helpers from fix: *arr log file ingestion emits no entries (timestamp regex + context parser contract) #57 (resolveArrEventName, describeArrEvent, toArrItemId). The Lidarr PR uses the same helpers and severity table, so the two behave the same, including metadata keys and description wording.
  • History normalisation:
    • Covers every EntityHistoryEventType value, checked against Readarr source. That includes the missing value 2, which maps to unknown.
    • Numeric and camelCase event types are both accepted.
    • downloadFailed and any unknown *Failed event are errors. bookImportIncomplete is a warning, and downloadIgnored is info, the same as Lidarr.
    • Activity ids are stable: readarr-history-<id>.
  • Health and queue: reuses the base implementation. Readarr's metadata server is gone, so its health check reports a permanent error, which is expected.
  • Log files: reuses the existing READARR_LOG_FILE_CONFIG to tail readarr.txt.
  • Wiring:
    • backend registration;
    • env seeding with READARR_URL, READARR_API_KEY and READARR_LOGS_PATH, mounted at /readarr-logs;
    • both Dockerfiles, the compose files and turbo.json env;
    • the Readarr integration flipped to available with a retirement notice;
    • a logs-page deep link and README updates.

Testing

  • @logarr/provider-readarr has 84 unit tests covering:
    • the v1 URL and X-Api-Key header, retries, and 401 handling;
    • a 19-row event-type table;
    • unknown and failed event names;
    • health and queue handling, including error isolation;
    • multi-line exception parsing under the fixed context-parser contract.
  • pnpm build, lint, typecheck and test all pass. pnpm install --frozen-lockfile is clean, and the lockfile diff only adds the new package.
  • Not yet tested against a live Readarr instance.

@vbrzezina
vbrzezina force-pushed the feat/readarr-integration branch from 0ae105d to 3e06df6 Compare October 10, 2026 18:46
@vbrzezina vbrzezina changed the title feat(providers): add Readarr integration (retired upstream, best-effort) feat(providers): add Readarr integration Oct 12, 2026
@vbrzezina

Copy link
Copy Markdown
Contributor Author

Part of a set of integration PRs. Overview, merge order and design notes: #64

@vbrzezina
vbrzezina marked this pull request as ready for review October 12, 2026 16:43

@itz4blitz itz4blitz left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Requesting changes. The Readarr provider itself matches upstream: API v1, no event type 2, bookFileImported at 3 through downloadIgnored at 10, id readarr, registered in both backend provider maps.

  1. Please rebase onto current master after #57 (and #60) land. This branch has the parser fix but not 0808207, which excludes *.debug.* and *.trace.*. Merging it alone would tail those rolling logs now that one-digit NLog lines are actually ingested. A merge onto post-#57 master keeps the excludes; once Lidarr is in, the shared wiring files will conflict and a rebase is required anyway.

  2. Standing health errors will insert a new activity on every poll. ArrBaseProvider.normalizeHealthChecks uses `health-${check.source}-${Date.now()}`, and queue warnings do the same. Ingestion dedupes on (serverId, externalActivityId), so a new id is a new row. This provider's own header says most installs have a permanent BookInfo health error. Please override those ids so a standing check is stable (source + message), the same way Bazarr's health id is a hash of the issue text. Otherwise a Readarr server fills the log table every poll interval.

Follow-up: issue_source has no readarr value, so issues are stored as system. That needs a migration. Whisparr already has the same gap.

Add @logarr/provider-readarr on top of the shared provider-arr base, using
Readarr's v1 API. Readarr was retired upstream in June 2025 (last release
v0.4.18); it is supported best-effort and labelled as such in the UI and
README.

- v1 ArrClient with history and history/since (includeAuthor/includeBook)
- History normalization for all EntityHistoryEventType values (including
  the gap at 2), accepting numeric and camelCase event types; downloadFailed
  and unknown "*Failed" events are errors; stable readarr-history-<id> ids
- Reuses the existing READARR_LOG_FILE_CONFIG for readarr.txt file tailing
- Backend registration, env seeding (READARR_URL/READARR_API_KEY,
  /readarr-logs), Dockerfiles, compose, turbo env
- Frontend: Readarr integration flipped to available, logs deep link
- README updates with a retirement notice
…ties

Standing health checks and queue warnings used Date.now() in their id, so
every poll inserted a new activity row. Health ids are now a hash of
source/type/message and queue ids derive from the queue item id, warning
state and message. Fixes the same issue for all *arr providers.
@vbrzezina

Copy link
Copy Markdown
Contributor Author

Thanks, both points are addressed.

  1. Rebase: rebased onto master after fix: *arr log file ingestion emits no entries (timestamp regex + context parser contract) #57 and feat(providers): add Lidarr integration #60. The old fix: *arr log file ingestion emits no entries (timestamp regex + context parser contract) #57 commits dropped out, and READARR_LOG_FILE_CONFIG now carries the *.debug.*/*.trace.* excludes. The shared wiring conflicts are resolved with Lidarr kept, and the lockfile diff against master adds only the new package.
  2. Standing health errors: you were right, and the Date.now() ids affected every *arr provider, so I fixed it once in ArrBaseProvider rather than only in Readarr.
    • Health ids are now <provider>-health-<hash(source, type, message)>.
    • Queue-warning ids are <provider>-queue-<item id>-<tracked status/state>-<hash(message)>.
    • A standing check now produces one row instead of one per poll, for Lidarr, Sonarr, Radarr, Prowlarr and Whisparr as well.
    • Tests are in provider-arr (arr.provider.activity-ids.spec.ts) and in the Readarr spec, which checks that the ids are identical across two polls.

These ids conflict with #67, which flags the same health and queue rows so their "now" timestamps don't move the sync cursor. Whichever of the two merges second needs a small rebase, and I'll handle it.

issue_source has no readarr value yet. I'll do that as one migration PR for all the new providers once #62 (which adds migration 0010) is settled. The .env.tpl entries are commented out until the vault items exist.

@vbrzezina
vbrzezina force-pushed the feat/readarr-integration branch from 3e06df6 to 41517ec Compare October 13, 2026 13:08
@itz4blitz
itz4blitz merged commit e920635 into itz4blitz:master Oct 16, 2026
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