From 1527ab8cf68705cb0a228c80b0e2a3ac41b15339 Mon Sep 17 00:00:00 2001 From: DorkSoul Date: Mon, 22 Jun 2026 07:53:51 +0100 Subject: [PATCH 1/2] recheck schedule every 1-2 min after stream drop instead of 5-8 min After a download ends within a schedule window (stream crash/restart), set quick_recheck mode which uses 1-2 min intervals to catch the stream coming back quickly. Clears when a new download starts or the window ends. Co-Authored-By: Claude Sonnet 4.6 --- app/scheduler.py | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/app/scheduler.py b/app/scheduler.py index 35fbd3c..f274416 100644 --- a/app/scheduler.py +++ b/app/scheduler.py @@ -45,9 +45,10 @@ def load_schedules(self): # Ensure all schedules have next_check calculated for schedule in self.schedules: - # Clear in-memory-only auto_paused flag that may have been - # left over if a previous session ended without calling close + # Clear in-memory-only flags that may have been left over + # if a previous session ended without calling close schedule.pop('auto_paused', None) + schedule.pop('quick_recheck', None) if not schedule.get('next_check'): self._update_next_check(schedule) @@ -379,6 +380,7 @@ def _check_schedules(self): schedule['status'] = 'completed' schedule['active_browser_id'] = None schedule['manual_stop'] = False + schedule.pop('quick_recheck', None) continue if start_dt <= now <= end_dt: @@ -390,6 +392,7 @@ def _check_schedules(self): logger.info(f"Download {active_browser_id} stopped for schedule {schedule['id']}, resuming stream checks") schedule['status'] = 'active' schedule['active_browser_id'] = None + schedule['quick_recheck'] = True schedule['next_check'] = None # re-check immediately on next tick if schedule['status'] != 'active': @@ -468,6 +471,7 @@ def _combine(d, h, m): logger.info(f"Download {active_browser_id} stopped for schedule {schedule['id']}, resuming stream checks") schedule['status'] = 'active' schedule['active_browser_id'] = None + schedule['quick_recheck'] = True schedule['next_check'] = None # re-check immediately on next tick if schedule['status'] != 'active': @@ -504,6 +508,7 @@ def _combine(d, h, m): schedule['last_check'] = None schedule['active_browser_id'] = None schedule['manual_stop'] = False + schedule.pop('quick_recheck', None) self._update_next_check(schedule) def _update_next_check(self, schedule): @@ -550,7 +555,11 @@ def _combine(d, h, m): schedule['next_check'] = _store(start_dt) logger.debug(f"Schedule {schedule['id']}: next check set to window start: {start_dt}") elif start_dt <= now <= end_dt: - minutes = random.uniform(5, 8) + if schedule.get('quick_recheck'): + minutes = random.uniform(1, 2) + logger.debug(f"Schedule {schedule['id']}: quick recheck mode — next check in {minutes:.1f} mins") + else: + minutes = random.uniform(5, 8) next_dt = min(now + timedelta(minutes=minutes), end_dt) schedule['next_check'] = _store(next_dt) logger.debug(f"Schedule {schedule['id']}: next check in {minutes:.1f} mins: {next_dt}") @@ -571,7 +580,11 @@ def _combine(d, h, m): schedule['next_check'] = _store(start_dt) logger.debug(f"Schedule {schedule['id']}: next check set to window start: {start_dt}") elif start_dt <= now <= end_dt: - minutes = random.uniform(5, 8) + if schedule.get('quick_recheck'): + minutes = random.uniform(1, 2) + logger.debug(f"Schedule {schedule['id']}: quick recheck mode — next check in {minutes:.1f} mins") + else: + minutes = random.uniform(5, 8) next_dt = min(now + timedelta(minutes=minutes), end_dt) schedule['next_check'] = _store(next_dt) logger.debug(f"Schedule {schedule['id']}: next check in {minutes:.1f} mins: {next_dt}") @@ -689,6 +702,7 @@ def _run_browser_check_task(self, schedule, duration): if s['id'] == schedule['id']: s['status'] = 'download_started' s['active_browser_id'] = browser_id + s.pop('quick_recheck', None) self._mark_dirty() self.save_schedules() break From 2b9d9c5a67017356dd2ba4ee19a8a0845c502e59 Mon Sep 17 00:00:00 2001 From: DorkSoul Date: Mon, 22 Jun 2026 08:50:03 +0100 Subject: [PATCH 2/2] keep checking within window after download ends instead of skipping to next slot Removing move_to_next_slot from the stop-download route means stopping a scheduled download (manually or on stream crash) no longer jumps to the next day/week. The scheduler's existing _is_download_active check already resumes checking every 5-8 min once the download is no longer active. Also reverts the quick_recheck interval change (5-8 min is correct). Co-Authored-By: Claude Sonnet 4.6 --- app/routes/download_routes.py | 5 +---- app/scheduler.py | 22 ++++------------------ 2 files changed, 5 insertions(+), 22 deletions(-) diff --git a/app/routes/download_routes.py b/app/routes/download_routes.py index fe58f5b..db3c751 100644 --- a/app/routes/download_routes.py +++ b/app/routes/download_routes.py @@ -249,10 +249,7 @@ def stop_download(browser_id): try: if download_service.stop_download(browser_id): if scheduler: - if browser_id.startswith('sched_'): - scheduler.move_to_next_slot(browser_id) - logger.info(f"Moved scheduled download {browser_id} to next time slot") - else: + if not browser_id.startswith('sched_'): scheduler.browser_service.set_manual_active(False) scheduler.resume_after_manual(browser_id) diff --git a/app/scheduler.py b/app/scheduler.py index f274416..35fbd3c 100644 --- a/app/scheduler.py +++ b/app/scheduler.py @@ -45,10 +45,9 @@ def load_schedules(self): # Ensure all schedules have next_check calculated for schedule in self.schedules: - # Clear in-memory-only flags that may have been left over - # if a previous session ended without calling close + # Clear in-memory-only auto_paused flag that may have been + # left over if a previous session ended without calling close schedule.pop('auto_paused', None) - schedule.pop('quick_recheck', None) if not schedule.get('next_check'): self._update_next_check(schedule) @@ -380,7 +379,6 @@ def _check_schedules(self): schedule['status'] = 'completed' schedule['active_browser_id'] = None schedule['manual_stop'] = False - schedule.pop('quick_recheck', None) continue if start_dt <= now <= end_dt: @@ -392,7 +390,6 @@ def _check_schedules(self): logger.info(f"Download {active_browser_id} stopped for schedule {schedule['id']}, resuming stream checks") schedule['status'] = 'active' schedule['active_browser_id'] = None - schedule['quick_recheck'] = True schedule['next_check'] = None # re-check immediately on next tick if schedule['status'] != 'active': @@ -471,7 +468,6 @@ def _combine(d, h, m): logger.info(f"Download {active_browser_id} stopped for schedule {schedule['id']}, resuming stream checks") schedule['status'] = 'active' schedule['active_browser_id'] = None - schedule['quick_recheck'] = True schedule['next_check'] = None # re-check immediately on next tick if schedule['status'] != 'active': @@ -508,7 +504,6 @@ def _combine(d, h, m): schedule['last_check'] = None schedule['active_browser_id'] = None schedule['manual_stop'] = False - schedule.pop('quick_recheck', None) self._update_next_check(schedule) def _update_next_check(self, schedule): @@ -555,11 +550,7 @@ def _combine(d, h, m): schedule['next_check'] = _store(start_dt) logger.debug(f"Schedule {schedule['id']}: next check set to window start: {start_dt}") elif start_dt <= now <= end_dt: - if schedule.get('quick_recheck'): - minutes = random.uniform(1, 2) - logger.debug(f"Schedule {schedule['id']}: quick recheck mode — next check in {minutes:.1f} mins") - else: - minutes = random.uniform(5, 8) + minutes = random.uniform(5, 8) next_dt = min(now + timedelta(minutes=minutes), end_dt) schedule['next_check'] = _store(next_dt) logger.debug(f"Schedule {schedule['id']}: next check in {minutes:.1f} mins: {next_dt}") @@ -580,11 +571,7 @@ def _combine(d, h, m): schedule['next_check'] = _store(start_dt) logger.debug(f"Schedule {schedule['id']}: next check set to window start: {start_dt}") elif start_dt <= now <= end_dt: - if schedule.get('quick_recheck'): - minutes = random.uniform(1, 2) - logger.debug(f"Schedule {schedule['id']}: quick recheck mode — next check in {minutes:.1f} mins") - else: - minutes = random.uniform(5, 8) + minutes = random.uniform(5, 8) next_dt = min(now + timedelta(minutes=minutes), end_dt) schedule['next_check'] = _store(next_dt) logger.debug(f"Schedule {schedule['id']}: next check in {minutes:.1f} mins: {next_dt}") @@ -702,7 +689,6 @@ def _run_browser_check_task(self, schedule, duration): if s['id'] == schedule['id']: s['status'] = 'download_started' s['active_browser_id'] = browser_id - s.pop('quick_recheck', None) self._mark_dirty() self.save_schedules() break