VoucherBot v1.0.4
v1.0.4 — Reliability, Test Coverage & New Source
Patch release: transactional (idempotency-safe) email delivery for voucher alerts, a large offline unit-test suite, scheduling/readiness hardening, dependency cleanup, and a new community-wiki source for AWS voucher discounts.
What changed since v1.0.3
Three pull requests landed since v1.0.3:
- Reliability & code-quality hardening (M-2, M-4, M-7, M-8, L-9, deps)
- test: add unit tests for pipeline, analyzer, bootstrap, and collectors
- feat: add AWSCertifications wiki vouchers source
New Features
- AWSCertifications wiki vouchers source (PR #14) — the r/AWSCertifications community wiki's Vouchers & Discounts page is now ingested as a
WEBSITEsource. The page is a single MkDocs document (no per-card wrappers), so it is parsed as one post per crawl (article.md-content__inner/h1/link_selector=self) to preserve all promo codes, links, tables, and notes. Added aVENDOR_MAPPINGSURL-pattern entry so posts from this source are tagged with the canonicalawsvendor. - Community wiki are enabled by default — no schema migration required (config-driven catalog).
Reliability
- Transactional outbox for voucher email delivery (PR #12) — notification delivery intent is persisted to a new
notification_outboxtable in the same transaction as the pipeline run, so delivery state survives commit failures and is retried until delivered. Every send carries a stable idempotency key (voucher:{post_id}:{content_hash}) passed to Resend as theIdempotency-Keyheader, so replaying a pending row can never deliver a duplicate email. A successful send marks the rowSENTand setsposts.is_notifiedin one commit; the scheduler sweeps remainingPENDINGrows every 60s and marks themFAILEDafter 5 attempts. (New migration:k2l3m4n5o6p7_add_notification_outbox.) - Clamped
poll_interval_minutes(PR #12) — config intervals are clamped to[1, 43200]minutes, preventing scheduler busy-loops (0/negative) andtimedeltaoverflow (huge values). - Process boot time set at application startup (PR #12) —
PROCESS_BOOT_ATwas captured at module import (stale under uvicorn--preload); it is now set in the app lifespan so lease-staleness checks reflect the real process start. - DB-backed readiness check (PR #12) —
/healthnow executesSELECT count(*) FROM sourcesvia the session dependency instead of returning a static"ok", so it reports unhealthy when critical tables are missing. - Collector error-propagation fixes (PR #12) — broad
except Exception → return []was replaced with specific httpx handling across website/pearsonvue/rss/training-provider collectors. Auth-blocked (401/403) and transient errors return[]; unexpected errors re-raise so the dispatcher applies backoff/unrecoverable handling instead of silently marking the source successful. - Email DB-failure state fix — delivery failure state handling corrected in the ingestion pipeline.
Code Quality / Housekeeping
- Lazy imports moved to module level (PR #12) —
groq,google.genai,resend,urllib.request,soupsieve, asyncpg exceptions, and startup imports inmain.pynow import at module scope, giving clear early errors for missing dependencies and enabling full static dependency tracking. - Dependency cleanup (PR #12) — removed unused
apschedulerandpgvectorfrompyproject.toml. - mypy strict compliance in the test suite — tests updated to satisfy strict type-checking.
Testing
- Unit test suite (PR #13) — new offline, fully-mocked tests for the ingestion pipeline, AI analyzer, bootstrap, Pearson VUE and training-provider collectors, settings, and init_db. Suite grew from 198 passed to 341 passed (15 intentional skips). No live DB, network, or third-party APIs are touched.
- Transactional outbox tests — new
tests/test_notification_outbox.pycovers idempotency-key stability, staging, delivery success/failure/retry, and the scheduler sweep; extendedtests/test_email_sender.pyforIdempotency-Keypassthrough; added coverage forpoll_interval_minutesclamping,set_process_boot_at, and the DB-backed/healthcheck. - All CI quality gates pass:
ruff format --check,ruff check,mypy voucherbot tests, and the fullpytestsuite.
Full Changelog: v1.0.3...v1.0.4