pipeline

package
v0.0.3 Latest Latest
Warning

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

Go to latest
Published: Jul 12, 2026 License: BSD-2-Clause Imports: 11 Imported by: 0

Documentation

Overview

Package pipeline connects frame processors into a chain and drives them.

A Pipeline links a sequence of processors between a source and a sink. A Task runs a pipeline for one session: it sends the StartFrame, pushes frames, and shuts the pipeline down on an EndFrame or CancelFrame. A Runner runs a Task and ends it on an interrupt signal.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type ParallelPipeline

type ParallelPipeline struct {
	*processor.Base
	// contains filtered or unexported fields
}

ParallelPipeline runs several sub-pipelines, the branches, concurrently. Every frame entering the parallel pipeline is fanned out to all branches, and frames emerging from the branches are merged back out. A frame that more than one branch forwards unchanged escapes only once: the merge deduplicates by frame id.

Lifecycle frames — StartFrame, EndFrame and CancelFrame — are synchronized. The parallel pipeline waits for every branch to process the frame before letting a single copy continue, and buffers any other frames a branch emits in the meantime (flushing them after a StartFrame, before an EndFrame or CancelFrame). This stops a fast branch from leaking an EndFrame and shutting downstream processors down while a slower branch still has output to flush, or from emitting data before every branch has been started.

A ParallelPipeline is itself a processor, so it nests inside a Pipeline.

The deduplication set retains the id of every frame that escapes the parallel pipeline for the lifetime of the session; this mirrors the upstream design and is bounded only by the session's frame count.

func NewParallel

func NewParallel(branches ...[]processor.Processor) (*ParallelPipeline, error)

NewParallel builds a ParallelPipeline from one or more branches, each a list of processors connected in order. It returns an error if no branch is given.

func (*ParallelPipeline) Cleanup

func (p *ParallelPipeline) Cleanup(ctx context.Context) error

Cleanup cleans up the parallel pipeline and every branch.

func (*ParallelPipeline) ProcessFrame

func (p *ParallelPipeline) ProcessFrame(ctx context.Context, f frames.Frame, dir processor.Direction) error

ProcessFrame fans a frame out to every branch. For a lifecycle frame it first arms the synchronization counter, then blocks until every branch has processed the frame (or the context is canceled), so the next frame is not fanned out until the lifecycle frame has fully propagated.

func (*ParallelPipeline) Setup

Setup sets up the parallel pipeline and every branch.

type Pipeline

type Pipeline struct {
	*processor.Base
	// contains filtered or unexported fields
}

Pipeline is a linear chain of processors. It wraps the chain with a source and a sink so frames can be fed in and observed at the edges, and is itself a processor, so pipelines can nest.

func New

func New(procs ...processor.Processor) *Pipeline

New builds a Pipeline from procs, connected in order. Frames pushed out of the chain's source and sink are forwarded to the pipeline's own neighbors.

func (*Pipeline) Cleanup

func (p *Pipeline) Cleanup(ctx context.Context) error

Cleanup cleans up the pipeline and every processor in the chain.

func (*Pipeline) ProcessFrame

func (p *Pipeline) ProcessFrame(ctx context.Context, f frames.Frame, dir processor.Direction) error

ProcessFrame routes a frame into the chain: downstream frames enter at the source, upstream frames enter at the sink.

func (*Pipeline) Setup

func (p *Pipeline) Setup(ctx context.Context, s processor.Setup) error

Setup sets up the pipeline and every processor in the chain.

type Runner

type Runner struct {
	// contains filtered or unexported fields
}

Runner runs a single task to completion and shuts it down gracefully on an interrupt signal (SIGINT or SIGTERM).

func NewRunner

func NewRunner(opts ...RunnerOption) *Runner

NewRunner returns a Runner. By default it handles interrupt signals.

func (*Runner) Run

func (r *Runner) Run(parent context.Context, task *Task) error

Run runs task until it finishes. When signal handling is enabled, the first interrupt signal cancels the task (so the pipeline drains the CancelFrame and shuts down); the task keeps running on the parent context so cleanup can complete. If the parent context is canceled the task stops the same way.

type RunnerOption

type RunnerOption func(*Runner)

RunnerOption configures a Runner.

func WithoutSignalHandling

func WithoutSignalHandling() RunnerOption

WithoutSignalHandling disables the SIGINT/SIGTERM handling, leaving shutdown entirely to the caller's context.

type ServiceSwitcher

type ServiceSwitcher struct {
	*Pipeline
	// contains filtered or unexported fields
}

