Активное задание Rails: Perform_later не выполняется в фоновом режиме

У меня есть длительная задача, которую нужно запустить в фоновом режиме в моем приложении Rails 4.2.6. К сожалению, задание не отправляется в фоновый режим с помощью Active Job. Я создал задание:

class PhotoProcessorJob < ActiveJob::Base
  queue_as :default
  def perform(*args)
    ::Photo.process_photos
  end
end

который вызывает метод моего класса Photo (хранится в config/initializers):

class Photo
  require 'zxing'
  require 'csv'

  @tablePath = Dir.glob("#{Rails.root.to_s}/tmp/photo_processing/*.csv")[0]
  @output = "#{Rails.root.to_s}/tmp/photo_data.csv"

  def self.getStudentInfo(id)
    CSV.foreach(@tablePath, headers: true) do |row|
      if row["Student ID"] == id
        return row
      else
        next
      end
    end
  end

  def self.writeInfoToFile(data, file)
    first_name = data["First Name"]
    last_name = data["Last Name"]
    student_id = data["Student ID"]
    grade = data["Grade"]
    email = data["Email"]
    photo = file.to_s
    CSV.open(@output, "a+") do |csv|
      csv << [first_name, last_name, student_id, grade, email, photo]
    end
  end

  def self.process_photos
    extensions = %w(.jpg .jpeg .png .gif .tif)
    studentInfo = nil
    newfile = false
    if File.exist?(@output)
      outfile = CSV.new(File.read(@output))
      if outfile.count == 0
        newfile = true
      end
    else
      newfile = true
    end
    if newfile
      CSV.open(@output, "wb") do |csv|
        csv << ["First Name", "Last Name", "Student ID", "Grade", "Email", "Photo"]
      end
    end
    Dir.glob("#{Rails.root.to_s}/tmp/photo_processing/*").each do |file|
      if file.match(/#{extensions.join("|")}/)
        id = ZXing.decode File.new(file)
        unless id.nil?
          studentInfo = getStudentInfo(id)
        else
          writeInfoToFile(studentInfo, file) unless studentInfo.nil?
        end
      end
    end
  end

end

и вызывается из контроллера:

class ProcessingController < ApplicationController
  def finish
    PhotoProcessorJob.perform_later
  end
end

Я пытаюсь использовать бэкэнд Active Job Inline, поэтому у меня нет установленных библиотек очередей. Проблема в том, что представление "finish" задерживается, пока работает метод process_photos, а не отправляется в фоновый режим, а представление отображается немедленно. Это приводит к ошибке 502 в Nginx, вызванной upstream prematurely closed connection предположительно из-за того, что задача process_photos выполняется слишком долго.

Я сделал что-то не так с настройкой Active Job?


person aperture    schedule 23.05.2016    source источник


Ответы (2)


Чтобы процитировать документы:

Rails по умолчанию поставляется с реализацией очереди «немедленного запуска». Это означает, что каждое поставленное в очередь задание будет выполняться немедленно.

Это означает, что по умолчанию активное задание будет выполняться в основном потоке, а не в «фоновом режиме». Это обычная ошибка. По сути, активное задание — это просто общий API для нескольких бэкэндов очередей.

TL; DR Вам нужно настроить серверную очередь, например Sidekiq.

В остальном ваша установка выглядит великолепно, даже как учебник.

person Chase    schedule 23.05.2016
comment
Понятно, спасибо. Я неправильно понял строку немедленного исполнения. Настройка delayed_job и добавление config.active_job.queue_adapter = :delayed_job в config/application.rb работают успешно. - person aperture; 24.05.2016
comment
Да, доки могли бы быть получше, а API мне кажется немного волшебным. Ознакомьтесь с этим замечательным сообщением в блоге blog.codeship.com/how-to. -use-rails-active-job Ли Холлидей из CodeShip - person Chase; 24.05.2016

В моем случае я просто забыл запустить sidekiq с помощью:

bundle exec sidekiq

Надеюсь, это поможет кому-то еще

person Sergio Gonzalez    schedule 07.03.2020