Question

I tried passing an small object to sidekiq, but it converts it to a hash. This object is a tracking object for mixpanel. I also tried accessing session variables in my Worker but they aren't available there either.

Thoughts?

Controller

MixpanelWorker.perform_async(@mixpanel, 'person', mixpanel_distinct_id, cleaned_params)

MixpanelWorker

  def perform(mixpanel_object, type_of_send, distinct_id, event)
    case type_of_send
    when 'person'
      mixpanel_object.people.set(distinct_id, event)
    when 'event'
      mixpanel_object.track(distinct_id, event)
    end
  end
Was it helpful?

Solution

Best way to approach the problem you are trying to solve is to save the object data in a database and then pass the id of @mixpanel to your MixpanelWorker job like so:

@mixpanel = Mixpanel.create [your parameters]
MixpanelWorker.perform_async @mixpanel.id, 'person', mixpanel_distinct_id, cleaned_params

Then your MixpanelWorker would handle the job like this:

def perform(mixpanel_id, type_of_send, distinct_id, event)
  mixpanel_object = Mixpanel.find mixpanel_id

  case type_of_send
   when 'person'
     mixpanel_object.people.set(distinct_id, event)
   when 'event'
     mixpanel_object.track(distinct_id, event)
  end
end

Also read the link that Mike Perham posted, I think he may know a little about Sidekiq ;).

OTHER TIPS

If you are looking for the way of passing object to sidekiq jobs by default without the need of updating args of every one of them then go with middleware approach.

Sidekiq provides client and server middleware:

  • client middleware runs custom logic before pushing the job in redis
  • server middleware runs before processing any sidekiq job

In code example below we pass current_user but it could be any request specific data, for example request trace_id:

class SidekiqClientMiddleware
  def call(_worker_class, job, _queue, _redis_pool = nil)
    # Set current user login in job payload
    if Thread.current[:current_user].present?
      job['current_user'] = Thread.current[:current_user]
    end
    yield
  end
end

class SidekiqServerMiddleware
  def call(_worker, job, _queue)
    if job.key?('current_user')
      set_current_user(job['current_user'])
    end

    yield
  end

  private

  def set_current_user(current_user)
    Thread.current[:current_user] = current_user
  end
end

Sidekiq.configure_client do |config|
  config.client_middleware do |chain|
    chain.add SidekiqClientMiddleware
  end
end

Sidekiq.configure_server do |config|
  config.client_middleware do |chain|
    # sidekiq job can call another sidekiq job in which case
    # sidekiq server itself will act as the client
    chain.add SidekiqClientMiddleware
  end
  config.server_middleware do |chain|
    chain.add SidekiqServerMiddleware
  end
end

Ref https://blog.bigbinary.com/2018/12/05/passing-current-user-by-default-in-sidekiq.html

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top