Skip to content

Weekly Review — Month 3 · Week 3 (Days 071–077)

Journal index · Roadmap › this week

📅 The Week in One Line

Composed the Week 1–2 concurrency primitives into named patterns — worker pool, fan-out/fan-in, pipelines, semaphores — and made them cancellable and leak-free with context and errgroup.

✅ What I Completed

  • Day 071 — Worker pool pattern (bounded N goroutines over a jobs channel)
  • Day 072 — Fan-out / fan-in (merge with a single closer goroutine)
  • Day 073 — Pipelines (stage ownership, cancellation, goroutine-leak avoidance)
  • Day 074 — Bounded parallelism & counting semaphores (chan struct{})
  • Day 075 — context cancellation, deadlines & propagation
  • Day 076 — errgroup (first-error + cancel) & rate limiting
  • Day 077 — Week review + closed-book recall
  • Examples: workerpool, fanin-fanout, pipeline-cancel, bounded-sem, context-cancel (stdlib-only, -race clean)
  • Exercises solved: 3 (semaphore, boundedmap, taskgroup)

💡 Lessons Learned

  • Channel ownership is the through-line: the goroutine that sends on a channel is the one that closes it — never a worker, never a forwarder. Violations are send-on-closed panics.
  • Single closer goroutine is the canonical fan-in idiom: wg.Wait(); close(out) runs exactly once after every contributor finishes.
  • Goroutine leaks are the default failure mode of pipelines: any blocking send must select against <-ctx.Done(), or an early consumer freezes the whole upstream chain.
  • defer the cleanup the instant you acquire: a semaphore token (defer func(){ <-sem }()) and a context cancel func (defer cancel()) both leak silently if you forget.
  • Two different limits: bounded parallelism caps how many at once (semaphore / SetLimit); rate limiting caps how often (time.Ticker / token bucket). They compose.
  • errgroup = WaitGroup + first-error + cancel-the-rest; re-implementing it with sync.Once + context made the mechanism click.

💪 Strengths (what clicked)

  • Recognising worker pool / fan-out-in / pipeline as the same primitives recomposed.
  • The ctx-first / defer cancel() / errors.Is(err, context.Canceled) conventions feel automatic now.
  • Preserving input order with index-addressed result slices (no locks).

🧩 Weaknesses (what's still fuzzy)

  • Choosing pool size / semaphore limit empirically — I still guess instead of benchmarking.
  • Burst-tolerant token buckets (x/time/rate) vs steady Ticker — only conceptual so far.
  • Reasoning about leaks in a branching pipeline (multiple fan-outs) without pprof.

🔁 Spaced-Repetition Re-quiz (topics from earlier weeks)

  1. Q: (Wk1) Unbuffered vs buffered channel send semantics?
    A

Unbuffered: send blocks until a receiver is ready (rendezvous). Buffered: send blocks only when the buffer is full. 2. Q: (Wk2) Why wg.Add before go, not inside the goroutine?

A

Add inside races with Wait, which may observe a zero counter and return before the goroutine is even counted.

3. Q: (Wk2) What does CompareAndSwap(old, new) return and how is it used?
A

true if the value still equalled old and was set to new, else false; loop-and-retry on false for lock-free updates.

4. Q: (Wk1) Is receiving from a closed channel an error?
A

No — it returns the zero value immediately; the two-value form v, ok := <-ch reports ok == false once drained.

5. Q: (Wk2) Is a clean go test -race a proof of race-freedom?
A

No — it's a dynamic detector; it only catches races that actually occurred on that run.

🎯 Action Items

  • Write a micro-benchmark that sweeps semaphore limit (1, 2, 4, 8, 16) over an I/O-bound task and plot the crossover.
  • Add a TryGo-style non-blocking variant to the taskgroup exercise.
  • Add a context.WithTimeout deadline to the boundedmap test to exercise DeadlineExceeded.
  • Read the real golang.org/x/sync/errgroup source and diff it against my taskgroup.

🚀 Next Week Goals

  • Build the Week 4 mini-project: a concurrent web crawler — bounded worker pool + single-owner dedup (no mutex) + graceful shutdown via signal.NotifyContext.
  • Profile it with runtime/pprof and tune the worker/limit counts with data.

📊 Metrics

Hours Days hit Exercises Commits Avg confidence
9 7/7 3 7 3.⅗

Suggested commit: docs(journal): week 3 review