Repository navigation
feat: download scheduler (WI-1721) - #245
thedancingdeveloper wants to merge 3 commits into
Conversation
|
Review of f4642f9: 2 blockers (behaviour), plus nits. The 2 e2e failures are not from this PR. The e2e failures are on
Checks run locally:
Blockers
Correct as written
Nits
|
Two behaviour blockers from the review of #245. A manual Resume inside a pause window was undone within a minute, because apply_schedule was level-triggered and re-paused on every tick. The pause is now edge-triggered: the window pauses when it opens and leaves a manual resume alone until the next window. Ownership still decides who may lift it, and a window restored after a restart still lifts its own pause when it ends. A speed_limit_bps = 0 rule promised unlimited but evaluate() emitted None, which apply_effective_speed_limit reads as "no scheduled cap, use the configured general.speed_limit_bps". It now emits Some(0), so an unlimited window overrides both the configured limit and any lower cap. Tests: evaluator distinguishes unlimited from no-cap-rule; queue manager covers manual resume holding inside a window, a window opening while the user is paused, restart inside a window, and disabling the schedule; API tests cover the same two bugs end to end. Docs describe the edge-triggered pause and the 0-cap precedence. Refs WI-1721
|
Re-review of 07e866b: no blockers. GitHub e2e. Same 2 of 92 as before: Checks run locally:
Both blockers are fixed:
Should fix
Nits
|
Two behaviour blockers from the review of #245. A manual Resume inside a pause window was undone within a minute, because apply_schedule was level-triggered and re-paused on every tick. The pause is now edge-triggered: the window pauses when it opens and leaves a manual resume alone until the next window. Ownership still decides who may lift it, and a window restored after a restart still lifts its own pause when it ends. A speed_limit_bps = 0 rule promised unlimited but evaluate() emitted None, which apply_effective_speed_limit reads as "no scheduled cap, use the configured general.speed_limit_bps". It now emits Some(0), so an unlimited window overrides both the configured limit and any lower cap. Tests: evaluator distinguishes unlimited from no-cap-rule; queue manager covers manual resume holding inside a window, a window opening while the user is paused, restart inside a window, and disabling the schedule; API tests cover the same two bugs end to end. Docs describe the edge-triggered pause and the 0-cap precedence. Refs WI-1721
…1721) Add a download scheduler: rules name weekdays and a window and either pause downloads, cap the speed or take servers out of rotation. Windows may cross midnight and belong to the day they start on. - `nzb-core::schedule` evaluates rules as a pure function of wall-clock time, so window edges and midnight are tested without a clock or a queue. - `nzb-web` applies the decision every minute boundary and immediately on a config save. Pause ownership is tracked and persisted, so the schedule only lifts a pause it applied; a user pause, a timed pause or a disk-space hold survives. Speed caps and server exclusions are overlays: the configured limit and `enabled` flags are never rewritten. - `GET/PUT /api/config/schedule` validates every rule before saving, assigns ids and returns what is active now. - Settings gains a Scheduler tab (enable toggle, rule list, day/window/action editors, live status); the queue shows "paused · schedule" and the reason survives a reload. - Config example and CONFIGURATION.md document the section, including TZ. Tests: 13 evaluator unit tests, monitor and queue-manager ownership tests, 8 API integration tests, settings and queue component specs, and Playwright journeys for add/save/reload/remove and validation.
The scheduler tests asserted the stored schedule cap and the configured limit, but never the value the downloader actually reads. A cap that was recorded and never applied would have passed. Assert `get_speed_limit()` through a cap being applied, lifted when the window ends, and overridden by an explicit 0 (unlimited). Also cover a disabled schedule releasing a cap and a server exclusion it had applied, since `apply_schedule` substitutes an idle decision in that path. Refs WI-1721
Two behaviour blockers from the review of #245. A manual Resume inside a pause window was undone within a minute, because apply_schedule was level-triggered and re-paused on every tick. The pause is now edge-triggered: the window pauses when it opens and leaves a manual resume alone until the next window. Ownership still decides who may lift it, and a window restored after a restart still lifts its own pause when it ends. A speed_limit_bps = 0 rule promised unlimited but evaluate() emitted None, which apply_effective_speed_limit reads as "no scheduled cap, use the configured general.speed_limit_bps". It now emits Some(0), so an unlimited window overrides both the configured limit and any lower cap. Tests: evaluator distinguishes unlimited from no-cap-rule; queue manager covers manual resume holding inside a window, a window opening while the user is paused, restart inside a window, and disabling the schedule; API tests cover the same two bugs end to end. Docs describe the edge-triggered pause and the 0-cap precedence. Refs WI-1721
07e866b to
a595bd9
Compare
WI-1721, Polish J: the scheduler. Written by a DeepSeek worker; the handoff is on WI-1721. Full e2e run: 90 passed, 2 failed; the worker says the 2 failures are pre-existing on main.
🤖 Generated with Claude Code