Skip to content

fix(crossseed): fix batch completion searches and remove legacy settings#744

Merged
s0up4200 merged 5 commits intomainfrom
refactor/legacy-onCompletion
Dec 11, 2025
Merged

fix(crossseed): fix batch completion searches and remove legacy settings#744
s0up4200 merged 5 commits intomainfrom
refactor/legacy-onCompletion

Conversation

@s0up4200
Copy link
Collaborator

@s0up4200 s0up4200 commented Dec 10, 2025

Summary

  • Fix batch completion searches: When multiple torrents complete close together (e.g., downloading a full season), completion searches would previously be skipped due to rate limiting. Now they queue and wait their turn, ensuring all torrents get cross-seed searches.
  • Remove legacy completion settings: Drops the deprecated CrossSeedCompletionSettings structure and related database columns that were superseded by per-instance completion settings.

Root Cause

The completion search maxWait (30s) was shorter than the effective rate limit interval (42s). When torrents completed within seconds of each other, all indexers would be skipped because the required wait exceeded the max allowed wait time.

Fix

Completion searches now have no maxWait limit (like interactive searches). They queue and execute in order as rate limits clear, instead of being immediately skipped.

Summary by CodeRabbit

  • Breaking Changes

    • Removed completion configuration and related filters from cross-seed automation settings; completion fields are no longer supported.
  • Improvements

    • Simplified automation settings and API patch behavior with more optional/nullable fields.
    • Scheduler behavior adjusted: longer waits and completion-priority tasks now queue (no fixed per-priority cap).
  • Chores

    • Database migration to remove legacy completion columns.
  • Tests

    • Updated tests to reflect removal of completion and new scheduler semantics.

✏️ Tip: You can customize this high-level summary in your review settings.

This commit removes the CrossSeedCompletionSettings structure and its associated fields from various models, tests, and the database schema. The changes streamline the automation settings by eliminating deprecated completion configurations, ensuring a cleaner and more maintainable codebase. Additionally, a migration script is added to drop legacy completion columns from the database.
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 10, 2025

Caution

Review failed

The pull request is closed.

Walkthrough

Removed per-automation and global "completion" settings from cross-seed: deleted related types/fields, removed DB columns via migration, updated API/OpenAPI/web types and tests, adjusted cross-seed service and Jackett scheduler timeouts/limits and related tests.

Changes

Cohort / File(s) Summary
API Handler
internal/api/handlers/crossseed.go
Deleted completion request/patch types and Completion fields; converted several patch fields to pointer/optional types; removed completion patch apply logic and updated isEmpty checks.
API Handler Tests
internal/api/handlers/crossseed_patch_test.go
Removed Completion initialization and assertions from patch tests; adapted tests to new patch semantics.
Data Model
internal/models/crossseed.go
Removed CrossSeedCompletionSettings type and Completion field from CrossSeedAutomationSettings; deleted getters and normalization; removed completion columns from DB queries and encode/decode paths; updated defaults.
Data Model Tests
internal/models/crossseed_test.go
Removed Completion fields and assertions from UpsertSettings test.
Database Migration
internal/database/migrations/030_remove_legacy_completion_columns.sql
Added migration recreating cross_seed_settings without legacy completion columns, copying data, dropping old table, renaming new table, and recreating updated_at trigger.
Cross-Seed Service
internal/services/crossseed/service.go
Removed normalization calls for completion settings in load/validate paths; adjusted completion search timeout log level/message.
Jackett Scheduler
internal/services/jackett/scheduler.go, internal/services/jackett/SCHEDULER.md
Removed fixed completionMaxWait; increased background defaults (45s → 60s); increased completion/background execution timeouts; getMaxWait() returns 0 for completion (no per-priority cap).
Jackett Scheduler Tests
internal/services/jackett/scheduler_test.go
Updated rate-limiter interval and expected waits; removed completion skip case; added subtest ensuring Completion-priority jobs queue (no hard skip).
Jackett Service
internal/services/jackett/service.go
Stopped setting MaxWait for RateLimitPriorityCompletion; clarified behavior in comments.
OpenAPI
internal/web/swagger/openapi.yaml
Removed CrossSeedCompletionSettingsPatch schema and removed completion fields from CrossSeedAutomationSettings and its Patch schema.
Web Types
web/src/types/index.ts
Removed CrossSeedCompletionSettings / CrossSeedCompletionSettingsPatch interfaces and deleted completion fields from automation interfaces.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Pay special attention to the DB migration SQL for correctness and data preservation.
  • Verify all serialization/DB encode-decode paths no longer reference completion columns.
  • Confirm patch semantics (pointer/optional fields) are handled consistently across API handlers and tests.
  • Review Jackett scheduler changes for queueing and rate-limit implications.

