wicked_pdf: 504 Gateway Timeout only when generating PDFs that take longer than 30 seconds
Issue description
I’m attempting to create a PDF for a large report that I’m working on dynamically using wicked pdf. The PDF generates beautifully when I create PDFs that only use a few lines of input data (for example I did one that used 125 lines of input data and it took about 25 seconds to create and looked amazing). However, when I have a lot of data it takes around 105 seconds to query the database and create the report from the report.html.erb file. I do exactly the same process as I do to create the 25 second PDF and I get a 504 gateway timeout error. The processing continues in puma which takes the full 105 seconds, and I get a 200 OK when it finishes.
I timed how long it takes for the 504 gateway timeout error to show up on the screen, and it takes around 35 seconds each time. I’m wondering if that’s the 30 second Heroku timeout for HTTP requests or something else.
I’ve attempted to put the render function in a Sidekiq worker class but the rails method “render” is not available there and I can’t figure out how to render the pdf in a different way.
The issue, in short, is that the 504 gateway timeout occurs when I attempt to render the PDF from a controller and I can’t figure out how to render it from the sidekiq worker instead because “render” isn’t available there.
System specifications
All of this is happening on my AWS Cloud9 IDE which is running on an EC2 instance (I think) but also may be running on Heroku somehow. That part baffles me (I inherited this project).
wicked_pdf gem version (output of cat Gemfile.lock | grep wicked_pdf
):
kmollinet:~/environment/gradSurvey (master) $ cat Gemfile.lock | grep wicked_pdf
remote: https://github.com/mileszs/wicked_pdf.git
wicked_pdf (1.4.0)
wicked_pdf (~> 1.1)!
wkhtmltopdf version (output of wkhtmltopdf --version
):
wkhtmltopdf 0.12.4 (with patched qt)
whtmltopdf provider gem and version if one is used: What does this mean???
platform/distribution and version (e.g. Windows 10 / Ubuntu 16.04 / Heroku cedar): I’m using a Windows 10 computer, but I believe this is running on Ubuntu
Code:
The code in the controller that takes either 25 seconds for small reports or 105 seconds for large ones and seems to work, but 504s out at times:
render pdf: pdf_name + " " + pdf_year.to_s,
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}
The code that is in my sidekiq to try to render the PDF from there instead:
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()
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
About this issue
- Original URL
- State: closed
- Created 5 years ago
- Comments: 16
You need to be able to pass those variables from the
render
method (now called in a Job instead of the Controller) into the template. You can use either thelocals
or theassigns
options to do that.I’ve added a commit showing how that works here.