Bob
Bob

Reputation: 1061

Oracle AQ with ODP.Net. Automatically Dequeue on connect

I'm using Oracle ODP.Net for enqueue and dequeue.

Process A : Enqueue Process B : Dequeue with MessageAvailable event

If Process A and B are running, there is no problem. On the "Process B", the event is always fired.

But, if "Process B" is off and "Process A" is on, when "Process B" restarts, the queues inserted during the off time are lost.

Is there an option for to fire the event for all queues inserted in the past ?

Many Thanks

Upvotes: 1

Views: 1911

Answers (2)

RichardB
RichardB

Reputation: 606

I've been looking at this one too and have ended up doing something similar to Greg. I've not used the Listen() method though as I don't think it offers me anything over and above a simple Dequeue() - Listen() seems to be beneficial when you want to listen on behalf of multiple consumers, which in my instance is not relevant (see Oracle Docs).

So, in my 'Process B' I first register for notifications before initiating a polling process to check for any existing messages. It doesn't Listen(), it just calls Dequeue() within a controlled loop with a Wait period of a couple of seconds set. If the polling process encounters an Oracle timeout the wait period has expired and polling stops. I may need to consider dealing with timeouts if the wait period hasn't expired (though not 100% sure this if this is likely to happen).

I've noticed that any messages which are enqueued whilst polling will call the message notification method but by the time this connects and tries to retrieve the message the polling process always seems to have taken it. So inside the message notification method I capture and ignore any OracleExceptions with number 25263 (no message in queue <...> with message ID <...>).

Upvotes: 0

Greg
Greg

Reputation: 51

There seem to be two approaches to address this issue:

  1. Call the Listen() method of the OracleAQQueue class (after registering for message notification) to pick up "orphaned" messages sitting in the queue. Note that Listen() blocks until a message is received or a timeout occurs. So you'd want to specify a (short) timeout to return back to the processing thread in the event no messages are on the queue.
  2. Call the Dequeue() method and trap Oracle error 25228 (no message available to dequeue). See the following thread from the Oracle support forums: https://forums.oracle.com/forums/thread.jspa?threadID=2186496.

I've been scratching my head on this topic. If you still have to "manually" test for new messages, what is the benefit of using the MessageAvaiable event callback in the first place? One route I've pondered is to wrap the Listen() method in an async call so that the caller isn't blocking on the thread (until a message is received or a timeout occurs). I wrapped Listen() and Dequeue() in a custom Receive() method and created my own MessageReceived event handler to pass the message details to the calling thread. Seems somewhat redundant, since ODP.NET provides the out-of-box callback, but I don't have to deal with the issue you describe (or write code to "manually" test for "orphaned" messages.

Any comments/thoughts on approach are welcomed.

Upvotes: 5

Related Questions