Skip to content

feat: résolution Premium → Debrid → Free et plugins Real-Debrid / AllDebrid (MAT-142)#183

Open
mpiton wants to merge 4 commits into
mainfrom
feat/mat-142-debrid-services
Open

feat: résolution Premium → Debrid → Free et plugins Real-Debrid / AllDebrid (MAT-142)#183
mpiton wants to merge 4 commits into
mainfrom
feat/mat-142-debrid-services

Conversation

@mpiton

@mpiton mpiton commented Jul 20, 2026

Copy link
Copy Markdown
Owner

Ferme MAT-142. Deux plugins debrid, une cascade de résolution configurable, et les entrées registry correspondantes.

Ce qui change côté hôte

La résolution d'un lien ne prenait plus le premier plugin qui revendiquait l'URL. Elle parcourt maintenant les niveaux dans l'ordre défini dans Settings → Downloads (Premium → Debrid → Free par défaut) et retient, pour chaque lien, le plugin et le compte à utiliser. Chaque niveau qui décline enregistre pourquoi, donc une cascade épuisée nomme les rungs essayés au lieu d'échouer sur un « aucune source » nu (R-04).

resolve_url trie désormais les plugins Debrid en dernier : sur l'ordre alphabétique seul, vortex-mod-alldebrid volait les URLs que vortex-mod-mediafire possède.

Un config.toml édité à la main ne peut plus casser la cascade : un niveau inconnu fait échouer le chargement bruyamment, une liste partielle ou dupliquée est renormalisée vers les trois niveaux.

Les deux plugins

Les deux passent le lien à leur API, renvoient l'URL CDN directe, et ne retournent jamais vers la page d'origine (R-02). Le token vit dans le keyring, lu via get_credential ; il n'est ni loggé, ni persisté, ni recopié dans un message d'erreur — y compris quand serde échoue sur le payload de credential, où l'erreur d'origine est volontairement jetée parce qu'elle cite la valeur fautive (R-05).

Les codes d'erreur de chaque service sont mappés sur les codes machine de l'hôte pour que la cascade sache pourquoi un niveau décline. Le sens du mapping compte : un code ACCOUNT_* fait cesser à l'hôte d'utiliser le compte pour tous les hosters, donc une panne qui appartient au hoster ou au service debrid n'est jamais classée comme telle. Deux codes AllDebrid étaient du mauvais côté et ont été corrigés — LINK_HOST_UNAVAILABLE (hoster HS) et NO_SERVER (AllDebrid saturé) désactivaient un abonnement payant valide pour une panne tierce.

AllDebrid répond HTTP 200 sur presque tous ses échecs, donc l'enveloppe est parsée avant que quoi que ce soit soit traité comme un succès.

Registry

Les checksums viennent des SHA256SUMS produits par la CI de chaque plugin, pas d'un build local : les artefacts WASM ne sont pas reproductibles bit à bit hors runner. Vérifiés en retéléchargeant les assets publiés.

Les deux entrées exigent Vortex 0.3.0 — c'est la version qui apporte la cascade. Sur un hôte plus ancien, un plugin debrid n'est qu'un revendiquant d'URL de plus et passerait devant le plugin hoster qui possède le domaine.

Écart assumé sur R-01

R-01 demande « trafic restant + expiration ». Seule l'expiration est remontée. Aucun des deux services n'expose un quota scalaire en octets : limitedHostersQuotas d'AllDebrid compte des téléchargements par hoster et par jour, et les limites Real-Debrid sont une map par hôte derrière /traffic. L'UI formate ces champs avec formatBytes, donc les remonter afficherait un chiffre faux. La vue Accounts dégrade proprement sur « inconnu ». Documenté dans les deux READMEs.

Tests

1817 tests Rust et 747 tests front passent. Chaque plugin a des tests de parsing sur payloads capturés plus un smoke test qui charge le vrai artefact WASM release et appelle chaque export à travers l'ABI Extism réelle, host functions stubbées comprises. Les deux CI plugin sont vertes et les releases v1.0.0 publiées.

Ce que les tests ne couvrent pas : l'ordonnancement Debrid en dernier dans resolve_url n'a pas de test automatisé — le dépôt hôte n'a aucune fixture WASM et en ajouter une pour une ligne de tri coûterait plus que ce qu'elle protège. La cascade elle-même, qui est le vrai mécanisme de R-03, est testée avec des mocks in-memory des deux services.


Summary by cubic

