I'm trying to disable retries for some specific exceptions completely.
I know that in my code - when I'm trying to handle message X and if the handler throw a "ZZZ" type exception, I'm sure there's no way any number of retries would help;
What I want to do is send that message directly to error queue immediately without any retries.
How can i do that ?
I know you've already accepted an answer, but since you are trying to circumvent the plumbing builtin for a very specific scenario, you could handle the message in a try/catch and either send the message directly to the error queue or let the FLR/SLR handle it.
Please note, this is not an ideal scenario. In most cases, it is actively discouraged to handle the error handling of messages and instead allow the infrastructure to manage it.
Here's a possible implementation:
public void Handle(SomeCommand message)
{
try
{
//Do thing that might throw exception
}
catch (SpecificException ex)
{
_bus.Send(new Address("errorQueue", "machine"), message);
}
catch (Exception ex)
{
throw ex;
}
}
EDIT I'm promoting Marcin's comment to be included in this answer so it isn't missed:
Please bear in mind that by using this approach without setting
appropriate message headers you will lose the ability to return these
failed messages to the source queue. Please take a look at this doco
for details: http://docs.particular.net/nservicebus/messaging/headers#retries-handling-headers. – Marcin
Hoppe
You can't for the first level retries, only for the second level retries. I personally wouldn't worry about it (I have something similar, where certain exceptions I know that it won't be fixed). There's generally no downside to letting them go in the FLR.
Related
I'm making a call to a WCF service that will initiate a batch of credit card charges. If an exception occurs, I want to know whether it occurred prior to the method executing and cards actually being charged. For example, with a TimeoutException, there's no way to know whether the WCF method executed so I need to make sure those charges aren't retried until the situation is investigated. But if the network was just down, or the server cert expired, or anything else happened prior to the method actually executing, I can un-lock my records to be retried later without human intervention.
try
{
var response = wcfClient.ProcessBatch(paymentBatch);
wcfClient.Close();
//...
}
catch(CommunicationException)
{
//Safe to assume ProcessBatch did not execute?
wcfClient.Abort();
}
catch(TimeoutException)
{
//Indeterminate state. Have to assume operation may have succeeded server-side
wcfClient.Abort();
}
catch(Exception)
{
//Assuming operation may have succeeded server-side
}
This is using a wsHttpBinding. Does a CommunicationException guarantee the method did not execute or could it also be thrown during the response?
According to the CommunicationException documentation on MSDN, a CommunicationException Exceptioon is a superclass of errors that fall into two subcategories, both related to to errors in the SOAP datagram.
Conversely, a TimeoutException is pretty straightforward: "The exception that is thrown when the time allotted for a process or operation has expired." The allotted time is probably set by the owner of the service, and you may or may not have a mechanism by which to override it.
For future reference, two quick Bing searches returned both of the articles cited herein.
I have an interesting use case where certain exception types mean "This message is no longer valid and should be ignored" but this code doesn't have any awareness of the Bus in order to call Bus.DoNotContinueDispatchingCurrentMessageToHandlers().
I loathe boilerplate code like try/catch blocks that need to be present in every single message handler. So I started implementing a UnitOfWork to handle and swallow the exception, but I can't find a way to tell the framework that "Yes, this code generated an exception, but forget about that and just complete the transaction."
Bus.DoNotContinueDispatchingCurrentMessageToHandlers() does not work. I tried having an ITransport injected and calling AbortHandlingCurrentMessage() but that caused the entire universe to blow up. Even stepping through the source code I seem to be at a loss.
Note that it very well may be that this is a horrible idea, because faking that there is no exception when there is in fact an exceptional case would cause the transaction to commit, causing who knows how many bad unknown side effects. So it would be preferable to have a method that still rolls back the transaction but discards the message. But I would be interested in a potential "Yes I know what I'm doing, commit the transaction regardless of the exception" option as well.
As of NServiceBus version 4.4 you can control this by injecting a behavior into our handler pipeline.
This let's you control which exceptions to mute.
class MyExceptionFilteringBehavior : IBehavior<HandlerInvocationContext>
{
public void Invoke(HandlerInvocationContext context, Action next)
{
try
{
//invoke the handler/rest of the pipeline
next();
}
//catch specific exceptions or
catch (Exception ex)
{
//modify this to your liking
if (ex.Message == "Lets filter on this text")
return;
throw;
}
}
There are several samples of how this works:
http://docs.particular.net/samples/pipeline/
That said I totally agree with Ramon that this trick should only be used if you can't change to design to avoid this.
A dirty solution would be having a unit of work test the exception, put the message id in a shared 'ignore' bag (concurrent dictionary in memory, db, what works for you) , let it fail so that everything is rolled back, in the retry have a generic message handler compare the message ID and let that call Bus.DoNotContinueDispatchingCurrentMessageToHandlers()
If you do not want to work with a unit of work then you could try to use the AppDomain.FirstChanceException.
I wouldn't advice any of these as good solution :-)
Why would you like to 'swallow' unhandled exceptions?
If you want to ignore an exception then you should catch these in the handler and then just return and log this.
What I'm more interested in is what about state? You maybe have already writen to a store. Shouldn't these writes be rolled back? If you swallow an exception the transaction commits.
It seems to me you are running in a kind of 'at least once delivery' environment. THen you need to store some kind of message id somewhere.
Or is it an action initiated by several actors based on a stale state? In that case you need to have first/last write wins construction that just ignores a command based on a stale item.
If you handl an event then swallowing a exception seems not correct. They usually say that you can ignore commands but that you always have to handle events.
Shouldn't this be part of validation? If you validate a command then you can decide to ignore it.
Using JOliver EventStore 3.0 and reciving commands from NServiceBus, what's the proper way to handle concurrency exceptions? If I have more than one worker thread, this could be a common occurance.
Option 1
try
{
// store the event
...
}
catch (ConcurrencyException)
{
_bus.HandleCurrentMessageLater();
}
Option 2
Let it throw back to NServiceBus and get retried with the MsMqTransportConfig.MaxRetries option from the config.
Option 3
Something I'm not thinking of?
You could compare the uncommitted events with the committed events and see if they actually conflict (according to your business rules) - if there's no conflicts then you can allow the events to be persisted, otherwise re-throw.
Generally though I just let it throw and have NServiceBus retry.
I am just learning WCF and wrote a Windows Service hosting a WCF service. Ever since I started it in service.msc in the remote server (physically remote, and very slow) I think I have already hit and fixed like a hundred errors here and there already. I am now finally stuck.
At this point, I have enabled tracing and message logging. The first and only function call looks like this:
[OperationContract]
public MyServiceResponse ConnectToAXDynamicsViaDotNET2BusinessConnectorWithSadFace()
{
try
{
throw new NotImplemented();
}
catch(Exception ex)
{
return new MyServiceResponse(ex, ex.Message);
}
}
[DataContract]
public class MyServiceResponse
{
// ...
}
Upon calling the operation, the client just sits and waits until timeout. Checking the trace, it records my thrown exception. So it makes me wonder if WCF actually blocks there and ignore my catch clause.
I then tested with just a simple return value without throwing and it FINALLY works.
My question is, how then can I make the above scenario work, ie. catch the exception and return a sensible result back to client? Maybe it's just the tracing that blocks me, but I want to enable tracing during this whole debugging process otherwise it's really hard to work.
Thanks for your precious help!
EDIT: Sorry, I found this right after I posted this question. Happens all the time: http://msdn.microsoft.com/en-us/library/ee942778.aspx but I have yet to read it as I got to run off now. Not sure it it will solve my problem.
Risk being downvoted, but just for documentation sake and general usefulness of having this question:
Through reading the FaultException handling articles, I guess the above behavior is due to Exception class not serializable. And the service silently disconnects itself without returning any error messages eventhough the "send (unknown) faults to client" is enabled. As for why it does so, I have no idea yet. Will update if I find out more.
I have since changed to throw new FaultException() instead of returning my own MyServiceResponses.
just a general question,
do you ALWAYS have to handle error?
i was just having this debate with one of my coworker where in his code I see a lot places where stuff are wrapped around a try statement and in the catch statement there is nothing.
I always thought it is a bad practice to not handling error or hide them from the user (except log them in the log file).
just want to know what other people thinks
thanks.
If you can't handle the exception, then don't catch it. It may be that someone further up the call stack can properly handle it, and congratulations, you've now prevented them from doing their job <golfclap/>.
The practice of catching an exception and then "silencing it" is EVIL! i think 99.99% of all SOers will agree on that one.
Here's a very nice article from CodeProject on exception handling best practices. Guess what one of the sections is devoted to?
The worst thing you can do is catch (Exception) and put an empty code block on it. Never do this.
Any exception handling article worth its salt will mention the exception swallowing concept, and not to do it, in some way.
Only a Sith deals in absolutes. Seriously, though, I can think of at least one instance we ran across just recently where it was desirable to just drop it and move on. We recently implemented an in-house click tracking solution that sends an async AJAX request to an MVC controller to be logged. We don't care if it does not get logged and we don't want our own logs filling up with error logs that we don't want. so why bother with the overhead of doing anything in the catch block. We considered adding code in the catch block to at least increment a counter when we got an error, but there was no business reason for it at this time.
It really comes down to whether you are doing it out of laziness or because there is actually a good reason not to.
I'll probably get flack for saying that as it is bad practice in general. Do I get points for bravery?
You have to handle the exception if there is something you can do with it
try
{
//CODE
}
catch
{
LogException();
//and/or
RollbackTransaction();
//and/or
ShowFriendlyMessageToUser();
//and/or
DoSomethingUsefullWithTheException();
throw; //This is optional
}
This make no sense, but I've seen it a lot
try
{
//CODE
}
catch
{
throw;
}
EDIT 1
And you need a very good argument to put something like this. And probably you'll get fired anyway :-p
try
{
//CODE
}
catch
{
//HIDE TO THE WORLD THAT THIS IS FAILING
}