Rails 活动作业:perform_later 未在后台执行
Rails Active Job: perform_later not executing in background
我的 Rails 4.2.6 应用程序需要在后台 运行 执行一项冗长的任务。不幸的是,作业没有使用 Active Job 发送到后台。我生成了一份工作:
class PhotoProcessorJob < ActiveJob::Base
queue_as :default
def perform(*args)
::Photo.process_photos
end
end
它在我的照片 class 上调用一个方法(存储在 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
方法 运行 时被延迟,而不是被发送到后台并立即显示视图。这导致 Nginx 中的 502 错误由 upstream prematurely closed connection
引起,大概是因为 process_photos
任务完成时间太长。
我的 Active Job 设置有问题吗?
引用文档:
Rails by default comes with an "immediate runner" queuing implementation. That means that each job that has been enqueued will run immediately.
这意味着默认情况下,活动作业将 运行 在主线程中,而不是在 "the background" 中。这是一个常见的问题。基本上活跃的工作只是跨多个排队后端的常见 API。
TL;DR 你必须设置一个像 Sidekiq 这样的排队后端。
否则,您的设置看起来很棒,甚至是教科书。
就我而言,我只是忘记了 运行 sidekiq 与:
bundle exec sidekiq
希望这对其他人有帮助
我的 Rails 4.2.6 应用程序需要在后台 运行 执行一项冗长的任务。不幸的是,作业没有使用 Active Job 发送到后台。我生成了一份工作:
class PhotoProcessorJob < ActiveJob::Base
queue_as :default
def perform(*args)
::Photo.process_photos
end
end
它在我的照片 class 上调用一个方法(存储在 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
方法 运行 时被延迟,而不是被发送到后台并立即显示视图。这导致 Nginx 中的 502 错误由 upstream prematurely closed connection
引起,大概是因为 process_photos
任务完成时间太长。
我的 Active Job 设置有问题吗?
引用文档:
Rails by default comes with an "immediate runner" queuing implementation. That means that each job that has been enqueued will run immediately.
这意味着默认情况下,活动作业将 运行 在主线程中,而不是在 "the background" 中。这是一个常见的问题。基本上活跃的工作只是跨多个排队后端的常见 API。
TL;DR 你必须设置一个像 Sidekiq 这样的排队后端。
否则,您的设置看起来很棒,甚至是教科书。
就我而言,我只是忘记了 运行 sidekiq 与:
bundle exec sidekiq
希望这对其他人有帮助