Object variables in multithreaded Sneaker works like a global mutable data
Ronaq13 opened this issue · 1 comments
I have a sneaker worker(given below) as a backend of a chatbot.
class RabbitMQWorker
include Sneakers::Worker
from_queue "message"
def work(options)
parsed_options = JSON.parse(options)
# Initializing some object variables
@question_id = parsed_options[:question_id]
@answer = parsed_option[:answer]
@session_id = parsed_option[:session_id]
ActiveRecord::Base.connection_pool.with_connection do
# send next question to the session_id based on answer
end
ack!
end
end
What's happening
The problem I am facing here is that when I run sneaker with more than 1 thread and multiple users are chatting at the same time, then the ampq event which comes slightly later cause to override the @session_id
and as a result, the second user gets two questions and the first one gets none. This happens because by the time 1st event is getting process the second event came and override @session_id. Now when it's time to send the next question to the first user by using @session_id, the question get's send to the second user.
My Questions
- Do the
work
method and anyinstance variables
I create in it works like global mutable data for sneaker's threads? - If yes then I am guessing I need to make them as thread-local variables. If I do that, then do I need to make these changes deep down in my Rails logic as well? As this worker works with Rails.
Curiosity question
How does Puma manage these things? It is a multi-threaded app server and we use instance variables in controllers and it manages to serve multiple requests simultaneously. Does it mean that Puma handles this multi-contexting implicitly and Sneakers don't?
What I have done till now
- I read the documentation of Sneaker and couldn't found anything regarding this.
- I perform load tests to verify the problem and it is the problem as I stated above.
- I tried getting my logic clear on how actually multi-threading works but everywhere there is only general stuff. The curiosity question I asked above will help a lot in terms of clearing the concepts, I am searching for an explanation of it for days but couldn't found any.
Any naturally shared mutable state in your consumer/worker code will be shared by Sneakers threads. How to use thread-local variables or other concurrency primitives in Ruby is a great question for the Ruby mailing list, there isn't anything Sneakers-specific about that.