< Summary

Information
Class: NexusLabs.Needlr.AgentFramework.Workflows.Sequential.ContinueOnFailureExecutor
Assembly: NexusLabs.Needlr.AgentFramework.Workflows
File(s): /home/runner/work/needlr/needlr/src/NexusLabs.Needlr.AgentFramework.Workflows/Sequential/ContinueOnFailureExecutor.cs
Line coverage
100%
Covered lines: 13
Uncovered lines: 0
Coverable lines: 13
Total lines: 47
Line coverage: 100%
Branch coverage
100%
Covered branches: 2
Total branches: 2
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
ExecuteAsync()100%22100%

File(s)

/home/runner/work/needlr/needlr/src/NexusLabs.Needlr.AgentFramework.Workflows/Sequential/ContinueOnFailureExecutor.cs

#LineLine coverage
 1namespace NexusLabs.Needlr.AgentFramework.Workflows.Sequential;
 2
 3/// <summary>
 4/// Wraps an inner executor, catching exceptions and returning a failed result
 5/// instead of throwing. This enables "advisory" stage behavior where a failure
 6/// does not halt the pipeline.
 7/// </summary>
 8/// <param name="inner">The executor to wrap.</param>
 9/// <param name="onFailure">Optional callback invoked when the inner executor throws.</param>
 10/// <example>
 11/// <code>
 12/// var safeExecutor = new ContinueOnFailureExecutor(
 13///     innerExecutor,
 14///     ex => logger.LogWarning(ex, "Stage failed but continuing"));
 15///
 16/// var result = await safeExecutor.ExecuteAsync(context, cancellationToken);
 17/// // result.Succeeded == false if the inner executor threw, but no exception propagates.
 18/// </code>
 19/// </example>
 20[DoNotAutoRegister]
 1221public sealed class ContinueOnFailureExecutor(
 1222    IStageExecutor inner,
 1223    Action<Exception>? onFailure = null) : IStageExecutor
 24{
 25    /// <inheritdoc />
 26    public async Task<StageExecutionResult> ExecuteAsync(
 27        StageExecutionContext context,
 28        CancellationToken cancellationToken)
 29    {
 30        try
 31        {
 932            return await inner.ExecuteAsync(context, cancellationToken);
 33        }
 334        catch (OperationCanceledException) when (context.CallerCancellationToken.IsCancellationRequested)
 35        {
 136            throw;
 37        }
 538        catch (Exception ex)
 39        {
 540            onFailure?.Invoke(ex);
 541            return StageExecutionResult.Failed(
 542                context.StageName,
 543                ex,
 544                disposition: FailureDisposition.ContinueAdvisory);
 45        }
 846    }
 47}