Как запустить фоновую задачу в Синатре, чтобы избежать Heroku 30 секунд тайм-аут - PullRequest
0 голосов
/ 02 марта 2020

Я создаю приложение Sinatra для обработки PDF-файлов с использованием Ghostscript, однако, когда я отправил его в Heroku, оно истекло, потому что Ghostscript обрабатывает PDF более 30 секунд.

Мне нужен способ, чтобы либо запустить команду Ghostscript в фоновом режиме и покажите индикатор загрузки, пока он не будет выполнен, или же мне нужно постоянно пинговать сервер, пока обработка не будет завершена. Я искал пару недель, как это сделать, и ничего не помогло.

Это мое 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 я попробовал несколько способов обработки PDF с помощью Ghostscript, и ничто не ускорило его настолько, чтобы оказаться в пределах этого 30-секундного перерыва на Heroku. Я даже пытался проверить success? Process::Status (что и обеспечивает самоцвет gs- ruby), но к тому времени, когда он даже достиг этого блока, он уже обработал и уже слишком поздно.

Локально это работает, только в Heroku происходит сбой, потому что обработка заняла слишком много времени.

1 Ответ

0 голосов
/ 16 марта 2020

Я рекомендую вам использовать DelayedJob (https://github.com/collectiveidea/delayed_job). Это самый простой процессор фоновых заданий, который вы можете настроить с учетом вашей архитектуры, и для хранения и обработки заданий ему требуется только база данных.

...