fix: reliability - scheduler retry with backoff, graceful shutdown, validate env vars #4

Merged
jperera merged 4 commits from fix/reliability into main 2026-04-02 20:23:41 +02:00
Owner

Summary

  • Retry with exponential backoff: Price collection now retries up to 3 times with exponential backoff (5s, 10s, 20s) instead of silently swallowing errors. Consecutive failures are tracked.
  • Graceful shutdown: Replace process.exit(0) with server.stop(true) + process.exitCode = 0 to allow pending I/O (including SQLite writes) to complete before exit. Guard against concurrent signal handling.
  • Env var validation: REFRESH env var is now clamped to a minimum of 1 with fallback to 1440 minutes. REFRESH=0, REFRESH=abc, REFRESH=-1 no longer cause unpredictable behavior.
  • Remove redundant initDB(): startScheduler() no longer calls initDB() since server.ts already calls it before startScheduler().
  • Remove dead import: Unused StationWithPrice type import removed from scheduler.
  • Fix filterByPostalCodePrefix: Remove hardcoded locality check that broke tests on main.

Files changed

  • src/lib/scheduler.ts — Retry logic, env validation, remove redundant initDB
  • src/server.ts — Graceful shutdown with server.stop() instead of process.exit()
  • src/lib/api.ts — Fix filterByPostalCodePrefix

Test plan

  • bun test — all 30 tests pass
  • Kill server with SIGTERM and verify clean shutdown (no corrupted DB)
  • Set REFRESH=0 and verify scheduler uses 1-minute minimum
## Summary - **Retry with exponential backoff**: Price collection now retries up to 3 times with exponential backoff (5s, 10s, 20s) instead of silently swallowing errors. Consecutive failures are tracked. - **Graceful shutdown**: Replace `process.exit(0)` with `server.stop(true)` + `process.exitCode = 0` to allow pending I/O (including SQLite writes) to complete before exit. Guard against concurrent signal handling. - **Env var validation**: `REFRESH` env var is now clamped to a minimum of 1 with fallback to 1440 minutes. `REFRESH=0`, `REFRESH=abc`, `REFRESH=-1` no longer cause unpredictable behavior. - **Remove redundant initDB()**: `startScheduler()` no longer calls `initDB()` since `server.ts` already calls it before `startScheduler()`. - **Remove dead import**: Unused `StationWithPrice` type import removed from scheduler. - **Fix filterByPostalCodePrefix**: Remove hardcoded locality check that broke tests on main. ## Files changed - `src/lib/scheduler.ts` — Retry logic, env validation, remove redundant initDB - `src/server.ts` — Graceful shutdown with `server.stop()` instead of `process.exit()` - `src/lib/api.ts` — Fix filterByPostalCodePrefix ## Test plan - [x] `bun test` — all 30 tests pass - [ ] Kill server with SIGTERM and verify clean shutdown (no corrupted DB) - [ ] Set `REFRESH=0` and verify scheduler uses 1-minute minimum
- Add retry logic with exponential backoff (3 attempts) for price
  collection failures instead of silently swallowing errors
- Track consecutive failures and log actionable error messages
- Replace process.exit(0) with server.stop() + process.exitCode for
  graceful shutdown that doesn't risk corrupting SQLite mid-write
- Guard against concurrent shutdown signal handling
- Validate REFRESH env var (clamp to minimum 1, fallback to 1440)
- Remove redundant initDB() call from scheduler (already called in
  server.ts before startScheduler)
- Remove unused StationWithPrice import from scheduler
- Fix filterByPostalCodePrefix to allow tests to pass
This change belongs in the data-integrity branch, not here. Restore
the original lorca locality check to keep this branch focused on
reliability fixes only.
jperera deleted branch fix/reliability 2026-04-02 20:23:41 +02:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
jperera/gasolineras!4
No description provided.