Documentation
¶
Index ¶
- func StateKey(r types.Record) string
- type BarrierSnapshotter
- type Cloneable
- type DescribableOperator
- type FilterOperator
- type FlatMapOperator
- type KeyByOperator
- func (op *KeyByOperator) DescribeOp() OperatorMeta
- func (op *KeyByOperator) GetLabel() string
- func (op *KeyByOperator) IsRouter() bool
- func (op *KeyByOperator) Name() string
- func (op *KeyByOperator) Process(in <-chan types.Record, out chan<- types.Record)
- func (op *KeyByOperator) Route(r types.Record) int
- func (op *KeyByOperator) RouteKey(key []byte) int
- func (op *KeyByOperator) SelectKey(r types.Record) []byte
- func (op *KeyByOperator) WithPartitions(n int) *KeyByOperator
- type KeySelector
- type Labeled
- type MapOperator
- type NativeSnapshotter
- type Operator
- type OperatorMeta
- type Parallel
- type Parallelizable
- type ProcFailurePolicy
- type ProcessOperator
- type ProcessOption
- type RecordSink
- type ReduceFn
- type ReduceOperator
- func (op *ReduceOperator) Backend() state.StateBackend
- func (op *ReduceOperator) Clone() Operator
- func (op *ReduceOperator) DescribeOp() OperatorMeta
- func (op *ReduceOperator) GetLabel() string
- func (op *ReduceOperator) Name() string
- func (op *ReduceOperator) Process(in <-chan types.Record, out chan<- types.Record)
- func (op *ReduceOperator) Restore(data []byte) error
- func (op *ReduceOperator) SetBarrierSnapshot(fn func(checkpointID string, snapshot []byte, err error))
- func (op *ReduceOperator) SetNativeSnapshot(fn func(checkpointID string) ([]byte, error))
- func (op *ReduceOperator) SetStateBackend(b state.StateBackend)
- func (op *ReduceOperator) Snapshot() ([]byte, error)
- type SingleProcessor
- type Snapshotable
- type StateConfigurable
- type WindowOperator
- func (op *WindowOperator) Backend() state.StateBackend
- func (op *WindowOperator) Clone() Operator
- func (op *WindowOperator) CurrentWatermark() time.Time
- func (op *WindowOperator) DescribeOp() OperatorMeta
- func (op *WindowOperator) GetLabel() string
- func (op *WindowOperator) Name() string
- func (op *WindowOperator) Process(in <-chan types.Record, out chan<- types.Record)
- func (op *WindowOperator) Restore(data []byte) error
- func (op *WindowOperator) SetBarrierSnapshot(fn func(checkpointID string, snapshot []byte, err error))
- func (op *WindowOperator) SetNativeSnapshot(fn func(checkpointID string) ([]byte, error))
- func (op *WindowOperator) SetStateBackend(b state.StateBackend)
- func (op *WindowOperator) Snapshot() ([]byte, error)
- func (op *WindowOperator) WithIdleTimeout(d time.Duration) *WindowOperator
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type BarrierSnapshotter ¶ added in v0.4.0
type BarrierSnapshotter interface {
// SetBarrierSnapshot registers a callback invoked with the
// operator's state each time a barrier passes through it.
SetBarrierSnapshot(fn func(checkpointID string, snapshot []byte, err error))
}
BarrierSnapshotter is implemented by stateful operators that can snapshot their state synchronously when a checkpoint barrier passes through their Process loop. Snapshotting there — between two records — is the only race-free point: the operator is quiescent and its state reflects exactly the pre-barrier stream. Snapshots taken from outside (e.g. when the barrier reaches the end of the pipeline) race with the operator processing post-barrier records.
type Cloneable ¶ added in v0.4.0
type Cloneable interface {
Clone() Operator
}
Cloneable is an optional interface for operators that can be duplicated with independent state. Stateful operators (Window, Reduce) implement this so each keyed worker gets its own instance with an isolated state backend.
type DescribableOperator ¶ added in v0.3.0
type DescribableOperator interface {
DescribeOp() OperatorMeta
}
DescribableOperator is an optional interface that operators implement to expose their configuration for the dashboard.
type FilterOperator ¶
type FilterOperator struct {
Parallelizable
Fn func(types.Record) bool
Label string
}
FilterOperator keeps records that match the predicate and drops the rest.
func Filter ¶
func Filter(fn func(types.Record) bool) *FilterOperator
Filter creates a FilterOperator with the given predicate. Only records where fn(record) == true will pass through.
func (*FilterOperator) DescribeOp ¶ added in v0.3.0
func (op *FilterOperator) DescribeOp() OperatorMeta
func (*FilterOperator) GetLabel ¶
func (op *FilterOperator) GetLabel() string
func (*FilterOperator) Name ¶
func (op *FilterOperator) Name() string
func (*FilterOperator) Process ¶
func (op *FilterOperator) Process(in <-chan types.Record, out chan<- types.Record)
Process reads each record from in and writes it to out only if the predicate returns true. Watermarks and barriers are always passed through.
func (*FilterOperator) ProcessOne ¶ added in v0.4.0
func (op *FilterOperator) ProcessOne(r types.Record) []types.Record
ProcessOne applies the predicate to a single record. Returns an empty slice when the record is dropped.
type FlatMapOperator ¶
FlatMapOperator applies a 1:many transformation to each record. The function returns a slice of records. If the slice is empty, the input record is effectively filtered out.
func FlatMap ¶
func FlatMap(fn func(types.Record) []types.Record) *FlatMapOperator
FlatMap creates a FlatMapOperator with the given transformation function.
func (*FlatMapOperator) DescribeOp ¶ added in v0.3.0
func (op *FlatMapOperator) DescribeOp() OperatorMeta
func (*FlatMapOperator) GetLabel ¶
func (op *FlatMapOperator) GetLabel() string
func (*FlatMapOperator) Name ¶
func (op *FlatMapOperator) Name() string
func (*FlatMapOperator) Process ¶
func (op *FlatMapOperator) Process(in <-chan types.Record, out chan<- types.Record)
Process reads each record from in, applies the flat map function, and writes each result record to out. Watermarks and barriers are passed through unchanged.
func (*FlatMapOperator) ProcessOne ¶ added in v0.4.0
func (op *FlatMapOperator) ProcessOne(r types.Record) []types.Record
ProcessOne applies the flat map function to a single record.
type KeyByOperator ¶
type KeyByOperator struct {
KeySelector KeySelector
Partitions int
Label string
}
KeyByOperator marks the start of a keyed stage. Records flow through a router that hash-dispatches each record to one of N worker channels. Each worker runs its own copy of the downstream stateful operators (Window, Reduce) with isolated state.
KeyBy is not a processing operator — Execute() detects it and builds the worker topology. Process() is a no-op.
func KeyBy ¶
func KeyBy(fn KeySelector) *KeyByOperator
KeyBy creates a KeyByOperator with the given key selector. Default partition count is 16. Use WithPartitions to change it.
func (*KeyByOperator) DescribeOp ¶ added in v0.3.0
func (op *KeyByOperator) DescribeOp() OperatorMeta
func (*KeyByOperator) GetLabel ¶
func (op *KeyByOperator) GetLabel() string
func (*KeyByOperator) IsRouter ¶ added in v0.4.0
func (op *KeyByOperator) IsRouter() bool
IsRouter returns true — KeyBy is handled by Execute() as a worker topology builder, not a regular channel operator.
func (*KeyByOperator) Name ¶
func (op *KeyByOperator) Name() string
func (*KeyByOperator) Process ¶
func (op *KeyByOperator) Process(in <-chan types.Record, out chan<- types.Record)
Process is never called by Execute() when IsRouter() is true.
func (*KeyByOperator) Route ¶ added in v0.4.0
func (op *KeyByOperator) Route(r types.Record) int
Route hashes the selected key and returns the target worker index.
func (*KeyByOperator) RouteKey ¶ added in v0.5.0
func (op *KeyByOperator) RouteKey(key []byte) int
RouteKey hashes key and returns the target worker index.
func (*KeyByOperator) SelectKey ¶ added in v0.5.0
func (op *KeyByOperator) SelectKey(r types.Record) []byte
SelectKey extracts the key used by the keyed stage. The router writes this key onto the record before downstream stateful operators process it.
func (*KeyByOperator) WithPartitions ¶
func (op *KeyByOperator) WithPartitions(n int) *KeyByOperator
WithPartitions sets the number of keyed workers and returns the operator. More workers = more parallelism for stateful processing.
type KeySelector ¶ added in v0.4.0
KeySelector extracts a routing key from a record. Used by KeyBy to deterministically route records to keyed workers.
type Labeled ¶
type Labeled interface {
GetLabel() string
}
Labeled operators carry a user-provided label for display in the dashboard. If no label is set, the dashboard falls back to Name().
type MapOperator ¶
MapOperator applies a 1:1 transformation to each record. Every input record produces exactly one output record. To conditionally drop records, use Filter before or after Map.
func Map ¶
func Map(fn func(types.Record) types.Record) *MapOperator
Map creates a MapOperator with the given transformation function.
func (*MapOperator) DescribeOp ¶ added in v0.3.0
func (op *MapOperator) DescribeOp() OperatorMeta
func (*MapOperator) GetLabel ¶
func (op *MapOperator) GetLabel() string
func (*MapOperator) Name ¶
func (op *MapOperator) Name() string
func (*MapOperator) Process ¶
func (op *MapOperator) Process(in <-chan types.Record, out chan<- types.Record)
Process reads each record from in, applies the map function, and writes the result to out. Watermarks and barriers are passed through unchanged.
func (*MapOperator) ProcessOne ¶ added in v0.4.0
func (op *MapOperator) ProcessOne(r types.Record) []types.Record
ProcessOne applies the map function to a single record.
type NativeSnapshotter ¶ added in v0.4.0
type NativeSnapshotter interface {
SetNativeSnapshot(fn func(checkpointID string) (snapshot []byte, err error))
Backend() state.StateBackend
}
NativeSnapshotter is implemented by stateful operators whose barrier-time snapshot can be replaced by a native (backend-level) checkpoint. When the engine detects a state.Checkpointable backend, it injects a snapshot function that hard-links the backend's files into the checkpoint's state directory and returns a small state-ref marker instead of serializing all state — this is what makes checkpoint cost scale with changed data instead of total state. The function runs at the same race-free point as BarrierSnapshotter (inside Process, as the barrier passes).
type Operator ¶
type Operator interface {
// Name returns the operator type name (e.g. "Map", "Filter", "Window").
// Used by the dashboard to display the pipeline graph.
Name() string
Process(in <-chan types.Record, out chan<- types.Record)
}
Operator transforms an input stream into an output stream. Each operator reads from an input channel, applies a transformation, and writes to an output channel. The output channel must be closed when the operator is done processing.
type OperatorMeta ¶ added in v0.3.0
type OperatorMeta struct {
Type string `json:"type"`
Label string `json:"label,omitempty"`
Config map[string]string `json:"config,omitempty"`
}
OperatorMeta describes the configuration of an operator for the dashboard.
type Parallel ¶ added in v0.4.0
Parallel is implemented by operators that can run with multiple workers. The planner groups consecutive operators with the same parallelism into one execution stage.
type Parallelizable ¶ added in v0.4.0
type Parallelizable struct {
Par int
}
Parallelizable provides the Parallel implementation for stateless operators via embedding. Zero value means parallelism 1.
func (*Parallelizable) Parallelism ¶ added in v0.4.0
func (p *Parallelizable) Parallelism() int
Parallelism returns the configured worker count (minimum 1).
func (*Parallelizable) SetParallelism ¶ added in v0.4.0
func (p *Parallelizable) SetParallelism(n int)
SetParallelism sets the worker count. Values < 1 are treated as 1. Note: with parallelism > 1, record order is not preserved across workers.
type ProcFailurePolicy ¶ added in v0.4.0
type ProcFailurePolicy int
ProcFailurePolicy determines what happens when a Process function returns an error. Follows the same pattern as sink FailurePolicy.
const ( ProcFailureDrop ProcFailurePolicy = iota ProcFailureDLQ ProcFailureFail )
type ProcessOperator ¶ added in v0.4.0
type ProcessOperator struct {
Parallelizable
Fn func(types.Record) (types.Record, error)
Label string
FailurePolicy ProcFailurePolicy
DLQ RecordSink
}
ProcessOperator wraps a user function that may return an error. On error, the failure policy is applied: drop the record, forward it to a DLQ, or fail the pipeline.
Watermarks and barriers pass through unchanged.
func NewProcess ¶ added in v0.4.0
func NewProcess(fn func(types.Record) (types.Record, error), opts ...ProcessOption) *ProcessOperator
NewProcess creates a ProcessOperator. Use ProcessOption functions to configure the failure policy and DLQ.
func (*ProcessOperator) DescribeOp ¶ added in v0.4.0
func (op *ProcessOperator) DescribeOp() OperatorMeta
func (*ProcessOperator) GetLabel ¶ added in v0.4.0
func (op *ProcessOperator) GetLabel() string
func (*ProcessOperator) Name ¶ added in v0.4.0
func (op *ProcessOperator) Name() string
func (*ProcessOperator) Process ¶ added in v0.4.0
func (op *ProcessOperator) Process(in <-chan types.Record, out chan<- types.Record)
Process reads each record, calls the user function, and handles errors according to the configured failure policy.
func (*ProcessOperator) ProcessOne ¶ added in v0.4.0
func (op *ProcessOperator) ProcessOne(r types.Record) []types.Record
ProcessOne applies the user function to a single record, handling errors via the configured failure policy.
type ProcessOption ¶ added in v0.4.0
type ProcessOption func(*ProcessOperator)
ProcessOption configures a ProcessOperator.
func WithProcessDLQ ¶ added in v0.4.0
func WithProcessDLQ(dlq RecordSink) ProcessOption
WithProcessDLQ sets the dead-letter queue for failed records. Only used when failure policy is ProcFailureDLQ.
func WithProcessFailurePolicy ¶ added in v0.4.0
func WithProcessFailurePolicy(p ProcFailurePolicy) ProcessOption
WithProcessFailurePolicy sets what happens when the function returns an error. Default is ProcFailureDrop.
func WithProcessLabel ¶ added in v0.4.0
func WithProcessLabel(l string) ProcessOption
WithProcessLabel sets a human-readable label for the dashboard.
type RecordSink ¶ added in v0.4.0
RecordSink is a minimal sink interface used to forward failed records to a dead-letter queue. Implementations include a KafkaSink, PostgresSink, or any custom handler.
type ReduceFn ¶
ReduceFn takes the current accumulator and the incoming record, and returns the new accumulator bytes. The accumulator is persisted per key.
On the first record for a given key, accum will be nil (no previous state). The function should return the initial accumulator based on the first record.
Example (count per key):
reduce := 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
})
type ReduceOperator ¶
ReduceOperator maintains per-key state and applies a reduce function to merge each incoming record into the accumulator.
It must be used after KeyBy — the key determines which accumulator to use. On every record:
- Look up the ValueState for the record's key
- If state exists, use it as accumulator; otherwise accum is nil
- Call reduceFn(accum, record) to get the new accumulator
- Save the new accumulator to state
- Emit the updated accumulator downstream as a new Record
func Reduce ¶
func Reduce(fn ReduceFn) *ReduceOperator
Reduce creates a ReduceOperator with the given reduce function. A fresh MemoryBackend is created for this operator's state.
func (*ReduceOperator) Backend ¶ added in v0.4.0
func (op *ReduceOperator) Backend() state.StateBackend
Backend returns the underlying state backend. Used by the checkpoint coordinator to check for native checkpointing support.
func (*ReduceOperator) Clone ¶ added in v0.4.0
func (op *ReduceOperator) Clone() Operator
Clone returns a copy with the same reduce function and label but a fresh in-memory state backend. Used for per-worker isolation in keyed parallel execution.
func (*ReduceOperator) DescribeOp ¶ added in v0.3.0
func (op *ReduceOperator) DescribeOp() OperatorMeta
func (*ReduceOperator) GetLabel ¶
func (op *ReduceOperator) GetLabel() string
func (*ReduceOperator) Name ¶
func (op *ReduceOperator) Name() string
func (*ReduceOperator) Process ¶
func (op *ReduceOperator) Process(in <-chan types.Record, out chan<- types.Record)
Process reads each record, applies the reduce function with per-key state, and emits the new accumulator value downstream. Watermarks and barriers are passed through. When records have window_start/window_end headers (from Window), state is scoped per-(key, window) so reduce is per-window.
When a barrier arrives, the operator snapshots its state and forwards the barrier downstream. This enables checkpointing.
func (*ReduceOperator) Restore ¶
func (op *ReduceOperator) Restore(data []byte) error
Restore replaces the operator's internal state from JSON bytes produced by Snapshot.
func (*ReduceOperator) SetBarrierSnapshot ¶ added in v0.4.0
func (op *ReduceOperator) SetBarrierSnapshot(fn func(checkpointID string, snapshot []byte, err error))
SetBarrierSnapshot implements BarrierSnapshotter.
func (*ReduceOperator) SetNativeSnapshot ¶ added in v0.4.0
func (op *ReduceOperator) SetNativeSnapshot(fn func(checkpointID string) ([]byte, error))
SetNativeSnapshot implements NativeSnapshotter.
func (*ReduceOperator) SetStateBackend ¶ added in v0.4.0
func (op *ReduceOperator) SetStateBackend(b state.StateBackend)
SetStateBackend implements StateConfigurable: the engine injects the backend created for this operator's owner ID. Called during plan construction, before any record is processed or state restored.
func (*ReduceOperator) Snapshot ¶
func (op *ReduceOperator) Snapshot() ([]byte, error)
Snapshot returns the operator's current per-key state as JSON bytes.
type SingleProcessor ¶ added in v0.4.0
SingleProcessor is implemented by stateless operators that can be invoked directly, one record at a time, without channels. The execution engine chains SingleProcessors inside a stage as plain function calls.
The returned slice length encodes the operator semantics: 0 = record dropped (Filter), 1 = transformed (Map), N = fan-out (FlatMap).
Barriers and watermarks are never passed to ProcessOne — the stage machinery forwards and aligns them itself.
type Snapshotable ¶
type Snapshotable interface {
// Snapshot returns the operator's current state as opaque bytes.
// The returned bytes must be sufficient to fully reconstruct the
// operator's state via Restore.
Snapshot() ([]byte, error)
// Restore replaces the operator's internal state from the given bytes.
// The bytes must have been produced by a prior call to Snapshot on the
// same operator type. Restore is called before the pipeline starts.
Restore(data []byte) error
}
Snapshotable operators can snapshot and restore their internal state. This is used for checkpointing — when a barrier passes through a stateful operator, its state is captured and can be restored on recovery.
type StateConfigurable ¶ added in v0.4.0
type StateConfigurable interface {
SetStateBackend(b state.StateBackend)
}
StateConfigurable is implemented by stateful operators whose state backend can be injected by the engine. The planner assigns each operator instance a backend created from the environment's BackendFactory (WithStateBackend), keyed by the owner ID used in checkpoint data. Operators keep a self-created in-memory backend as the default when no factory is configured.
SetStateBackend is called during plan construction, strictly before the operator processes any record or has state restored into it.
type WindowOperator ¶
type WindowOperator struct {
Assigner window.WindowAssigner
IdleTimeout time.Duration
Label string
// contains filtered or unexported fields
}
WindowOperator buffers records into time-based windows and fires them when the watermark passes the window's end time.
How it works:
- Data records are assigned to windows by the WindowAssigner and buffered in the injected state backend (Pebble when configured), so window contents live on disk instead of the Go heap.
- Watermark records advance the current watermark.
- When the watermark passes a window's end time, that window is "closed" — all its buffered records are emitted as a single result.
- Late records (timestamp < current watermark) are dropped.
- Checkpoint barriers snapshot state (natively via the backend when it supports hard-link checkpoints, else serialized to JSON).
Must be used after KeyBy in a keyed stream so each key gets its own set of windows.
State layout in the backend:
- records: ListState(windowRecordsNS), keyed by windowKey.String() ("<recordKey>/<start>/<end>"); each entry is one serialized record. Window bounds are recovered from the key, so the set of open windows is exactly Keys().
- watermark: ValueState(windowWatermarkNS)["wm"] — 8-byte UnixNano. A RAM working copy (currentWatermark) serves the per-record late-drop check without a backend read.
func Window ¶
func Window(assigner window.WindowAssigner) *WindowOperator
Window creates a WindowOperator with the given window assigner. Supported assigners: window.Tumbling, window.Sliding, window.Session. A default in-memory backend is used until one is injected.
func (*WindowOperator) Backend ¶ added in v0.4.0
func (op *WindowOperator) Backend() state.StateBackend
Backend implements NativeSnapshotter: exposes the backend so the engine can detect state.Checkpointable support.
func (*WindowOperator) Clone ¶ added in v0.4.0
func (op *WindowOperator) Clone() Operator
Clone returns a copy with the same configuration but a fresh default backend (the engine injects the real one afterwards). Used for per-worker isolation in keyed parallel execution.
func (*WindowOperator) CurrentWatermark ¶
func (op *WindowOperator) CurrentWatermark() time.Time
CurrentWatermark returns the operator's current watermark timestamp. Used for testing and checkpointing.
func (*WindowOperator) DescribeOp ¶ added in v0.3.0
func (op *WindowOperator) DescribeOp() OperatorMeta
func (*WindowOperator) GetLabel ¶
func (op *WindowOperator) GetLabel() string
func (*WindowOperator) Name ¶
func (op *WindowOperator) Name() string
func (*WindowOperator) Process ¶
func (op *WindowOperator) Process(in <-chan types.Record, out chan<- types.Record)
Process reads records and watermarks, buffers data records into windows (in the backend), and emits results when watermarks indicate windows are complete. If IdleTimeout is set, the operator fires remaining windows and exits when no records arrive within the timeout.
func (*WindowOperator) Restore ¶
func (op *WindowOperator) Restore(data []byte) error
Restore replaces the backend's window contents from JSON produced by Snapshot. The backend is injected before Restore runs.
func (*WindowOperator) SetBarrierSnapshot ¶ added in v0.4.0
func (op *WindowOperator) SetBarrierSnapshot(fn func(checkpointID string, snapshot []byte, err error))
SetBarrierSnapshot implements BarrierSnapshotter.
func (*WindowOperator) SetNativeSnapshot ¶ added in v0.4.0
func (op *WindowOperator) SetNativeSnapshot(fn func(checkpointID string) ([]byte, error))
SetNativeSnapshot implements NativeSnapshotter.
func (*WindowOperator) SetStateBackend ¶ added in v0.4.0
func (op *WindowOperator) SetStateBackend(b state.StateBackend)
SetStateBackend implements StateConfigurable: the engine injects the backend created for this operator's owner ID. Called during plan construction, before any record is processed or state restored.
func (*WindowOperator) Snapshot ¶
func (op *WindowOperator) Snapshot() ([]byte, error)
Snapshot serializes the backend's window contents to JSON. Used for the memory backend and any backend without native checkpoint support.
func (*WindowOperator) WithIdleTimeout ¶
func (op *WindowOperator) WithIdleTimeout(d time.Duration) *WindowOperator
WithIdleTimeout sets the idle timeout for the window operator. If no records arrive for this duration after windowing, the operator fires all pending windows and stops. Useful for infinite streams that don't receive shutdown signals.