Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
825c825686
commit
efe0c241ab
1 changed files with 7 additions and 24 deletions
31
CLAUDE.md
31
CLAUDE.md
|
|
@ -16,34 +16,17 @@ controlled by `CF_WORKER_URL` + `CF_WORKER_SECRET` env vars on the backend.
|
|||
|
||||
## Backlog (implement when ready, in priority order)
|
||||
|
||||
### #12 — Two-layer in-memory caching (backend/main.go only)
|
||||
### #12 — Two-layer in-memory caching ✅ DONE (feat/caching-layer, merged)
|
||||
|
||||
Goal: reduce Microsoft API traffic from thousands/day to ~50–100/day,
|
||||
eliminating the 715-123130 rate-limit block under real traffic.
|
||||
|
||||
- [ ] **1. Singleflight** — `golang.org/x/sync/singleflight` wrapping all Microsoft fetches.
|
||||
Prevents cache stampede: 500 concurrent cache misses → 1 Microsoft hit.
|
||||
- [ ] **2. SKU info cache** — 7-day TTL, keyed by `product_id`.
|
||||
Language lists are stable; no need to hit Microsoft on every page load.
|
||||
- [ ] **3. Download link cache** — ~22h TTL, keyed by `product_id:sku_id`.
|
||||
Signed URLs are not IP-bound — safe to serve the same link to all users.
|
||||
- [ ] **4. Negative response caching** — cache 429 / 715-123130 failures for 30–60s.
|
||||
Prevents thundering herd from retries worsening an existing block.
|
||||
- [ ] **5. Dynamic TTL** — parse expiry from Microsoft's signed URL instead of fixed 22h.
|
||||
Derive as: `(link_expiry - now) - 30min`. Safer against clock skew.
|
||||
Store `cached_at` + `expires_at` metadata with each entry.
|
||||
- [ ] **6. Stale-on-failure** — if refresh fails (rate-limited/transient), serve stale link
|
||||
temporarily and retry refresh in background. Prevents global outages.
|
||||
- [ ] **7. Jitter** — add ±few minutes random offset to TTLs.
|
||||
Prevents synchronized mass-expiry spikes.
|
||||
All 7 items shipped: singleflight, SKU cache (7d TTL), link cache (dynamic TTL from `se` param),
|
||||
negative cache (60s), dynamic TTL, stale-on-failure, jitter. Verified in production.
|
||||
|
||||
### Beyond #12 — Observability & resilience
|
||||
|
||||
- [ ] **Per-IP / per-product rate limiter** on the backend as extra protection against abuse.
|
||||
- [ ] **Cache hit/miss logging** — extend existing request logs to show cache hits vs Microsoft calls.
|
||||
- [ ] **`/metrics` endpoint** (auth-protected) — expose cache hit rate, miss count, stale serves.
|
||||
- [ ] **README architecture section** — document the caching layer once implemented
|
||||
(CF Worker section already done, extend for caching).
|
||||
- [x] **Cache hit/miss logging** — logged on every request (fetched vs cached, cached until timestamp).
|
||||
- [x] **`/metrics` endpoint** (auth-protected) — exposes cache hit rate, miss count, stale serves. Auth via `METRICS_SECRET` env var. (feat/metrics, merged)
|
||||
- [x] **README architecture section** — caching layer, `/metrics`, env vars documented.
|
||||
- [ ] **Per-IP / per-product rate limiter** — deferred; revisit after 1 month of production traffic data.
|
||||
|
||||
### Known bugs / open issues
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue