Skip to content

feat(arrs): unified queue cleanup across all *arr types + health UI theming#656

Closed
yoshitaka420 wants to merge 12 commits into
javi11:mainfrom
yoshitaka420:feat/arrs-queue-cleanup-and-health-ui
Closed

feat(arrs): unified queue cleanup across all *arr types + health UI theming#656
yoshitaka420 wants to merge 12 commits into
javi11:mainfrom
yoshitaka420:feat/arrs-queue-cleanup-and-health-ui

Conversation

@yoshitaka420
Copy link
Copy Markdown
Contributor

Summary

This bundles two areas of work on top of main, plus removal of unused scaffolding:

  1. A rewrite of the arrs queue-cleanup subsystem into a single unified pass that covers all six *arr types.
  2. Health-page UI cleanup and theme-consistent colors.

Arrs queue cleanup (unified)

  • *One cleanup pass for all 6 arr types (radarr / sonarr / whisparr / lidarr / readarr / sportarr). Ghost / empty-folder detection (file already imported, or source path gone) runs grace-free, then message rules are applied. Previously ghost cleanup only ran for radarr/sonarr/sportarr — whisparr/lidarr/readarr never got it.
  • Unified message-rule model (queue_cleanup_rules): each rule is { message, enabled, action } where action ∈ remove | blocklist | blocklist_search. One enable toggle and one grace period (default 5 min). Replaces the old split "stuck cleanup" list + "allowlist" + the "Purge Automatic Failures" toggle.
  • Removed the cleanup_automatic_import_failure toggle. It was a hardcoded single-phrase, remove-only rule that duplicated and shadowed the rules system (it ran before the rule pass) and only covered 3 of the 6 types. It's folded into the rules (seeded disabled on fresh installs); migrateArrsCleanup enables a matching rule when the legacy toggle was on. The field is kept deprecated for one-time migration only.
  • Config migration (migrateArrsCleanup): folds legacy configs (stuck rules + allowlist + enable flag + grace period + the toggle) into the unified model on load and drops the deprecated keys from saved YAML, so existing setups upgrade without losing custom entries. Unit tests cover append / enable-existing / enable-substring / no-op cases.
  • Ownership matching fix: recognize the AltMount SABnzbd download client case-insensitively (registrar.IsAltmountDownloadClient), so manually-added clients named e.g. Altmount are no longer skipped. Only items owned by AltMount's download client are ever touched (issue Arr Webhooks removes failed downloads of other Download Clients #523).
  • Sportarr config-response fix: Sportarr instances were saved to disk but omitted from the arrs config API response, so they vanished from the UI on reload.
  • Validation: reject unknown queue_cleanup_rules actions in Config.Validate (both the API-save and config-load paths); empty action is still allowed and treated as remove at runtime.

Frontend

  • Collapsed the two cleanup config sections into a single Queue Cleanup section; restored the add-rule input; clearer interval vs. grace-period copy; Cleanup Interval and Grace Period shown side-by-side.

Docs

  • Synced config.sample.yaml and the integration guide to the unified queue_cleanup_rules model (dropped deprecated toggle/allowlist references, documented the rule actions, corrected the grace-period default to 5).

Health UI

  • Theme-consistent colors across provider + indexer health: replace hardcoded tailwind palette / rgba glows with daisyUI theme tokens (success / warning / error / primary, var(--color-*)), so colors follow the active theme; fix a stale daisyUI v4 tooltip var.
  • Indexer health: drop the best/worst performer chips, persist the chosen sort (key + direction) to localStorage, and remove the HUD comparison chart.
  • Convert filter/sort role=group divs to <fieldset> for accessibility.

Housekeeping

  • Remove unused / dead scaffolding that is no longer referenced anywhere (an uninstantiated library-item finder, unused post-processor interfaces, unused metadata/utility helpers, etc.). No behavior change.

Testing

  • go build ./..., go vet ./internal/..., go test ./internal/config/... ./internal/arrs/... — all pass.
  • Frontend bun run check + bun run build — pass.
  • Full CI green on the source branch (Run Tests, Build Frontend, Dev Image AMD64/ARM64, CLI binaries).

Add automatic cleanup of imports that get stuck on known *arr errors,
configurable via a grace period and per-message action rules
(remove / blocklist / blocklist + search). Runs on the cleanup
interval or on demand from the Queue page.

Squashed from the feature's iterative development: initial
implementation, API-response config persistence, removal of the
manual cleanup dropdown and dead endpoint, and the Queue Cleanup
rename with friendlier UI copy.
… sort, theme-consistent colors

