Show HN: Rill – Composable concurrency toolkit for Go
Overview of Rill
- Channel-based concurrency toolkit for Go focused on composable “channel transformations.”
- Provides helpers like
FromSlice,Map,ForEach, batching, order preservation, and centralized error handling. - Zero dependencies; grows out of production use to reduce goroutine/WaitGroup boilerplate.
API Design and Use Cases
- Treats channels as streams, not containers; supports infinite streams and large datasets.
- Typical pattern: source channel → concurrent map/processing → concurrent sink.
- Used or considered for HTTP fan‑out (e.g., RSS readers), analytics batching, data pipelines, and DAG-style runners.
Performance, Channels, and Backpressure
- Main bottleneck is channel operations; library overhead is reported as negligible.
- Considered suitable for workloads where Go channels are already appropriate; used on pipelines moving hundreds of GBs.
- Backpressure is inherited from channel semantics; buffering can be inserted via helper functions.
Error Handling and Context/Cancellation
- Centralized error handling is a key goal, but details get scrutiny.
- Library is intentionally context-agnostic: callers are expected to manage
context.Contextthemselves for timeouts and cancellation. - Some see lack of built-in context integration (e.g., auto-cancel on first error) as a significant gap.
- Concern raised that early returns from pipelines don’t necessarily mean all goroutines are done, unless user wiring handles cancellation.
Comparisons to Other Tools and Paradigms
- Compared to
conc, worker-pool libs, state-machine/retry frameworks, Rx-style libs, and iterator-based APIs. - Rill emphasizes generics, type safety, and explicit channels rather than hiding them behind observables or iterators.
- Some argue iterators could provide concurrency without channels; others stress channels’ many-to-many and
selectcapabilities.
Debate on Abstractions vs Raw Go
- Some praise the API as intuitive and closer to functional constructs like
Map/ForEach. - Others feel these abstractions clash with Go’s preference for simple loops and explicit constructs, and worry about readability and adoption.
Testing, Concurrency Bugs, and Reliability
- Long sub-thread debates whether comprehensive unit tests can reliably catch subtle concurrency and security issues.
- One side argues that thorough, well-planned tests can essentially eliminate bugs.
- Others counter that concurrency and security failures often involve complex, emergent conditions that are hard to anticipate and test exhaustively, so better abstractions and tools are still valuable.