-
Notifications
You must be signed in to change notification settings - Fork 36
Azure Functions ServiceBusTrigger prevent abandon on Exception #183
Comments
Hello everyone. I am working on exactly the same requirement. Do we have any progress on this? |
Hello @alrod :) |
Still seeing this issue, has anyone found the solution? I thought adding "autoComplete": true to the host.json would help, but doesn't seem to work for me
|
I have the exact same problem. We have two requirements:
Everything I've read has told me the only way to have a function show as "Failed" is to throw an Exception at the end of it (which is kind of awful if you ask me) - forcing us to do the following: [FunctionName("SomeSubscriberAsync")]
public async Task Run(ILogger logger, [ServiceBusTrigger("%ASubscriptionTopic%", "%ASubscription%", Connection = "AServiceBusConnectionString", IsSessionsEnabled = true)]Message message, MessageReceiver messageReceiver)
{
ReturnCode returnCode = await ProcessMessage(message, logger);
await ReleaseMessage(returnCode, message, messageReceiver, logger, "SomeSubscriber");
// See https://stackoverflow.com/questions/42782379 - the only way notify Azure of an error
// in the function app run is to raise an unhandled exception (even if it has been handled cleanly)
if(returnCode != ReturnCode.Success)
throw new Exception("Function execution failed - its all in the logs.");
} This was supposed to be the method we use to put the message where we want it to go: /// <summary>Based on how the message was handled, completes, abandons, or dead-letters it.</summary>
public static async Task ReleaseMessage(ReturnCode result, Message message, MessageReceiver messageReceiver, ILogger logger, string handlerName)
{
switch (result)
{
case ReturnCode.Success:
await messageReceiver.CompleteAsync(message.SystemProperties.LockToken);
logger.LogInformation($"{handlerName} has 'completed' the message {message.MessageId} due to successful handling.");
break;
case ReturnCode.TemporaryFailure:
await messageReceiver.AbandonAsync(message.SystemProperties.LockToken);
logger.LogWarning($"{handlerName} has 'abandoned' the message {message.MessageId} so that it can try again later.");
break;
case ReturnCode.PermanentFailure:
await messageReceiver.DeadLetterAsync(message.SystemProperties.LockToken);
logger.LogWarning($"{handlerName} has 'dead-lettered' the message {message.MessageId} due to a permanent failure.");
break;
}
} But in the ticket description, some sort of auto-handling kicks in after the exception is thrown (despite my
I even tried " The only thing that prevents these red-herring errors from capping off every failed execution is to go back to not |
I'm currently hitting this issue as well (and I'm quite surprised since this issue exists for almost 2 years now!). The docs clearly state that when |
Don't forget about that issue with using Startup: #81 |
@mathewc I'm sorry for tagging you, but it's been 7 months after my comment, and this issue seems to have been buried under all the other issues. I would like to know if it will be fixed, because it will make our monitoring a lot more reliable. |
I have the same requirement - need to deadletter the message on failure and show the function invocation as well. and I got the same exceptions :( |
Alright, after seeing the availability of version 4.3.0 with the addition to mark an individual trigger with Without specifying So, while I have the expected behavior at the moment, I'm still baffled that it's only possible to get this by using the attribute setting.
|
I am not able to reproduce this locally using and setting I still get this error message logged if I deadletter the message in the code and then throw an exception: I do not get this message logged if I throw an exception without deadlettering, completing, or abandoning the message in my code. This was both with and without all three I have these nuget packages:
.NET Core 3.1 and |
I created Azure/azure-sdk-for-net/pull/23423 for this, but I'm not sure how to complete these two steps listed as "prior to issuing a pull request":
(of course, the fix itself ended up being very straightforward) |
That is odd. I have double checked my code, and it seems to be working on my end locally: [FunctionName("AutoComplete")]
public static async Task AutoComplete(
[ServiceBusTrigger("autocomplete", AutoComplete = false)] Message message,
MessageReceiver messageReceiver,
ILogger logger,
CancellationToken cancellationToken)
{
await Task.Delay(TimeSpan.FromSeconds(1)); // Delay it a bit
var text = Encoding.UTF8.GetString(message.Body);
logger.LogWarning($"Now: {DateTime.UtcNow}");
logger.LogWarning($"Locked until: {message.SystemProperties.LockedUntilUtc}");
logger.LogWarning($"Lock token: {message.SystemProperties.LockToken}");
switch (text)
{
case "abandon":
logger.LogWarning("Abandon and throw exception");
await messageReceiver.AbandonAsync(message.SystemProperties.LockToken, new Dictionary<string, object> { ["Hello"] = "Abandoned" });
throw new Exception("test");
case "deadletter":
logger.LogWarning("Deadletter and throw exception");
await messageReceiver.DeadLetterAsync(message.SystemProperties.LockToken, new Dictionary<string, object> { ["Hello"] = "Deadlettered" });
throw new Exception("test");
case "timeout":
logger.LogWarning("Time out operation");
await Task.Delay(TimeSpan.FromSeconds(120), cancellationToken);
break;
case "exception":
logger.LogWarning("Just throw exception");
throw new Exception("test");
case "nothing":
logger.LogWarning("Do nothing");
break;
default:
logger.LogWarning("Complete successfully");
await messageReceiver.CompleteAsync(message.SystemProperties.LockToken);
break;
}
} In my host.json file, the functionTimeout and maxAutoRenewDuration are both set to 1 minute. I got the following results with the code above:
The results from both not changing auto complete, and setting auto complete to false through the attribute, are what I mostly expect*. And we know that the host.json setting should do the same as the attribute, but for completion's sake I've put it here as well. Can you check as well with the same code, and share your results? *One thing to note, is that with both host.json and the attribute setting to false, throwing an exception without abandoning or deadlettering it yourself, still abandons it (there's no lock delay). I had expected the lock to act the same as doing "nothing".
Because the lock clearly doesn't seem to remain in my testing. |
I set up a repository to try this out, using your example: https://github.com/zamzowd/service-bus-sans-autocomplete On manual deadletter followed by an exception, I still get the message that it attempts to abandon the message: Maybe there's some race condition between no longer writing to a log for a given message and the attempt to abandon the message in Regardless of whether the log includes the error for attempting to abandon the message, I'm pretty confident it still attempts to abandon the message whether the AutoComplete is set by way of ServiceBusTrigger's attribute or the host.json. There doesn't seem to be any code that would make this part behave differently in those scenarios. As seen in my PR, the |
As I'll be removing my work account in favor of my main account, I can contacted at @Archomeda from now on for further updates. |
it's fixed in latest SB extension: https://www.nuget.org/packages/Microsoft.Azure.WebJobs.Extensions.ServiceBus/5.3.0 |
As a developer I would like to be able to send a Service Bus message to the DeadLetter Queue and throw an Exception without triggering the automatic Abandon behavior when an Exception is thrown. This is because I want to surface errors in Application Insights by considering requests that results in a message being DeadLettered as a failed request. This occurs even when extensions.serviceBus.messageHandlerOptions.autoComplete is false.
Repro steps
Create an ServiceBusTrigger function like below:
Add an item to the test queue and observe the behavior.
Expected/Desired behavior
One exception thrown.
Actual behavior
Two exceptions are thrown.
Known workarounds
You can not throw the Exception and DeadLetter the message. However, this will not log as a failure in Application Insights.
You can ignore the second Exception, but it is unwieldy and clutters the logs.
Related Information
Packages:
Microsoft.Azure.WebJobs.Extensions.ServiceBus 3.0.3
Microsoft.NET.Sdk.Functions 1.0.26
Related ticket regarding AutoAbandon #691
The text was updated successfully, but these errors were encountered: