We have a multi-tenant app that runs resque for background processing.
The issue we occasionally run into is when a single tenant performs a lot of background work within a very short period of time. This essentially clogs up the queue for a while -- every other tenant's jobs are delayed while we work through the backlog for this single tenant.
Yes, we can add more workers. But that's not really a "solution", it's more a band-aid that still results in a delay for other tenants -- just a shorter delay as we process faster.
Is there more multi-tenant friendly way to use resque? Or a more multi-tenant friendly background queue entirely?
We've looking at either:
- using a queue per tenant, and a worker per tenant (dynamically created queues?)
- modifying
resqueso that it somehow round-robins through a queue per tenant
We're just wondering if there's something we're missing / a better way...
You could use your
Rails.cacheto maintain temporary job counters for each participant and assign the job to different queues depending on the number of active jobs.You would need to subclass your jobs to support different queues and write a method that resolves to the correct class for the job. Something like:
and then call
Worker.queued(tenant_id).performwhen you are running the workers and make sure thatWorker.tenant_idis set onbefore_filtersin the application. See Resque Priorities and Queue Lists for more information on queues and priorities.You should call increment on job queue and decrement from within the job.
Ugly, but workable.
And can be made more dry by some metaprogramming - to extract these methods into a module and then make sure the queue subclasses are generated on module include.