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

Most upvoted comments

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 the locals or the assigns options to do that.

I’ve added a commit showing how that works here.