ServiceSwitcher routes the pipeline through one of several interchangeable services at a time. Every service is started and kept warm, but only the active one receives data; the rest are gated off. Switching is manual (via SwitchTo or a SwitchServiceFrame) and, under SwitchFailover, automatic when the active service reports a non-fatal error.

It is built on a ParallelPipeline: each service becomes a branch wrapped in a pair of filters that pass lifecycle and system frames (so every service stays ready) but gate data frames on whether the service is active. A control processor in front consumes switch requests and watches for the errors that drive failover.

func NewServiceSwitcher

func NewServiceSwitcher(services []processor.Processor, strategy SwitcherStrategy) (*ServiceSwitcher, error)

NewServiceSwitcher builds a switcher over services, the first of which starts active, using the given switching strategy.

func (*ServiceSwitcher) ActiveService

func (s *ServiceSwitcher) ActiveService() processor.Processor

ActiveService returns the currently active service.

func (*ServiceSwitcher) OnSwitch

func (s *ServiceSwitcher) OnSwitch(fn func(processor.Processor))

OnSwitch registers fn to be called whenever the active service changes.

func (*ServiceSwitcher) SwitchTo

func (s *ServiceSwitcher) SwitchTo(svc processor.Processor) bool

SwitchTo makes svc the active service, returning false if svc is not one of the switcher's services.

type SwitchServiceFrame

type SwitchServiceFrame struct {
	frames.BaseControlFrame
	// Service is the service to activate; it must belong to the switcher.
	Service processor.Processor
}

SwitchServiceFrame requests that a ServiceSwitcher make Service active. Queue it downstream into the pipeline, or call ServiceSwitcher.SwitchTo directly.

func NewSwitchServiceFrame

func NewSwitchServiceFrame(svc processor.Processor) *SwitchServiceFrame

NewSwitchServiceFrame builds a SwitchServiceFrame targeting svc.

type SwitcherStrategy

type SwitcherStrategy int

SwitcherStrategy selects how a ServiceSwitcher changes its active service.

const (
	// SwitchManual changes the active service only on an explicit request.
	SwitchManual SwitcherStrategy = iota
	// SwitchFailover additionally moves to the next service when the active one
	// reports a non-fatal error.
	SwitchFailover
)

type Task

type Task struct {
	// contains filtered or unexported fields
}

Task runs a pipeline for a single session. It drives the lifecycle: it sends the StartFrame, waits for the pipeline to be ready, pushes queued frames, and shuts the pipeline down once an EndFrame or CancelFrame has traveled all the way through.

func NewTask

func NewTask(pipe processor.Processor, params TaskParams) *Task

NewTask wraps pipe in a Task. pipe is usually a *Pipeline but may be any processor.

func (*Task) Cancel

func (t *Task) Cancel()

Cancel stops the pipeline immediately by queueing a CancelFrame.

func (*Task) HasFinished

func (t *Task) HasFinished() bool

HasFinished reports whether the task has finished running.

func (*Task) QueueFrame

func (t *Task) QueueFrame(f frames.Frame)

QueueFrame queues a frame to be pushed downstream through the pipeline.

func (*Task) QueueFrames

func (t *Task) QueueFrames(fs []frames.Frame)

QueueFrames queues several frames to be pushed downstream, in order.

func (*Task) Run

func (t *Task) Run(ctx context.Context) error

Run sets up the pipeline and drives it until an EndFrame or CancelFrame completes its journey through the pipeline, or ctx is canceled. It then cleans up the pipeline. Run blocks until the pipeline has finished.

func (*Task) StopWhenDone

func (t *Task) StopWhenDone()

StopWhenDone schedules the pipeline to stop once all queued frames have been processed, by queueing an EndFrame.

type TaskParams

type TaskParams struct {
	// Clock is the pipeline clock; a system clock is used when nil.
	Clock clock.Clock
	// AudioInSampleRate is the StartFrame input sample rate; default 16000.
	AudioInSampleRate int
	// AudioOutSampleRate is the StartFrame output sample rate; default 24000.
	AudioOutSampleRate int
	// EnableMetrics enables performance-metrics collection across the pipeline.
	EnableMetrics bool
	// EnableUsageMetrics enables usage-metrics collection (e.g. LLM token usage)
	// across the pipeline.
	EnableUsageMetrics bool
	// OnReachedDownstream, if set, is called for every frame that reaches the
	// end of the pipeline.
	OnReachedDownstream func(frames.Frame)
	// OnReachedUpstream, if set, is called for every frame that reaches the
	// start of the pipeline.
	OnReachedUpstream func(frames.Frame)
}

TaskParams configures a Task.

Jump to

Keyboard shortcuts

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