operator

package
v0.7.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 19, 2026 License: MIT Imports: 9 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func StateKey

func StateKey(r types.Record) string

StateKey returns the key used for Reduce state lookup. If the record has window metadata, the key includes window bounds so reduce is scoped per-(key, window).

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

type FlatMapOperator struct {
	Parallelizable
	Fn    func(types.Record) []types.Record
	Label string
}

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

type KeySelector func(types.Record) []byte

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

type MapOperator struct {
	Parallelizable
	Fn    func(types.Record) types.Record
	Label string
}

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

type Parallel interface {
	Parallelism() int
	SetParallelism(n int)
}

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

type RecordSink interface {
	Write(ctx context.Context, r types.Record) error
}

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

type ReduceFn func(accum []byte, curr types.Record) []byte

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

type ReduceOperator struct {
	Fn ReduceFn

	Label string
	// contains filtered or unexported fields
}

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:

  1. Look up the ValueState for the record's key
  2. If state exists, use it as accumulator; otherwise accum is nil
  3. Call reduceFn(accum, record) to get the new accumulator
  4. Save the new accumulator to state
  5. 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

type SingleProcessor interface {
	ProcessOne(r types.Record) []types.Record
}

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:

  1. 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.
  2. Watermark records advance the current watermark.
  3. When the watermark passes a window's end time, that window is "closed" — all its buffered records are emitted as a single result.
  4. Late records (timestamp < current watermark) are dropped.
  5. 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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL