Skip to content

Close qBitrr parity gaps: category workers, MatchSubcategories, retries#280

Merged
cursor[bot] merged 7 commits into
masterfrom
cursor/qbitrr-parity-gaps-5644
Jun 22, 2026
Merged

Close qBitrr parity gaps: category workers, MatchSubcategories, retries#280
cursor[bot] merged 7 commits into
masterfrom
cursor/qbitrr-parity-gaps-5644

Conversation

@Feramance

Copy link
Copy Markdown
Owner

Summary

Implements the functional gaps identified in the qBitrr vs Torrentarr comparison report (baseline: qBitrr 5.12.3).

Critical

  • MatchSubcategories — config key on [qBit] and per-Arr sections; CategoryOwnershipHelper resolves torrent ownership; TorrentProcessor gathers torrents with prefix matching when enabled
  • qBit-only ManagedCategories — new QBitCategoryWorkerManager runs full torrent lifecycle for categories not owned by an Arr instance (PlaceHolderArr / qBitCategoryManager parity)

High / medium

  • ApplySeedingLimitsAsync wired in TorrentProcessor pre-step
  • qBittorrent category auto-creation via QBitCategoryEnsureService on worker startup
  • Import path dedup (ImportPathTracker / sent_to_scan) + empty-folder cleanup after processing
  • HTTP retries — Polly policies on Arr and qBit clients (HttpRetryHelper)
  • Config reload → worker restart on Host for full / multi_arr / single_arr reload types
  • ProfileSwitchRetryAttempts enforced in QualityProfileSwitcherService
  • Periodic WAL checkpoint every 5 minutes (PeriodicWalCheckpointService)
  • RemoveCompletedTorrentsAsync called from Host torrent processing path
  • Tracker tag pre-creation at worker startup
  • DatabaseHealthService.RepairAsync fixed using SQLite backup API
  • DatabaseRetryExtensions for transient SQLite save retries

Docs / tests

Remaining intentional / partial items

  • OpenAPI spec still documents a subset of Host routes (webui.py row → partial)
  • No repair_database_targeted.py port (documented intentional divergence)
  • Coordinated cross-process DB restart after repair not ported (db_lock.pypartial)

Test plan

  • dotnet build
  • dotnet test --filter "Category!=Live" — 764 passed (172 Core + 396 Infrastructure + 196 Host)
Open in Web Open in Cursor 

cursoragent and others added 7 commits June 22, 2026 13:31
Implement gap-report items from qBitrr 5.12.3 comparison:

- Add CategoryOwnershipHelper and MatchSubcategories config (qBit + per-Arr)
- Add QBitCategoryWorkerManager for qBit-only ManagedCategories (PlaceHolderArr parity)
- Wire ApplySeedingLimitsAsync, RemoveCompletedTorrentsAsync, import path tracking
- Add post-import empty-folder cleanup via ImportPathTracker
- Auto-create qBittorrent categories on all instances (QBitCategoryEnsureService)
- Add Polly HTTP retries for Arr/qBit clients (HttpRetryHelper)
- Enforce ProfileSwitchRetryAttempts in QualityProfileSwitcherService
- Add PeriodicWalCheckpointService (5-minute interval on Host)
- Fix DatabaseHealthService.RepairAsync using SQLite backup API
- Add DatabaseRetryExtensions for transient SQLite errors
- Restart Arr workers on config reload (full/multi_arr/single_arr)
- Register ConfigReloader on Host; pre-create tracker tags at worker start
- Add CategoryOwnershipHelperTests; update full-parity-matrix.md

Co-authored-by: Feramance <Feramance@users.noreply.github.com>
- Add MatchSubcategories checkbox to qBit and Arr config editor fields
- Update torrent handling summary text for prefix vs exact category matching
- Refactor QBitCategoryWorkerManager with proper worker lifecycle (restart/sync)
- Add DatabaseRestartCoordinator and watchdog for coordinated worker recovery
- Wire SaveChangesWithRetryAsync into high-traffic DB write paths
- Register coordinator in Host and Workers DI

Co-authored-by: Feramance <Feramance@users.noreply.github.com>
- Expand docs/assets/openapi.json to 72 paths (all 66 qBitrr paths + 6 extensions)
- Add scripts/generate-openapi-from-qbitrr.py and strengthen check-openapi-drift.sh
- Serve curated spec at /api|web/openapi.json; Swagger aliases at /api|web/docs
- Implement Lidarr artists missing/reason query param filters
- Mark db_lock.py as intentional-divergence; close parity matrix (no partial rows)

Co-authored-by: Feramance <Feramance@users.noreply.github.com>
…er rebase

Co-authored-by: Feramance <Feramance@users.noreply.github.com>
@cursor cursor Bot force-pushed the cursor/qbitrr-parity-gaps-5644 branch from 7fc0e61 to e0bf9fe Compare June 22, 2026 13:43
@cursor cursor Bot marked this pull request as ready for review June 22, 2026 13:43
@cursor cursor Bot merged commit 8578a8f into master Jun 22, 2026
12 checks passed
cursor Bot pushed a commit that referenced this pull request Jun 22, 2026
Inspects all open PRs (#280-#283, #285, #292-#293, #296, #300) with
local CI-equivalent checks, per-PR verdicts, merge order, and #280
feature-slice breakdown.

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Feramance <Feramance@users.noreply.github.com>
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