我有一项必须以顺序方式执行的任务。数据库写作很简陋。
问题是我很难在Rails 5中实现它。
我正在class EventLoadJob < ApplicationJob
MUTEX = Mutex.new
rescue_from(StandardError) do |exception|
puts exception.to_s
end
def perform
MUTEX.synchronize
SomeModel.new.save!
end
end
end
任务中实现它。首先我尝试了互斥:
ActiveRecord
但这会导致死锁。假设:一个线程在临界区内,另一个在临界区输入。所以数据库查询的第一个线程块。它永远等待查询。我认为class EventLoadJob < ApplicationJob
rescue_from(StandardError) do |exception|
puts exception.to_s
end
def perform
File.open(Rails.root.join('tmp', 'event_mutex'), File::RDWR|File::CREAT, 0644) do |file|
file.flock(File::LOCK_EX)
SomeModel.new.save!
file.flock(File::LOCK_UN)
end
end
end
线程/连接存在问题 - 它以某种方式被阻止。但为什么呢?
我已尝试锁定文件:
ActiveJob
我得到了同样奇怪的行为。我在Controller而不是ActiveRecord
尝试过相同的操作。同样:ActiveJob
查询死锁。
你们知道在Rails应用程序中以顺序方式执行任务的方法吗?创建关键部分的正确方法?
也许有$file
队列适配器是单线程的,没有上下文切换等?我不想在我的简单应用程序中添加redis或其他内容。
答案 0 :(得分:1)
在使用ActiveJob(或任何异步作业框架)时,您可能实现此目的的唯一方法是将作业分解为多个单独的作业,其中第一项工作将下一项工作列为另一项工作。或者您必须通过其他数据存储中的作业存储进度状态,因此每个作业都可以检查以前的作业是否已完成。
互斥锁无法正常工作,因为作业可以在不同的进程/线程中运行,也可以在完全不同的时间运行,具体取决于您的资源。