Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails Sidekiq:确保队列上的所有作业都是唯一的_Ruby On Rails_Ruby_Message Queue_Sidekiq - Fatal编程技术网

Ruby on rails Sidekiq:确保队列上的所有作业都是唯一的

Ruby on rails Sidekiq:确保队列上的所有作业都是唯一的,ruby-on-rails,ruby,message-queue,sidekiq,Ruby On Rails,Ruby,Message Queue,Sidekiq,我有一些更新触发器,可以将作业推到Sidekiq队列上。因此,在某些情况下,可以有多个作业来处理同一对象 有几个惟一性插件(,),它们没有太多的文档记录,但它们似乎更像是阻止重复处理的节流器;我想要的是一个阻止重复创建相同作业的节流器。这样,对象将始终以其最新状态进行处理。有没有一个插件或技术用于此 更新:我没有时间制作一个中间件,但我最终使用了一个相关的清理功能来确保队列是唯一的:看看这个: 这是添加了唯一作业的sidekiq也许你可以使用它将作业排在Postgres数据库中(以一种真正开放

我有一些更新触发器,可以将作业推到Sidekiq队列上。因此,在某些情况下,可以有多个作业来处理同一对象

有几个惟一性插件(,),它们没有太多的文档记录,但它们似乎更像是阻止重复处理的节流器;我想要的是一个阻止重复创建相同作业的节流器。这样,对象将始终以其最新状态进行处理。有没有一个插件或技术用于此


更新:我没有时间制作一个中间件,但我最终使用了一个相关的清理功能来确保队列是唯一的:

看看这个:


这是添加了唯一作业的sidekiq

也许你可以使用它将作业排在Postgres数据库中(以一种真正开放的方式),这样它就可以扩展(开源)以在这样做之前检查唯一性。

我的建议是,在安排新作业之前,根据一些选择条件搜索先前安排的作业并删除。当我想要为特定对象和/或其方法之一安排单个计划作业时,这对我很有用

此上下文中的一些示例方法:

 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

那么简单的客户端中间件呢

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
登记就行了

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

然后,在你的工作中,只要在需要时在sidekiq_选项中设置
unique:true

我在问题中提到了这一点。它有很好的文档记录,详细说明了在我看来,它在处理时检查唯一性,而不是排队时。但是文档没有明确说明。我们使用sidekiq unique jobs 2.7.0,它在排队时工作。只需在工作人员的
sidekiq\u选项中设置
unique\u job\u expiration
,并将其设置为作业平均执行时间的倍数。示例:您的作业每分钟排定一次,需要20秒才能完成,请使用
sidekiq_选项队列:unique,unique_job_expiration:40
这种方式,如果sidekiq试图在这40秒内将作业重新排队,则不会产生任何效果。@aledalgrande谢谢,但我不需要基于时间的过期。我想要一种方法,当Sidekiq尝试排队时,检查作业是否存在,如果存在,则什么也不做;但如果它不存在,请将其排队。我猜一个插件可能需要维护所有作业的散列才能有效地完成它。不是说troll,而是Sidekiq的一个假设是作业是幂等的,这正是您所抱怨的问题。我不担心重复作业会导致一些不必要的后果;我担心表现。相同的工作意味着浪费周期。e、 g.如果一个对象被更改,并且一个作业被添加到队列中,那么当作业仍然在队列中时,该对象再次更改,执行两个相同的作业是没有意义的。直觉告诉你这是一个优化问题还是一个证明性能瓶颈的基准测试?由于Sidekiq以非阻塞方式并发运行其作业,因此这些作业以很少的开销并行执行。执行一个查找唯一作业的操作可能会占用更多的周期,或者导致阻塞操作,这将使您的速度降低到线程中执行的多个重复操作的速度。再一次,你永远不会知道,直到你有基准。不管怎样,祝你好运!谢谢你,戴夫!当你说“很少的开销”时,你指的是Sidekiq的努力,但是如果工作本身需要大量的网络活动和繁重的工作,那么节省下来的成本是巨大的。我的意思是,这些工作之所以被推迟是有原因的,毕竟,其中一些工作可能会很繁重。对于任何混乱,很抱歉,我所说的小开销是指低内存配置文件和在后台操作环境下的非阻塞。Sidekiq也非常开放,很容易扩展tbh。谢谢,这不是一个完整的答案,但我认为这是最接近这一策略的。在我看来,这不是一个好的解决方案。它的时间复杂性是O(n),拥有后台作业处理器的全部目的是不延迟主线程的执行。然而,这个中间件可能会成为性能瓶颈,这取决于您的队列有多大。完全同意。这只是一个小队列的示例。任何大队列都需要使用基于作业参数的哈希查找,而不是这种迭代方法。