【发布时间】:2021-03-07 16:38:13
【问题描述】:
我正在通过后台作业处理在Cloundinary 上上传 PDF 文件。我从after_save 回调中将它们排入队列。困境是,对于一次更新,我的后台作业会被多次触发。为了解决这个缺陷,我尝试使用around_perform 实现一种方法,以确保我的工作只会被触发一次。但实际上并没有奏效。我想知道你们中是否有人知道如何处理那些不需要的工作电话
这是我的代码
我的after_save回调
回调被放置在我的模型发票和报价单上。
Class Invoice
after_save :upload_pdf
def upload_pdf
UploadPdfJob.perform_later(self.id,'invoice')
new_notif_paid = Notification.create(user: self.user,
category: "PDF",
content: "Your PDF #{self.reference}
is available ",
element: "invoice",
element_id: self.id)
end
结束
我的工作UploadPDFJob
def perform(id, type)
create_pdf_copy(id, type)
end
def create_pdf_copy(id, type)
wicked = WickedPdf.new
value = type == 'invoice'? Invoice.find(id) : Quote.find(id)
template_path = type == 'invoice'? 'invoices/show': 'quotes/show.html.erb'
file_type = type == 'invoice'? 'facture': 'devis'
pdf_html = ApplicationController.render(
locals: {
current_user: value.user,
},
assigns: {
"#{type}": value,
format: 'pdf'
},
template: template_path,
layout: 'pdf'
)
pdf_file = wicked.pdf_from_string(pdf_html,
page_size: 'A4',
orientation: "portrait",
lowquality: true,
zoom: 0.9,
dpi: 75
)
tempfile = Tempfile.new("#{file_type}-#{value.id}.pdf")
File.open(tempfile.path, 'wb') do |file|
file << pdf_file
end
tempfile.close
unless pdf_file.blank?
value.photo.attach(io: File.open(tempfile.path), filename: "#{file_type}-#{value.id}.pdf")
end
end
我的around_perform
在这一部分中,我将我的实例放在一个名为 element 的变量中。
这个想法是,如果UploadPdfJob 作业不止一次排队。 PDF 只会上传一次。第一个作业将uploaded设置为true,然后第二个作业将在检查done后退出
around_perform do |job, block|
id = job.arguments.first
element = job.arguments.last == 'invoice'? Invoice.find(id) : Quote.find(id)
element.with_lock do
return if element.uploaded
if block.call
element.update(uploaded: true)
else
retry_job
end
end
另外,由于我不想在更新时触发回调,所以我尝试了这种方式。使用名为 start 的变量,它不依赖于我检索到的实例
around_perform do |job, block|
id = job.arguments.first
element = job.arguments.last == 'invoice'? Invoice.find(id) : Quote.find(id)
start = false
element.with_lock do
return if start == true
if block.call
start = true
else
retry_job
end
end
end
【问题讨论】:
-
它可能在不同的线程中排队,因此线程局部变量不够好。它也可能是由发生的多次保存触发的。您可能希望在数据库记录或相关表(如
pdf_generated)上创建一个布尔值,然后检查它以确定它是否应该运行。 -
我们能看到 after_save 回调吗?
-
@Unixmonkey,这正是我的第一个想法。在使用“保存”变量之前,我进行了迁移并使用了属性“上传”。我正在更新我的帖子,以便您可以清楚地看到它
-
@Schwern,我编辑了我的帖子。你现在可以看到了。
-
@DaviGo 是
after_save :upload_pdf吗?回调在哪个类上?得救的东西在哪里?我们需要推断的越少,就越容易回答这个问题。
标签: ruby-on-rails jobs sidekiq