Reputation:
I want to perform some tasks in background but with something like "run as". In other words, like a task was launched by the user from the context of his session.
Something like
def perform
env['warden'].set_user(@task_owner_user)
MyService::current_user_dependent_method
end
but I'm not sure it' won't collide with other tasks. I'm not very familiar with Sidekiq. Can I safely perform separate tasks, each with a different user context, somehow?
Upvotes: 0
Views: 1382
Reputation: 22208
The proper design is to use a server-side middleware + a thread local variable to set the current user context per job.
class MyServerMiddlware
def call(worker, message, queue)
Thread.current[:current_user] = message['uid'] if message['uid']
yield
ensure
Thread.current[:current_user] = nil
end
end
You'd create a client-side middleware to capture the current uid and put it in the message. In this way, the logic is encapsulated distinctly from any one type of Worker. Read more:
https://github.com/mperham/sidekiq/wiki/Middleware
Upvotes: 2
Reputation: 3451
I'm not sure what your shooting for with the "run as" context, but I've always setup sidekiq jobs that need a unique object by passing the id in the perform. This way the worker always knows which object it is trying to work on. Maybe this is what you're looking for?
def perform id
user = User.find(id)
user.current_user_dependent_method
end
Then setup a route in a controller for triggering this worker to start, something like:
def custom_route_for_performing_job
@users= User.where(your_conditions)
@users.each do |user|
YourWorker.perform_async user.id
end
redirect_to :back, notice: "Starting background job for users_dependent_method"
end
Upvotes: 2