我不是专家,但是我数小时的谷歌搜索和堆栈溢出并没有给我解决问题的答案,因此我决定提出自己的问题。
我正在使用Ruby on Rails 5,正在尝试在AWS上使用Cloud9 IDE。该应用是使用Heroku部署的,该请求的HTTP请求超时时间为30秒。我需要从html.erb文件中生成一个PDF,该文件中包含很多逻辑和查询,因此通常需要100秒左右的时间才能完成,并且由于它发生在控制器中,因此被视为HTTP请求,并且需要少于30秒的时间或作为后台过程完成。如果您知道另一种解决Heroku 30秒HTTP请求超时的方法,请告诉我。
我在另一篇文章中对此进行了询问,并得到了反馈,以尝试使用带有Rails的Sidekiq之类的东西来处理大量过程,而不是通过HTTP请求进行尝试。这里的想法是将其放在后台请求中,并使其在整个100秒钟内完成其工作,然后以某种方式将PDF返回给最终用户(例如自动下载PDF)。我决定去做,让我的代码工作到可以同时运行Redis服务器(Sidekiq需要),Sidekiq服务器和常用的Rails服务器的地步,以允许我从中加载和渲染PDF。 Sidekiq工作者而不是控制器。
我的问题是'render'方法在工作人员中不可用!我试图通过使用直接从源中访问它
av = ActionView::Base.new()
接着
av.render #pdf code here
但是在我的Sidekiq控制台中出现以下错误:
“ WARN:NameError:未初始化的常量PDFWorker :: ActionView”
我的控制器中的代码:
# /app/controllers/recentgrad_controller.rb
require 'sidekiq'
require "redis"
class RecentgradController < ApplicationController
def report
# things that prepare the name of the pdf, etc. go here
PDFWorker.perform_async(pdf_name, pdf_year)
redirect_to emphs_path
end
end
我的工作人员中的代码:
# /app/workers/pdf_worker.rb
Sidekiq.configure_client do |config|
# config.redis = { db: 1 }
config.redis = { url: 'redis://172.31.6.51:6379/0' }
end
Sidekiq.configure_server do |config|
# config.redis = { db: 1 }
config.redis = { url: 'redis://172.31.6.51:6379/0' }
end
class PDFWorker
include Sidekiq::Worker
sidekiq_options retry: false
def perform(pdf_name, pdf_year)
# create an instance of ActionView, so we can use the render method outside of a controller
av = ActionView::Base.new() # THIS is where the error comes from
av.view_paths = ActionController::Base.view_paths
av.class_eval do
include ActionController::UrlWriter
include ApplicationHelper
end
av.render pdf: "mypdf",
disposition: 'attachment',
page_height: 1300,
encoding: 'utf8',
page_size: 'A4',
footer: {html: {template: 'recent_grad/footer.html.erb'}, spacing: 0 },
margin: { top: 10, # default 10 (mm)
bottom: 20,
left: 10,
right: 10 },
template: "recent_grad/report.html.erb",
locals: {start: @start, survey: @survey, years: @years, college: @college, department: @department, program: @program, emphasis: @emphasis, questions: @questions}
end
end
运行生成PDF的程序部分时出现错误:
WARN: NameError: uninitialized constant PDFWorker::ActionView
答案 0 :(得分:0)
Sidekiq作业不是控制器操作,它没有隐式状态,例如参数,查询字符串,请求标头,Cookie等。
您可能会发现直接渲染模板更简单。我不确定您要使用什么将HTML输出转换为PDF,我在系统中使用wkhtmltopdf
。这是我呈现一个简单的HTML ERB模板并将其转换为PDF的方式,以便我可以通过电子邮件将其发送给客户。
require 'erb'
localvar = "this is visible to the template"
content = ERB.new(File.read("some_template.html.erb")).result(binding)
tmpf = Tempfile.new(['sometemplate', '.html'])
tmpf.write(content)
tmpf.close
result = `wkhtmltopdf #{tmpf.path} #{tmpf.path}.pdf 2>&1`
raise result if $?.exitstatus != 0
答案 1 :(得分:0)
事实证明,使用作业而不是使用工作程序要容易得多,因为作业使您可以使用从free(): invalid pointer
继承的render函数。
这里真正的赢家是@unixmonkey,他是邪恶的pdf for rails的创建者,他为我安装了一个可运行的应用程序。您可以在这里看到问题:https://github.com/mileszs/wicked_pdf/issues/835
可以在这里查看真正改变其工作方式的提交: https://github.com/unixmonkey/generate_pdf_async_example/commit/85e8dcd98fe6580a8692842fcc5316b931ce4eea
享受!