Possibly related PRs

  • autobrr/qui#614 — Previously added PATCH support including completion patch types and merge logic (directly related to the removed types/logic).
  • autobrr/qui#736 — Overlaps cross-seed completion additions/removal and touches the same handlers/models/OpenAPI.
  • autobrr/qui#641 — Modifies Jackett scheduler and rate-limiting behavior tied to completion priorities and timeouts.

Suggested labels

bugfix

Suggested reviewers

  • Audionut

Poem

I hop through code with floppy ears,
Nibbling completion’s last small gears,
Fields gone, tables trimmed with care,
Queues now wait and logs declare —
A lighter trail of bytes I share 🐇✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 12.50% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main changes: fixing batch completion searches and removing legacy completion settings from the CrossSeed functionality.

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3cffaf4 and c6f0d9b.

📒 Files selected for processing (1)
  • internal/services/crossseed/service.go (2 hunks)

Comment @coderabbitai help to get the list of available commands and usage tips.

@s0up4200 s0up4200 added this to the v1.10.0 milestone Dec 10, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
internal/services/jackett/SCHEDULER.md (1)

228-241: Consider documenting execution timeouts alongside MaxWait defaults.

The AI summary mentions that execution timeouts were adjusted (completionExecutionTimeout: 30s→45s, backgroundExecutionTimeout: 45s→60s), but these aren't shown in the Configuration section. While MaxWait and execution timeouts are separate concerns (dispatch vs. execution), documenting both together would provide a complete picture of scheduler limits for different priorities.

Consider adding an "Execution Timeouts" subsection after line 241:

### Execution Timeouts

