Documentation
¶
Overview ¶
Package rill provides a toolkit for composable concurrency in Go, making it easier to build concurrent programs from simple, reusable parts.
Rill reduces boilerplate while preserving Go's natural channel-based model and backpressure behavior. It provides functions for transforming, filtering, batching, and reducing streams of data with full control over concurrency.
Key features:
- Map, Filter, FlatMap with configurable concurrency
- Ordered versions of all transformation functions
- Batch processing with size and timeout controls
- Reduce and MapReduce for aggregating results
- Error handling through the Try container type
Basic usage:
// Convert a slice to a stream
ids := rill.FromSlice([]int{1, 2, 3, 4, 5}, nil)
// Process concurrently with Map
users := rill.Map(ids, 3, func(id int) (*User, error) {
return fetchUser(id)
})
// Consume the stream
err := rill.ForEach(users, 2, func(u *User) error {
return saveUser(u)
})
Index ¶
- Constants
- func All[A any](in <-chan Try[A], n int, f func(A) (bool, error)) (bool, error)
- func Any[A any](in <-chan Try[A], n int, f func(A) (bool, error)) (bool, error)
- func AnyWithContext[A any](ctx context.Context, in <-chan Try[A], n int, ...) (bool, error)
- func Batch[A any](in <-chan Try[A], size int, timeout time.Duration) <-chan Try[[]A]
- func BatchWithContext[A any](ctx context.Context, in <-chan Try[A], size int, timeout time.Duration) <-chan Try[[]A]
- func Catch[A any](in <-chan Try[A], n int, f func(error) error) <-chan Try[A]
- func CatchWithContext[A any](ctx context.Context, in <-chan Try[A], n int, ...) <-chan Try[A]
- func CatchWithFallback[A any](in <-chan Try[A], n int, fallbackValue A, f func(error) error) <-chan Try[A]
- func Concat[A any](ins ...<-chan Try[A]) <-chan Try[A]
- func ConcatWithContext[A any](ctx context.Context, ins ...<-chan Try[A]) <-chan Try[A]
- func Count[A any](in <-chan Try[A]) (int, error)
- func CountWindow[A any](in <-chan Try[A], size int) <-chan []Try[A]
- func Debounce[A any](ctx context.Context, in <-chan Try[A], delay time.Duration) <-chan Try[A]
- func Discard[A any](in <-chan A)
- func Distinct[A comparable](in <-chan Try[A]) <-chan Try[A]
- func DistinctBy[A any, K comparable](in <-chan Try[A], keyFunc func(A) K) <-chan Try[A]
- func DistinctByWithLimit[A any, K comparable](in <-chan Try[A], keyFunc func(A) K, maxSize int) <-chan Try[A]
- func DistinctWithLimit[A comparable](in <-chan Try[A], maxSize int) <-chan Try[A]
- func Drain[A any](ctx context.Context, in <-chan Try[A]) error
- func Err[A any](in <-chan Try[A]) error
- func FanIn[A any](ctx context.Context, ins ...<-chan Try[A]) <-chan Try[A]
- func FanOut[A any](ctx context.Context, in <-chan Try[A], n int) []<-chan Try[A]
- func Filter[A any](in <-chan Try[A], n int, f func(A) (bool, error)) <-chan Try[A]
- func FilterMap[A, B any](in <-chan Try[A], n int, f func(A) (B, bool, error)) <-chan Try[B]
- func FilterMapWithContext[A, B any](ctx context.Context, in <-chan Try[A], n int, ...) <-chan Try[B]
- func FilterWithContext[A any](ctx context.Context, in <-chan Try[A], n int, ...) <-chan Try[A]
- func First[A any](in <-chan Try[A]) (value A, found bool, err error)
- func FlatMap[A, B any](in <-chan Try[A], n int, f func(A) <-chan Try[B]) <-chan Try[B]
- func FlatMapWithContext[A, B any](ctx context.Context, in <-chan Try[A], n int, ...) <-chan Try[B]
- func ForEach[A any](in <-chan Try[A], n int, f func(A) error) error
- func ForEachWithContext[A any](ctx context.Context, in <-chan Try[A], n int, f func(context.Context, A) error) error
- func FromChan[A any](values <-chan A, err error) <-chan Try[A]
- func FromChans[A any](values <-chan A, errs <-chan error) <-chan Try[A]
- func FromSlice[A any](slice []A, err error) <-chan Try[A]
- func Generate[A any](f func(send func(A), sendErr func(error))) <-chan Try[A]
- func Map[A, B any](in <-chan Try[A], n int, f func(A) (B, error)) <-chan Try[B]
- func MapReduce[A any, K comparable, V any](in <-chan Try[A], nm int, mapper func(A) (K, V, error), nr int, ...) (map[K]V, error)
- func MapReduceWithContext[A any, K comparable, V any](ctx context.Context, in <-chan Try[A], nm int, ...) (map[K]V, error)
- func MapWithContext[A, B any](ctx context.Context, in <-chan Try[A], n int, ...) <-chan Try[B]
- func Merge[A any](ins ...<-chan Try[A]) <-chan Try[A]
- func MergeWithContext[A any](ctx context.Context, ins ...<-chan Try[A]) <-chan Try[A]
- func Must[A any](result Try[A], err error) A
- func MustOk[A any](result Try[A], err error) (A, error)
- func OrElse[A any](in <-chan Try[A], fallback <-chan Try[A]) <-chan Try[A]
- func OrderedFilter[A any](in <-chan Try[A], n int, f func(A) (bool, error)) <-chan Try[A]
- func OrderedFilterWithContext[A any](ctx context.Context, in <-chan Try[A], n int, ...) <-chan Try[A]
- func OrderedFlatMap[A, B any](in <-chan Try[A], n int, f func(A) <-chan Try[B]) <-chan Try[B]
- func OrderedFlatMapWithContext[A, B any](ctx context.Context, in <-chan Try[A], n int, ...) <-chan Try[B]
- func OrderedMap[A, B any](in <-chan Try[A], n int, f func(A) (B, error)) <-chan Try[B]
- func OrderedMapWithContext[A, B any](ctx context.Context, in <-chan Try[A], n int, ...) <-chan Try[B]
- func ParallelMap[A, B any](ctx context.Context, items []A, workers int, ...) ([]B, error)
- func ParallelProcess[A any](ctx context.Context, items []A, workers int, fn func(context.Context, A) error) error
- func Range(start, end int) <-chan Try[int]
- func Reduce[A any](in <-chan Try[A], n int, f func(A, A) (A, error)) (result A, hasResult bool, err error)
- func ReduceWithContext[A any](ctx context.Context, in <-chan Try[A], n int, ...) (result A, hasResult bool, err error)
- func Repeat[A any](value A, count int) <-chan Try[A]
- func Retry[A any](ctx context.Context, in <-chan Try[A], opts *RetryOptions, ...) <-chan Try[A]
- func SetTracer(t Tracer)
- func Skip[A any](in <-chan Try[A], n int) <-chan Try[A]
- func Take[A any](in <-chan Try[A], n int) <-chan Try[A]
- func Tap[A any](in <-chan Try[A], f func(A)) <-chan Try[A]
- func Throttle[A any](ctx context.Context, in <-chan Try[A], rate int, burst int) <-chan Try[A]
- func TimeWindow[A any](in <-chan Try[A], size int, timeout time.Duration) <-chan []Try[A]
- func Timeout[A any](in <-chan Try[A], timeout time.Duration) <-chan Try[A]
- func ToChans[A any](in <-chan Try[A]) (<-chan A, <-chan error)
- func ToSlice[A any](in <-chan Try[A]) ([]A, error)
- func Unbatch[A any](in <-chan Try[[]A]) <-chan Try[A]
- func Window[A any](in <-chan Try[A], cfg WindowConfig) <-chan []Try[A]
- func WithBackoff(d time.Duration) func(*RetryOptions)
- func WithBackpressure(enabled bool) func(*StreamConfig)
- func WithBufferSize(size int) func(*StreamConfig)
- func WithContext[A any](ctx context.Context, in <-chan Try[A]) (<-chan Try[A], <-chan error)
- func WithMaxAttempts(n int) func(*RetryOptions)
- func WithMaxBackoff(d time.Duration) func(*RetryOptions)
- func WithMaxWorkers(n int) func(*StreamConfig)
- func Zip[A, B any](ctx context.Context, inA <-chan Try[A], inB <-chan Try[B]) <-chan Try[[2]any]
- type LRUCache
- type Metrics
- func (m *Metrics) DecrementActiveWorkers()
- func (m *Metrics) IncrementActiveWorkers() int32
- func (m *Metrics) RecordBlockedGoroutine()
- func (m *Metrics) RecordChannelReceive()
- func (m *Metrics) RecordChannelSend()
- func (m *Metrics) RecordError()
- func (m *Metrics) RecordItem()
- func (m *Metrics) RecordProcessingTime(d time.Duration)
- func (m *Metrics) Reset()
- func (m *Metrics) Snapshot() MetricsSnapshot
- type MetricsSnapshot
- type OnceWithWait
- type PipelineBuilder
- func (p *PipelineBuilder) Batch(size int) *PipelineBuilder
- func (p *PipelineBuilder) Build() Stream[any]
- func (p *PipelineBuilder) Filter(f func(context.Context, any) (bool, error)) *PipelineBuilder
- func (p *PipelineBuilder) FilterMap(f func(context.Context, any) (any, bool, error)) *PipelineBuilder
- func (p *PipelineBuilder) FlatMap(f func(context.Context, any) ([]any, error)) *PipelineBuilder
- func (p *PipelineBuilder) ForEach(f func(context.Context, any) error) *PipelineBuilder
- func (p *PipelineBuilder) Map(f func(context.Context, any) (any, error)) *PipelineBuilder
- func (p *PipelineBuilder) Run() error
- func (p *PipelineBuilder) WithWorkers(n int) *PipelineBuilder
- type RetryOptions
- type Span
- type Stream
- type StreamConfig
- type Tracer
- type Try
- type WindowConfig
Constants ¶
const ( DefaultBufferSize = 256 DefaultMaxWorkers = 16 DefaultLRUSize = 10000 )
Variables ¶
This section is empty.
Functions ¶
func AnyWithContext ¶
func BatchWithContext ¶
func CatchWithContext ¶
func CatchWithFallback ¶
func CatchWithFallback[A any](in <-chan Try[A], n int, fallbackValue A, f func(error) error) <-chan Try[A]
CatchWithFallback catches errors and replaces them with a fallback value. Unlike Catch which can silently drop items, this always outputs either the original value or the fallback.
func ConcatWithContext ¶
func Distinct ¶
func Distinct[A comparable](in <-chan Try[A]) <-chan Try[A]
func DistinctBy ¶
func DistinctBy[A any, K comparable](in <-chan Try[A], keyFunc func(A) K) <-chan Try[A]
func DistinctByWithLimit ¶
func DistinctByWithLimit[A any, K comparable](in <-chan Try[A], keyFunc func(A) K, maxSize int) <-chan Try[A]
func DistinctWithLimit ¶
func DistinctWithLimit[A comparable](in <-chan Try[A], maxSize int) <-chan Try[A]
func FilterMapWithContext ¶
func FilterWithContext ¶
func FlatMapWithContext ¶
func ForEachWithContext ¶
func MapReduceWithContext ¶
func MapWithContext ¶
func MergeWithContext ¶
func OrElse ¶
OrElse provides a fallback stream when the input stream encounters errors. If an error occurs, it switches to consuming from the fallback stream.
func OrderedFilter ¶
func OrderedFlatMap ¶
func OrderedMap ¶
func OrderedMapWithContext ¶
func ParallelMap ¶
func ParallelProcess ¶
func ReduceWithContext ¶
func TimeWindow ¶
func Timeout ¶
Timeout returns a stream that will timeout if no items are received within the specified duration. Unlike the original buggy implementation, this correctly manages the context lifecycle.
func WithBackoff ¶
func WithBackoff(d time.Duration) func(*RetryOptions)
func WithBackpressure ¶
func WithBackpressure(enabled bool) func(*StreamConfig)
func WithBufferSize ¶
func WithBufferSize(size int) func(*StreamConfig)
func WithContext ¶
func WithMaxAttempts ¶
func WithMaxAttempts(n int) func(*RetryOptions)
func WithMaxBackoff ¶
func WithMaxBackoff(d time.Duration) func(*RetryOptions)
func WithMaxWorkers ¶
func WithMaxWorkers(n int) func(*StreamConfig)
Types ¶
type LRUCache ¶
type LRUCache struct {
// contains filtered or unexported fields
}
func NewLRUCache ¶
func (*LRUCache) Add ¶
Add returns true if the key is NEW (added), false if it already existed (duplicate). This is the correct semantics for deduplication.
type Metrics ¶
type Metrics struct {
// contains filtered or unexported fields
}
func GetMetrics ¶
func GetMetrics() *Metrics
func (*Metrics) DecrementActiveWorkers ¶
func (m *Metrics) DecrementActiveWorkers()
func (*Metrics) IncrementActiveWorkers ¶
func (*Metrics) RecordBlockedGoroutine ¶
func (m *Metrics) RecordBlockedGoroutine()
func (*Metrics) RecordChannelReceive ¶
func (m *Metrics) RecordChannelReceive()
func (*Metrics) RecordChannelSend ¶
func (m *Metrics) RecordChannelSend()
func (*Metrics) RecordError ¶
func (m *Metrics) RecordError()
func (*Metrics) RecordItem ¶
func (m *Metrics) RecordItem()
func (*Metrics) RecordProcessingTime ¶
func (*Metrics) Snapshot ¶
func (m *Metrics) Snapshot() MetricsSnapshot
type MetricsSnapshot ¶
type OnceWithWait ¶
type OnceWithWait struct {
// contains filtered or unexported fields
}
func (*OnceWithWait) Do ¶
func (o *OnceWithWait) Do(f func())
func (*OnceWithWait) Wait ¶
func (o *OnceWithWait) Wait()
func (*OnceWithWait) WasCalled ¶
func (o *OnceWithWait) WasCalled() bool
type PipelineBuilder ¶
type PipelineBuilder struct {
// contains filtered or unexported fields
}
PipelineBuilder provides a fluent API for building data processing pipelines. Note: Due to Go generics limitations, this builder uses Try[any] internally. Callers should use type assertions on the output. Prefer standalone functions (Map, Filter, FlatMap, etc.) for compile-time type safety.
func NewPipeline ¶
func NewPipeline[A any](ctx context.Context, source Stream[A]) *PipelineBuilder
NewPipeline creates a new PipelineBuilder from a source stream.
func (*PipelineBuilder) Batch ¶
func (p *PipelineBuilder) Batch(size int) *PipelineBuilder
Batch groups elements into batches of the specified size.
func (*PipelineBuilder) Build ¶
func (p *PipelineBuilder) Build() Stream[any]
Build executes the pipeline and returns the output stream.
func (*PipelineBuilder) Filter ¶
func (p *PipelineBuilder) Filter(f func(context.Context, any) (bool, error)) *PipelineBuilder
Filter keeps elements that satisfy the predicate.
func (*PipelineBuilder) FilterMap ¶
func (p *PipelineBuilder) FilterMap(f func(context.Context, any) (any, bool, error)) *PipelineBuilder
FilterMap transforms and filters elements.
func (*PipelineBuilder) FlatMap ¶
func (p *PipelineBuilder) FlatMap(f func(context.Context, any) ([]any, error)) *PipelineBuilder
FlatMap transforms each element into multiple elements.
func (*PipelineBuilder) ForEach ¶
func (p *PipelineBuilder) ForEach(f func(context.Context, any) error) *PipelineBuilder
ForEach executes a function for each element and forwards results.
func (*PipelineBuilder) Map ¶
func (p *PipelineBuilder) Map(f func(context.Context, any) (any, error)) *PipelineBuilder
Map transforms each element using the provided function.
func (*PipelineBuilder) Run ¶
func (p *PipelineBuilder) Run() error
Run executes the pipeline and discards all results.
func (*PipelineBuilder) WithWorkers ¶
func (p *PipelineBuilder) WithWorkers(n int) *PipelineBuilder
type RetryOptions ¶
func DefaultRetryOptions ¶
func DefaultRetryOptions() *RetryOptions
type StreamConfig ¶
func DefaultStreamConfig ¶
func DefaultStreamConfig() *StreamConfig