Skip to content
github-actions[bot] edited this page Jul 23, 2026 · 3 revisions

This page documents how F-Mesh works under the hood. You do not need it to build meshes — see the user guide for that. Read this when debugging the scheduler, inspecting run-time reports, or extending the framework.


Activation cycles

F-Mesh execution is organized into activation cycles — discrete steps where the scheduler activates all ready components, then moves signals through pipes.

Phases of one cycle

  1. Schedule — find components with at least one signal on any input port.
  2. Activate — run all scheduled components concurrently (each in its own goroutine). Component hooks fire around the activation function.
  3. Drain — clear processed input ports; flush output ports into pipes so signals reach downstream inputs.

If a component is waiting for inputs, its inputs may be kept and its outputs are not flushed.

The mesh repeats cycles until a terminal state is reached.

Mesh-level hooks per cycle

BeforeRun → for each cycle: CycleBegin → activations → drain → CycleEndAfterRun. See Hooks.


RuntimeInfo

Run() returns (*RuntimeInfo, error). The report is populated even when Run() returns an error.

Field / method Description
Cycles *cycle.Group Ordered history of all activation cycles
StartedAt, StoppedAt Wall-clock timestamps
Duration() Total execution time
ri, err := fm.Run()
if err != nil {
    log.Printf("mesh stopped: %v (ran %d cycles in %v)", err, ri.Cycles.Len(), ri.Duration())
}

for _, cyc := range ri.Cycles.All() {
    fmt.Printf("Cycle #%d: %d activations, errors=%v\n",
        cyc.Number(),
        cyc.ActivationResults().Len(),
        cyc.HasActivationErrors(),
    )
}

cycle package

Models one execution step and its history.

cycle.Cycle

Method Description
Number() 1-based sequence number
ActivationResults() *component.ActivationResultCollection
HasActivationErrors() / HasActivationPanics() Status checks
HasActivatedComponents() At least one component activated
AllErrorsCombined() / AllPanicsCombined() Joined errors from all components
Labels(), WithLabel(), Scalars(), WithScalar() Cycle-level metadata

cycle.Group

Ordered cycle history (RuntimeInfo.Cycles). Same group API as signals and ports: All, First, Last, Find, Filter, Map, ForEach, etc.


ActivationResult and ActivationResultCollection

Each component activation produces an ActivationResult:

type ActivationResult struct {
    componentName    string
    activated        bool
    code             ActivationResultCode
    activationErrors []error
}

Key methods: ComponentName(), Activated(), Code(), ActivationError(), ActivationErrors(), IsError(), IsPanic().

Activation result codes

Code Meaning
ActivationCodeOK Success
ActivationCodeNoInput Not activated — no input signals
ActivationCodeReturnedError Activation function returned an error
ActivationCodePanicked Panic during activation
ActivationCodeWaitingForInputsClear Waiting; inputs will be cleared
ActivationCodeWaitingForInputsKeep Waiting; inputs kept for next cycle
ActivationCodeHookFailed A hook failed
ActivationCodeUndefined Zero value / undefined

ActivationResultCollection is a thread-safe map keyed by component name, stored on each cycle.Cycle. Methods: ByName, All, Filter, ForEach, HasActivationErrors, HasActivationPanics, HasActivatedComponents, Every, Any, Count, FindAny.

Helper functions: component.IsWaitingForInput(result), component.WantsToKeepInputs(result).


Validation

Pre-run checks (return error on failure):

Method When Checks
component.ValidateBeforeAddingToMesh() AddComponents Activation function is set
component.ValidateBeforeActivating() Before Run Parent mesh is assigned
port.ValidateBeforeActivation() Before Run Port has valid parent component

fmesh also validates the full mesh topology (pipe directions, parent relationships) in validateBeforeRun.


MaybeActivate

component.MaybeActivate() is called by the scheduler for each component each cycle. It can be used in tests to activate a single component outside a full mesh run. Returns *ActivationResult.


hook.Group

The internal/hook package provides hook.Group[T] — a generic ordered hook collection used by fmesh.Hooks, component.Hooks, and port.Hooks. It is internal machinery, not importable by user code — hooks are registered through the closure-based API shown in Hooks:

g := hook.NewGroup[*MyContext]()
g.Add(func(ctx *MyContext) error { ... })
err := g.Trigger(myContext) // fail-fast

Methods: Add, Trigger, All, ForEach, Clear, Len, IsEmpty.


Run-time errors

Run() may return (use errors.Is):

Error When
ErrReachedMaxAllowedCycles CyclesLimit exceeded
ErrTimeLimitExceeded TimeLimit exceeded
ErrHitAnErrorOrPanic Error/panic with StopOnFirstErrorOrPanic
ErrHitAPanic Panic with StopOnFirstPanic
ErrFailedToDrain Signal draining failed
ErrUnsupportedErrorHandlingStrategy Invalid strategy

Natural completion returns nil.


ParentMesh

Each component holds a reference to its parent mesh (ParentMesh interface — Name() string), set by AddComponents. The scheduler uses this to validate topology before run.

Clone this wiki locally