Day 077 — Week 3 Review Day¶
Month 3 · Week 3 · ⬅ Day 076 · Day 078 ➡ · Journal index
📋 Full structured review:
week-3-review.md
🎯 Learning Objective¶
Consolidate Week 3's concurrency patterns (worker pool → fan-out/fan-in → pipelines → semaphores → context → errgroup) by re-deriving each from memory and re-running every example and exercise under the race detector.
📚 Topics¶
- Recap: worker pool, fan-out/fan-in
merge, cancellable pipelines, counting semaphores,contextcancellation/deadlines/propagation,errgroup, rate limiting.
📝 Notes¶
- Re-ran each example (
go run ./examples/month-03/{workerpool,fanin-fanout,pipeline-cancel,bounded-sem,context-cancel}) — all clean output, no leaks. go test -race ./exercises/month-03/week-3/...— semaphore, boundedmap, taskgroup all green; the bound/limit invariants held every run.- Ran
gofmt -l .andgo vet ./...— no missingcancel(), no copied locks, no loop-var issues. - Re-implemented
mergeand the stdlibtaskgroupfrom a blank file (active recall); got the single-closer-goroutine anderrOncedetails right on the second pass.
🧠 Closed-Book Recall (Week 3)¶
- Q: Who closes
jobsand who closesresultsin a worker pool?A
The single producer closes jobs; a closer goroutine closes results after wg.Wait().
2. Q: Why a single closer goroutine for a fan-in merge? A
So out is closed exactly once, after every forwarder finishes — otherwise a forwarder still sending hits a send-on-closed panic.
3. Q: How does an early-exiting consumer leak a pipeline, and the fix? A
Upstream stages block forever on out <- v; select each send against <-ctx.Done() and return on cancel.
4. Q: Buffered channel as a semaphore — acquire/release? A
make(chan struct{}, N); send to acquire (blocks at N), receive to release. defer the release.
5. Q: context.Canceled vs context.DeadlineExceeded? A
Canceled = cancel() was called; DeadlineExceeded = the deadline/timeout passed. Read with ctx.Err() via errors.Is.
6. Q: What does errgroup.Wait return, and what does WithContext add? A
The first non-nil error; WithContext cancels a derived context on that first error so siblings can stop.
7. Q: Rate limiting vs bounded parallelism? A
Rate limiting caps how often (events/sec); bounded parallelism caps how many at once. Orthogonal, often combined.
🐛 Mistakes / Themes This Week¶
- Closing a channel from the wrong goroutine (worker / forwarder) → send-on-closed panic (Days 071–072).
- Leaking goroutines by not selecting sends against
ctx.Done()(Day 073). - Leaking a semaphore token / a
contextcancel func by skipping thedefer(Days 074–075).
🪶 Feynman Reflection¶
Week 3 was the "compose the primitives" week: channels + goroutines + sync from Weeks 1–2 snap together into named patterns — pool, fan-out/in, pipeline, semaphore — and context is the cross-cutting kill switch that makes any of them cancellable and leak-free. errgroup is the batteries-included combination of all of it.
🕳️ Knowledge Gaps Carried Forward¶
- Profiling parallel work (
runtime/pprof) and tuning the limits empirically (Day 083 / optimisation month). - Wiring
contextdeadlines through real HTTP/gRPC calls (API month).
✅ Summary¶
Week 3 concurrency patterns consolidated; all examples and exercises formatted, vetted, and -race-clean. Confidence on pool/fan-in/pipeline/semaphore/context now 3–⅘.
⏭️ Next Steps¶
- Week 4: put it together in a concurrent crawler — bounded worker pool + dedup + graceful shutdown.
| Time spent | Difficulty | Confidence |
|---|---|---|
| 75 min | 🟦⬜⬜⬜⬜ | 🟦🟦🟦🟦⬜ |
Suggested commit: docs(journal): month 3 week 3 review (day 077)