Skip to content

perf: Add cancellation support and short-circuit to ModuleConditionHandler#1720

Merged
thomhurst merged 1 commit into
mainfrom
fix/module-condition-handler-cancellation
Jan 1, 2026
Merged

perf: Add cancellation support and short-circuit to ModuleConditionHandler#1720
thomhurst merged 1 commit into
mainfrom
fix/module-condition-handler-cancellation

Conversation

@thomhurst
Copy link
Copy Markdown
Owner

Summary

Fixes #1571

  • Added CancellationToken parameter to IModuleConditionHandler.ShouldIgnore for proper cancellation support
  • Changed from parallel condition evaluation to sequential with short-circuit optimization:
    • Mandatory conditions short-circuit on first failure
    • Non-mandatory conditions short-circuit on first success
  • Removed dependency on EnumerableAsyncProcessor for simpler, more efficient code
  • Added ConfigureAwait(false) to async calls

Rationale

The previous implementation evaluated all conditions in parallel, which was wasteful when:

  1. A mandatory condition fails early - no need to check remaining conditions
  2. A non-mandatory condition succeeds - no need to check remaining conditions

Sequential evaluation with short-circuiting is both simpler and more efficient for this use case.

Test plan

  • Build succeeds
  • Existing tests pass
  • Verify cancellation behavior in module condition evaluation

🤖 Generated with Claude Code

…ndler

- Add CancellationToken parameter to ShouldIgnore method
- Change from parallel evaluation to sequential with short-circuit:
  - Mandatory conditions: stop on first failure
  - Non-mandatory conditions: stop on first success
- Remove unused EnumerableAsyncProcessor dependency
- Add cancellation checks between condition evaluations

This reduces wasted work when conditions fail early and allows proper
cancellation during condition evaluation.

Fixes #1571

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings January 1, 2026 16:58
@thomhurst
Copy link
Copy Markdown
Owner Author

Summary

This PR adds cancellation token support and switches from parallel to sequential short-circuit evaluation in ModuleConditionHandler for better performance and proper cancellation handling.

Critical Issues

None found ✅

Suggestions

1. Consider passing CancellationToken at call site (ModuleRetriever.cs:55)

While the new parameter has a default value, for proper cancellation propagation you might want to update the call site in ModuleRetriever.GetInternal() to pass a cancellation token:

var (shouldIgnore, skipDecision) = await _moduleConditionHandler.ShouldIgnore(module, cancellationToken).ConfigureAwait(false);

This would require adding a CancellationToken parameter to GetOrganizedModules() and GetInternal(). This could be a follow-up improvement if you want full cancellation support throughout the module organization phase.

2. Condition evaluation remains non-cancellable

The RunConditionAttribute.Condition() method does not accept a CancellationToken, so individual condition evaluations cannot be cancelled mid-execution. The PR adds cancellationToken.ThrowIfCancellationRequested() between evaluations which is good, but if a single condition takes a long time, it will not respect cancellation until it completes. This is a broader architectural consideration beyond this PR scope.

Previous Review Status

No previous comments found.

Verdict

APPROVE - No critical issues. The changes are well-reasoned: sequential evaluation with short-circuiting is both simpler and more efficient than parallel evaluation for this use case. The cancellation token support is a good addition, even if propagation could be improved in future work.

@thomhurst thomhurst merged commit e37c200 into main Jan 1, 2026
15 of 16 checks passed
@thomhurst thomhurst deleted the fix/module-condition-handler-cancellation branch January 1, 2026 17:05
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR enhances the ModuleConditionHandler with cancellation support and optimizes condition evaluation by replacing parallel processing with sequential short-circuit logic. The change simplifies the code by removing the dependency on EnumerableAsyncProcessor and improves efficiency by stopping evaluation as soon as the outcome is determined.

Key changes:

  • Added CancellationToken parameter to IModuleConditionHandler.ShouldIgnore method
  • Replaced parallel condition evaluation with sequential evaluation that short-circuits on first failure (mandatory) or first success (non-mandatory)
  • Added ConfigureAwait(false) to async calls and removed the RunnableConditionMet record class

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
src/ModularPipelines/Engine/IModuleConditionHandler.cs Added CancellationToken parameter to ShouldIgnore method signature with default value
src/ModularPipelines/Engine/ModuleConditionHandler.cs Implemented cancellation support, replaced parallel evaluation with sequential short-circuit logic, removed dependency on EnumerableAsyncProcessor, and cleaned up unused code

foreach (var attr in mandatoryRunConditionAttributes)
{
return (false, SkipDecision.Skip($"A condition to run this module has not been met - {mandatoryCondition.RunConditionAttribute.GetType().Name}"));
cancellationToken.ThrowIfCancellationRequested();
Copy link

Copilot AI Jan 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The cancellation token is being checked between evaluating conditions, but it's not being passed to the attr.Condition(pipelineContext) call on line 86. This means the actual condition evaluation cannot be cancelled, which limits the effectiveness of the cancellation support added in this PR. Consider updating the RunConditionAttribute.Condition method signature to accept a CancellationToken parameter.

Copilot uses AI. Check for mistakes.
foreach (var attr in runConditionAttributes)
{
return (true, null);
cancellationToken.ThrowIfCancellationRequested();
Copy link

Copilot AI Jan 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The cancellation token is being checked between evaluating conditions, but it's not being passed to the attr.Condition(pipelineContext) call on line 103. This means the actual condition evaluation cannot be cancelled, which limits the effectiveness of the cancellation support added in this PR. Consider updating the RunConditionAttribute.Condition method signature to accept a CancellationToken parameter.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Code smell: ModuleConditionHandler evaluates conditions in parallel without cancellation support

2 participants