views:

175

answers:

2

We are having MVC application which reads data from MSMQ. We are trying to find out a way to read message from queue and remove it from queue only if user has done a successful operation on the queue. The message should remain in the queue until user completes the processing, the message should not be available to anyone else until the user who is processing the message object has finished the operation.

Is there a property for a Message object to be set as Peeked which will not allow reading of this message again until ether it is put back into the queue or removed from the queue?

We are not sure if using MSMQ is a good idea in this case?

A: 

The Queue is the right idea. Your approach of "leave it in the queue, locked, but still kind-of-available" is wrong.

You may need multiple queues.

  1. Process A enqueues something in Queue 1

  2. Process B dequeues from Queue 1 and starts work.

    • If B is successful, that's it.

    • Otherwise, it gets queued somewhere else (perhaps the same queue, or perhaps Queue 2) for follow-up work.

If it went back into Queue 1, B will find it again, eventually. If it went to another Queue, then another process does cleanup, logging, error fixup or whatever, possibly putting something back in Queue 1.

A Queue isn't a database -- there's nothing stateful (no "don't look at me, I'm being processed").

A Queue is transient storage. Someone writes, someone else reads, and that's it.


If you want reliability, read this: http://msdn.microsoft.com/en-us/library/ms978430.aspx

And this: http://blogs.msdn.com/shycohen/archive/2006/02/20/535717.aspx

And this: http://www.request-response.com/blog/PermaLink,guid,03fb0e40-b446-42b5-ad90-3be9b0260cb5.aspx

Reliability is a feature of the queue, not your application. You can do a "recoverable read". It's a transaction that's part of the queue API.

S.Lott
If you're opposed to the "leave it in the queue, but lock it" method, how do you handle application crashes or loss of connectivity, in case your processor stops working? I'm concerned that items I've removed from the queue so I can process them won't ever make it back into the queue in the event that it's not completed. I can code for exceptions and handle the crash, but I'm afraid I'd miss some edge case.
rwmnau
That's exactly the issue we are having. How do we make sure that the Message is not lost once we read the message from the queue.
Balaji
A: 

It sounds like you need to use your queue(s) in transactional mode. Then, your client can receive a message, process it, and then commit the transaction, at which point the message will be finally dequeued. While the transaction is active, however, other clients will not see the message -- it will be held in reserve until the transaction completes or is aborted.

This MSDN article has a decent overview of usage patterns for reliable messaging with MSMQ:

http://msdn.microsoft.com/en-us/library/ms978430.aspx

rcoder
In that case i will have to pass the transaction object to the UI layer. Is it a good idea to do so? We have never used MSMQ transactions so any input would be of great help to us.
Balaji
Without knowing more about your application, I can't say for certain whether putting transaction logic into your view layer is a good idea or not, but I would generally recommend against it.
rcoder
In our application we are reading a message from the queue.The message object is displayed onto the view to the user.The user might change the values are hit on save.At this point the message is placed in another queue.We want to make sure that the message is not lost in this process of reading data from queue and doing a save operation (Which is triggered by the user).Could you please suggest if using a transaction is appropriate in this case?
Balaji
I think a transaction should be totally appropriate. If your view is currently directly pull messages from queues, I see no real harm in extending it to also handle transactions.At some point, however, you may want to investigate putting a controller tier between your view and back-end queues to insure transactions are properly started and resolved. Re-implementing the same message-handling logic in every view will needlessly duplicate code.
rcoder