From aa9e580e1ba04ed1f5b287388787c3d054c9cb64 Mon Sep 17 00:00:00 2001 From: Claude Agent Date: Wed, 1 Apr 2026 13:57:22 +0000 Subject: [PATCH] fix(scheduler): prevent auto-enable with wrong interval on page load Root cause: GET /api/sync/schedule returned interval_minutes=null when scheduler was stopped, causing dropdown to stay on first HTML option (1 min). Setting .value programmatically could trigger onchange, sending a second PUT with interval=1 right after the user's intended interval. - GET schedule falls back to DB/default (10 min) when scheduler is off - Add _schedulerLoading flag to block onchange during loadSchedulerStatus - Default interval 10 min everywhere (was 5 in backend) - Cache bust dashboard.js v=33 Co-Authored-By: Claude Opus 4.6 (1M context) --- api/app/main.py | 2 +- api/app/routers/sync.py | 8 ++++++-- api/app/services/scheduler_service.py | 2 +- api/app/static/js/dashboard.js | 9 ++++++--- api/app/templates/dashboard.html | 2 +- 5 files changed, 15 insertions(+), 8 deletions(-) diff --git a/api/app/main.py b/api/app/main.py index 89c15a5..326154f 100644 --- a/api/app/main.py +++ b/api/app/main.py @@ -53,7 +53,7 @@ async def lifespan(app: FastAPI): try: config = await sqlite_service.get_scheduler_config() if config.get("enabled") == "True": - interval = int(config.get("interval_minutes", "5")) + interval = int(config.get("interval_minutes", "10")) scheduler_service.start_scheduler(interval) except Exception: pass diff --git a/api/app/routers/sync.py b/api/app/routers/sync.py index c0bea7c..ff3b7e8 100644 --- a/api/app/routers/sync.py +++ b/api/app/routers/sync.py @@ -804,8 +804,12 @@ async def update_schedule(config: ScheduleConfig): @router.get("/api/sync/schedule") async def get_schedule(): - """Get current scheduler status.""" - return scheduler_service.get_scheduler_status() + """Get current scheduler status (falls back to DB for interval).""" + status = scheduler_service.get_scheduler_status() + if status["interval_minutes"] is None: + config = await sqlite_service.get_scheduler_config() + status["interval_minutes"] = int(config.get("interval_minutes", "10")) + return status @router.get("/api/settings") diff --git a/api/app/services/scheduler_service.py b/api/app/services/scheduler_service.py index 4a9e8cc..7a54f82 100644 --- a/api/app/services/scheduler_service.py +++ b/api/app/services/scheduler_service.py @@ -15,7 +15,7 @@ def init_scheduler(): logger.info("Scheduler initialized") -def start_scheduler(interval_minutes: int = 5): +def start_scheduler(interval_minutes: int = 10): """Start the scheduler with the given interval.""" global _is_running if _scheduler is None: diff --git a/api/app/static/js/dashboard.js b/api/app/static/js/dashboard.js index 1ebf08e..1ca7d75 100644 --- a/api/app/static/js/dashboard.js +++ b/api/app/static/js/dashboard.js @@ -11,6 +11,7 @@ let _lastRunId = null; let _currentRunId = null; let _pollIntervalMs = 5000; // default, overridden from settings let _knownLastRunId = null; // track last_run.run_id to detect missed syncs +let _schedulerLoading = false; // prevent onchange during programmatic load // ── Init ────────────────────────────────────────── @@ -202,6 +203,7 @@ async function toggleScheduler() { } async function updateSchedulerInterval() { + if (_schedulerLoading) return; // ignore programmatic changes during load const enabled = document.getElementById('schedulerToggle').checked; if (enabled) { await toggleScheduler(); @@ -209,15 +211,16 @@ async function updateSchedulerInterval() { } async function loadSchedulerStatus() { + _schedulerLoading = true; try { const res = await fetch('/api/sync/schedule'); const data = await res.json(); document.getElementById('schedulerToggle').checked = data.enabled || false; - if (data.interval_minutes) { - document.getElementById('schedulerInterval').value = data.interval_minutes; - } + document.getElementById('schedulerInterval').value = data.interval_minutes || 10; } catch (err) { console.error('loadSchedulerStatus error:', err); + } finally { + _schedulerLoading = false; } } diff --git a/api/app/templates/dashboard.html b/api/app/templates/dashboard.html index b723f98..29db90b 100644 --- a/api/app/templates/dashboard.html +++ b/api/app/templates/dashboard.html @@ -114,5 +114,5 @@ {% endblock %} {% block scripts %} - + {% endblock %}