-
-
Notifications
You must be signed in to change notification settings - Fork 1
999. Internals
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.
F-Mesh execution is organized into activation cycles — discrete steps where the scheduler activates all ready components, then moves signals through pipes.
- Schedule — find components with at least one signal on any input port.
- Activate — run all scheduled components concurrently (each in its own goroutine). Component hooks fire around the activation function.
- 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.
BeforeRun → for each cycle: CycleBegin → activations → drain → CycleEnd → AfterRun. See Hooks.
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(),
)
}Models one execution step and its history.
| 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 |
Ordered cycle history (RuntimeInfo.Cycles). Same group API as signals and ports: All, First, Last, Find, Filter, Map, ForEach, etc.
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().
| 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).
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.
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.
The hook package provides hook.Group[T] — a generic ordered hook collection used by fmesh.Hooks, component.Hooks, and port.Hooks:
g := hook.NewGroup[*MyContext]()
g.Add(func(ctx *MyContext) error { ... })
err := g.Trigger(myContext) // fail-fastMethods: Add, Trigger, All, ForEach, Clear, Len, IsEmpty.
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.
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.