Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
112 commits
Select commit Hold shift + click to select a range
07f20fc
Introduced the `PipelineResult<T>` class.
kolan72 Dec 25, 2025
15f6574
Introduced the internal `Func<T, U>.ToHandledByPolicy` extension meth…
kolan72 Dec 26, 2025
8b084e5
DRY refactor `SimplePolicyProcessor.Execute<TParam>` catch block.
kolan72 Dec 27, 2025
b26c464
Inline internal `IPolicyProcessor.AddExcludedError` and `AddIncludedE…
kolan72 Dec 28, 2025
b953e65
Further DRY refactor the `SimplePolicyProcessor.Execute<TParam>` catc…
kolan72 Dec 29, 2025
8e9632b
Defer allocation of the catch-block handler class until an exception …
kolan72 Dec 30, 2025
a4ae49f
Refactored internal `PolicyProcessorCatchBlockSyncHandler<T>` to use …
kolan72 Jan 1, 2026
a6f2331
Deprecate the `PolicyProcessorCatchBlockHandlerBase<T>.PreHandle` met…
kolan72 Jan 1, 2026
5b9a5bb
Materialize `BulkProcessResult.ProcessErrors` once and replace LINQ `…
kolan72 Jan 1, 2026
4cc779c
Add the `BulkProcessResult.HasProcessErrors` property and tests for t…
kolan72 Jan 2, 2026
d1bdc1d
Guard the call to `BulkProcessResult.ToCatchBlockExceptions` with `Bu…
kolan72 Jan 3, 2026
4fff8bb
Inline the protected `PolicyProcessorCatchBlockHandlerBase.PostHandle…
kolan72 Jan 3, 2026
55ec19f
Deprecate the `PolicyProcessorCatchBlockHandlerBase.PostHandle` method.
kolan72 Jan 3, 2026
1a0e5ae
Make the `ErrorContext<T>` class public (previously internal).
kolan72 Jan 4, 2026
14d12bf
Follow up: further DRY refactor `SimplePolicyProcessor.Execute<TParam…
kolan72 Jan 5, 2026
f70b1f4
Added the protected internal `PolicyProcessor.HandleException<T>` met…
kolan72 Jan 6, 2026
280f501
Refactor the `PolicyProcessor.HandleException<T>` method
kolan72 Jan 7, 2026
96891d6
Add the internal static `PolicyProcessor.DefaultErrorSaver` property.
kolan72 Jan 8, 2026
86c5884
Add internal `ErrorProcessingCancellationEffect` enum.
kolan72 Jan 9, 2026
484dcee
Make `ErrorProcessingCancellationEffect` public and use it in `Policy…
kolan72 Jan 10, 2026
3121fee
Added the internal static `PolicyProcessor.CreateDefaultPolicyRule<T>…
kolan72 Jan 11, 2026
1e06090
DRY refactor catch-block handling in `SimplePolicyProcessor.Execute<T…
kolan72 Jan 11, 2026
32f6938
Fix `PolicyProcessor.HandleException<T>` method.
kolan72 Jan 12, 2026
ea5723f
DRY refactor catch block into a private method used by `SimplePolicyP…
kolan72 Jan 13, 2026
0e2514b
DRY refactor catch block into a private method used by `SimplePolicyP…
kolan72 Jan 14, 2026
52127cb
Added the internal static `PolicyProcessor.CreateDefaultAsyncErrorSav…
kolan72 Jan 15, 2026
1c237ae
Add the internal static `PolicyProcessor.DefaultAsyncErrorSaver` prop…
kolan72 Jan 16, 2026
e471cbd
Refactor `PolicyProcessor.HandleException<T>`.
kolan72 Jan 17, 2026
55d08d9
Follow up on refactor `PolicyProcessor.HandleException<T>`.
kolan72 Jan 18, 2026
dcdc959
Added the protected internal `PolicyProcessor.HandleExceptionAsync<T>…
kolan72 Jan 18, 2026
bf02cf6
DRY refactor catch block into a private method used by `SimplePolicyP…
kolan72 Jan 19, 2026
5a2aa43
Refactor `PolicyProcessor.HandleException<T>`.
kolan72 Jan 20, 2026
527ad70
New tests for `PolicyProcessor.HandleException`.
kolan72 Jan 21, 2026
025ce8f
Refactor `PolicyProcessor.HandleExceptionAsync<T>`.
kolan72 Jan 22, 2026
2d38577
Correct usage of `SimplePolicyProcessor.HandleExceptionAsync` with th…
kolan72 Jan 23, 2026
3902e66
DRY refactor catch block into a private method used by `SimplePolicyP…
kolan72 Jan 24, 2026
b164d16
DRY refactor catch-block handling in `SimplePolicyProcessor.ExecuteAs…
kolan72 Jan 25, 2026
f4e47db
DRY refactor catch-block handling in `SimplePolicyProcessor.Execute<T…
kolan72 Jan 26, 2026
6568e5d
Introduce the `ICanAddErrorFilter<T>.AddExceptionFilter` extension me…
kolan72 Jan 27, 2026
0dc3e30
Introduce the `ExceptionFilter.IncludeErrorSet` extension method.
kolan72 Jan 28, 2026
9617ce6
Deprecate internal `FallbackFuncExecResult.FromErrorAndToken` overloads.
kolan72 Jan 29, 2026
4d33d59
Introduce `ProcessingOrder` enum.
kolan72 Jan 29, 2026
c3b5ee2
DRY refactor catch-block handling in `SimplePolicyProcessor.ExecuteAs…
kolan72 Jan 30, 2026
61ac2dd
Implement `ProcessingOrder.ProcessThenEvaluate` path in `PolicyProce…
kolan72 Jan 31, 2026
c19ab01
Add `CancellationToken` parameter to policy rule `Func` when handling…
kolan72 Feb 1, 2026
bdb6652
Refactor private `EvaluatePolicyRule<T>` method called from `PolicyPr…
kolan72 Feb 2, 2026
c289ffc
Simplify cancellation-related `AggregateException` filtering in synch…
kolan72 Feb 3, 2026
d416f8e
Add private `EvaluatePolicyRuleAsync` method called from `PolicyProce…
kolan72 Feb 3, 2026
b0b0108
Introduce `ServiceOperationCanceledException` for cancellation observ…
kolan72 Feb 4, 2026
c51731c
Use `ServiceOperationCanceledException` as the fallback exception in …
kolan72 Feb 5, 2026
413e7d3
Store `ServiceOperationCanceledException` in `PolicyResult.PolicyCanc…
kolan72 Feb 6, 2026
7c03f18
Introduce the `ExceptionFilter.ExcludeErrorSet` method.
kolan72 Feb 7, 2026
1ad22e2
Refactor private `EvaluatePolicyRuleAsync` and `EvaluatePolicyRule` m…
kolan72 Feb 8, 2026
4cb304c
Add `MethodImpl(MethodImplOptions.AggressiveInlining)` to `PolicyResu…
kolan72 Feb 9, 2026
3350bb7
Add tests for `SimplePolicyProcessor.Execute` to verify cancellation …
kolan72 Feb 10, 2026
3d07ac4
Add tests for `SimplePolicyProcessor.Execute` with context to verify …
kolan72 Feb 11, 2026
39930f4
Store `ServiceOperationCanceledException` in `PolicyResult.PolicyCanc…
kolan72 Feb 12, 2026
fd338e3
Store `ServiceOperationCanceledException` in `PolicyResult.PolicyCanc…
kolan72 Feb 13, 2026
39ddcfc
Implement `ProcessingOrder.ProcessThenEvaluate` path in `PolicyProces…
kolan72 Feb 14, 2026
ae7c134
Introduce `ExceptionFilter.IncludeError<TException>` method overloads.
kolan72 Feb 15, 2026
4ace2e7
Introduce `ExceptionFilter.ExcludeError<TException>` method overloads.
kolan72 Feb 16, 2026
c932a7b
Refactor `ErrorProcessorRegistration` methods to use expression-bodie…
kolan72 Feb 17, 2026
d7e4a51
Refactor `ICanAddErrorProcessor` methods to use expression-bodied syn…
kolan72 Feb 17, 2026
9b39b6d
Refactor `PolicyWrapper` and `PolicyWrapper<T>` `PolicyDelegateResult…
kolan72 Feb 17, 2026
c7ecf4b
Remove duplicated implementations in FuncEntensions
kolan72 Feb 17, 2026
5a193d9
Store `ServiceOperationCanceledException` in `PolicyResult.PolicyCanc…
kolan72 Feb 18, 2026
effa836
DRY refactor catch block into a private method used by `DefaultFallba…
kolan72 Feb 19, 2026
6ff7660
Store `ServiceOperationCanceledException` in `PolicyResult.PolicyCanc…
kolan72 Feb 20, 2026
39f09f8
Introduce `ExceptionFilter.IncludeError` and `ExcludeError` methods a…
kolan72 Feb 21, 2026
4563acd
DRY refactor catch-block handling in `DefaultFallbackProcessor.Fallba…
kolan72 Feb 22, 2026
5e5b4ee
Add `MethodImpl(MethodImplOptions.AggressiveInlining)` to `PolicyResu…
kolan72 Feb 23, 2026
b61de43
DRY refactor internal `DefaultErrorProcessorT` class.
kolan72 Feb 24, 2026
663402f
Add `ConvertExceptionDelegates.ToSubException` static method to inter…
kolan72 Feb 24, 2026
6090fe3
Introduce `DefaultTypedErrorProcessor<TException>` for typed exceptio…
kolan72 Feb 25, 2026
60aba65
Store `ServiceOperationCanceledException` in `PolicyResult.PolicyCanc…
kolan72 Feb 26, 2026
021d262
DRY refactor catch block into a private method used by `DefaultFallba…
kolan72 Feb 27, 2026
9fb375f
Introduce abstract `TypedErrorProcessor<TException>` with an overrida…
kolan72 Feb 28, 2026
7d6ebf9
Store `ServiceOperationCanceledException` in `PolicyResult.PolicyCanc…
kolan72 Mar 1, 2026
06d9847
DRY refactor catch block into a private method used by `DefaultFallba…
kolan72 Mar 2, 2026
c0d096c
Add implicit conversion from `ConstantRetryDelayOptions` to `Constant…
kolan72 Mar 3, 2026
e12e80b
Add implicit conversion from `LinearRetryDelayOptions` to `LinearRetr…
kolan72 Mar 4, 2026
98c5859
Add implicit conversion from `ExponentialRetryDelayOptions` to `Expon…
kolan72 Mar 5, 2026
c559d78
Store `ServiceOperationCanceledException` in `PolicyResult.PolicyCanc…
kolan72 Mar 6, 2026
9a038e2
DRY refactor catch-block handling in `DefaultFallbackProcessor.Fallba…
kolan72 Mar 7, 2026
e7ec42e
DRY refactor catch-block handling in `DefaultFallbackProcessor.Fallba…
kolan72 Mar 8, 2026
e7cbe8a
Add `FromErrors<TException1, TException2>` and `FromErrors<TException…
kolan72 Mar 9, 2026
84d631e
DRY refactor catch block handling in `DefaultFallbackProcessor` `Fall…
kolan72 Mar 10, 2026
bdfb881
Add `HasError<TException>` and `HasInnerError<TInnerException>` metho…
kolan72 Mar 10, 2026
47f1b33
Add implicit conversion from `TimeSeriesRetryDelayOptions` to `TimeSe…
kolan72 Mar 11, 2026
43fff4a
DRY refactor catch-block handling in `DefaultFallbackProcessor.Fallba…
kolan72 Mar 12, 2026
86373a6
DRY refactor catch block into a private method used by `DefaultFallba…
kolan72 Mar 13, 2026
5cd00d5
Add `MethodImpl(MethodImplOptions.AggressiveInlining)` to `PolicyResu…
kolan72 Mar 14, 2026
bc7b65a
Remove unused private `SimplePolicyProcessor.GetFilterUnsatisfiedOrFi…
kolan72 Mar 15, 2026
ebee27f
DRY refactor catch block handling in `DefaultFallbackProcessor` `Fall…
kolan72 Mar 16, 2026
b3e401e
Merge branch 'dev' of https://github.com/kolan72/PoliNorError into dev
kolan72 Mar 16, 2026
4dba312
DRY refactor catch block into a private method used by `DefaultFallba…
kolan72 Mar 17, 2026
6cf823e
Edit PoliNorError.Tests.csproj.
kolan72 Mar 18, 2026
05a0a0c
Bump System.ValueTuple from 4.6.1 to 4.6.2
dependabot[bot] Mar 18, 2026
0f01b11
Merge pull request #183 from kolan72/dependabot/nuget/tests/dev/Syste…
kolan72 Mar 19, 2026
c579b57
DRY refactor catch block into a private method used by `DefaultFallba…
kolan72 Mar 20, 2026
7f16de9
Update NUnit to 4.5.1.
kolan72 Mar 22, 2026
cb9217b
Eliminate per-call `MaxDelayDelimiter` allocations in `ConstantRetryD…
kolan72 Mar 23, 2026
b7251f8
Add internal `StandardJitter` class.
kolan72 Mar 24, 2026
2db0e05
Add `ConstantDelayCore` and simplify `ConstantRetryDelay` constructor…
kolan72 Mar 24, 2026
0c7f5b1
Add `LinearDelayCore` and simplify `LinearRetryDelay` constructor ini…
kolan72 Mar 25, 2026
4c1ed84
Extract `DelayCoreBase` abstract base class and use it in `ConstantRe…
kolan72 Mar 26, 2026
95e2975
Make `LinearDelayCore` inherit from `DelayCoreBase` and simplify `Lin…
kolan72 Mar 27, 2026
40654dd
Add `ExponentialDelayCore` and simplify `ExponentialRetryDelay` const…
kolan72 Mar 28, 2026
f40d9ad
Defer pipeline functions to future release in separate branch.
kolan72 Mar 29, 2026
1a6c325
Add `TimeSeriesDelayCore`, simplify `TimeSeriesRetryDelay` constructo…
kolan72 Mar 30, 2026
805719a
Add `propagateCancellation` parameter (default: `true`) to internal `…
kolan72 Mar 31, 2026
e501a3c
Merge pull request #186 from kolan72/main
kolan72 Mar 31, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/CatchBlockHandlers/CatchBlockFilter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ public class CatchBlockFilter
{
public static CatchBlockFilter Empty() => new CatchBlockFilter();

internal PolicyProcessor.ExceptionFilter ErrorFilter { get; } = new PolicyProcessor.ExceptionFilter();
internal PolicyProcessor.ExceptionFilter ErrorFilter { get; set; } = new PolicyProcessor.ExceptionFilter();

public CatchBlockFilter ExcludeError<TException>(ErrorType errorType = ErrorType.Error) where TException : Exception
{
Expand Down
2 changes: 1 addition & 1 deletion src/CatchBlockHandlers/ErrorContext.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
namespace PoliNorError
{
internal abstract class ErrorContext<T>
public abstract class ErrorContext<T>
{
protected ErrorContext(T t)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,14 @@ public PolicyProcessorCatchBlockAsyncHandler(PolicyResult policyResult, IBulkErr

public async Task<HandleCatchBlockResult> HandleAsync(Exception ex, ErrorContext<T> errorContext = null)
{
var (Result, CanProcess) = PreHandle(ex, errorContext);
if (!CanProcess)
return Result;
var shouldHandleResult = ShouldHandleException(ex, errorContext);
if(shouldHandleResult != HandleCatchBlockResult.Success)
return shouldHandleResult;

var bulkProcessResult = await _bulkErrorProcessor.ProcessAsync(ex, errorContext.ToProcessingErrorContext(), _configAwait, _cancellationToken).ConfigureAwait(_configAwait);

return PostHandle(bulkProcessResult, Result);
_policyResult.AddBulkProcessorErrors(bulkProcessResult);
return bulkProcessResult.IsCanceled ? HandleCatchBlockResult.Canceled : shouldHandleResult;
}
}
}
15 changes: 15 additions & 0 deletions src/CatchBlockHandlers/PolicyProcessorCatchBlockHandlerBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,18 @@ protected PolicyProcessorCatchBlockHandlerBase(PolicyResult policyResult, IBulkE
_policyRuleFunc = policyRuleFunc ?? ((_) => true);
}

protected HandleCatchBlockResult ShouldHandleException(Exception ex, ErrorContext<T> errorContext)
{
if (_cancellationToken.IsCancellationRequested)
{
return HandleCatchBlockResult.Canceled;
}
return CanHandle(ex, errorContext);
}

#pragma warning disable S1133 // Deprecated code should be removed
[Obsolete("This method is obsolete")]
#pragma warning restore S1133 // Deprecated code should be removed
protected (HandleCatchBlockResult Result, bool CanProcess) PreHandle(Exception ex, ErrorContext<T> errorContext)
{
if (_cancellationToken.IsCancellationRequested)
Expand All @@ -45,6 +57,9 @@ private HandleCatchBlockResult CanHandle(Exception ex, ErrorContext<T> errorCont
return HandleCatchBlockResult.Success;
}

#pragma warning disable S1133 // Deprecated code should be removed
[Obsolete("This method is obsolete")]
#pragma warning restore S1133 // Deprecated code should be removed
protected HandleCatchBlockResult PostHandle(BulkProcessResult bulkProcessResult, HandleCatchBlockResult resultIfNotCanceled)
{
_policyResult.AddBulkProcessorErrors(bulkProcessResult);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,14 @@ public PolicyProcessorCatchBlockSyncHandler(PolicyResult policyResult, IBulkErro

public HandleCatchBlockResult Handle(Exception ex, ErrorContext<T> errorContext = null)
{
var (Result, CanProcess) = PreHandle(ex, errorContext);
if (!CanProcess)
return Result;
var shouldHandleResult = ShouldHandleException(ex, errorContext);
if (shouldHandleResult != HandleCatchBlockResult.Success)
return shouldHandleResult;

var bulkProcessResult = _bulkErrorProcessor.Process(ex, errorContext.ToProcessingErrorContext(), _cancellationToken);

return PostHandle(bulkProcessResult, Result);
_policyResult.AddBulkProcessorErrors(bulkProcessResult);
return bulkProcessResult.IsCanceled ? HandleCatchBlockResult.Canceled : shouldHandleResult;
}
}
}
12 changes: 12 additions & 0 deletions src/ConvertExceptionDelegates.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,17 @@ public static bool ToInnerException<TException>(Exception exception, out TExcept
return false;
}
}

public static bool ToSubException<TException>(Exception exception, out TException typedException) where TException : Exception
{
if (exception is TException found)
{
typedException = found;
return true;
}

typedException = null;
return false;
}
}
}
62 changes: 24 additions & 38 deletions src/ErrorProcessorRegistration.ForErrorContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,41 +4,27 @@

namespace PoliNorError
{
public static partial class ErrorProcessorRegistration
{
internal static T WithErrorContextProcessorOf<T, TErrorContext>(this T policyProcessor, Action<Exception, ProcessingErrorInfo<TErrorContext>> actionProcessor) where T : IPolicyProcessor
{
return policyProcessor.WithErrorContextProcessorOf(actionProcessor, _addErrorProcessorAction);
}

internal static T WithErrorContextProcessorOf<T, TErrorContext>(this T policyProcessor, Action<Exception, ProcessingErrorInfo<TErrorContext>> actionProcessor, CancellationType cancellationType) where T : IPolicyProcessor
{
return policyProcessor.WithErrorContextProcessorOf(actionProcessor, cancellationType, _addErrorProcessorAction);
}

internal static T WithErrorContextProcessorOf<T, TErrorContext>(this T policyProcessor, Action<Exception, ProcessingErrorInfo<TErrorContext>, CancellationToken> actionProcessor) where T : IPolicyProcessor
{
return policyProcessor.WithErrorContextProcessorOf(actionProcessor, _addErrorProcessorAction);
}

internal static T WithErrorContextProcessorOf<T, TErrorContext>(this T policyProcessor, Func<Exception, ProcessingErrorInfo<TErrorContext>, Task> funcProcessor) where T : IPolicyProcessor
{
return policyProcessor.WithErrorContextProcessorOf(funcProcessor, _addErrorProcessorAction);
}

internal static T WithErrorContextProcessorOf<T, TErrorContext>(this T policyProcessor, Func<Exception, ProcessingErrorInfo<TErrorContext>, Task> funcProcessor, CancellationType cancellationType) where T : IPolicyProcessor
{
return policyProcessor.WithErrorContextProcessorOf(funcProcessor, cancellationType, _addErrorProcessorAction);
}

internal static T WithErrorContextProcessorOf<T, TErrorContext>(this T policyProcessor, Func<Exception, ProcessingErrorInfo<TErrorContext>, CancellationToken, Task> funcProcessor) where T : IPolicyProcessor
{
return policyProcessor.WithErrorContextProcessorOf(funcProcessor, _addErrorProcessorAction);
}

internal static T WithErrorContextProcessor<T, TErrorContext>(this T policyProcessor, DefaultErrorProcessor<TErrorContext> errorProcessor) where T : IPolicyProcessor
{
return policyProcessor.WithErrorProcessor(errorProcessor, _addErrorProcessorAction);
}
}
}
public static partial class ErrorProcessorRegistration
{
internal static T WithErrorContextProcessorOf<T, TErrorContext>(this T policyProcessor, Action<Exception, ProcessingErrorInfo<TErrorContext>> actionProcessor) where T : IPolicyProcessor
=> policyProcessor.WithErrorContextProcessorOf(actionProcessor, _addErrorProcessorAction);

internal static T WithErrorContextProcessorOf<T, TErrorContext>(this T policyProcessor, Action<Exception, ProcessingErrorInfo<TErrorContext>> actionProcessor, CancellationType cancellationType) where T : IPolicyProcessor
=> policyProcessor.WithErrorContextProcessorOf(actionProcessor, cancellationType, _addErrorProcessorAction);

internal static T WithErrorContextProcessorOf<T, TErrorContext>(this T policyProcessor, Action<Exception, ProcessingErrorInfo<TErrorContext>, CancellationToken> actionProcessor) where T : IPolicyProcessor
=> policyProcessor.WithErrorContextProcessorOf(actionProcessor, _addErrorProcessorAction);

internal static T WithErrorContextProcessorOf<T, TErrorContext>(this T policyProcessor, Func<Exception, ProcessingErrorInfo<TErrorContext>, Task> funcProcessor) where T : IPolicyProcessor
=> policyProcessor.WithErrorContextProcessorOf(funcProcessor, _addErrorProcessorAction);

internal static T WithErrorContextProcessorOf<T, TErrorContext>(this T policyProcessor, Func<Exception, ProcessingErrorInfo<TErrorContext>, Task> funcProcessor, CancellationType cancellationType) where T : IPolicyProcessor
=> policyProcessor.WithErrorContextProcessorOf(funcProcessor, cancellationType, _addErrorProcessorAction);

internal static T WithErrorContextProcessorOf<T, TErrorContext>(this T policyProcessor, Func<Exception, ProcessingErrorInfo<TErrorContext>, CancellationToken, Task> funcProcessor) where T : IPolicyProcessor
=> policyProcessor.WithErrorContextProcessorOf(funcProcessor, _addErrorProcessorAction);

internal static T WithErrorContextProcessor<T, TErrorContext>(this T policyProcessor, DefaultErrorProcessor<TErrorContext> errorProcessor) where T : IPolicyProcessor
=> policyProcessor.WithErrorProcessor(errorProcessor, _addErrorProcessorAction);
}
}
48 changes: 12 additions & 36 deletions src/ErrorProcessorRegistration.ForInnerError.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,63 +7,39 @@ namespace PoliNorError
public static partial class ErrorProcessorRegistration
{
internal static T WithInnerErrorProcessorOf<T, TException>(this T policyProcessor, Action<TException> actionProcessor) where T : IPolicyProcessor where TException : Exception
{
return policyProcessor.WithInnerErrorProcessorOf(actionProcessor, _addErrorProcessorAction);
}
=> policyProcessor.WithInnerErrorProcessorOf(actionProcessor, _addErrorProcessorAction);

internal static T WithInnerErrorProcessorOf<T, TException>(this T policyProcessor, Action<TException, CancellationToken> actionProcessor) where T : IPolicyProcessor where TException : Exception
{
return policyProcessor.WithInnerErrorProcessorOf(actionProcessor, _addErrorProcessorAction);
}
=> policyProcessor.WithInnerErrorProcessorOf(actionProcessor, _addErrorProcessorAction);

internal static T WithInnerErrorProcessorOf<T, TException>(this T policyProcessor, Action<TException> actionProcessor, CancellationType cancellationType) where T : IPolicyProcessor where TException : Exception
{
return policyProcessor.WithInnerErrorProcessorOf(actionProcessor, cancellationType, _addErrorProcessorAction);
}
=> policyProcessor.WithInnerErrorProcessorOf(actionProcessor, cancellationType, _addErrorProcessorAction);

internal static T WithInnerErrorProcessorOf<T, TException>(this T policyProcessor, Func<TException, Task> funcProcessor) where T : IPolicyProcessor where TException : Exception
{
return policyProcessor.WithInnerErrorProcessorOf(funcProcessor, _addErrorProcessorAction);
}
=> policyProcessor.WithInnerErrorProcessorOf(funcProcessor, _addErrorProcessorAction);

internal static T WithInnerErrorProcessorOf<T, TException>(this T policyProcessor, Func<TException, Task> funcProcessor, CancellationType cancellationType) where T : IPolicyProcessor where TException : Exception
{
return policyProcessor.WithInnerErrorProcessorOf(funcProcessor, cancellationType, _addErrorProcessorAction);
}
=> policyProcessor.WithInnerErrorProcessorOf(funcProcessor, cancellationType, _addErrorProcessorAction);

internal static T WithInnerErrorProcessorOf<T, TException>(this T policyProcessor, Func<TException, CancellationToken, Task> funcProcessor) where T : IPolicyProcessor where TException : Exception
{
return policyProcessor.WithInnerErrorProcessorOf(funcProcessor, _addErrorProcessorAction);
}
=> policyProcessor.WithInnerErrorProcessorOf(funcProcessor, _addErrorProcessorAction);

internal static T WithInnerErrorProcessorOf<T, TException>(this T policyProcessor, Action<TException, ProcessingErrorInfo> actionProcessor) where T : IPolicyProcessor where TException : Exception
{
return policyProcessor.WithInnerErrorProcessorOf(actionProcessor, _addErrorProcessorAction);
}
=> policyProcessor.WithInnerErrorProcessorOf(actionProcessor, _addErrorProcessorAction);

internal static T WithInnerErrorProcessorOf<T, TException>(this T policyProcessor, Action<TException, ProcessingErrorInfo, CancellationToken> actionProcessor) where T : IPolicyProcessor where TException : Exception
{
return policyProcessor.WithInnerErrorProcessorOf(actionProcessor, _addErrorProcessorAction);
}
=> policyProcessor.WithInnerErrorProcessorOf(actionProcessor, _addErrorProcessorAction);

internal static T WithInnerErrorProcessorOf<T, TException>(this T policyProcessor, Action<TException, ProcessingErrorInfo> actionProcessor, CancellationType cancellationType) where T : IPolicyProcessor where TException : Exception
{
return policyProcessor.WithInnerErrorProcessorOf(actionProcessor, cancellationType, _addErrorProcessorAction);
}
=> policyProcessor.WithInnerErrorProcessorOf(actionProcessor, cancellationType, _addErrorProcessorAction);

internal static T WithInnerErrorProcessorOf<T, TException>(this T policyProcessor, Func<TException, ProcessingErrorInfo, Task> funcProcessor) where T : IPolicyProcessor where TException : Exception
{
return policyProcessor.WithInnerErrorProcessorOf(funcProcessor, _addErrorProcessorAction);
}
=> policyProcessor.WithInnerErrorProcessorOf(funcProcessor, _addErrorProcessorAction);

internal static T WithInnerErrorProcessorOf<T, TException>(this T policyProcessor, Func<TException, ProcessingErrorInfo, Task> funcProcessor, CancellationType cancellationType) where T : IPolicyProcessor where TException : Exception
{
return policyProcessor.WithInnerErrorProcessorOf(funcProcessor, cancellationType, _addErrorProcessorAction);
}
=> policyProcessor.WithInnerErrorProcessorOf(funcProcessor, cancellationType, _addErrorProcessorAction);

internal static T WithInnerErrorProcessorOf<T, TException>(this T policyProcessor, Func<TException, ProcessingErrorInfo, CancellationToken, Task> funcProcessor) where T : IPolicyProcessor where TException : Exception
{
return policyProcessor.WithInnerErrorProcessorOf(funcProcessor, _addErrorProcessorAction);
}
=> policyProcessor.WithInnerErrorProcessorOf(funcProcessor, _addErrorProcessorAction);
}
}
23 changes: 17 additions & 6 deletions src/ErrorProcessors/BulkErrorProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,8 @@ public class BulkProcessResult
{
private readonly bool _isCanceledBetweenProcessOne;

private readonly IReadOnlyList<ErrorProcessorException> _processErrors;

/// <summary>
/// Initializes a new instance of the <see cref="BulkProcessResult"/> class.
/// </summary>
Expand All @@ -242,7 +244,7 @@ public class BulkProcessResult
public BulkProcessResult(Exception handlingError, IEnumerable<ErrorProcessorException> processErrors, bool isCanceledBetweenProcessOne = false)
{
HandlingError = handlingError;
ProcessErrors = processErrors;
_processErrors = (processErrors ?? Array.Empty<ErrorProcessorException>()).ToList();
_isCanceledBetweenProcessOne = isCanceledBetweenProcessOne;
}

Expand All @@ -254,22 +256,31 @@ public BulkProcessResult(Exception handlingError, IEnumerable<ErrorProcessorExce
/// <summary>
/// Gets a collection of exceptions that occurred within the error processors.
/// </summary>
public IEnumerable<ErrorProcessorException> ProcessErrors { get; }
public IEnumerable<ErrorProcessorException> ProcessErrors => _processErrors;

/// <summary>
/// Gets a value indicating whether any processing errors occurred.
/// </summary>
public bool HasProcessErrors => _processErrors.Count > 0;

/// <summary>
/// Gets a value indicating whether the bulk processing operation was canceled.
/// </summary>
public bool IsCanceled => ProcessErrors.Any(e => e.ErrorStatus == ProcessStatus.Canceled) || _isCanceledBetweenProcessOne;
public bool IsCanceled => _processErrors.Any(e => e.ErrorStatus == ProcessStatus.Canceled) || _isCanceledBetweenProcessOne;

/// <summary>
/// Converts the processing errors into a collection of <see cref="CatchBlockException"/>.
/// </summary>
/// <returns>An enumerable of <see cref="CatchBlockException"/>.</returns>
public IEnumerable<CatchBlockException> ToCatchBlockExceptions()
{
return ProcessErrors?.Any() != true
? Array.Empty<CatchBlockException>()
: ProcessErrors.Select(pe => new CatchBlockException(pe, HandlingError, CatchBlockExceptionSource.ErrorProcessor));
foreach (var pe in _processErrors)
{
yield return new CatchBlockException(
pe,
HandlingError,
CatchBlockExceptionSource.ErrorProcessor);
}
}
}
}
Expand Down
21 changes: 17 additions & 4 deletions src/ErrorProcessors/DefaultErrorProcessor.T.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public static DefaultErrorProcessorT Create<TParam>(Action<Exception, Processing
{
void action(Exception ex, ProcessingErrorInfo pi, CancellationToken token)
{
if (pi is ProcessingErrorInfo<TParam> gpi)
if (TryGetProcessingErrorInfo<TParam>(pi, out var gpi))
actionProcessor(ex, gpi, token);
}
var res = new DefaultErrorProcessorT();
Expand Down Expand Up @@ -90,7 +90,7 @@ public static DefaultErrorProcessorT Create<TParam>(Func<Exception, ProcessingEr
{
Task fn(Exception ex, ProcessingErrorInfo pi, CancellationToken token)
{
if (pi is ProcessingErrorInfo<TParam> gpi)
if (TryGetProcessingErrorInfo<TParam>(pi, out var gpi))
return funcProcessor(ex, gpi, token);
else
return Task.CompletedTask;
Expand All @@ -112,7 +112,7 @@ private static Action<Exception, ProcessingErrorInfo> ConvertToNonGenericAction<
{
return (Exception ex, ProcessingErrorInfo pi) =>
{
if (pi is ProcessingErrorInfo<TParam> gpi)
if (TryGetProcessingErrorInfo<TParam>(pi, out var gpi))
actionProcessor(ex, gpi);
};
}
Expand All @@ -121,13 +121,26 @@ private static Func<Exception, ProcessingErrorInfo, Task> ConvertToNonGenericFun
{
return (Exception ex, ProcessingErrorInfo pi) =>
{
if (pi is ProcessingErrorInfo<TParam> gpi)
if (TryGetProcessingErrorInfo<TParam>(pi, out var gpi))
return funcProcessor(ex, gpi);
else
return Task.CompletedTask;
};
}

public static bool TryGetProcessingErrorInfo<TParam>(
ProcessingErrorInfo pi,
out ProcessingErrorInfo<TParam> gpi)
{
if (pi is ProcessingErrorInfo<TParam> result)
{
gpi = result;
return true;
}
gpi = null;
return false;
}

protected override Func<ProcessingErrorInfo, ProcessingErrorInfo> ParameterConverter => (_) => _;
}
}
40 changes: 40 additions & 0 deletions src/ErrorProcessors/DefaultTypedErrorProcessor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using System;
using System.Threading;
using System.Threading.Tasks;

namespace PoliNorError
{
public class DefaultTypedErrorProcessor<TException> : IErrorProcessor where TException : Exception
{
private readonly DefaultTypedErrorProcessorT<TException> _errorProcessor;

public DefaultTypedErrorProcessor(Action<TException, ProcessingErrorInfo, CancellationToken> actionProcessor)
{
_errorProcessor = DefaultTypedErrorProcessorT<TException>.Create(actionProcessor);
}

public Exception Process(Exception error, ProcessingErrorInfo catchBlockProcessErrorInfo = null, CancellationToken cancellationToken = default)
{
return _errorProcessor.Process(error, catchBlockProcessErrorInfo, cancellationToken);
}

public async Task<Exception> ProcessAsync(Exception error, ProcessingErrorInfo catchBlockProcessErrorInfo = null, bool configAwait = false, CancellationToken cancellationToken = default)
{
return await _errorProcessor.ProcessAsync(error, catchBlockProcessErrorInfo, configAwait, cancellationToken).ConfigureAwait(configAwait);
}
}

internal class DefaultTypedErrorProcessorT<TException> : ErrorProcessorBase<ProcessingErrorInfo> where TException : Exception
{
public static DefaultTypedErrorProcessorT<TException> Create(Action<TException, ProcessingErrorInfo, CancellationToken> actionProcessor)
{
var action = ErrorProcessorFuncConverter.Convert(actionProcessor, ConvertExceptionDelegates.ToSubException);

var res = new DefaultTypedErrorProcessorT<TException>();
res.SetSyncRunner(action);
return res;
}

protected override Func<ProcessingErrorInfo, ProcessingErrorInfo> ParameterConverter => (_) => _;
}
}
Loading
Loading