gbuffer
Generic Go buffering for batching typed records, aggregating keyed updates, and scheduling flushes through a shared priority worker pool.
Tech Stack
Overview
gbuffer keeps high-frequency writes out of request paths. It accepts typed values, turns them into a flush payload, then runs sinks directly or through one shared priority worker pool.
The public sink is deliberately small:
T is the payload ready to write. A batcher flushes []T; an aggregator flushes map[K]V.
Why It Exists
Applications often need both of these workloads:
- Write records together: logs, orders, audit events, analytics events
- Merge repeated keyed updates: views, likes, impressions, inventory deltas
These workloads should share scheduling without forcing every caller into untyped queues or separate worker pools.
Core Pieces
| Piece | Job |
|---|---|
Sinker[T] | Writes one flushed payload |
Batcher[T] | Turns many values into []T |
Aggregator[K, V] | Turns keyed updates into map[K]V |
WorkerPool | Runs submitted jobs by priority |
SinkJob[T] | Bridges typed payloads to shared pool jobs |
Batch Records
Use Batcher[T] when individual records should reach storage together.
Aggregate Updates
Use Aggregator[K, V] when repeated updates to same key should be coalesced before writing.
Shared Priority Pool
Typed buffers can share one non-generic WorkerPool. Each flushed payload becomes a Job, preserving typed sinks while centralizing concurrency and priority.
Shutdown And Limits
Flush(context.Context) submits pending work. Close(context.Context) stops new writes, flushes remaining data, and waits for scheduled work until context expiry. Future Add calls return ErrClosed.
Pending in-memory values are bounded. ErrFull signals that an aggregator cannot accept another distinct key. Durable overflow stores such as Redis, Kafka, or disk are documented extension patterns, not core runtime dependencies.