Object variables in multithreaded Sneaker works like a global mutable data

260 views Asked by At

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

  1. Do the work method and any instance variables I create in it works like global mutable data for sneaker's threads?
  2. 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

  1. I read the documentation of Sneaker and couldn't found anything regarding this.
  2. I perform a load tests to verify the problem and it is the problem as I stated above.
  3. 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.
1

There are 1 answers

1
rept On BEST ANSWER

After 2 days of searching for an issue where messages seemed to get mixed up I was finally able to solve this by removing all instance variables from my workers.

This thread gave me the clue to do so: https://github.com/jondot/sneakers/issues/244

maybe we should simply disallow instance variables in workers since changing the behavior to instantiate multiple worker instances might break existing code somehow

and:

I think that an instance per thread is the way to go.

So when you remove your instance variables you should be fine!