This is a problem particular to the storage emulator - we have not yet attempted to reproduce it in production.
The issue is something like this:
- enqueue three messages with initialVisibilityDelay set to 30 seconds (TimeSpan.FromSeconds(30))
- the messages become visible at 30 seconds, and the first one is dequeued as you might expect
- the other two messages vanish and are never dequeued
We've played with staggering the visibility timeouts, so that the first is at 30 seconds, then second at two minutes, the third at four, and watch the whole thing in the debugger. The behavior is the same. The first is dequeued, and the others never are. By monitoring the QueueMessage table in the backing DevelopmentStorage database, you can actually watch as your app polls the queue, getting nothing out of it, and the messages sequentially vanish from the QueueMessage table without ever being dequeued (or showing up in, say, Cerebrata if you're watching the queue using other tools.)
This thread describes a similar (apparently unresolved) problem, though it doesn't play with initialVisibilityDelay.
We haven't built an app to test this in isolation. Is this a known issue with the emulator, queues in general, or something?
We're pretty confident in our code to enqueue/dequeue as its being used in production for lots of message handling. The only variable here is the initialVisibility variable, which definitely seems not to work as (we understand it to be) advertised in emulation.
At least for more than one message. One message at a time seems to work perfectly.
- Tipo cambiado Arwind - MSFTModerator jueves, 31 de mayo de 2012 8:38
Todas las respuestas
I'm sorry I never replied to this at the time. The emulator was the one prior to the latest release - I guess that was November 2011?
The issue seemed to be an interaction with TPL and enqueue/dequeue. In particular, our message loop would get a message off the queue, read it, and call a message handler which would invoke the actual code which would do the work.
The handler was wrapping the work in a new task (e.g. Task.Factory.StartNew, etc.).
The effect of this was what I described above. We never built a reproduction case, since removing two lines of code resolved the issue, and since the use of TPL in this case was logically incorrect for our scenario, anyway. I still don't understand why this would be the case - from the perspective of the message loop looking for messages on the queue, it seems like the only difference would be that in the failure case the handler would return much more quickly than in the success case.
The other thing to know was that the code being invoked in the task was itself dropping messages to a queue.