github plexguide/Huntarr.io 9.4.3

7 hours ago

Release Notes — Resource Optimization & Scheduler Fixes

🧠 RAM Optimization — Media Hunt Disable Fully Stops Background Processes

Disabling Media Hunt in General Settings now completely halts all related background activity, reducing RAM usage to near-zero for those subsystems.

What's gated by enable_media_hunt = false:

Component Before After
NZB Hunt child process Stayed alive, respawned on crash Immediately killed, blocked from respawning
NZB Hunt idle watcher thread Ran every 60s unconditionally Checks flag → kills child if disabled, does no work
Tor Hunt child process Stayed alive, respawned on crash Immediately killed, blocked from respawning
Tor Hunt idle watcher thread Ran every 60s unconditionally Checks flag → kills child if disabled, does no work
Indexer Hunt health check Made network calls every hour Skips all work (including network calls) when disabled
Movie Hunt / TV Hunt background loops Ran full processing cycles Skips entirely, sleeps 60s between checks

Files Modified:

  • src/primary/apps/nzb_hunt/download_process.py — Added _media_hunt_enabled() check to _ensure_alive() and _start_idle_watcher()
  • src/primary/apps/tor_hunt/tor_hunt_process.py — Added _media_hunt_enabled() check to _ensure_alive() and _start_idle_watcher()
  • src/primary/routes/indexer_hunt/health.py — Gated _health_check_loop() behind enable_media_hunt flag
  • src/primary/background.py — Skips movie_hunt and tv_hunt processing cycles when disabled

Key Design Decision:

All checks use load_settings("general", use_cache=False) to bypass the 30-second settings cache, ensuring toggles take effect immediately without restarting.


🚫 P2P Disabled by Default (Tor Hunt)

Tor Hunt's P2P functionality is now disabled by default on new installs via the enable_p2p setting.

Behavior:

  • enable_p2p defaults to False when the setting is missing
  • When disabled:
    • TorHuntManager._p2p_enabled() returns False
    • No torrent child process is spawned
    • No libtorrent sessions are created
    • Zero RAM overhead from torrent subsystem
  • Uses use_cache=False for immediate toggle effect

Files Modified:

  • src/primary/apps/tor_hunt/tor_hunt_manager.py_p2p_enabled() defaults to False, reads fresh from DB

🔒 Requestarr API Gate — enable_requestarr Now Enforced Backend

Previously, disabling Requests in General Settings only hid the sidebar link. All API endpoints remained fully accessible.

Now:

  • All /api/requestarr/* routes return HTTP 503 with {"disabled": true} when enable_requestarr is false
  • Non-requestarr routes (like /api/settings/feature-flags) are not affected
  • Re-enabling restores full API access immediately

Implementation:

Uses app.before_request() with a path check — avoids Flask's restriction on modifying blueprints after registration.

Files Modified:

  • src/primary/web_server.py — Added _requestarr_gate() as app-level before_request handler

📅 Scheduler Fixes — Per-Instance Schedules for All Apps

Fixed a critical bug where per-instance schedules for Whisparr, Eros, and all other apps were silently being saved as "Global Apps" and lost on page refresh.

Root Cause (3 layers):

  1. Race condition on page load — Two competing populateInstanceDropdown functions existed: an inline script (fires at DOM parse time, before settings loaded) and a JS module (fires after async fetch). The inline version always ran first with empty data, setting the hidden scheduleApp field to global.

  2. Async dropdown overwrite — Every navigation to the Scheduling section triggered refreshSchedulingInstances(), which rebuilt the instance dropdown from scratch and destroyed the user's current selection.

  3. Bundle out of sync — The compiled bundle-features.js had the old code baked in without fixes.

Fixes Applied:

Fix Description
Event-driven re-population After async settings fetch completes, dispatches huntarr:scheduler-instances-ready event. The inline script listens for it and re-populates with real data.
Selection preservation populateInstanceDropdown() now saves previousVal before clearing options, then restores it after rebuild. Prevents async refresh from resetting user's choice.
addSchedule DOM fallback If the hidden scheduleApp field is stale/global but the visible dropdown shows a non-global app, re-derives the values from live DOM elements.
deleteSchedule cross-bucket search If a schedule isn't found in the expected bucket (legacy misroute), searches ALL buckets before giving up. Prevents silent delete failures.
Memory leak fix last_executed_actions dict now prunes stale date-keyed entries from previous days each scheduler cycle, preventing unbounded growth.

Apps Affected (all fixed):

Sonarr, Radarr, Lidarr, Readarr, Whisparr, Eros, Movie Hunt, TV Hunt

Files Modified:

  • frontend/static/js/modules/features/scheduling.js — All frontend fixes
  • frontend/static/js/dist/bundle-features.js — Bundle kept in sync
  • frontend/templates/components/scheduling_section.html — Inline script fixes
  • src/primary/scheduler_engine.py — Memory leak fix in `check_and_execute_schedules()

Don't miss a new Huntarr.io release

NewReleases is sending notifications on new releases.