Files
zarinpal-analytics-backend/docs/decisions/0011-lazy-merchant-analytics-cache.md

27 lines
2.0 KiB
Markdown

# ADR 0011: Calculate and cache merchant analytics lazily
- Status: Accepted
- Date: 2026-08-20
## Context
The hackathon dataset is static after its one-time bootstrap. Continuously refreshing analytics would spend resources before any merchant requests the data. The production boundary may later receive new append-only rows written directly by ZarinPal, bypassing Go request handlers, so any invalidation contract must also work at the database boundary.
## Decision
Calculate a merchant's approved analytics projections on the first relevant dashboard request and persist typed projections in PostgreSQL. Reuse them while their merchant source revision, relevant cohort revision, and metric-definition version remain current.
Schema-owned database logic atomically increments the affected merchant revision whenever a related payment fact is inserted. Inserts that affect peer benchmarks also increment the corresponding category/cohort revision. This covers direct ZarinPal writes without a refresh worker or Redis.
On a cache miss or revision mismatch, the backend obtains a merchant-scoped PostgreSQL advisory/row lock, computes the projections once, publishes them atomically, and then advances the cached revision. Concurrent requests wait for or reuse that result. A failed calculation does not advance the cached revision; an older snapshot may be returned only when clearly marked stale.
Payment facts are append-only for this MVP. Cache invalidation for updates or hard deletion is out of scope and requires a future contract change.
## Consequences
- The static dataset is aggregated at most once per merchant and metric-definition revision when requested.
- No scheduled analytics worker, nightly reconciliation, Redis, or time-based cache expiry is required.
- Cache correctness is version-based, not age-based.
- Cohort revision tracking prevents a new merchant fact from silently leaving peer comparisons current for other merchants.
- Trigger/revision behavior, concurrency deduplication, failure recovery, and traceability require integration tests.