Add the arr-subs crate with the provider trait #184

Closed
opened 2026-08-24 21:28:31 +01:00 by naps62-yolo · 1 comment
Owner

Create crates/arr-subs, the crate that owns everything subtitle-shaped that
touches the outside world: providers, extraction, translation backends and the
alass wrapper. Selection and ranking rules stay pure in arr-core (#185),
the same way arr-probe shells out to ffprobe while the policy engine that
consumes its output does not.

Scope for this issue is the skeleton the rest of the milestone builds on:

  • Workspace member, [lints] workspace = true, dependencies referenced by name
    from [workspace.dependencies] per CLAUDE.md.
  • The domain types a provider deals in: a subtitle language (carrying the
    pt-PT / pt-BR distinction arr-probe's language module already resolves),
    a candidate with the fields ranking needs — provider, hash match, release
    name, group, source, rating, download count, forced flag, SDH flag — and the
    fetched result.
  • A Provider trait: search for candidates for a media file, download one by
    id. Async, error type per the crate's own error.rs, no provider
    implementations yet.
  • The cargo feature skeleton for translation backends, with every feature
    declared and no backend behind them yet.

Non-goals: any provider implementation, any translation code, any ranking
logic. Those are separate issues and this one must not anticipate their
interfaces beyond the trait above.

See DESIGN.md §15 (added by #183) for the wanted-set and provider decisions.

Depends on: #183

Create `crates/arr-subs`, the crate that owns everything subtitle-shaped that touches the outside world: providers, extraction, translation backends and the `alass` wrapper. Selection and ranking rules stay pure in `arr-core` (#185), the same way `arr-probe` shells out to `ffprobe` while the policy engine that consumes its output does not. Scope for this issue is the skeleton the rest of the milestone builds on: - Workspace member, `[lints] workspace = true`, dependencies referenced by name from `[workspace.dependencies]` per `CLAUDE.md`. - The domain types a provider deals in: a subtitle language (carrying the pt-PT / pt-BR distinction `arr-probe`'s `language` module already resolves), a candidate with the fields ranking needs — provider, hash match, release name, group, source, rating, download count, forced flag, SDH flag — and the fetched result. - A `Provider` trait: search for candidates for a media file, download one by id. Async, error type per the crate's own `error.rs`, no provider implementations yet. - The cargo feature skeleton for translation backends, with every feature declared and no backend behind them yet. Non-goals: any provider implementation, any translation code, any ranking logic. Those are separate issues and this one must not anticipate their interfaces beyond the trait above. See DESIGN.md §15 (added by #183) for the wanted-set and provider decisions. Depends on: #183
naps62-yolo added this to the Subtitles milestone 2026-08-24 21:28:31 +01:00
naps62-yolo added the area/substype/featuredifficulty/moderatephase/9-subtitles labels 2026-08-24 21:28:31 +01:00
naps62-yolo added a new dependency 2026-08-24 21:29:17 +01:00
naps62-yolo added a new dependency 2026-08-24 21:29:27 +01:00
naps62-yolo added a new dependency 2026-08-24 21:29:27 +01:00
naps62-yolo added a new dependency 2026-08-24 21:29:27 +01:00
naps62-yolo added a new dependency 2026-08-24 21:29:27 +01:00
naps62-yolo added a new dependency 2026-08-24 21:29:27 +01:00
Author
Owner

Added crates/arr-subs as a workspace member with [lints] workspace = true and dependencies referenced by name from [workspace.dependencies]. The crate carries the domain types a provider deals in — ProviderId and CandidateId newtypes, MediaRef/MediaFile/SearchRequest for the file being searched for, Candidate with the facts §15's ranking needs (hash match, release name, group, source, rating, download count, forced, SDH), and Fetched with a SubtitleFormat. Language is arr_core::Language, so the pt-PT / pt-BR distinction arr-probe's language module already resolves is reused rather than duplicated. The Provider trait has id, search and download, using boxed futures like arr-daemon's Action trait so it stays object safe — the enabled provider set is a database setting (#198), not a compile-time fact. Errors live in error.rs, each variant naming the provider, with RateLimited split out so #197 can render a cap as a queue state rather than a failure. The four translation-backend cargo features (translate-openai, translate-deepl, translate-google, translate-command) are declared with no backend behind them. No provider implementation, no translation code, no ranking.

Branch: subtitles/184-subs-crate

just ci passed: 473 tests, clippy clean, cargo machete clean, web-check clean.

Findings

  • #187 and this trait disagree about what a download returns. #187 says "download a chosen candidate to a temporary path"; the trait returns the bytes in Fetched.content instead. Bytes were chosen because what happens next is not the provider's call — alass runs over it (#194) before it gets a name and a place in the title folder (#195), and a provider that writes temp files also owns cleaning them up. If the temp-path shape is wanted, it should change here rather than in one provider.
  • arr_core::SubtitleTrack cannot express a forced embedded track. It carries only language. §15 says a forced track never satisfies a want, so #186 and #189 will record a forced embedded track as satisfying its language and the reconcile loop will stop looking. #189 already covers adding the codec to that struct (text versus bitmap); the forced disposition flag is not in any issue I can find and probably belongs to the same probe change.
Added `crates/arr-subs` as a workspace member with `[lints] workspace = true` and dependencies referenced by name from `[workspace.dependencies]`. The crate carries the domain types a provider deals in — `ProviderId` and `CandidateId` newtypes, `MediaRef`/`MediaFile`/`SearchRequest` for the file being searched for, `Candidate` with the facts §15's ranking needs (hash match, release name, group, source, rating, download count, forced, SDH), and `Fetched` with a `SubtitleFormat`. Language is `arr_core::Language`, so the pt-PT / pt-BR distinction `arr-probe`'s `language` module already resolves is reused rather than duplicated. The `Provider` trait has `id`, `search` and `download`, using boxed futures like `arr-daemon`'s `Action` trait so it stays object safe — the enabled provider set is a database setting (#198), not a compile-time fact. Errors live in `error.rs`, each variant naming the provider, with `RateLimited` split out so #197 can render a cap as a queue state rather than a failure. The four translation-backend cargo features (`translate-openai`, `translate-deepl`, `translate-google`, `translate-command`) are declared with no backend behind them. No provider implementation, no translation code, no ranking. Branch: `subtitles/184-subs-crate` `just ci` passed: 473 tests, clippy clean, `cargo machete` clean, web-check clean. ## Findings - **#187 and this trait disagree about what a download returns.** #187 says "download a chosen candidate to a temporary path"; the trait returns the bytes in `Fetched.content` instead. Bytes were chosen because what happens next is not the provider's call — `alass` runs over it (#194) before it gets a name and a place in the title folder (#195), and a provider that writes temp files also owns cleaning them up. If the temp-path shape is wanted, it should change here rather than in one provider. - **`arr_core::SubtitleTrack` cannot express a forced embedded track.** It carries only `language`. §15 says a forced track never satisfies a want, so #186 and #189 will record a forced embedded track as satisfying its language and the reconcile loop will stop looking. #189 already covers adding the codec to that struct (text versus bitmap); the `forced` disposition flag is not in any issue I can find and probably belongs to the same probe change.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Reference: yolo/arr#184