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 by priority. - Attribute
IModuleReadyHandlerhandlers run sequentially by priority. - Global
IModuleEventHandler.OnModuleStartAsynchandlers run sequentially by priority. - Attribute
IModuleStartHandlerhandlers run sequentially by priority. - 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 by priority. - Attribute
IModuleEndHandlerhandlers run sequentially by priority. - 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
Priorityorder within their registration family, even after a handler fails.ContinueOnErrorcontrols failure propagation:falserethrows one recorded failure or aggregates multiple failures after dispatch;truesuppresses that handler's failure.
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.