[ https://issues.apache.org/jira/browse/ARTEMIS-3949?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17583082#comment-17583082 ]
Robbie Gemmell commented on ARTEMIS-3949: ----------------------------------------- Since a session is to be used single threaded, as mentioned before that means that if you are using a consumer handler/listener callback the entire session (and all its producers + consumers) also becomes dedicated to the handler/listener callback thread of the session, which thus also becomes the only thread allowed to acknowledge. That means you dont need to know the session or the originally subscribing thread in your handler/listener since the thread delivering the message to it is the only one allowed to acknowledge, or do anything else on the session+children (except for close). If you need concurrent processing of listeners you can use multiple sessions, this giving them distinct delivery processing. Alternatively you could skip handlers and create multiple sessions+recievers on their own threads and call the consumer receive method(s) to get messages and later ack after processing them. Or you could use a single thread to call receive on one/many consumers and then dispatch details to other threads for processing, and then coordinate return to the thread operating the session/consumers so it can acknowledge messages. Yes, users need to understand the threading model. Also, regardless of the approach you should be careful with acknowledge() itself; it doesnt do what it seems you maybe think it does. The acknowledge() method actually acks *all* previously delivered messages on a session, not just the specific message it is called on (this bizareness is as per JMS Client Acknowledge mode...though vendors often have specific extended ack modes for individual-ack). It looks like the Core Message exposes an individualAcknowledge() method that may be more akin to what you are after. > Internally synchronize methods in ClientSession implementations > --------------------------------------------------------------- > > Key: ARTEMIS-3949 > URL: https://issues.apache.org/jira/browse/ARTEMIS-3949 > Project: ActiveMQ Artemis > Issue Type: Improvement > Affects Versions: 2.24.0 > Reporter: Peter Machon > Priority: Major > > {{ClientSessionImpl}} has two internal functions i.e. {{startCall}} and > {{{}endCall{}}}. These function count concurrent access and throw in case of > concurrent access. > They are used e.g. in {{{}ClientProducerImpl{}}}s {{doSend}} method and in > the {{ClientSessionImpls}} {{acknowledge}} method. > This forces user code to synchronize the use of the session object. That is a > pain for two reasons: > 1. From a user perspective it is not even clear, which methods are internally > counting concurrent access. E.g. the `doSend` method does not even belong to > the session. > 2. The session object is not accessible from the user code at any time. E.g. > the {{ClientMessageImpl}} internally uses the {{{}ClientSession{}}}s > {{acknowledge}} method. From user code it is not necessarily clear which > session the `ClientMessage` belongs to. > Thus, it would require user code to e.g. implement their own message store > just to be able to synchronize the right session. > Solution: > The {{ClientSessionImpl}} and all other internal objects like > {{{}ClientProducerImpl, ClientMessageImpl{}}}, and similar have full access > and knowledge about their synchronization needs. > I thus suggest to implement synchronization where needed instead of leaving > the user alone with this issue, where the solution actually means to > reimplement a lot of functionality of the client. > E.g. > {{startCall();}} > {{try {}} > {{sessionContext.sendACK(false, blockOnAcknowledge, consumer, message);}} > {{} finally {}} > {{endCall();}} > > could be replaced with something like > {{synchronized(this) {}} > {{sessionContext.sendACK(false, blockOnAcknowledge, consumer, message);}} > {{} }} > -- This message was sent by Atlassian Jira (v8.20.10#820010)