- remove the best/worst performer chips (Highest efficiency rating / Needs telemetry inspection)
- persist the chosen sort (key + direction) to localStorage so it survives refresh
- replace hardcoded teal/emerald/amber/rose/slate + rgba with daisyUI theme tokens (success/warning/error/primary) so colors follow the active theme
- convert filter/sort role=group divs to fieldset (a11y)
Replace hardcoded tailwind palette colors and rgba glows with daisyUI
theme tokens across the provider health UI, matching the indexer health page:
- charts: palette + tooltip/cursor sourced from theme vars (var(--color-*))
  instead of fixed hex; fixed stale daisyUI v4 hsl(var(--bc/--b1)) tooltip
- provider table badges/dots: emerald/amber/rose -> success/warning/error
- quota vials + slate text: themed via base/success/warning/error tokens
  (index.css vial liquid/glass), drop hardcoded glow shadows
Bring back the input bar for adding custom *arr error-match rules, and
reword the grace-period and error-rules help text to read more clearly.
Collapse the two overlapping arrs cleanup features into one. The
rules-with-actions model (remove / blocklist / blocklist+search) is now
the single message-rule list (queue_cleanup_rules), governed by one
enable toggle and one grace period (default 5 min). Ghost/empty-folder
detection and the Purge Automatic Failures toggle remain as separate
non-message mechanisms.

The former queue-cleanup allowlist is gone: its entries are equivalent
to rules with action 'remove'. migrateArrsCleanup folds legacy configs
(stuck rules + allowlist + enable flag + grace) into the unified model
on load and drops the deprecated fields from saved YAML, so existing
setups upgrade without losing custom entries.

Frontend collapses the two config sections into one Queue Cleanup
section. Adds migration unit tests.
… rule

Sportarr instances were saved to disk but omitted from the arrs config
API response, so they vanished from the UI on reload. Add SportarrInstances
to the response struct and mapping.

Also remove the default 'Sample file' cleanup rule (the substring 'Sample'
rule already covers it) and make the legacy-config migration skip allowlist
entries already matched by an existing rule, so no dead duplicate rules are
carried over.
Add a one-line description to Cleanup Interval (how often queues are
checked) and reword Cleanup Grace Period to cover both stuck and failed
imports (how long one must persist before cleanup acts), so the two
fields read distinctly. Align the grace-period input default with the
backend (5 min).
…ive auto-import match

Queue cleanup gated every pass on the download client name matching the
literal "AltMount (SABnzbd)". Users who add the SABnzbd client manually
under another name (e.g. "Altmount") were never recognized, so cleanup
skipped all their items. Add registrar.IsAltmountDownloadClient (case-
insensitive "altmount" match) and use it in all four ownership checks.

Also match the 'automatic import is not possible' phrase case-insensitively
in the auto-failure purge — *arrs emit it mid-sentence (e.g. 'Movie title
mismatch, automatic import is not possible.'), which the exact-case check
missed. Add a unit test for the client-name matcher.
… across all arrs

Remove the cleanup_automatic_import_failure toggle — it was a hardcoded
single-phrase remove-only rule that duplicated the unified rules system,
ran before the rule pass (shadowing user rules), and only covered
radarr/sonarr/sportarr.

- Fold it into the rules: seed a default 'automatic import is not possible'
  rule (disabled, action remove). migrateArrsCleanup enables a matching/
  substring rule (or appends one) when the legacy toggle was on, then drops
  the flag. Field kept deprecated for one-time migration only.
- Unify ghost/empty-folder detection into the single all-types cleanup pass:
  stuckItem now carries OutputPath, and ghost detection runs grace-free
  before rule matching in selectStuckActions. Deletes the old
  radarr/sonarr/sportarr-only CleanupQueue path. Whisparr/Lidarr/Readarr now
  get ghost cleanup too, and the auto-failure phrase is handled for all six
  via the rule pass.
- Drop the field from the API response and frontend; show Cleanup Interval
  and Grace Period side-by-side. Add migration tests (append / enable-existing
  / enable-substring / false-clears).
- Docs: sync config.sample.yaml and the integration guide to the unified
  queue_cleanup_rules model (drop the deprecated toggle and allowlist refs,
  document the rule actions, correct the grace-period default to 5).
…p scaffold

Reject unknown queue_cleanup_rules actions in Config.Validate (empty still
allowed, treated as "remove" at runtime). Covers both the API-save path
(ValidateConfigUpdate) and config load.

Remove the unused force parameter and StuckCleanupResult/InstanceCleanupResult
types from CleanupStuckQueue and its helpers — the manual-trigger endpoint that
used them is gone, so the periodic tick is the only caller. Grace-period bypass
is preserved via the gracePeriod <= 0 branch.
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.

1 participant