Skip to content

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, context cancellation/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 . and go vet ./... — no missing cancel(), no copied locks, no loop-var issues.
  • Re-implemented merge and the stdlib taskgroup from a blank file (active recall); got the single-closer-goroutine and errOnce details right on the second pass.

🧠 Closed-Book Recall (Week 3)

  1. Q: Who closes jobs and who closes results in 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 context cancel func by skipping the defer (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 context deadlines 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)