#3267

feat(crossseed): route season pack adds to the Cross-seed instance

Opens0up4200opened 13d ago

Parent

#3256

What to build

PR 2. Season pack apply and manual season pack assembly follow the route of the instance that holds the matched torrents, with the same rules as the per-candidate add. Season pack history records the instance that received the add.

Acceptance criteria

  • The season pack add looks up the route of the winning instance. A match found on the Cross-seed instance stays on it.
  • The routed season pack add follows these rules:
    • The stored route must pass every route rule, or the add fails with "Cross-seed instance unavailable" and the reason.
    • The availability check runs after qui picks the winning instance. If the Cross-seed instance is unavailable, the add fails with "Cross-seed instance unavailable".
    • In the loop over eligible instances, qui checks the Cross-seed instance's hashes and its blocklist (not the Source instance's blocklist), and skips a hash that this run already added.
    • When the receiving instance is a Cross-seed instance, qui uses the shared Source instance hash check: a disabled Source instance is skipped, and an offline one fails the add and names it.
    • One capability read from the instance pool (Write) gives the Source instance's backend and row, and the row must be in local mode.
    • The Source instance's link settings decide the link mode and the folder preset. The "by-instance" preset uses the Cross-seed instance's name.
    • The route uses the base folder that qui picks after the cross-device retry from PR #3197.
    • qui maps the tree root and the category save path with the route path helper.
    • Before the add, qui runs the listing check with retries and the per-run memory from the check ticket, and removes the tree after a failed check.
    • The add, category, tags, recheck, resume, and hooks run on the Cross-seed instance. Auto management stays off.
    • The add never falls back to regular mode or to the Source instance. Link errors, unsupported filesystems, and failed adds keep their own statuses.
    • Partial-pool completion is off.
  • The season pack history table gets a column for the instance that received the add, with one SQLite and one Postgres migration under the rules in internal/database/AGENTS.md.
  • Tests through the season pack add: the add lands on the Cross-seed instance with mapped paths; a missing entry blocks the add and removes the tree; a hash on either instance skips it; the Cross-seed instance's blocklist applies; an unavailable Cross-seed instance fails without a fallback; a link error fails with its status; a match on the Cross-seed instance stays there and checks its Source instances' hashes; history records the receiving instance.
  • Swagger updated, make test-openapi passes.

Out of scope

  • Regular mode for routed cross-seeds.
  • Routing Dir Scan adds. Dir Scan always adds to its own target instance, even when that instance has a route. It only reads the Cross-seed instance's hashes to skip duplicates.

Merge order

Lands after PR #3197, which changes the season pack planner and its cross-device retry. PR #3120 also edits the season pack add. Whichever lands second adapts.

Rules for every ticket of #3256

  • "Unavailable" means one of these: offline, disabled in qui, or (for an add or a directory listing only) older than qBittorrent 5.0 (WebAPI 2.11.2). Use the shared availability check from the route storage ticket. Do not write a new one.
  • Tests talk only to local fakes and temp folders, never to a real host. Each new test fails before the change and passes after it.
  • No user-facing text mentions SSH. No text calls the Cross-seed instance "remote", because "remote instance" means an SSH instance. An error for an instance that is in remote mode can say "remote instance".
  • If the ticket changes the API, update internal/web/swagger and make sure that make test-openapi passes.
  • Glossary terms: Cross-seed instance (the instance that receives the cross-seeds found on another instance) and Source instance (an instance that names a Cross-seed instance and holds the matched torrents). Do not say "target instance" or "library instance" for these.
  • Delivery: tickets for PR 1 land on one integration branch that becomes PR 1. Tickets for PR 2 land on a second branch that becomes PR 2, after PR 1 merges. Do not merge one ticket to develop alone.

Activity

0

No activity yet.