Module execution lifecycle
A module combines execution policy, module-owned virtual hooks, opt-in attribute handlers, and global event handlers.
Execution phases
For a module that runs successfully, the phases are:
- Dependencies become ready.
- Global
IModuleEventHandler.OnModuleReadyAsynchandlers run sequentially in ascendingOrder. - Attribute
IModuleReadyHandlerhandlers run sequentially in ascendingOrder. - Global
IModuleEventHandler.OnModuleStartAsynchandlers run sequentially in ascendingOrder. - Attribute
IModuleStartHandlerhandlers run sequentially in ascendingOrder. - The module skip condition is evaluated.
Module<T>.OnBeforeExecuteAsyncruns once.Module<T>.ExecuteAsyncruns through timeout handling and the configured resilience shield, which may compose retries with other resilience strategies.Module<T>.OnAfterExecuteAsyncruns once.- Global
IModuleEventHandler.OnModuleEndAsynchandlers run sequentially in ascendingOrder. - Attribute
IModuleEndHandlerhandlers run sequentially in ascendingOrder. - The module result is published and dependants become eligible.
OnBeforeExecuteAsync and OnAfterExecuteAsync wrap the complete resilience shield, not each
individual attempt.
Skipped modules
The skip condition is evaluated before the module-owned before hook. If it returns a skip decision:
Module<T>.OnSkippedAsync- Attribute
IModuleSkippedHandler - Global
IModuleEventHandler.OnModuleSkippedAsync
OnBeforeExecuteAsync, ExecuteAsync, and OnAfterExecuteAsync do not run.
Failed modules
When module execution throws:
Module<T>.OnFailedAsyncModule<T>.OnAfterExecuteAsync, with a failedModuleResult<T>- Attribute
IModuleFailureHandler - Global
IModuleEventHandler.OnModuleFailureAsync
Retry attempts complete before this failure sequence. If the configured failure condition ignores the failure, the resulting module status reflects that policy.
Hook failures
- An exception from
OnBeforeExecuteAsyncprevents module execution.OnFailedAsyncand the failure event handlers are notified, butOnAfterExecuteAsyncdoes not run. - Exceptions from
OnFailedAsync,OnSkippedAsync, andOnAfterExecuteAsyncare logged and do not replace the module outcome. - Attribute and global handlers all run in ascending
Orderwithin their registration family, even after a handler fails.ContinueOnErrorcontrols failure propagation:falserecords the failure (one exception, or an aggregate when several handlers fail);trueonly logs a warning. - Ready and Start handler failures fail the module through the normal failure path: the module
does not execute, the failure handlers are notified, and the module status is
Failed. Global and attribute handlers behave the same way. - End, Failure, and Skipped handlers observe the outcome and never change it. Each family runs in isolation, so a failing attribute family does not stop the global family (or the reverse). The failure is logged and recorded as a secondary pipeline error, surfaced with the pipeline's other errors.
- A failing
OnPipelineEndAsynchandler fails the pipeline, but never replaces an exception thrown by execution; in that case it is recorded as a secondary pipeline error. - Estimated-time reads and writes are best-effort: provider exceptions are logged and never change the module outcome.
Choosing an extension point
Use module virtual hooks when behavior is part of one module. Use attribute handlers when
behavior should be explicitly attached to selected module types. Use IModuleEventHandler
when one service must observe every module in the pipeline.
See Hooks for implementation examples.