Sidekiq: Ensure all jobs on the queue are unique

前端 未结 4 758
醉话见心
醉话见心 2020-12-13 22:24

I have some update triggers which push jobs onto the Sidekiq queue. So in some cases, there can be multiple jobs to process the same object.

There are a couple of un

相关标签:
4条回答
  • 2020-12-13 23:12

    Take a look at this: https://github.com/mhenrixon/sidekiq-unique-jobs

    It's sidekiq with unique jobs added

    0 讨论(0)
  • 2020-12-13 23:22

    Maybe you could use Queue Classic which enqueues jobs on a Postgres database (in a really open way), so it could be extended (open-source) to check for uniqueness before doing so.

    0 讨论(0)
  • 2020-12-13 23:31

    My suggestion is to search for prior scheduled jobs based on some select criteria and delete, before scheduling a new one. This has been useful for me when i want a single scheduled job for a particular Object, and/or one of its methods.

    Some example methods in this context:

     find_jobs_for_object_by_method(klass, method)
    
      jobs = Sidekiq::ScheduledSet.new
    
      jobs.select { |job|
        job.klass == 'Sidekiq::Extensions::DelayedClass' &&
            ((job_klass, job_method, args) = YAML.load(job.args[0])) &&
            job_klass == klass &&
            job_method == method
      }
    
    end
    
    ##
    # delete job(s) specific to a particular class,method,particular record
    # will only remove djs on an object for that method
    #
    def self.delete_jobs_for_object_by_method(klass, method, id)
    
      jobs = Sidekiq::ScheduledSet.new
      jobs.select do |job|
        job.klass == 'Sidekiq::Extensions::DelayedClass' &&
            ((job_klass, job_method, args) = YAML.load(job.args[0])) &&
            job_klass == klass &&
            job_method == method  &&
            args[0] == id
      end.map(&:delete)
    
    end
    
    ##
    # delete job(s) specific to a particular class and particular record
    # will remove any djs on that Object
    #
    def self.delete_jobs_for_object(klass, id)
    
      jobs = Sidekiq::ScheduledSet.new
      jobs.select do |job|
        job.klass == 'Sidekiq::Extensions::DelayedClass' &&
            ((job_klass, job_method, args) = YAML.load(job.args[0])) &&
            job_klass == klass &&
            args[0] == id
      end.map(&:delete)
    
    end
    
    0 讨论(0)
  • 2020-12-13 23:31

    What about a simple client middleware?

    module Sidekiq
      class UniqueMiddleware
    
        def call(worker_class, msg, queue_name, redis_pool)
          if msg["unique"]
            queue = Sidekiq::Queue.new(queue_name)
            queue.each do |job|
              if job.klass == msg['class'] && job.args == msg['args']
                return false
              end
            end
          end
    
          yield
    
        end
      end
    end
    

    Just register it

      Sidekiq.configure_client do |config|
        config.client_middleware do |chain|
          chain.add Sidekiq::UniqueMiddleware
        end
      end
    

    Then in your job just set unique: true in sidekiq_options when needed

    0 讨论(0)
提交回复
热议问题