```go
const (
    completionExecutionTimeout = 45 * time.Second
    backgroundExecutionTimeout = 60 * time.Second
    rssExecutionTimeout        = 45 * time.Second
)

These timeouts limit how long a single search execution can run before being cancelled.


</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used**: CodeRabbit UI

**Review profile**: CHILL

**Plan**: Pro

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 438252b11c66939582a8e8102080322463b92a34 and 3cffaf4df0c45a84c069655ada50896c2e8c5c45.

</details>

<details>
<summary>📒 Files selected for processing (2)</summary>

* `internal/services/crossseed/service.go` (1 hunks)
* `internal/services/jackett/SCHEDULER.md` (2 hunks)

</details>

<details>
<summary>🚧 Files skipped from review as they are similar to previous changes (1)</summary>

* internal/services/crossseed/service.go

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🧠 Learnings (1)</summary>

<details>
<summary>📓 Common learnings</summary>

Learnt from: s0up4200
Repo: autobrr/qui PR: 641
File: internal/services/crossseed/service.go:209-212
Timestamp: 2025-11-28T20:32:30.126Z
Learning: Repo: autobrr/qui PR: 641
File: internal/services/crossseed/service.go
Learning: The cross-seed recheck-resume worker intentionally runs for the process lifetime and keys pending entries by hash only. This is acceptable under the current constraint that background seeded-search runs operate on a single instance at a time; graceful shutdown and instanceID|hash keying are deferred by design.


</details>

</details>

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)</summary>

* GitHub Check: Run tests

</details>

<details>
<summary>🔇 Additional comments (2)</summary><blockquote>

<details>
<summary>internal/services/jackett/SCHEDULER.md (2)</summary><blockquote>

`236-240`: **Documentation clearly reflects the removal of completionMaxWait and the new queuing behavior.**

The update to lines 238-239 effectively communicates the shift: completion and interactive searches now have no maxWait limit and will queue indefinitely instead of being skipped. This directly addresses the PR objective and is well-documented.

---

`243-266`: **getMaxWait() implementation documentation accurately reflects the new priority-based defaults.**

The function now correctly shows Completion priority returning 0 (matching Interactive), enabling the queuing behavior described in the PR objectives. The inline comments at lines 254-263 clearly explain each priority's behavior, making it easy for developers to understand why completion searches can wait indefinitely while background searches have a 60s timeout.

</blockquote></details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->

Remove reference to CrossSeedCompletionSettings which was removed in
d647c01. The matchesCompletionFilters function now only uses
per-instance InstanceCrossSeedCompletionSettings.
@s0up4200 s0up4200 merged commit fd9e054 into main Dec 11, 2025
1 of 2 checks passed
@s0up4200 s0up4200 deleted the refactor/legacy-onCompletion branch December 11, 2025 00:07
alexlebens pushed a commit to alexlebens/infrastructure that referenced this pull request Dec 18, 2025
This PR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [ghcr.io/autobrr/qui](https://github.com/autobrr/qui) | minor | `v1.9.1` -> `v1.10.0` |

---

### Release Notes

<details>
<summary>autobrr/qui (ghcr.io/autobrr/qui)</summary>

### [`v1.10.0`](https://github.com/autobrr/qui/releases/tag/v1.10.0)

[Compare Source](autobrr/qui@v1.9.1...v1.10.0)

#### Changelog

##### New Features

- [`f2b17e6`](autobrr/qui@f2b17e6): feat(config): add SESSION\_SECRET\_FILE env var ([#&#8203;661](autobrr/qui#661)) ([@&#8203;undefined-landmark](https://github.com/undefined-landmark))
- [`f5ede56`](autobrr/qui@f5ede56): feat(crossseed): add RSS source filters for categories and tags ([#&#8203;757](autobrr/qui#757)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`9dee7bb`](autobrr/qui@9dee7bb): feat(crossseed): add Unicode normalization for title and file matching ([#&#8203;742](autobrr/qui#742)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`d44058f`](autobrr/qui@d44058f): feat(crossseed): add skip auto-resume settings per mode ([#&#8203;755](autobrr/qui#755)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`9e3534a`](autobrr/qui@9e3534a): feat(crossseed): add webhook source filters for categories and tags ([#&#8203;763](autobrr/qui#763)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`c8bbe07`](autobrr/qui@c8bbe07): feat(crossseed): only poll status endpoints when features are enabled ([#&#8203;738](autobrr/qui#738)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`fda8101`](autobrr/qui@fda8101): feat(sidebar): add size tooltips and deduplicate cross-seed sizes ([#&#8203;724](autobrr/qui#724)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`e4c0556`](autobrr/qui@e4c0556): feat(torrent): add sequential download toggles ([#&#8203;776](autobrr/qui#776)) ([@&#8203;rare-magma](https://github.com/rare-magma))
- [`2a43f15`](autobrr/qui@2a43f15): feat(torrents): autocomplete paths ([#&#8203;634](autobrr/qui#634)) ([@&#8203;rare-magma](https://github.com/rare-magma))
- [`1c07b33`](autobrr/qui@1c07b33): feat(torrents): replace filtered speeds with global ([#&#8203;745](autobrr/qui#745)) ([@&#8203;jabloink](https://github.com/jabloink))
- [`cd0deee`](autobrr/qui@cd0deee): feat(tracker): add per-domain stats inclusion toggle for merged trackers ([#&#8203;781](autobrr/qui#781)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`b6a6200`](autobrr/qui@b6a6200): feat(web): add Size column to Tracker Breakdown table ([#&#8203;770](autobrr/qui#770)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`560071b`](autobrr/qui@560071b): feat(web): add zebra striping to torrent table ([#&#8203;726](autobrr/qui#726)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`f8f65a8`](autobrr/qui@f8f65a8): feat(web): improve auto-search on completion UX ([#&#8203;743](autobrr/qui#743)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`e36312f`](autobrr/qui@e36312f): feat(web): improve torrent selection UX with unified click and escape behavior ([#&#8203;782](autobrr/qui#782)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`27c1daa`](autobrr/qui@27c1daa): feat(web): napster theme ([#&#8203;728](autobrr/qui#728)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`e3950de`](autobrr/qui@e3950de): feat(web): new torrent details panel for desktop ([#&#8203;760](autobrr/qui#760)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`6c66ba5`](autobrr/qui@6c66ba5): feat(web): persist tab state in URL for CrossSeed and Settings pages ([#&#8203;775](autobrr/qui#775)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`59884a9`](autobrr/qui@59884a9): feat(web): share tracker customizations with filtersidebar ([#&#8203;717](autobrr/qui#717)) ([@&#8203;s0up4200](https://github.com/s0up4200))

##### Bug Fixes

- [`fafd278`](autobrr/qui@fafd278): fix(api): add webhook source filter fields to PATCH settings endpoint ([#&#8203;774](autobrr/qui#774)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`bdf0339`](autobrr/qui@bdf0339): fix(api): support apikey query param with custom base URL ([#&#8203;748](autobrr/qui#748)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`c3c8d66`](autobrr/qui@c3c8d66): fix(crossseed): compare Site and Sum fields for anime releases ([#&#8203;769](autobrr/qui#769)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`cb4c965`](autobrr/qui@cb4c965): fix(crossseed): detect file name differences and fix hasExtraSourceFiles ([#&#8203;741](autobrr/qui#741)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`fd9e054`](autobrr/qui@fd9e054): fix(crossseed): fix batch completion searches and remove legacy settings ([#&#8203;744](autobrr/qui#744)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`26706a0`](autobrr/qui@26706a0): fix(crossseed): normalize punctuation in title matching ([#&#8203;718](autobrr/qui#718)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`db30566`](autobrr/qui@db30566): fix(crossseed): rename files before folder to avoid path conflicts ([#&#8203;752](autobrr/qui#752)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`8886ac4`](autobrr/qui@8886ac4): fix(crossseed): resolve category creation race condition and relax autoTMM ([#&#8203;767](autobrr/qui#767)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`f8f2a05`](autobrr/qui@f8f2a05): fix(crossseed): support game scene releases with RAR files ([#&#8203;768](autobrr/qui#768)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`918adee`](autobrr/qui@918adee): fix(crossseed): treat x264/H.264/H264/AVC as equivalent codecs ([#&#8203;766](autobrr/qui#766)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`c4b1f0a`](autobrr/qui@c4b1f0a): fix(dashboard): merge tracker customizations with duplicate displayName ([#&#8203;751](autobrr/qui#751)) ([@&#8203;jabloink](https://github.com/jabloink))
- [`3c6e0f9`](autobrr/qui@3c6e0f9): fix(license): remove redundant validation call after activation ([#&#8203;749](autobrr/qui#749)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`a9c7754`](autobrr/qui@a9c7754): fix(reannounce): simplify tracker detection to match qbrr logic ([#&#8203;746](autobrr/qui#746)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`3baa007`](autobrr/qui@3baa007): fix(rss): skip download when torrent already exists by infohash ([#&#8203;715](autobrr/qui#715)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`55d0ccc`](autobrr/qui@55d0ccc): fix(swagger): respect base URL for API docs routes ([#&#8203;758](autobrr/qui#758)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`47695fd`](autobrr/qui@47695fd): fix(web): add height constraint to filter sidebar wrapper for proper scrolling ([#&#8203;778](autobrr/qui#778)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`4b3bfea`](autobrr/qui@4b3bfea): fix(web): default torrent format to v1 in creator dialog ([#&#8203;723](autobrr/qui#723)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`2d54b79`](autobrr/qui@2d54b79): fix(web): pin submit button in Services sheet footer ([#&#8203;756](autobrr/qui#756)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`2bcd6a3`](autobrr/qui@2bcd6a3): fix(web): preserve folder collapse state during file tree sync ([#&#8203;740](autobrr/qui#740)) ([@&#8203;ewenjo](https://github.com/ewenjo))
- [`57f3f1d`](autobrr/qui@57f3f1d): fix(web): sort Peers column by total peers instead of connected ([#&#8203;759](autobrr/qui#759)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`53a8818`](autobrr/qui@53a8818): fix(web): sort Seeds column by total seeds instead of connected ([#&#8203;747](autobrr/qui#747)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`d171915`](autobrr/qui@d171915): fix(web): sort folders before files in torrent file tree ([#&#8203;764](autobrr/qui#764)) ([@&#8203;s0up4200](https://github.com/s0up4200))

##### Other Changes

- [`172b4aa`](autobrr/qui@172b4aa): chore(assets): replace napster.svg with napster.png for logo update ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`dc83102`](autobrr/qui@dc83102): chore(deps): bump the github group with 3 updates ([#&#8203;761](autobrr/qui#761)) ([@&#8203;dependabot](https://github.com/dependabot)\[bot])
- [`75357d3`](autobrr/qui@75357d3): chore: fix napster logo ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`206c4b2`](autobrr/qui@206c4b2): refactor(web): extract CrossSeed completion to accordion component ([#&#8203;762](autobrr/qui#762)) ([@&#8203;s0up4200](https://github.com/s0up4200))

**Full Changelog**: <autobrr/qui@v1.9.1...v1.10.0>

#### Docker images

- `docker pull ghcr.io/autobrr/qui:v1.10.0`
- `docker pull ghcr.io/autobrr/qui:latest`

#### What to do next?

- Join our [Discord server](https://discord.autobrr.com/qui)

Thank you for using qui!

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0Mi4zOS4xIiwidXBkYXRlZEluVmVyIjoiNDIuMzkuMSIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsiaW1hZ2UiXX0=-->

Reviewed-on: https://gitea.alexlebens.dev/alexlebens/infrastructure/pulls/2664
Co-authored-by: Renovate Bot <renovate-bot@alexlebens.net>
Co-committed-by: Renovate Bot <renovate-bot@alexlebens.net>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant