Summary
Add a ValidatePipelines() method (similar to Brighter's PipelineValidator) that validates that all registered query types have resolvable handlers and decorators, catching configuration errors at startup rather than at first query execution.
Context
From V5 discussion #273.
Currently, a missing handler registration or unresolvable decorator type only surfaces as a MissingHandlerException or MissingHandlerDecoratorException at runtime when a query is first executed. In production, this means configuration errors may hide until a specific code path is hit.
When handler interfaces are split into sync and async (#304), misconfiguration becomes possible— for example, registering an async handler and then calling QueryProcessor.Execute() (sync). Currently, this would fail at runtime when the query is first executed. Validating pipelines at startup catches these errors early.
Proposal
Implement pipeline validation rules similar to Brighter's approach:
- Handler type visibility (public handlers only)
- Sync/async consistency (handler interface matches the execution path)
- Decorator attribute ordering validation
A rough outline
- Add
ValidatePipelines() to IQueryProcessor or as an extension method
- For each registered query type in the handler registry:
- Verify the handler type can be resolved by the factory
- Reflect on the handler's
Execute/ExecuteAsync for decorator attributes
- Verify each decorator type can be resolved by the decorator factory
- Return a validation result with all errors (don't throw on first failure)
- Integrate with ASP.NET Core health checks or startup validation
- Consider calling this automatically in
AddDarker() during development (via IHostEnvironment.IsDevelopment())
This should be callable from DI registration (e.g., services.AddDarker().ValidatePipelines()).
To Be Determined
We don't have an implementation of the Specification pattern in Darker, which Brighter uses to define its validation rules. Either we add that, or we use a simpler scheme for this validation because we decide it doesn't have the same complexity, yet. Notice that we made a similar decision during Fluent Validation to just support data annotations or fluent validation due to a belief in lower complexity and a desire to not increase the scope of V5 too far.
Related
Summary
Add a
ValidatePipelines()method (similar to Brighter'sPipelineValidator) that validates that all registered query types have resolvable handlers and decorators, catching configuration errors at startup rather than at first query execution.Context
From V5 discussion #273.
Currently, a missing handler registration or unresolvable decorator type only surfaces as a
MissingHandlerExceptionorMissingHandlerDecoratorExceptionat runtime when a query is first executed. In production, this means configuration errors may hide until a specific code path is hit.When handler interfaces are split into sync and async (#304), misconfiguration becomes possible— for example, registering an async handler and then calling
QueryProcessor.Execute()(sync). Currently, this would fail at runtime when the query is first executed. Validating pipelines at startup catches these errors early.Proposal
Implement pipeline validation rules similar to Brighter's approach:
A rough outline
ValidatePipelines()toIQueryProcessoror as an extension methodExecute/ExecuteAsyncfor decorator attributesAddDarker()during development (viaIHostEnvironment.IsDevelopment())This should be callable from DI registration (e.g.,
services.AddDarker().ValidatePipelines()).To Be Determined
We don't have an implementation of the Specification pattern in Darker, which Brighter uses to define its validation rules. Either we add that, or we use a simpler scheme for this validation because we decide it doesn't have the same complexity, yet. Notice that we made a similar decision during Fluent Validation to just support data annotations or fluent validation due to a belief in lower complexity and a desire to not increase the scope of V5 too far.
Related
PipelineValidatorandHandlerPipelineValidationRules