Gordon Sim wrote:
Rafael Schloming wrote:
Gordon Sim wrote:
Rafael Schloming wrote:
I don't think this is the only difference. A broker can DLQ unacked
messages, but not released messages.
What are the rules around that? I would expect unacked messages to be
left on the queue, as the delivery hasn't succeeded. DLQing them
seems quite wrong to me. Certainly neither of the qpid brokers do that.
I'm not sure the spec has language explicitly stating this, but I had
always assumed it was an option. If you can't do this then a message
that causes a client to repeatedly crash before it has a chance to
reject will effectively block up a queue forever.
I think that is an issue that applications should deal with (or else
require administrator intervention). To allow unacked messages to be
dequeued seems an extremely bad idea to me unless there is precise rules
around it.
The reliability model in my view sets the expectation that a message
stays on a queue until acked or until explicitly rejected.
I'm really not suggesting that unacked messages should be arbitrarily
dequeued willy-nilly. What I'm suggesting is that brokers should have
room to detect that a particular message is causing a client to crash.
See my other email for more details on this.
There is also another difference. Released messages will be available
to the broker immediately, whereas unacked messages won't be available
until the session closes, so a client impl can't depend on recovery of
unacked messages for cleanup when it closes a consumer since those
unacked messages would be stranded with that client until the whole
session closes.
Yes, I agree that release is good for early indication that a message is
not required, and would be useful for handling MessageConsumer.close().
As the ack is a key reliability mechanism, allowing arbitrary DLQ
decisions based on unacked deliveries seems to me to undermine the
ack-based reliability model.
It's not arbitrary. An ack informs you that a message has been
processed, but you can't infer one way or another from the absence of
an ack, therefore you *have* to deal with the possibility that these
messages have been processed already regardless of whether you do it
by setting the redelivered flag or by DLQing the message.
What seems arbitrary is the decision to either leave it on the original
queue with the redelivered flag set or DLQ the message. Its the latter
option I'm against; I don't think its valid behaviour.
Either way I don't think it's acceptable for a routine close of a
consumer to cause redelivery of a slew of messages that may already
have been processed. It would, for example, be unacceptable to any
application that requires human intervention to deal with redelivered
messages.
I agree that minimising the number of messages that the broker marks as
redelivered is desirable. As I said in the first mail I also think that
release is a valuable addition to cater for the case where there is no
ambiguity about processed state. My original point was that I didn't see
much benefit in retrofitting it to older versions of the protocol.
I would state this a bit more strongly. In my view normal open/close of
sessions and consumers should never cause redelivery of messages. C-c,
kill -9, network outages are all another matter of course, but IMHO
session.close() or consumer.close() is the thing that you try *before*
resorting to C-c or kill -9.
(Btw, we have been talking about session.close here aren't we? i.e. not
MessageConsumer.close() which would I think be a better place for
handling any releasing).
They are pretty much the same. Session.close() is defined the same way
as MessageConsumer.close() except it operates on all MessageConsumers,
not just the one.
[...]
In the case of the no-ack mode, the whole aim is to allow
optimisation of the case where redelivery is not required (e.g.
often where a client has its own exclusive queue representing a
subscription).
That's a good point. Releasing prefetched messages in no-ack mode
won't actually do anything since they may have already been
discarded. Given that I would fall back to processing all prefetched
messages in the case of no-ack and letting the user choose to throw
them away if that is appropriate for the application.
I think by closing the session the application is saying it wants to
quit. Perhaps the close on the MessageConsumer could do something
like this... i.e. don't return from that close until all the messages
have been pumped through the listener?
I think this would be reasonable if you wanted to avoid back-porting
release to 0-8, but as the code already mis-uses reject to indicate
release, I'm not sure there is much point to avoiding it.
My point was that MessageConsumer.close would perhaps be a better place
to try and handle the closing of consumer state (being under the
assumption that the debate thus far had been focused on Session.close()).
Yes, I think the JMS semantics pretty much imply that Session.close()
calls MessageConsumer.close() for all open consumers on the session.
However I don't think that retrofitting release is any better than using
reject in a way that may not be portable. Neither cases is guaranteed to
work with other brokers, but adding a new method seems even less likely
to be interoperable.
The idea is to fail fast rather than fail subtly by using reject in a
non standard way. For interoperability I think that continuing to
process prefetched messages is the way to go.
--Rafael