init commit

This commit is contained in:
medunes
2026-01-04 20:40:07 +01:00
commit 60a6e52449
27 changed files with 1061 additions and 0 deletions

View File

@@ -0,0 +1,42 @@
# Kata 09: The Cache Stampede Shield
**Target Idioms:** `singleflight`, TTL Cache, DoChan + Context Select, Lock Avoidance
**Difficulty:** 🔴 Advanced
## 🧠 The "Why"
In many stacks, caching is “just Redis”. In Go, an in-process cache is common, but people:
- hold locks while calling the loader (deadly),
- refresh the same key N times concurrently (stampede),
- cant cancel waiters cleanly.
This kata is about **deduplicating in-flight loads** and making waiters **context-cancellable**.
## 🎯 The Scenario
You have expensive per-key loads (e.g., DB or remote API). If 200 goroutines ask for the same key at once:
- loader must run **once**
- others must wait (or return on ctx cancel)
- TTL must be enforced
## 🛠 The Challenge
Implement:
- `type Cache[K comparable, V any] struct { ... }`
- `Get(ctx context.Context, key K, loader func(context.Context) (V, error)) (V, error)`
### 1. Functional Requirements
- [ ] Return cached value if not expired.
- [ ] If expired/missing: load once, share result to all callers.
- [ ] Callers must be able to stop waiting via `ctx.Done()`.
### 2. The "Idiomatic" Constraints (Pass/Fail Criteria)
- [ ] **Must** use `golang.org/x/sync/singleflight.Group`.
- [ ] **Must** use `DoChan` + `select` on `ctx.Done()` to cancel waiters.
- [ ] **Must NOT** hold a mutex while calling `loader`.
- [ ] Errors must be wrapped with key context using `%w`.
## 🧪 Self-Correction (Test Yourself)
- **If 200 goroutines trigger 200 loads:** you failed (no stampede protection).
- **If a canceled context still blocks waiting:** you failed.
- **If you lock around loader execution:** you failed (contention / deadlocks).
## 📚 Resources
- https://pkg.go.dev/golang.org/x/sync/singleflight
- https://go.dev/blog/go1.13-errors