Suppose that we have a message passing system using mailboxes. When sending to a full mail box or trying to receive from an empty one, a process does not block, instead, it gets an error code back. The process responds to the error code by just trying again, over and over, until it succeeds. Does this lead to race condition?
First at all I recommend to review what a race condition means.
If the mailbox system handles "atomicity" when receiving/retrieving emails, there is no race condition. Your app may loop forever trying to retrieve a message but it isn't a race condition.
Now, let's imagine that the mailbox system does not use any kind of locking mechanism. If at the same time, you are trying to read if a new message exists, a new message is arriving to the mailbox, you may read an uncompleted message because is still reaching.
In the best case you get the uncompleted message but usually a crash occurs because of an invalid pointer, etc.
The situation you describe wouldn't in itself lead to a race, though the actions you take in response to the error could, e.g pushing a "detected this mail box is empty" message to the empty mail box. Do that from two threads, you could easily end up with two mails.
Related
I'm new to NServiceBus, so maybe I'm asking something pretty silly here, but is there a way to make NServiceBus not stop sending any messages that are sent in response to a message whose handler fails?
Let me explain with a simple example.
Suppose I have an OrderPaidEvent that has a handler that does the following:
Look for the customer
Start a DB transaction
Update the customer to a good customer
Send an CustomerUpgradedToGoodCustomerEvent message
Commit the DB transaction
Fairly straightforward, all is well in the world. Now a few months later someone else figures that an email would be nice when an order is paid and thus adds another handler to the OrderPaidEvent to send an email.
Unfortunately, now whenever the mailserver has an issue, this second handler will fail with an error which will however prevent the original CustomerUpgradedToGoodCustomerEvent message from being sent (step 4). But because the DB transaction was already committed (step 5) the customer has already been upgraded to a good customer in the database.
This means that even if the OrderPaidEvent handler is retried the customer no longer changes and thus the CustomerUpgradedToGoodCustomerEvent message is never sent. Worse yet, this is all because of a change to the code that has nothing to do with the original message handler and will thus be difficult to detect.
This seems like a massive flaw and since I'm new to this I'm certain there's something I'm doing wrong, but I can't seem to figure out what it is.
Any help from you fine people would be great.
Thanks in advance.
How about breaking down your procedural code into separate handlers?
Thereafter each logical operation will either be done or will not be done based on successful completion of each granular task.
If you add a Saga to the mix then you can make business decisions based on the completed steps in your Saga.
Also maybe read more about transactions and NServiceBus here
First of all I would send out the CustomerUpgradedToGoodCustomerEvent after the commit. At that point you are sure that the event actually took place.
And in response to your question: You could handle the email in some 'SendEmail' command that is raised after the db commit and before the event is published. If that command fails it will not hurt the handling of the OrderPaid event. When mail is up again, the command can be retried and handled normally.
When I set up manual Ack with RMQ, but how could i know whether ack is successfully done?If there is a exception before basic.ack when i have long operations to perform, the message will be sent to another consumer .How can i avoid that?
How can i avoid that?
You can't.
At some point it will happen and your code needs to deal with this scenario gracefully. This is typically done with idempotence in your message processing.
That is, you allow the message to be processed more than once (because it will happen), but you only make the underlying change to the system once.
A common / simple way of handling this is to have an ID associated with each message. Before processing the message, check to see if that ID is marked as complete in your database. If it's not, then process the message. When the message is processed, you update a database with that ID. That way, when (not if) you run into the scenario where a message is processed twice, you won't actually do the processing / system changes twice.
If processing emails in an outlook mailbox, is it possible to use some kind of ID to record the last message processed avoiding the need to iterate through all messages every time?
I'm trying to write a quick 'attachment stripper' to free up mailbox space and don't want to have to iterate through every message in a mail folder each time the code is ran. At a pinch I could use the mail folder name and the message date, but what happens if a folder is renamed, or messages moved? (Besides, I REALLY hate dates!!! formats to start with, and I have recently experienced randomly changing environment settings in my work environment - a citrix remote desktop - so now have a near phobia of the damn things!)
I was hoping there was some kind of message ID I could use but can see neither the MAPI ID nor the Outlook Mail ID being suitable here (though I could well be wrong). Is there a means of doing this?
If you need to avoid reprocessing previously processed emails, you have no recourse but to either record the email's unique identifiers externally for later checking, or flagging emails with a specific value (such as adding a Category, setting a flag, adding a custom field, setting an internal field, etc.) to avoid processing them later.
How do I get a list of worker threads of nservicebus. I need to register workerThread ids in to db and then bind some type of messages to the exact workerthread. Real idea is handling poison messages. Want to block all the threads not to handle poison messages except specified ones. There will be a seperate service that will manage threads through database.
I would not try to do that. It is almost sure to run into problems.
Of course, in order to get some sort of "identity" for each thread, you could place something like this in your message handler:
[ThreadStatic]
private static readonly Guid ThreadId = Guid.NewGuid();
But again, I wouldn't do that! The guids would change every time the endpoint was restarted, for one.
You could also query the list of threads direct from .NET and try to determine which ones were the message handling threads, but that sounds so scary I don't even want to go into it.
The real issue: Poison Message Handling
As your comment states, the real problem is that a poison message is REALLY poison. Not only is it failing, but it's taking so long to do so that it's really screwing up all the other threads!
Since you are able to identify these messages based on certain properties of the message, I would detect and throw an exception before the operation that times out. All the time.
If you want to be able to test periodically to see if the issue has been fixed, you have a few options:
Test via other means, and return the messages to the source queue when it has been fixed.
Add an appSetting so that the quick-throw behavior is skipped when the config setting is enabled. Then periodically you can edit the config, restart the endpoint, see if it's fixed, and then switch it back if it isn't.
Create another message handler that maintains a thread-locked increment value of zero. Send it a control message to say "Hey, try one now." Then your quick-throw behavior can decrement that value and allow one through to see what happens. This is also dangerous of course. Make sure your locking is tight since you are now sharing this state between different message processing threads.
I am using Peter Huber's POP3 client to connect to gmail and download messages.
The inboxes being accessed are transactional inboxes used only for code-access. That is, a message comes in with a order file attached, code will process it and then delete the message. One stipulation of the code though was a DEBUG flag, which if set would prevent the code from deleting the message so that you can run the program again later without the debug flag and reprocess the message. So, in my code I have
If Not Arguments.Debug Then pop.DeleteEmail(eid)
This works fine. Problem is, even when not deleting the message, running the program a second time will not re-retrieve the message, even though if I login to gmail and look at the inbox, it is still there. The only way I can get the program to see the message again is to forward the message back to the same inbox. But in Peter's code I do not see anywhere where he is keeping track of seen messages between sessions.
Is this something that is done on gmail's end? Refusing to deliver a message to the same client a second time? If so, is there any way I can change my gmail account so that it will always show all messages in the inbox to a client when retrieving the list of messages, even ones already "seen"? I don't see anything in the gmail settings screen.
UPDATE: I tried adding a method to send a RSET command to the server, as per this comment on the codeproject page. I then call my new Reset() method after retrieving my messages but before disconnecting, ... but I still have the same problem.
Okay... found a "sort of" answer after reading through pages of the comments on the codeproject project.
According to this comment, the RSET command does not actually do anything when you are dealing with gmail's servers.
The "answer" is to prepend your username with the string "recent:", so instead of logging in with [myaccount#gmail.com] you log in with [recent:myaccount#gmail.com]. Rather hackish, ... but it works.