v1.2.0 Phase B: delivery outbox + pipeline lifecycle #100
No reviewers
Labels
No labels
area:ai
area:ci-cd
area:notifications
area:observability
area:public-pages
backlog
bug
duplicate
enhancement
help wanted
invalid
question
type:decision
type:feature
type:infra
type:maintenance
type:security
v1.0.1
v1.1.0
v1.2.0
v1.3.0
v2.0.0
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
rbrooks/WeatherBot!100
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/v1.2.0-phaseB-outbox"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
The delivery-reliability core of v1.2.0 — the milestone's keystone.
#50 — delivery outbox (bounded retries)
Previously every dispatch path committed the dedup
SentAlertbefore sending, so a transient channel failure was logged and then permanently dropped (at-most-once delivery). Now:notification_deliveriestable (migration 0020) records per-(alert, channel, kind)attempts with status/attempts/last_error/next_attempt_at and a serialized payload (so a retry in a later process reconstructs the full warning text).pendingrow, attempts the send inline (prompt initial delivery preserved), then aprocess_delivery_outboxscheduler job retriesfailedrows with exponential backoff (FOR UPDATE SKIP LOCKED) up toDELIVERY_MAX_ATTEMPTS/DELIVERY_MAX_AGE_HOURS, thendead. Asentrow is never re-sent (idempotent).notifiers/errors.py):send_alert/send_alert_liftedraiseTransientDeliveryError(5xx/timeout/connection → retry) orPermanentDeliveryError(disabled/misconfig/4xx → dead) instead of swallowing HTTP errors — so the outbox observes and retries the real transient failures, not just unexpected exceptions. SPC/forecast sends keep their existing swallow behavior.#53 — pipeline lifecycle hardening
with_for_update(skip_locked=True)) on the clear/lifted selections so overlapping runs can't double-send all-clears.#56 tail
TimezoneFinderis now a module-level singleton (was constructed per location-resolution).Testing
Full suite green on the dev server: 593 passed (incl. discord/matrix delivery-error paths); migration
0020applies cleanly to head on real Postgres. The core acceptance is covered end-to-end: a transient send failure leaves afailedrow that a later outbox run delivers successfully; a permanent failure goesdead; asentrow is never re-sent.Notes / judgment calls
Closes #50, #53
🤖 Generated with Claude Code