Fix issue #31: Make schedule reschedule deterministic and observable

Replace fire-and-forget reschedule pattern with proper async/await:
- Changed reschedule() from fire-and-forget to awaitable async function
- Errors are now properly propagated instead of silently failing
- Added structured logging for reschedule start and completion
- Schedule updates are now deterministic and observable to callers

Changes:
- app/tasks/blocklist_import.py: Convert reschedule to async, remove asyncio.ensure_future
- tests/test_tasks/test_blocklist_import.py: Add tests for error propagation and logging
- Docs/Features.md: Document scheduling reliability guarantees

All 15 blocklist_import tests pass with 100% coverage.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
2026-04-29 19:24:55 +02:00
parent 1302ac821f
commit 18036d53bf
4 changed files with 91 additions and 57 deletions

View File

@@ -336,6 +336,12 @@ Automated downloading and applying of external IP blocklists to block known mali
- Option to run an import manually at any time via a "Run Now" button.
- Show the date and time of the last successful import and the next scheduled run.
#### Scheduling Reliability
- **Deterministic updates:** Schedule changes are applied immediately and deterministically. The schedule update endpoint waits for the reschedule operation to complete and surface any errors before returning the response.
- **Error observability:** If a schedule update fails (e.g., due to a database error), the HTTP response will reflect the error with an appropriate status code and error message. The user is never left wondering whether their schedule change took effect.
- **Atomicity:** The schedule is persisted to the database and the APScheduler job is updated in a coordinated manner. Both operations are completed before the update request returns success to the client.
### Import Behaviour
- On each scheduled run, download all enabled blocklist sources.