diff --git a/CHANGELOG.md b/CHANGELOG.md index 3bfac63b..67279491 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ Represents the **NuGet** versions. +## v3.3.1 +- *Fixed:* `ServiceBusSubscriber` was not correctly bubbling (not handling) exceptions where `UnhandledHandling` was set to `ErrorHandling.None`. Was incorrectly treating same as `ErrorHandling.ThrowSubscriberException` and automatically dead-lettering and continuing. + ## v3.3.0 - *Enhancement:* [Distributed tracing](https://learn.microsoft.com/en-us/dotnet/core/diagnostics/distributed-tracing-instrumentation-walkthroughs#best-practices) has been added via the `InvokerBase` set of classes throughout `CoreEx` to ensure coverage and consistency of implementation. A new `InvokeArgs` has been added to house the [`ActivitySource`](https://learn.microsoft.com/en-us/dotnet/api/system.diagnostics.activitysource) instance; this also provides for further extension opportunities limiting future potential breaking changes. diff --git a/Common.targets b/Common.targets index 7e5293d6..17065141 100644 --- a/Common.targets +++ b/Common.targets @@ -1,6 +1,6 @@  - 3.3.0 + 3.3.1 preview Avanade Avanade diff --git a/src/CoreEx.Azure/ServiceBus/ServiceBusSubscriberInvoker.cs b/src/CoreEx.Azure/ServiceBus/ServiceBusSubscriberInvoker.cs index 5190e562..5866308f 100644 --- a/src/CoreEx.Azure/ServiceBus/ServiceBusSubscriberInvoker.cs +++ b/src/CoreEx.Azure/ServiceBus/ServiceBusSubscriberInvoker.cs @@ -147,6 +147,10 @@ private static async Task HandleExceptionAsync(EventSubscriberBase invoker return true; // Keep throwing; i.e. bubble exception. } + // Where the unhandled handling is set to None then keep bubbling; do not dead-letter. + if (invoker.UnhandledHandling == Events.Subscribing.ErrorHandling.None) + return true; + // Dead-letter the unhandled exception. await DeadLetterExceptionAsync(invoker, message, messageActions, ErrorType.UnhandledError.ToString(), exception, cancellationToken).ConfigureAwait(false); return false; diff --git a/tests/CoreEx.Test/TestFunction/ServiceBusSubsciberTest.cs b/tests/CoreEx.Test/TestFunction/ServiceBusSubsciberTest.cs index be8cdee5..0cd8ff97 100644 --- a/tests/CoreEx.Test/TestFunction/ServiceBusSubsciberTest.cs +++ b/tests/CoreEx.Test/TestFunction/ServiceBusSubsciberTest.cs @@ -208,19 +208,61 @@ public async Task Complete() } [Test] - public async Task Unhandled_DeadLetter() + public async Task Unhandled_Throw_DeadLetter() { using var test = FunctionTester.Create(); var actions = test.CreateServiceBusMessageActions(); var message = test.CreateServiceBusMessage(new { id = "A", name = "B", price = 1.99m }); var sbs = test.Services.GetRequiredService(); - sbs.AbandonOnTransient = true; + sbs.UnhandledHandling = Events.Subscribing.ErrorHandling.ThrowSubscriberException; await sbs.ReceiveAsync(message, actions, (_, _) => throw new DivideByZeroException("Zero is bad dude!")); actions.AssertRenew(0); actions.AssertDeadLetter("UnhandledError", "Zero is bad dude!"); } + + [Test] + public async Task Unhandled_None_Bubble() + { + using var test = FunctionTester.Create(); + var actions = test.CreateServiceBusMessageActions(); + var message = test.CreateServiceBusMessage(new { id = "A", name = "B", price = 1.99m }); + + var sbs = test.Services.GetRequiredService(); + sbs.UnhandledHandling = Events.Subscribing.ErrorHandling.None; + + try + { + await sbs.ReceiveAsync(message, actions, (_, _) => throw new DivideByZeroException("Zero is bad dude!")); + } + catch (DivideByZeroException) + { + } + catch (Exception ex) + { + Assert.Fail($"Expected {nameof(DivideByZeroException)} but got {ex.GetType().Name}."); + } + + actions.AssertRenew(0); + actions.AssertNone(); + } + + [Test] + public async Task Unhandled_ContinueAsSilent_Complete() + { + using var test = FunctionTester.Create(); + var actions = test.CreateServiceBusMessageActions(); + var message = test.CreateServiceBusMessage(new { id = "A", name = "B", price = 1.99m }); + + var sbs = test.Services.GetRequiredService(); + sbs.UnhandledHandling = Events.Subscribing.ErrorHandling.CompleteAsSilent; + + await sbs.ReceiveAsync(message, actions, (_, _) => throw new DivideByZeroException("Zero is bad dude!")); + + actions.AssertRenew(0); + actions.AssertComplete(); + } } } \ No newline at end of file