Adds debrid support with a configurable Premium → Debrid → Free resolution order and safer fallbacks with clear reasons. Addresses MAT-142 by integrating vortex-mod-realdebrid and vortex-mod-alldebrid to expand host coverage.

  • New Features

    • Debrid plugins: vortex-mod-realdebrid and vortex-mod-alldebrid return direct CDN links via keyring-held tokens, map service errors to host codes, and parse AllDebrid’s 200-error envelope.
    • Resolution cascade: the host walks the order set in Settings → Downloads, choosing the plugin and account before any hoster is contacted; every declined tier records why. Debrid plugins are ordered after hosters during URL claiming.
    • Settings/API: new “Resolution priority” UI with i18n; resolution_order added to IPC and config with validation and normalization.
    • Registry: both plugins added with CI SHA256 checksums and a minimum Vortex version of 0.3.0.
    • Tests: cascade walk and download-time fallback tests, plus UI tests for the setting.
  • Bug Fixes

    • Debrid that fails at download time now falls through to anonymous hoster extraction; when no rung delivers, ResolutionExhausted lists all reasons. Captcha challenges pass through, and premium never downgrades to free.
    • Fallthrough targets only hosters, never a second debrid, avoiding misreporting the free rung.
    • IPC hardening: resolution tier identifiers are length-bounded to prevent oversized error strings.

Written for commit f9f0cec. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • New Features
    • Added support for Real-Debrid and AllDebrid, including premium expiry reporting.
    • Introduced a configurable Premium → Debrid → Free resolution order for link resolution and hoster extraction.
  • Bug Fixes
    • Improved debrid/free fallback behavior with clearer multi-tier error reporting when all rungs are exhausted.
    • Hardened IPC/config handling by rejecting oversized resolution tier identifiers.
  • Documentation
    • Updated changelog and added localized UI strings for the new resolution order setting.
  • Tests
    • Added/updated unit and UI tests covering tier ordering, fallback scenarios, and settings behavior.

mpiton added 2 commits July 20, 2026 15:29
…ster

Link resolution used to pick the first plugin that claimed a URL. It now
walks the resolution tiers in the order set under Settings → Downloads and
records why each rung declined, so an exhausted cascade names every tier it
tried instead of failing as a bare "no source".

A hand-edited config can no longer disable a rung: an unknown tier fails the
load loudly, and a partial or duplicated list is normalised back to the full
three-tier order.

Refs MAT-142
Checksums come from each plugin's CI release SHA256SUMS, not a local build:
the WASM artefacts are not byte-reproducible off the runner.

Both entries require Vortex 0.3.0, the release that introduces the
Premium → Debrid → Free cascade. On an older host a debrid plugin is just
another URL claimant and would outrank the hoster plugin that owns the
domain.

Refs MAT-142
@qodo-code-review

Copy link
Copy Markdown

Qodo reviews are paused for this user.

Troubleshooting steps vary by plan Learn more →

On a Teams plan?
Reviews resume once this user has a paid seat and their Git account is linked in Qodo.
Link Git account →

Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center?
These require an Enterprise plan - Contact us
Contact us →

@github-actions github-actions Bot added documentation Improvements or additions to documentation rust frontend ui labels Jul 20, 2026
@coderabbitai

coderabbitai Bot commented Jul 20, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds a configurable Premium → Debrid → Free link-resolution cascade, persists and exposes its ordering, discovers eligible Debrid plugins and accounts, reports exhausted tiers, supports Debrid-to-free fallback, and provides a sortable localized settings control.

Changes

Resolution cascade

