core

package
v1.0.0 Latest Latest
Warning

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

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

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type ColorSpace

type ColorSpace string

ColorSpace represents the image colour model.

const (
	ColorSpaceRGB  ColorSpace = "rgb"
	ColorSpaceRGBA ColorSpace = "rgba"
	ColorSpaceCMYK ColorSpace = "cmyk"
	ColorSpaceGray ColorSpace = "gray"
)

type Decoder

type Decoder interface {
	// Decode reads from r and returns a decoded ImageData.
	Decode(ctx context.Context, r io.Reader) (*ImageData, error)
	// CanDecode reports whether this decoder handles the given format hint.
	CanDecode(format Format) bool
}

Decoder converts raw bytes / a reader into an in-memory ImageData. Implementations live in adapters/decoder/.

type DefaultRegistry

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

DefaultRegistry is a thread-safe implementation of Registry.

func NewRegistry

func NewRegistry() *DefaultRegistry

NewRegistry returns an empty DefaultRegistry.

func (*DefaultRegistry) DecoderFor

func (r *DefaultRegistry) DecoderFor(f Format) (Decoder, bool)

func (*DefaultRegistry) EncoderFor

func (r *DefaultRegistry) EncoderFor(f Format) (Encoder, bool)

func (*DefaultRegistry) RegisterDecoder

func (r *DefaultRegistry) RegisterDecoder(f Format, d Decoder)

func (*DefaultRegistry) RegisterEncoder

func (r *DefaultRegistry) RegisterEncoder(f Format, e Encoder)

type EncodeOptions

type EncodeOptions struct {
	Quality    int  // 1-100; 0 = use encoder default
	Lossless   bool // WebP / PNG lossless mode
	StripEXIF  bool
	Interlaced bool // progressive JPEG / interlaced PNG
}

EncodeOptions carries format-specific encoding parameters.

type Encoder

type Encoder interface {
	Encode(ctx context.Context, img *ImageData, opts EncodeOptions) ([]byte, error)
	CanEncode(format Format) bool
}

Encoder serialises an ImageData to bytes in a target format. Implementations live in adapters/encoder/.

type Format

type Format string

Format identifies an image codec.

const (
	FormatJPEG    Format = "jpeg"
	FormatPNG     Format = "png"
	FormatWebP    Format = "webp"
	FormatUnknown Format = "unknown"
)

type Hook

type Hook interface {
	BeforeStep(ctx context.Context, stepName string, img *ImageData)
	AfterStep(ctx context.Context, stepName string, img *ImageData, d time.Duration, err error)
}

Hook is an optional observer invoked around pipeline steps.

type ImageData

type ImageData struct {
	// Encoded bytes — non-nil when the image has been encoded or is raw input.
	Data   []byte
	Format Format

	// Decoded pixel buffer — populated lazily by decode steps only when needed.
	// Using image.Image keeps us CGO-free; libvips adapters can use unsafe pointers
	// wrapped in their own types and satisfy the Processor interface directly.
	Image interface{} // actual type: image.Image or vips.Image depending on backend

	// Metadata extracted during decode.
	Meta Metadata

	// Size of the original raw input for adaptive compression decisions.
	OriginalSize int64
}

ImageData is the in-memory representation passed through a pipeline. Data holds encoded bytes; Image holds the decoded pixel buffer when needed.

type Job

type Job struct {
	ID      string
	Ctx     context.Context //nolint:containedctx // intentional for async jobs
	Source  Source
	Steps   []Step
	Options JobOptions
	// Result channel; nil for fire-and-forget.
	ResultCh chan<- JobResult
}

Job encapsulates a single unit of work for the worker pool.

type JobOptions

type JobOptions struct {
	MaxRetries  int
	RetryDelay  time.Duration
	VariantDefs []VariantDefinition
}

JobOptions controls per-job behaviour.

type JobResult

type JobResult struct {
	JobID  string
	Result *ProcessingResult
	Err    error
}

JobResult wraps the outcome of an async job.

type Logger

type Logger interface {
	Debug(msg string, fields ...interface{})
	Info(msg string, fields ...interface{})
	Warn(msg string, fields ...interface{})
	Error(msg string, fields ...interface{})
}

Logger is a minimal structured logging interface.

type Metadata

type Metadata struct {
	Width       int
	Height      int
	Format      Format
	ColorSpace  ColorSpace
	HasAlpha    bool
	SizeBytes   int64
	EXIF        map[string]string // nil when stripped or absent
	HasEXIF     bool
	Orientation int // EXIF orientation tag (1-8)
}

Metadata holds extracted image information without loading pixel data.

type MetricsCollector

