-
Notifications
You must be signed in to change notification settings - Fork 80
Description
Is it possible/recommended to ack a message from a worker thread? I've been using a STOMP server (corporate ActiveMQ) and client acks ({ack: 'client-individual'}) to provide reliable receipt and storage of messages. So I'm receiving a STOMP message, storing it to an external service, and then acking the message. I'd like to not block the receive thread and increase the concurrency of the storage requests. As such, I created a thread pool to do the storage of the message and then ack the message, which should provide the guarantee that all messages that are acked to STOMP are also stored.
Unforutnately, I'm developing on a closed network, so the pseudo-code below is all constructed/simplified for this issue:
require 'stomp'
require 'concurrent'
@thread_pool = Concurrent::FixedThreadPool.new(5)
@client = Stomp.new
@client.subscribe('/topic/mytopic', :id => 'mytopic', :ack => 'client-individual') do |msg|
@thread_pool.post do
begin
store_to_external_service(msg)
ensure
@client.ack(msg)
end
end
end
loop do
sleep(10)
endThis seems to work fine in MRI. After a while, I needed to do a bit more work in the store_to_external_service, and MRI's parallelism was really lacking, so I attempted to switch to JRuby. When in JRuby, everything seems to chug along just fine to start, however the message receipt deadlocks after a few seconds, right after a @client.ack. When I eliminate the thread pool (and just do the storing/acking inline), no deadlocks are observed. If I use even one storage thread (@thread_pool = Concurrent::FixedThreadPool.new(1)), however, I get a deadlock after a few seconds of message receipt.
So, ultimate question ... is message acking threadsafe? Is it OK to ack a message from a thread other than the receive thread? Or am I doing something else boneheaded wrt the worker thread(s)?