Layer / File(s) Summary
Resolution configuration contracts
src-tauri/src/domain/model/config.rs, src-tauri/src/adapters/driven/config/toml_config_store.rs, src-tauri/src/adapters/driving/tauri_ipc.rs, src/types/settings.ts
Adds tier types, normalization, persistence, IPC validation and serialization, and frontend configuration typing.
Plugin capability discovery
src-tauri/src/domain/ports/driven/plugin_loader.rs, src-tauri/src/adapters/driven/plugin/extism_loader.rs
Adds targeted plugin URL checks and deprioritizes Debrid plugins during initial URL ownership resolution.
Tier walking and link resolution
src-tauri/src/application/commands/resolve_links_tiers.rs, src-tauri/src/application/commands/resolve_links.rs, src-tauri/src/domain/error.rs, src-tauri/src/application/commands/resolve_links_tiers_tests.rs
Selects Premium, Debrid, or Free plans, carries module and account data through hoster resolution, and records per-tier exhaustion reasons.
Debrid download fallback
src-tauri/src/application/commands/hoster_download_source.rs, src-tauri/src/application/commands/hoster_download_source_tests.rs
Falls back from failed Debrid extraction to anonymous hoster extraction and combines Debrid and Free failure details when both fail.
Cascade settings UI
src/views/SettingsView/*, src/i18n/locales/*, src/**/__tests__/*
Adds sortable tier controls, localized labels, and updated configuration fixtures.
Plugin registry and release metadata
registry/registry.toml, CHANGELOG.md
Registers Real-Debrid and AllDebrid plugins and documents the cascade and fallback behavior.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant SettingsView
  participant TauriIPC
  participant ConfigStore
  participant CommandBus
  participant PluginLoader
  participant AccountRotator
  User->>SettingsView: reorder resolution tiers
  SettingsView->>TauriIPC: submit resolution_order
  TauriIPC->>ConfigStore: validate and persist configuration
  CommandBus->>ConfigStore: read resolution_order
  CommandBus->>PluginLoader: check eligible Debrid plugins
  CommandBus->>AccountRotator: select account for chosen tier
  AccountRotator-->>CommandBus: return module and account_id
  CommandBus-->>User: return resolved link or tier exhaustion details
Loading

Possibly related PRs

  • mpiton/vortex#171: Modifies premium-account context and hoster-resolution plumbing used by this cascade.

Suggested labels: configuration

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 69.35% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main changes: configurable Premium→Debrid→Free resolution and the new Real-Debrid/AllDebrid plugins.

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
src-tauri/src/application/commands/resolve_links_tiers.rs (1)

62-78: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Premium exhaustion aborts the cascade — add a test for this path.

premium_tier returns Err(AppError::Domain(...)) on AllExhausted (line 72), which ? propagates immediately, aborting the entire cascade. This is the documented design ("the caller waits for the cooldown rather than silently downgrading"), but no test exercises this path. The existing tests only cover NoneAvailable (no accounts) and QuotaExhausted for debrid. A premium account in cooldown should error out rather than fall through to Debrid/Free — this behavior should be explicitly tested to prevent regressions.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src-tauri/src/application/commands/resolve_links_tiers.rs` around lines 62 -
78, Add a test covering the `premium_tier` `NextAccountOutcome::AllExhausted`
path, configuring a premium account in cooldown and invoking the cascade. Assert
that it returns `Err(AppError::Domain(...))` and does not fall through to Debrid
or Free tiers, preserving the documented cooldown behavior.
src-tauri/src/application/commands/resolve_links_tiers_tests.rs (1)

118-128: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

AccountType::Debrid is used for all accounts including the hoster premium account.

The account() helper hardcodes AccountType::Debrid for every account, including the premium hoster account at line 156 (account("premium-1", HOSTER, ...)). If the account rotator ever filters by AccountType, these tests would silently produce wrong results. Consider parameterizing AccountType or at least using a more appropriate type for hoster accounts.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src-tauri/src/application/commands/resolve_links_tiers_tests.rs` around lines
118 - 128, Update the account helper to accept an AccountType parameter and pass
it into Account::new, then provide the appropriate type at each call site,
including AccountType::Debrid for debrid accounts and the hoster account’s
correct type for premium-1. Preserve the existing status setup and test
behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src-tauri/src/adapters/driven/plugin/extism_loader.rs`:
- Around line 473-476: Update the plugin selection logic around the infos
sorting and resolve_url flow to exclude PluginCategory::Debrid entries from URL
ownership candidates entirely, rather than merely sorting them last. Preserve
Debrid discovery through debrid_plugins_covering for its fallback tier, allowing
unclaimed HTTP URLs to reach HttpModule without requiring a Debrid account.

---

Nitpick comments:
In `@src-tauri/src/application/commands/resolve_links_tiers_tests.rs`:
- Around line 118-128: Update the account helper to accept an AccountType
parameter and pass it into Account::new, then provide the appropriate type at
each call site, including AccountType::Debrid for debrid accounts and the hoster
account’s correct type for premium-1. Preserve the existing status setup and
test behavior.

In `@src-tauri/src/application/commands/resolve_links_tiers.rs`:
- Around line 62-78: Add a test covering the `premium_tier`
`NextAccountOutcome::AllExhausted` path, configuring a premium account in
cooldown and invoking the cascade. Assert that it returns
`Err(AppError::Domain(...))` and does not fall through to Debrid or Free tiers,
preserving the documented cooldown behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c73772e1-839d-4f00-83ae-210ca9d92394

📥 Commits

Reviewing files that changed from the base of the PR and between e4f01c9 and 7752d19.

📒 Files selected for processing (26)
  • CHANGELOG.md
  • registry/registry.toml
  • src-tauri/src/adapters/driven/config/toml_config_store.rs
  • src-tauri/src/adapters/driven/plugin/extism_loader.rs
  • src-tauri/src/adapters/driving/tauri_ipc.rs
  • src-tauri/src/application/commands/mod.rs
  • src-tauri/src/application/commands/resolve_links.rs
  • src-tauri/src/application/commands/resolve_links_tiers.rs
  • src-tauri/src/application/commands/resolve_links_tiers_tests.rs
  • src-tauri/src/application/commands/tests_support.rs
  • src-tauri/src/domain/error.rs
  • src-tauri/src/domain/model/config.rs
  • src-tauri/src/domain/ports/driven/plugin_loader.rs
  • src/components/__tests__/ClipboardIndicator.test.tsx
  • src/hooks/__tests__/useAppEffects.test.ts
  • src/i18n/locales/en.json
  • src/i18n/locales/fr.json
  • src/layouts/__tests__/AppLayout.test.tsx
  • src/stores/__tests__/settingsStore.test.ts
  • src/types/settings.ts
  • src/views/LinkGrabberView/__tests__/LinkGrabberView.test.tsx
  • src/views/SettingsView/DownloadsSection.tsx
  • src/views/SettingsView/ResolutionOrderSetting.tsx
  • src/views/SettingsView/__tests__/ResolutionOrderSetting.test.tsx
  • src/views/SettingsView/__tests__/Sections.test.tsx
  • src/views/SettingsView/__tests__/SettingsView.test.tsx

Comment thread src-tauri/src/adapters/driven/plugin/extism_loader.rs
@codspeed-hq

codspeed-hq Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will degrade performance by 7.84%

⚠️ Different runtime environments detected

Some benchmarks with significant performance changes were compared across different runtime environments,
which may affect the accuracy of the results.

Open the report in CodSpeed to investigate

⚡ 1 improved benchmark
❌ 4 regressed benchmarks
✅ 21 untouched benchmarks

Warning

Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Benchmark BASE HEAD Efficiency
from_status_code_500 125.6 ns 154.7 ns -18.85%
apply_patch_many_fields 4.7 µs 5.7 µs -17.35%
from_status_code_404 154.7 ns 183.9 ns -15.86%
reject_invalid 522.8 ns 581.1 ns -10.04%
from_status_code_200 123.3 ns 94.2 ns +30.97%

Tip

Investigate this regression by commenting @codspeedbot fix this regression on this PR, or directly use the CodSpeed MCP with your agent.


Comparing feat/mat-142-debrid-services (f9f0cec) with main (e4f01c9)

Open in CodSpeed

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

cubic analysis

All reported issues were addressed across 26 files

Linked issue analysis

Linked issue: MAT-142: [Lot 4] Intégrer les services debrid Real-Debrid et AllDebrid

Status Acceptance criteria Notes
⚠️ R-01 — An added Real‑Debrid or AllDebrid account is validated against the real service and shows traffic remaining + expiration. Account validation and expiry are implemented and surfaced. The PR explicitly documents a scoped deviation: services do not expose a reliable scalar bytes quota, so only expiration is reported and 'remaining traffic' degrades to “unknown”.
R-02 — A link covered by a configured debrid is unrestrict’ed and downloaded from the direct CDN URL (never from the page origin). Debrid plugins return direct CDN URLs and the host uses that module/account for the download; tests exercise the cascade and the extractor returns direct_url. Plugin repos include smoke/native tests and CI for their WASM.
R-03 — The Premium → Debrid → Free order is respected and reconfigurable; hoster-specific premium accounts outrank debrid by default. A domain-level ResolutionTier and default order were added, normalization and persistence are implemented, a Settings UI to reorder tiers was added, and unit/integration tests validate default precedence and reordering behaviour.
R-04 — Debrid failures (quota/hoster not covered/panic) fall through cleanly to the next tier with explicit reasons; no false “success”. Cascade accumulates per‑tier decline reasons and returns a ResolutionExhausted error; host surfaces the composed explanation rather than a bare ‘no source’. Tests assert the exhausted cascade message includes the rungs tried.
R-05 — Tokens live in the keyring only; no secrets persisted in SQLite, config or logs. Plugins and host are using the credential/keyring API (get_credential) and the PR states tokens are not logged or persisted. Tests and test harness use credential stores that exercise the keyring path.
⚠️ R-06 — Tests: handlers with in‑memory mocks for both services, native plugin tests, CI green, registry with checksums in CI. The PR adds extensive domain and UI tests and the plugin repos are reported as having native/smoke tests and green CI. One explicit gap is noted: there is no automated test for the specific resolver ordering change that forces Debrid plugins to be considered last in resolve_url (an uncovered, low‑risk sorting fixture).

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread src-tauri/src/application/commands/resolve_links_tiers.rs
Comment thread src-tauri/src/domain/error.rs
Comment thread src-tauri/src/adapters/driving/tauri_ipc.rs Outdated
The link check picks a debrid while it is healthy and persists the module
and account, but resolution at download time only rotates within that
module and HosterNoFile is not rotatable. A quota spent since the check, a
hoster dropped from coverage, or an outage therefore left the download in
error instead of trying the next configured tier (MAT-142 R-04).

Only the free rung is retried, and only for Debrid modules. Premium is
deliberately not: any premium account for the hoster was already offered
this link at check time and lost to the debrid. CaptchaRequired stays
unwrapped so the engine can still answer the challenge; anything else
reports both reasons through ResolutionExhausted.

Also bounds resolution tier identifiers arriving over IPC, since the parse
error quotes what it rejected, and drops the per-call Vec allocation in
normalize_resolution_order.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src-tauri/src/application/commands/hoster_download_source.rs`:
- Around line 111-136: Update free_tier_source to require the plugin returned by
plugins.resolve_url for the URL to be in the Hoster category before calling
extract_hoster_link. Preserve the existing same-module exclusion and
debrid_error fallback, and ensure other Debrid-category plugins return the
original debrid error without being invoked; add coverage for two distinct
Debrid plugins if the existing test setup permits it.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 076faa04-f37b-4cb7-9325-2748c18588b2

📥 Commits

Reviewing files that changed from the base of the PR and between 7752d19 and 39d2c14.

📒 Files selected for processing (7)
  • CHANGELOG.md
  • src-tauri/src/adapters/driving/tauri_ipc.rs
  • src-tauri/src/application/commands/hoster_download_source.rs
  • src-tauri/src/application/commands/hoster_download_source_tests.rs
  • src-tauri/src/application/commands/resolve_links_tiers_tests.rs
  • src-tauri/src/domain/error.rs
  • src-tauri/src/domain/model/config.rs
🚧 Files skipped from review as they are similar to previous changes (5)
  • CHANGELOG.md
  • src-tauri/src/domain/error.rs
  • src-tauri/src/adapters/driving/tauri_ipc.rs
  • src-tauri/src/application/commands/resolve_links_tiers_tests.rs
  • src-tauri/src/domain/model/config.rs

Comment thread src-tauri/src/application/commands/hoster_download_source.rs

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

All reported issues were addressed across 7 files (changes from recent commits).

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread CHANGELOG.md
resolve_url keeps debrid candidates and merely orders them last, so for a
URL no hoster claims the runner-up is another debrid. The same-module
guard let that through: the fall-through called it without credentials and
labelled the refusal "free", naming a rung that was never tried.

Requires PluginCategory::Hoster on the resolved plugin, so the debrid's own
error stands when no free rung covers the URL.
@mpiton

mpiton commented Jul 20, 2026

Copy link
Copy Markdown
Owner Author

CodSpeed: what is real and what is not

Two separate things in that report.

apply_patch_many_fields (4.7 → 5.6 µs) is real and inherent to the feature. The benchmark builds AppConfig::default() inside the iteration loop, and this PR adds one field to AppConfig: resolution_order: Vec<ResolutionTier>. That is one extra heap allocation and free per iteration, on top of the handful the existing String fields already do. The benchmark's patch leaves resolution_order at None, so normalize_resolution_order never even runs — the cost is purely constructing and dropping the default.

I already took the one free win here: normalize_resolution_order was calling default_resolution_order() to build a throwaway Vec on every call, now a private const array. That moved it 5.7 → 5.6 µs, which confirms the remaining cost is the field itself.

The only way to get the rest back is making the field a fixed [ResolutionTier; 3]. It is defensible — normalization guarantees all three tiers are always present, so the Vec length is an invariant the type does not express — but it changes the type across 17 files spanning serde, the TOML store, the IPC DTOs and the frontend. That is not worth sub-microsecond on a path that runs when a user saves settings. Leaving it, and flagging it here rather than quietly acknowledging it.

The three from_status_code_* entries are measurement noise. LinkStatus::from_status_code is not touched by this PR. The values shifted within the group:

BASE HEAD
from_status_code_200 123.3 ns 94.2 ns
from_status_code_500 125.6 ns 154.7 ns
from_status_code_404 154.7 ns 183.9 ns

from_status_code_500's HEAD value is from_status_code_404's BASE value to four significant figures. Under Simulation mode that is code layout shifting under instruction counting, not three benchmarks independently moving 16-31% in opposite directions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

configuration documentation Improvements or additions to documentation frontend rust ui

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant