Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multiple concurrency keys #182

Open
wnm opened this issue Mar 22, 2024 · 5 comments
Open

Multiple concurrency keys #182

wnm opened this issue Mar 22, 2024 · 5 comments

Comments

@wnm
Copy link

wnm commented Mar 22, 2024

We are migrating to Solid Queue and trying to find out how to support our use case:

We currently use sidekiq and a custom currency control that makes sure there is always 1 job running per customer, and only 1 job with the same arguments. We do this by having multiple concurrency keys, and I was hoping I could do something similiar with Solid Queue, eg:

class FirstJob < ApplicationJob
  # make sure only 1 job per customer across all jobs
  limits_concurrency to: 1, key: ->(customer) group: "CustomerJobs"
  # make sure only 1 job with the same arguments
  limits_concurrency to: 1, key: ->(customer, project, other_argument)

class SecondJob < ApplicationJob
  limits_concurrency to: 1, key: ->(customer) group: "CustomerJobs"
  limits_concurrency to: 1, key: ->(customer, mailbox, other_argument)

If I understood correctly, there is only one concurrency key per job in Solid Queue? Would I be able to do it in another way? Thanks in advance! ❤️

@rosa
Copy link
Member

rosa commented Mar 22, 2024

If I understood correctly, there is only one concurrency key per job in Solid Queue?

Yes, that's right, you can only specify a single concurrency key per job.

Would I be able to do it in another way?

🤔 It depends on your case, but would it work just to limit on the customer? For example, if you have FirstJob enqueued with customer ID 1, you can't have SecondJob enqueued with customer ID 1, but also you can't have another FirstJob enqueued with the same arguments because the customer would be included in those arguments.

@wnm
Copy link
Author

wnm commented Mar 22, 2024

If I understood correctly, there is only one concurrency key per job in Solid Queue?

Yes, that's right, you can only specify a single concurrency key per job.

Would I be able to do it in another way?

🤔 It depends on your case, but would it work just to limit on the customer? For example, if you have FirstJob enqueued with customer ID 1, you can't have SecondJob enqueued with customer ID 1, but also you can't have another FirstJob enqueued with the same arguments because the customer would be included in those arguments.

In terms of concurrency yes, that would be enough. But we are using one concurrency key to make sure identical jobs don't even get enqueued, just to not do unneccessary work, similar to the on_conflict: :discard you were thinking about in #176

So maybe my question isn't about multiple concurrency keys, but rather how do I make sure to not enqueue duplicate jobs. And maybe #105 will solve this!

@rosa
Copy link
Member

rosa commented Mar 22, 2024

Ahh got it. I think #176 might not quite work for your case, then, because it'd still be just with a single concurrency key; the only difference would be that you could choose what to do if more than one job is enqueued, but either by all arguments or by the customer. For Solid Queue, I think having more than one concurrency key per job adds too much overhead in the way this is implemented with semaphores (the best way we could come up with, considering our database constraints), so I don't see that being added in the near future, at least not in the way this works now 😞

@rosa
Copy link
Member

rosa commented Mar 22, 2024

About #105, yeah, that would work if we do something else, different to #176. I still haven't made up my mind on that one 😅 For example, in your case, if a job is scheduled in the future, do you allow other jobs to be enqueued with the same arguments before that other job is due? Or is it not allowed at all, even if the scheduled job is not due yet?

@nhorton
Copy link

nhorton commented May 1, 2024

@rosa - maybe it is worth designing in public on this.

For handling of your above situation, my implementation instinctively would be:
Have a uniqueness_key method on the job classes that you use to generate a key at enqueue that is put into a DB column, then have either explicit match only or, somewhat better, support for an Arel statement so people could do complex stuff like OR conditions on the string. The default could include all params including queue and perform_at timing or exclude those attributes - either is fine - as users could implement different versions as needed. This would also allow one to specify different queries to use on the key for handling of enqueue conflicts and dequeueing / performing conflicts.

In the future, one could easily wrap the above with some syntactic sugar to handle common cases.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants