aboutsummaryrefslogtreecommitdiff
QUACKER
=======

Type-safe, composable concurrency patterns with backpressure for Go.

Quacker provides composable, channel-native concurrency primitives.
Backpressure propagates naturally through Go's channel semantics —
no custom protocols, no framework lock-in.


INSTALLATION
------------

    go get git.sangtran.io.vn/quacker.git

Requirements: Go 1.25+


PACKAGES
--------

pipeline
    Stream processing with backpressure. Compose stages into pipelines.
    Each stage transforms a channel into a channel.

    Example:
        ctx, cancel := context.WithCancelCause(ctx)

        out := pipeline.Run(ctx, input,
            pipeline.Map(3, func(ctx context.Context, e Event) (Event, bool) {
                enriched, err := enrich(ctx, e)
                if err != nil {
                    cancel(err)
                    return e, false
                }
                return enriched, true
            }),
            pipeline.Filter(func(e Event) bool { return e.Priority > 0 }),
            pipeline.Sink(5, func(ctx context.Context, e Event) {
                store(ctx, e)
            }),
        )

        for range out {}
        if err := context.Cause(ctx); err != nil {
            log.Fatal(err)
        }

    Stages: Map, Filter, ForEach, Buffer, Tee, Take, Sink, Batch.

fanout
    1-to-N distribution. Distribute a single stream to multiple
    consumers. RoundRobin for load balancing, Broadcast for pub/sub.

    Example:
        fo, _ := fanout.NewFanOut[int](
            fanout.WithWorkerCount(3),
            fanout.WithStrategy(fanout.Broadcast),
        )
        fo.Run(ctx, input)

        for _, ch := range fo.Outputs() {
            go consume(ch)
        }

fanin
    N-to-1 merge. Merge multiple channels into a single stream.

    Example:
        fi, _ := fanin.NewFanIn[int]()
        fi.Add(stream1)
        fi.Add(stream2)
        fi.Add(stream3)
        merged := fi.Run(ctx)

workerpool
    Fixed-size worker pool with push-based task queuing, metrics,
    and graceful shutdown.

    Example:
        pool, _ := workerpool.NewWorkerPool[MyTask](ctx,
            workerpool.WithNumWorkers(4),
            workerpool.WithTaskQueueSize(100),
        )
        pool.Start()
        pool.Push(task)
        pool.StopAndWait()


HOW THEY COMPOSE
----------------

The primitives connect through channels — Go's universal connector:

                    +-- pipeline --+
    source --> fanout --+-- pipeline --+-- fanin --> pipeline --> sink
                        +-- pipeline --+

    Example:
        fo.Run(ctx, source)

        fast := pipeline.Run(ctx, fo.Outputs()[0], pipeline.Map(10, enrichFast))
        slow := pipeline.Run(ctx, fo.Outputs()[1], pipeline.Map(2, enrichSlow))

        fi.Add(fast)
        fi.Add(slow)
        merged := fi.Run(ctx)

        out := pipeline.Run(ctx, merged, pipeline.Sink(5, store))


DESIGN
------

- Backpressure is free. Channels block when full. No custom protocol.
- Errors use stdlib. context.WithCancelCause + context.Cause.
- Shutdown is clear. Close input for drain; cancel context for stop.
- Small interfaces. Observer interfaces are 2-3 methods, optional.
- Zero dependencies. Core logic is stdlib only (golang.org/x/sync).


LICENSE
-------

MIT (see LICENSE)