如何在Sinatra中运行后台任务以避免Heroku 30秒的时间限制

问题描述 投票:0回答:1

我正在构建一个使用Ghostscript处理PDF的Sinatra应用程序,但是当我将其推送到Heroku时,它超时了,因为Ghostscript处理PDF所需的时间超过30秒。

我需要一种方法在后台运行Ghostscript命令并显示加载指示符,直到完成为止,否则,我需要连续ping服务器,直到处理完成。我搜索了几个星期以完成此操作,但没有任何效果。

这是我的POST操作:

post '/process_pdf' do
    unless params[:file] && params[:file][:tempfile] && params[:file][:filename]
      return erb :form
    end

    @filename = params[:file][:filename].gsub!(/[^0-9A-Za-z.]/, '')
    @output_file_name = "#{Time.now.strftime('%b_%d_%I_%M')}_#{@filename}"
    @file = params[:file][:tempfile]

    File.open("#{settings.root}/tmp/#{@filename}", 'wb') do |file|
      file.write(@file.read)
      file.close
    end

    # @pdf = GS.run("#{settings.root}/tmp/#{@filename}") do |command|
    #   command.option(GS::PDFA)
    #   command.option(GS::BATCH)
    #   command.option(GS::NO_PAUSE)
    #   command.option(GS::PROCESS_COLOR_MODEL, 'DeviceCMYK')
    #   command.option(GS::DEVICE, 'pdfwrite')
    #   command.option(GS::PDFA_COMPATIBILITY_POLICY, '1')
    #   command.option('CompatibilityLevel', '1.4')
    #   command.option('PDFSETTINGS', 'prepress')
    #   command.option(GS::OUTPUT_FILE,
    #                  "#{settings.root}/tmp/#{@output_file_name}")
    # end

    # until @pdf.success?
    #   puts 'loading...'
    #   sleep 1
    # end

    Kernel.system 'gs -dPDFA -dBATCH -dNOPAUSE'\
                  ' -sProcessColorModel=DeviceCMYK'\
                  ' -sDEVICE=pdfwrite -sPDFACompatibilityPolicy=1'\
                  ' -dCompatibilityLevel=1.4 -dPDFSETTINGS=/prepress'\
                  " -sOutputFile=#{settings.root}/tmp/#{@output_file_name}"\
                  " #{settings.root}/tmp/#{@filename}"

    erb :process_pdf
  end

并在处理完成后显示:

<!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
    <link rel="stylesheet" type="text/css" href="<%= url("/style.css")%>">
    <title>Processing PDF</title>
  </head>
  <body>
    <%= send_file "#{settings.root}/tmp/#{@output_file_name}" %>

    <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
  </body>
</html>

[在我的POST操作中,我尝试了多种使用Ghostscript处理PDF的方式,但没有加快速度以至于在Heroku的30秒超时时间内。我什至尝试检查success?Process::Status(这是gs-ruby gem所提供的),但是到它碰到那个块时,它已经处理完毕,已经来不及了。

这在本地可以正常工作,直到在Heroku上它失败,因为处理时间太长。

ruby heroku sinatra
1个回答
0
投票

我建议您使用DelayedJob(https://github.com/collectiveidea/delayed_job)。它是根据您的体系结构可以设置的最简单的后台作业处理器,它仅需要一个数据库即可存储和处理作业。

© www.soinside.com 2019 - 2024. All rights reserved.