我有一个后台工作,在MongoDB上执行map / reduce作业。当用户向文档发送更多数据时,它会踢出在文档上运行的后台作业。如果用户发送多个请求,它将启动同一文档的多个后台作业,但只有一个真正需要运行。有没有办法可以阻止多个重复的实例?我正在考虑为每个文档创建一个队列,并确保在我提交新作业之前它是空的。或者也许我可以设置一个与我的文档ID相同的作业ID,并在提交之前检查它们是否存在?
另外,我刚刚找到了一个sidekiq-unique-jobs gem。但文档不存在。这样做我想要的吗?
答案 0 :(得分:12)
我最初的建议是这个特定工作的互斥量。但是,由于你可能有多个应用程序服务器在使用sidekiq作业,我建议在redis级别使用。
例如,在sidekiq worker定义中使用redis-semaphore。 未经测试的示例:
def perform
s = Redis::Semaphore.new(:map_reduce_semaphore, connection: "localhost")
# verify that this sidekiq worker is the first to reach this semaphore.
unless s.locked?
# auto-unlocks in 90 seconds. set to what is reasonable for your worker.
s.lock(90)
your_map_reduce()
s.unlock
end
end
def your_map_reduce
# ...
end
答案 1 :(得分:6)
https://github.com/krasnoukhov/sidekiq-middleware
UniqueJobs 为工作提供独特性。
用法
示例工人:
class UniqueWorker
include Sidekiq::Worker
sidekiq_options({
# Should be set to true (enables uniqueness for async jobs)
# or :all (enables uniqueness for both async and scheduled jobs)
unique: :all,
# Unique expiration (optional, default is 30 minutes)
# For scheduled jobs calculates automatically based on schedule time and expiration period
expiration: 24 * 60 * 60
})
def perform
# Your code goes here
end
end
答案 2 :(得分:1)
还有https://github.com/mhenrixon/sidekiq-unique-jobs(SidekiqUniqueJobs)。
答案 3 :(得分:0)
您可以执行此操作,假设您已将所有作业添加到排队存储桶中。
class SidekiqUniqChecker
def self.perform_unique_async(action, model_name, id)
key = "#{action}:#{model_name}:#{id}"
queue = Sidekiq::Queue.new('elasticsearch')
queue.each { |q| return if q.args.join(':') == key }
Indexer.perform_async(action, model_name, id)
end
end
以上代码仅是示例,但您可以根据需要进行调整。