这个bug是在使用delay_job(2.1.2)查出来的,后来google了一下,发现已经有人提交了这个问题
delay_job中如果有失败任务的话,后台会一直不停的运行失败任务
源代码修改,加注释的为原来的代码,注释后的为自己添加的修改代码
# Reserve a single job in a single update query. This causes workers to serialize on the
# database and avoids contention.
def self.reserve(worker, max_run_time = Worker.max_run_time)
# affected_rows = 0
# ::ActiveRecord::Base.silence do
# affected_rows = jobs_available_to_worker(worker.name, max_run_time).limit(1).update_all(["locked_at = ?, locked_by = ?", db_time_now, worker.name])
# end
# if affected_rows == 1
# locked_by_worker(worker.name, max_run_time).first
# else
# nil
# end
#修改代码start
success = false
::ActiveRecord::Base.silence do
available_job = jobs_available_to_worker(worker.name, max_run_time).first
success = available_job.update_attributes(:locked_at => db_time_now, :locked_by => worker.name) if available_job
end
if success
locked_by_worker(worker.name, max_run_time).first
else
nil
end
#修改代码end
end
引起的原因就是,那个update_all了。因为update_all前有limit处理,这样limit前的所有条件就会失效了,这样返回的结果就会始终有一个正在处理的任务。
[1]https://rails.lighthouseapp.com/projects/8994/tickets/6058-update_all-ignores-conditions-when-orders-and-limit-options-are-supplied