tirsen / activemessaging

ActiveMessaging is an attempt to bring the simplicity and elegance of Rails development to the world of messaging. Messaging, (or event-driven architecture) is widely used for enterprise integration, with frameworks such as Java's JMS, and products such as ActiveMQ, Tibco, IBM MQSeries etc
0 stars 0 forks source link

ActiveMessaging::AbortMessageException still removes message from queue #36

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
I want to wrap my processor code so that if an  exception occurs, the
message is NOT removed from the message queue. In this case, I'm using
ActiveMQ and STOMP with a13g

What steps will reproduce the problem?
1. have your message processor raise ActiveMessaging::AbortMessageException 
2. Send a message that your processor handles
3. Note that the message is still consumed from the queue. 

What is the expected output? What do you see instead?
Expected: The message would remain on the queue, for any other consumers to
handle. 

What version of the product are you using? On what operating system?
Rails 2.1 ; 

Please provide any additional information below.
I note that there's a teasing message in the example broker.yml about
maxRetry and deadLetterQueue, neither of which seem to work.

Original issue reported on code.google.com by brian.mo...@gmail.com on 29 Aug 2008 at 9:10

GoogleCodeExporter commented 9 years ago
Stomp doesn't have transaction receipt of messages that can be rolled back so 
that
messages return to the queue on error by the processor.

There is a client ack mode, which sorta does this, but does not have a rollback
method short of severing the connection. 

You can read more about this issue here:

http://www.nabble.com/putting-a-message-back-td12367572.html

and here:

http://groups.google.com/group/activemessaging-discuss/browse_thread/thread/57b1
953daf468c60

Original comment by kooks...@gmail.com on 29 Aug 2008 at 10:01

GoogleCodeExporter commented 9 years ago
If the ack mode is client, the message shouldn't be ack'd until the processor's 
code
has been executed, IMHO.

In looking at the received method, the ack is sent on receipt of the message, 
not on
successful processing of the message. Perhaps the received method can indicate 
to a
post-successful-processing method to send the ack?

ALSO, in maxRetry in the example broker.yml file really should be retryMax, 
since
that's what in the source code. 

Original comment by brian.mo...@gmail.com on 29 Aug 2008 at 10:32

GoogleCodeExporter commented 9 years ago
> If the ack mode is client, the message shouldn't be ack'd until the 
processor's 
> code has been executed, IMHO.

> In looking at the received method, the ack is sent on receipt of the message, 
> not on successful processing of the message. Perhaps the received method can
> indicate to a post-successful-processing method to send the ack?

I used to think that too, and implemented it that way at first, till I actually
tested it.

Answer me this - what do you think the broker does if you don't ack a message?
You never get sent another message - no timeout, no rollback - if you don't 
ack, you
stop getting messages, and all processing stops cold, end of story. I don't 
mean to
sound dismissive, but I have been dealing with this problem for awhile, believe 
me, 

I didn't implement it this way by accident or b/c I overlooked this - client 
ack mode
is not transactional, you can't roll it back, it is really only good as a 
throttle,
and to handle the case that your process dies with messages already received by 
the
stomp client connection, but unprocessed, and subsequently lost.

Please review the pages I referenced - this is the crux of the problem - if you 
don't
ack the message, you will never get sent another on that 
connection/subscription -
not ack'ing the message is not the same thing at all as return it to the queue.

> ALSO, in maxRetry in the example broker.yml file really should be retryMax, 
since
> that's what in the source code. 

Yeah yeah, my bad. This got pointed out on the list yesterday, and I checked in 
a fix
to that comment in the generated yml file already. Apologies for the confusion.

Original comment by kooks...@gmail.com on 29 Aug 2008 at 10:45

GoogleCodeExporter commented 9 years ago
BTW, we use the 'break the connection and the message stays in the queue' for 
another
application, and it works well. 

Original comment by brian.mo...@gmail.com on 29 Aug 2008 at 10:46

GoogleCodeExporter commented 9 years ago
So now I am confused - what do you want? 

Did you ever get the retryMax stuff to work, or do you just not like that
implementation and prefer the connection break method?

If you know about this stuff, why the vague defect report?

For what it is worth - your analysis of how the received messages gets called 
is off
a bit - exactly as you are asking for, messages are ack'ed only after the 
successful
completion of the message being processed by at least one subscribing 
processor, not
on receipt of the message. Look at the gateway lines 227 - 237 - you will see 
that
the acknowledge_message method is called in an ensure block after the process 
method
is called, so if the ruby process were to die/get disconnected mid-processing, 
the
message would get returned to the queue.

My abort logic alters this slightly as it sends the cloned message back to the
destination and sends the ack in a transaction together, so were something to 
go bad,
the ack and dupe message would both be lost, and the original message would be
returned to the queue.

You like the 'break the connection' hack? That's a choice you can make in your 
app,
but that is a work-around with it's own trade-offs, and I find that returning a 
clone
of the message to the queue has trade offs I prefer.

For example: What happens to messages that are supposed to come in to your
subscription while you are breaking the connection, reconnecting, and 
resubscribing?

For queues this might be ok - the message will wait for you, or some other 
subscribed
client - but what about when you have topics to which you are subscribed, and 
now if
you missed that message? And don't tell me the answer is that the reconnect is
usually fast or that you can use durable topics - that's just saying this will 
be
rare, and requiring features specific to one stomp broker impl, not a solution 
- I
know users throwing pretty high load of messages at their destinations, this 
will
happen for them, and I know users not using activemq for their stomp server. 

And another trade off -  what about possibly infinite retry loops? Let's say 
you have
a message that every time it gets processed, it fails, gets put back on the 
queue by
connection reset method, and then does the same thing all over again.  Perhaps 
the
broker will allow for a timeout on the message so eventually this will end, and 
the
message will wither expire or go to a dead letter, but then I would be relying 
on the
existence of broker capabilities not at all specified or assured by supporting 
stomp
- e.g. maybe activemq could be made to behave this way (though most users of 
active
messaging would not be quick to know how to configure this), I don't think
StompServer does this at all, and again, I have more than a few users on that 
broker. 

The downside to my approach is that you lose message order in the destination - 
which
for some apps will be unacceptable, but I see fewer people complaining about 
that
than about loosing messages from topics or jamming up their pollers with 
constant
reprocessing of erroneous messages. 

Original comment by kooks...@gmail.com on 29 Aug 2008 at 11:58