type MetricsCollector interface {
	RecordProcessingTime(stepName string, d interface{ Seconds() float64 })
	RecordThroughput(bytes int64)
	RecordMemory(bytes int64)
	RecordError(stepName string, category string)
}

MetricsCollector receives performance observations from the pipeline.

type PipelineRunner

type PipelineRunner interface {
	Run(ctx context.Context, img *ImageData) (*ImageData, map[string]time.Duration, error)
	Clone() PipelineRunner
}

PipelineRunner is a minimal interface over pipeline.Pipeline so that core does not import the pipeline package (avoiding a circular dependency).

type ProcessingResult

type ProcessingResult struct {
	Primary  *ImageData
	Variants map[string]*ImageData // keyed by variant name

	// Observability.
	ProcessingTime time.Duration
	StepTimings    map[string]time.Duration
	MemoryUsedB    int64
}

ProcessingResult is returned to the caller after the full pipeline completes.

type Processor

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

Processor is the central orchestrator. It is safe for concurrent use.

func New

func New(cfg config.Config, reg Registry) *Processor

New creates a Processor with the given config. Call Start() before submitting jobs; call Stop() when done.

func (*Processor) AddHook

func (p *Processor) AddHook(h Hook)

AddHook registers a pipeline hook.

func (*Processor) Batch

func (p *Processor) Batch(ctx context.Context, sources []Source, steps ...Step) ([]*ProcessingResult, []error)

Batch processes multiple sources concurrently (fan-out / fan-in).

func (*Processor) ErrorCount

func (p *Processor) ErrorCount() int64

ErrorCount returns the total number of processing errors.

func (*Processor) Process

func (p *Processor) Process(ctx context.Context, src Source, steps ...Step) (*ProcessingResult, error)

Process is the primary synchronous API. It reads from src, runs steps, and returns a ProcessingResult.

func (*Processor) ProcessVariants

func (p *Processor) ProcessVariants(ctx context.Context, src Source, baseSteps []Step, variants []VariantDefinition) (*ProcessingResult, error)

ProcessVariants runs each VariantDefinition against the decoded image in parallel and returns a ProcessingResult with a populated Variants map.

func (*Processor) ProcessedCount

func (p *Processor) ProcessedCount() int64

ProcessedCount returns the total number of successfully processed images.

func (*Processor) Registry

func (p *Processor) Registry() Registry

Registry returns the underlying registry so callers can register encoders/decoders after construction.

func (*Processor) SetLogger

func (p *Processor) SetLogger(l Logger)

SetLogger attaches a structured logger.

func (*Processor) SetMetrics

func (p *Processor) SetMetrics(m MetricsCollector)

SetMetrics attaches a metrics collector.

func (*Processor) Start

func (p *Processor) Start()

Start launches the worker pool. It is idempotent.

func (*Processor) Stop

func (p *Processor) Stop()

Stop drains the queue and shuts down all workers.

func (*Processor) Submit

func (p *Processor) Submit(job Job) error

Submit enqueues an async job. Returns ErrWorkerPoolFull if the queue is full.

type Registry

type Registry interface {
	DecoderFor(format Format) (Decoder, bool)
	EncoderFor(format Format) (Encoder, bool)
	RegisterDecoder(format Format, d Decoder)
	RegisterEncoder(format Format, e Encoder)
}

Registry maps Format values to Decoder/Encoder implementations.

type Source

type Source struct {
	Reader      io.Reader
	ContentType string // optional hint
	Name        string // optional logical name / filename
	Size        int64  // -1 if unknown
}

Source abstracts where raw bytes come from (reader, file path, URL, etc.).

type Step

type Step interface {
	Name() string
	Execute(ctx context.Context, img *ImageData) (*ImageData, error)
}

Step is the fundamental pipeline building block. Each Step transforms an *ImageData value and must be safe for concurrent use across goroutines.

type StorageAdapter

type StorageAdapter interface {
	Put(ctx context.Context, key StorageKey, r io.Reader, meta map[string]string) error
	Get(ctx context.Context, key StorageKey) (io.ReadCloser, error)
	Delete(ctx context.Context, key StorageKey) error
	Exists(ctx context.Context, key StorageKey) (bool, error)
}

StorageAdapter persists processed images and retrieves them later. Implementations live in adapters/storage/.

type StorageKey

type StorageKey struct {
	Bucket string
	Path   string
}

StorageKey uniquely identifies a stored image.

type VariantDefinition

type VariantDefinition struct {
	Name  string
	Steps []Step
}

VariantDefinition instructs the pipeline to produce a named output variant.

Jump to

Keyboard shortcuts

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