【问题标题】:How to achieve sequential processing in Rails?在 Rails 中如何实现顺序处理?
【发布时间】:2016-11-23 12:37:05
【问题描述】:

我有一项任务必须按顺序执行。主要是写数据库。

问题是我很难在 Rails 5 中实现它。

我在 ActiveJob 任务中实现它。首先我尝试了互斥锁:

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

我也遇到了同样的奇怪行为。我在 Controller 而不是ActiveJob 中尝试了相同的方法。相同:ActiveRecord 查询处的死锁。

你们知道在 Rails 应用程序中按顺序执行任务的方法吗?创建临界区的正确方法?

也许有ActiveJob 队列适配器,它是单线程的,没有上下文切换等?我不想在我的简单应用中添加 redis 或其他东西。

【问题讨论】:

    标签: ruby-on-rails ruby multithreading activerecord rails-activejob


    【解决方案1】:

    在仍然使用 ActiveJob(或任何异步作业框架)的同时,您可能实现此目的的唯一方法是将作业分解为多个单独的作业,其中第一个工作将下一个工作作为另一个作业排入队列。或者您必须将作业的进度状态存储在其他数据存储中,以便每个作业都可以检查之前的作业是否已完成。

    互斥锁不起作用,因为作业可能在不同的进程/线程中运行,或者在完全不同的时间运行,具体取决于您的资源。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-03-05
      • 1970-01-01
      • 2015-02-10
      • 1970-01-01
      • 2016-08-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多