Skip to content
Ovsep Avakian edited this page Jun 1, 2026 · 4 revisions

Mesh configuration

F-Mesh is configured at construction time via functional options on fmesh.New. See also Scheduling rules for how config affects execution.

Config struct

type Config struct {
    ErrorHandlingStrategy ErrorHandlingStrategy
    Debug                 bool
    Logger                *log.Logger
    CyclesLimit           int           // 0 = unlimited
    TimeLimit             time.Duration // 0 = unlimited
}

Defaults: StopOnFirstErrorOrPanic, 1000 cycles, 5 second time limit, debug off.

fm, err := fmesh.New("simple mesh")

Configuration options

fm, err := fmesh.New("simple mesh",
    fmesh.WithErrorHandlingStrategy(fmesh.IgnoreAll),
    fmesh.WithCyclesLimit(100),
    fmesh.WithTimeLimit(30 * time.Second),
    fmesh.WithUnlimitedCycles(),
    fmesh.WithUnlimitedTime(),
    fmesh.WithDebug(true),
    fmesh.WithLogger(myLogger),
    fmesh.WithLabelOption("env", "production"),
    fmesh.WithScalarOption("version", 2.0),
)

Or replace the entire config:

fm, err := fmesh.New("simple mesh", fmesh.WithConfig(fmesh.Config{
    ErrorHandlingStrategy: fmesh.IgnoreAll,
    CyclesLimit:           0,
    TimeLimit:             0,
    Debug:                 true,
    Logger:                myLogger,
}))
Option Description
WithConfig Replace entire Config
WithErrorHandlingStrategy StopOnFirstErrorOrPanic, StopOnFirstPanic, or IgnoreAll
WithCyclesLimit Max cycles (must be > 0)
WithUnlimitedCycles Remove cycle limit
WithTimeLimit Max duration (must be > 0)
WithUnlimitedTime Remove time limit
WithDebug Log per-component activation results each cycle
WithLogger Logger inherited by components without their own
WithLabelOption / WithScalarOption Set mesh metadata at construction

FMesh identity and metadata

Beyond config, FMesh exposes:

fm.Name()                          // mesh name (set at construction)
fm.SetDescription("ETL pipeline")  // optional human-readable description
fm.Description()

// Labels (mutating API — same as components/ports)
fm.AddLabel("env", "prod")
fm.SetLabels(map[string]string{"team": "data"})
fm.Labels().ValueOrDefault("env", "dev")

// Scalars
fm.AddScalar("priority", 1.0)
fm.Scalars().GetOrDefault("priority", 0)

Logging

When WithDebug(true) is set, the mesh logs activation results each cycle via LogDebug. Access the logger at runtime:

fm.Logger()
fm.IsDebug()

Components without an explicit logger inherit fm.Logger() when added via AddComponents.

Removing default limits

The default 5-second time limit and 1000-cycle limit can cause unexpected termination:

fm, err := fmesh.New("long-running",
    fmesh.WithUnlimitedCycles(),
    fmesh.WithUnlimitedTime(),
)

Signal immutability

Signals are copy-on-write. When a signal is fanned out to multiple ports, all destinations share the same pointer. Always use WithLabel, WithLabels, MapPayload, etc. to produce modified copies rather than mutating shared state.

Nil-safe lookups

Methods like ComponentByName, InputByName, and OutputByName return nil when the entity is not found. Always check for nil:

if port := c.InputByName("data"); port != nil {
    // use port
}

PutPayloads shortcut

Instead of wrapping payloads in signal.New, use PutPayloads:

_ = c.InputByName("i1").PutPayloads("hello", "world")

Predicate helpers for filtering

Use built-in signal predicates instead of inline closures when possible:

highPriority := port.Signals().Filter(signal.LabelEquals("priority", "high"))

Clone this wiki locally