Documentation
¶
Index ¶
- Constants
- type CheckpointInfo
- type OperatorInfo
- type PipelineInfo
- type Stream
- func (s *Stream) Filter(fn func(types.Record) bool, label ...string) *Stream
- func (s *Stream) FlatMap(fn func(types.Record) []types.Record, label ...string) *Stream
- func (s *Stream) KeyBy(fn operator.KeySelector, label ...string) *Stream
- func (s *Stream) Map(fn func(types.Record) types.Record, label ...string) *Stream
- func (s *Stream) Process(fn func(types.Record) (types.Record, error), opts ...operator.ProcessOption) *Stream
- func (s *Stream) Reduce(fn operator.ReduceFn, label ...string) *Stream
- func (st *Stream) ToSink(sk sink.Sink) *StreamExecutionEnv
- func (s *Stream) Window(assigner window.WindowAssigner, label ...string) *Stream
- func (s *Stream) WindowWithIdleTimeout(assigner window.WindowAssigner, idleTimeout time.Duration, label ...string) *Stream
- func (s *Stream) WithParallelism(n int) *Stream
- func (s *Stream) WithPartitions(n int) *Stream
- type StreamExecutionEnv
- func (env *StreamExecutionEnv) Describe() PipelineInfo
- func (env *StreamExecutionEnv) DescribeJSON() string
- func (env *StreamExecutionEnv) Execute(ctx context.Context) error
- func (env *StreamExecutionEnv) FromSource(src source.Source) *Stream
- func (env *StreamExecutionEnv) WithBufferSize(n int) *StreamExecutionEnv
- func (env *StreamExecutionEnv) WithCheckpointHook(fn func(checkpoint.Step, string) checkpoint.HookAction) *StreamExecutionEnv
- func (env *StreamExecutionEnv) WithCheckpointListener(fn func(id string)) *StreamExecutionEnv
- func (env *StreamExecutionEnv) WithCheckpointing(interval time.Duration, storage checkpoint.Storage) *StreamExecutionEnv
- func (env *StreamExecutionEnv) WithShutdownTimeout(d time.Duration) *StreamExecutionEnv
- func (env *StreamExecutionEnv) WithStateBackend(f state.BackendFactory) *StreamExecutionEnv
Constants ¶
const DefaultEdgeCapacity = 1024
DefaultEdgeCapacity is the default buffer size of the bounded edges between execution stages. Override with WithBufferSize.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type CheckpointInfo ¶
CheckpointInfo describes the checkpointing configuration.
type OperatorInfo ¶
type OperatorInfo struct {
Type string `json:"type"`
Label string `json:"label,omitempty"`
Config map[string]string `json:"config,omitempty"`
}
OperatorInfo describes a single operator in the pipeline chain.
type PipelineInfo ¶
type PipelineInfo struct {
Source source.SourceInfo `json:"source"`
Operators []OperatorInfo `json:"operators"`
Sink sink.SinkInfo `json:"sink"`
Checkpoint *CheckpointInfo `json:"checkpoint,omitempty"`
}
PipelineInfo is the JSON-serializable description of a pipeline. It is returned by Describe() and consumed by the dashboard.
type Stream ¶
type Stream struct {
// contains filtered or unexported fields
}
Stream represents a pipeline stage. Method calls on Stream append operators to the chain and return the updated Stream.
Streams are built using a fluent API:
env.FromSource(src).Map(fn).Filter(fn).ToSink(s)
The pipeline is lazy — nothing runs until env.Execute() is called.
func (*Stream) Filter ¶
Filter keeps only records where fn returns true. The optional label is shown in the dashboard.
func (*Stream) FlatMap ¶
FlatMap applies a 1:many transformation to each record. The function returns a slice; if empty, the record is dropped. The optional label is shown in the dashboard.
func (*Stream) KeyBy ¶
func (s *Stream) KeyBy(fn operator.KeySelector, label ...string) *Stream
KeyBy partitions the stream by the given key selector function. All records with the same key are routed to the same keyed worker. Required before stateful operations like Window and Reduce.
Use WithPartitions to control the number of keyed workers:
stream.KeyBy(fn, "by-customer").WithPartitions(8).Window(...).Reduce(...)
func (*Stream) Map ¶
Map applies a 1:1 transformation to each record in the stream. If the function returns the zero value of Record, the record is dropped. The optional label is shown in the dashboard.
func (*Stream) Process ¶ added in v0.4.0
func (s *Stream) Process(fn func(types.Record) (types.Record, error), opts ...operator.ProcessOption) *Stream
Process applies a user function that may return an error. On error the failure policy (Drop / DLQ / Fail) is applied. Use the operator.WithProcessFailurePolicy and operator.WithProcessDLQ options to configure failure handling.
stream.Process(func(r types.Record) (types.Record, error) {
if !isValid(r) { return r, fmt.Errorf("invalid") }
return enrich(r), nil
}, operator.WithProcessFailurePolicy(operator.ProcFailureDLQ)).
ToSink(s)
func (*Stream) Reduce ¶
Reduce applies a stateful aggregation per key. Must be used after KeyBy. The reduce function is called with the current accumulator (nil on first call) and the incoming record, and returns the new accumulator. The updated accumulator is emitted downstream after every record.
Example (count per key):
stream.KeyBy(func(r types.Record) []byte { return r.Key }).
Reduce(func(accum []byte, curr types.Record) []byte {
count := 0
if accum != nil {
count = int(binary.BigEndian.Uint64(accum))
}
count++
buf := make([]byte, 8)
binary.BigEndian.PutUint64(buf, uint64(count))
return buf
})
func (*Stream) ToSink ¶
func (st *Stream) ToSink(sk sink.Sink) *StreamExecutionEnv
ToSink connects the stream to a sink and returns the execution environment. The pipeline is still lazy — call env.Execute() to start processing.
func (*Stream) Window ¶
func (s *Stream) Window(assigner window.WindowAssigner, label ...string) *Stream
Window groups records into time-based windows. Must be used after KeyBy. Records are buffered into windows, and when a watermark passes a window's end time, the window fires — all its records are emitted as a single result.
Supported window types:
- window.Tumbling(size): fixed-size, non-overlapping (e.g. 5-minute buckets)
- window.Sliding(size, slide): overlapping windows (e.g. 5-min every 1-min)
- window.Session(gap): variable-size, closes after inactivity gap
Example (5-minute tumbling window):
stream.KeyBy(func(r types.Record) []byte { return r.Key }).
Window(window.Tumbling(5 * time.Minute)).
Reduce(aggregateFn)
func (*Stream) WindowWithIdleTimeout ¶
func (s *Stream) WindowWithIdleTimeout(assigner window.WindowAssigner, idleTimeout time.Duration, label ...string) *Stream
WindowWithIdleTimeout creates a window with an idle timeout. If no records arrive within the timeout duration, all remaining windows are fired and the pipeline stage completes. Useful for infinite streams that don't receive shutdown signals.
func (*Stream) WithParallelism ¶ added in v0.4.0
WithParallelism sets the number of workers for the most recently added stateless operator (Map, Filter, FlatMap, Process). Must be called directly after the operator it configures.
Consecutive operators with the same parallelism share one execution stage. Note: with parallelism > 1, record order is NOT preserved across workers — use it for CPU-heavy, order-insensitive transforms.
func (*Stream) WithPartitions ¶ added in v0.4.0
WithPartitions sets the number of keyed workers for the most recently added KeyBy operator. Must be called directly after KeyBy.
type StreamExecutionEnv ¶
type StreamExecutionEnv struct {
// contains filtered or unexported fields
}
StreamExecutionEnv is the entry point for building and running stream pipelines. Create one with NewEnv(), define your pipeline using FromSource/ToSink, then call Execute() to run it.
env := mailer.NewEnv() env.FromSource(src).Map(fn).Filter(fn).ToSink(stdout) env.Execute(ctx)
func (*StreamExecutionEnv) Describe ¶
func (env *StreamExecutionEnv) Describe() PipelineInfo
Describe returns a serializable description of the pipeline: source, operator chain, sink, and checkpoint config. Call this before Execute() to get the pipeline graph for the dashboard.
func (*StreamExecutionEnv) DescribeJSON ¶
func (env *StreamExecutionEnv) DescribeJSON() string
DescribeJSON returns the pipeline description as indented JSON.
func (*StreamExecutionEnv) Execute ¶
func (env *StreamExecutionEnv) Execute(ctx context.Context) error
Execute runs the pipeline. Operators are grouped into execution stages (see the pipeline package); stages run concurrently, connected by bounded edges. A full edge blocks the upstream stage — backpressure propagates stage by stage back to the source, so a slow sink throttles ingestion instead of growing memory.
Graceful shutdown (on context cancellation, C3 two-phase):
- The source stops producing and flushes pending offset commits.
- A final checkpoint barrier is injected (if checkpointing is on).
- Channel closes cascade downstream; every stage drains in-flight records — nothing is dropped.
- The sink drains and the final checkpoint is saved.
- Only if draining exceeds shutdownTimeout are blocked stages forcibly aborted.
Prometheus metrics are collected automatically during execution.
func (*StreamExecutionEnv) FromSource ¶
func (env *StreamExecutionEnv) FromSource(src source.Source) *Stream
FromSource sets the data source for the pipeline and returns a Stream that you can chain operators on.
func (*StreamExecutionEnv) WithBufferSize ¶ added in v0.4.0
func (env *StreamExecutionEnv) WithBufferSize(n int) *StreamExecutionEnv
WithBufferSize sets the capacity of the bounded edges between execution stages (default 1024). Larger buffers absorb bursts; smaller buffers propagate backpressure to the source sooner. Values < 1 are ignored.
func (*StreamExecutionEnv) WithCheckpointHook ¶ added in v0.4.0
func (env *StreamExecutionEnv) WithCheckpointHook(fn func(checkpoint.Step, string) checkpoint.HookAction) *StreamExecutionEnv
WithCheckpointHook installs a test-only hook fired after each coordinated checkpoint protocol step. Used by crash-window tests to halt or fail the coordinator at exact positions. Not for production.
func (*StreamExecutionEnv) WithCheckpointListener ¶ added in v0.5.0
func (env *StreamExecutionEnv) WithCheckpointListener(fn func(id string)) *StreamExecutionEnv
WithCheckpointListener registers an observer called with the checkpoint ID whenever a checkpoint completes — covering both the uncoordinated (at-least-once) and coordinated (exactly-once) paths. It is a progress signal for supervisors such as the job agent; the callback must not block and must not mutate pipeline state.
func (*StreamExecutionEnv) WithCheckpointing ¶
func (env *StreamExecutionEnv) WithCheckpointing(interval time.Duration, storage checkpoint.Storage) *StreamExecutionEnv
WithCheckpointing enables periodic checkpointing with the given interval and storage backend. Barriers are injected into the stream at the specified interval; when a barrier passes through all operators and reaches the sink, the checkpoint is complete.
On recovery, Execute() will load the latest checkpoint, restore all stateful operators, and resume from the saved source offset.
Example:
env := mailer.NewEnv()
env.WithCheckpointing(30*time.Second, checkpoint.NewFileStorage("/tmp/checkpoints"))
func (*StreamExecutionEnv) WithShutdownTimeout ¶ added in v0.4.0
func (env *StreamExecutionEnv) WithShutdownTimeout(d time.Duration) *StreamExecutionEnv
WithShutdownTimeout sets how long the pipeline waits for in-flight records to drain before forcing shutdown (default 30s).
func (*StreamExecutionEnv) WithStateBackend ¶ added in v0.4.0
func (env *StreamExecutionEnv) WithStateBackend(f state.BackendFactory) *StreamExecutionEnv
WithStateBackend sets the factory used to create state backends for stateful operators (Reduce, and any operator implementing operator.StateConfigurable). The factory is called once per state owner while the execution plan is built — "op-<i>" for top-level operators, "worker-<idx>" for keyed-worker clones — so every owner gets isolated state. Backends implementing io.Closer are closed when Execute returns.
Default: state.InMemory() semantics (each operator keeps its own in-memory backend).
Directories
¶
| Path | Synopsis |
|---|---|
|
cmd
|
|
|
mailer-runner
command
Command mailer-runner is the generic job entrypoint baked into the runner container image.
|
Command mailer-runner is the generic job entrypoint baked into the runner container image. |
|
mailer-workflow
command
|
|
|
control
module
|
|
|
examples
|
|
|
backpressure
command
Backpressure demo: a fast source feeding a deliberately slow sink through tiny edges.
|
Backpressure demo: a fast source feeding a deliberately slow sink through tiny edges. |
|
exactly-once
command
Exactly-once pipeline: Kafka → keyed aggregation → transactional Kafka.
|
Exactly-once pipeline: Kafka → keyed aggregation → transactional Kafka. |
|
kafka-orders
command
|
|
|
pg-orders
command
|
|
|
windowing
command
|
|
|
wordcount
command
|
|
|
Package jobagent supervises a single Mailer job in-process and exposes its lifecycle over HTTP.
|
Package jobagent supervises a single Mailer job in-process and exposes its lifecycle over HTTP. |
|
observability
|
|
|
Package pipeline implements stage-based execution for stream pipelines.
|
Package pipeline implements stage-based execution for stream pipelines. |
|
Package sdk is the harness for SDK (Go) jobs run through the mailer control plane.
|
Package sdk is the harness for SDK (Go) jobs run through the mailer control plane. |
|
Package state provides keyed state storage for stateful stream processing.
|
Package state provides keyed state storage for stateful stream processing. |
|
Package watermark provides watermark generation for event-time processing.
|
Package watermark provides watermark generation for event-time processing. |
|
Package window provides window assigners for grouping unbounded streams into finite chunks based on time.
|
Package window provides window assigners for grouping unbounded streams into finite chunks based on time. |
|
Package workflow defines a declarative format for Mailer pipelines.
|
Package workflow defines a declarative format for Mailer pipelines. |
|
compiler
Package compiler turns a parsed, validated workflow spec into the existing Mailer SDK objects (sources, operators, sinks, environment).
|
Package compiler turns a parsed, validated workflow spec into the existing Mailer SDK objects (sources, operators, sinks, environment). |
|
operators
Package operators provides built-in stateless operators for declarative workflows.
|
Package operators provides built-in stateless operators for declarative workflows. |
|
record
Package record provides a structured JSON view of a types.Record so declarative, field-level operations (map/filter/project by field name) can read and modify record contents safely.
|
Package record provides a structured JSON view of a types.Record so declarative, field-level operations (map/filter/project by field name) can read and modify record contents safely. |