Skip to content

Run jobs in sequence (run 1 job at a time) #687

@ArturT

Description

@ArturT

Is there a way to run 1 job at a time no matter what are the job's arguments?

Here is the use case.
I'd like to create multiple invoices via external API. They must be created in sequence to avoid duplicated invoice numbers.
The worker class creates 1 invoice based on arguments passed to perform method.

Current problem:
If many workers run concurrently then there is a risk that concurrent requests to external API are going to create duplicated invoice numbers. In order to avoid that I'd like to run jobs in sequence.

Possible solution
In order to run 1 job at a time (in sequence) I tried something like:

class MyWorker
  include Sidekiq::Worker
  sidekiq_options lock: :while_executing,
    lock_args_method: ->(args) { ['the-same-key-for-all-jobs'] },
    lock_timeout: nil,
    log_duplicate_payload: true,
    on_conflict: :reschedule

  def perform(amount)
     # create an invoice via external API
  end
end

But I'm getting this error: #686

Expected behavior:
Each job can have different arguments passed to perform method.
Each job should be executed.
No job should be skipped.
The job should be run in sequence. It's fine if they are rescheduled and put back to Redis queue, or they are run a bit later.

Do you think it's possible to use sidekiq-unique-jobs for this use case?

Or is it better to spin off a separate sidekiq process to run 1 thread and this way costume a queue in sequence? The worker class could assign job to a sequential queue name. Then the separate sidekiq process could consume the sequential queue name. The downside is that we need to spin off a separate sidekiq process and this is an extra cost.

Thanks

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions