Heroku: распаковка Gzip-файла через грабли не удалась - PullRequest
0 голосов
/ 13 июня 2018

Я использую Rails 5.2 с ruby ​​2.5.1 и развертываю мое приложение на Heroku .

У меня возникли проблемы, когда я попытался запустить локальную задачу rake.Задача вызывает API, который отвечает файлом *.gz, сохраняет его, архивирует, а затем использует извлеченный JSON для заполнения базы данных и, наконец, удаляет файл *.gz.Задача проходит гладко в разработке, но при вызове в производство.Последняя строка, напечатанная в консоли: «Разархивировать файл ...», поэтому я предполагаю, что проблемы происходят из библиотеки zlib.

companies_list.rake

require 'json'
require 'open-uri'
require 'zlib'
require 'openssl'
require 'action_view'

include ActionView::Helpers::DateHelper

desc 'Updates Company table'
task update_db: :environment do
  start = Time.now
  zip_file_url = 'https://example.com/api/download'

  TEMP_FILE_NAME = 'companies.gz'

  puts 'Creating folders...'

  tempdir = Dir.mktmpdir
  file_path = "#{tempdir}/#{TEMP_FILE_NAME}"

  puts 'Downloading the file...'

  open(file_path, 'wb') do |file|
    open(zip_file_url, { ssl_verify_mode: OpenSSL::SSL::VERIFY_NONE }) do |uri|
      file.write(uri.read)
    end
  end

  puts 'Download complete.'
  puts 'Unzipping the file...'

  gz = Zlib::GzipReader.new(open(file_path))
  output = gz.read
  @companies_array = JSON.parse(output)

  puts 'Unzipping complete.'

  (...)
end

Кто-нибудь еще сталкивался с подобными проблемами и знает, как заставить его работать?

Ответы [ 2 ]

0 голосов
/ 19 июля 2018

Проблема была связана с ограничением памяти, а не с распаковкой Gzip (поэтому проблема возникла только в производстве).

Решение было использовать Json::Streamer, чтобы весь файл не загружался в память приодин раз.

Это важная часть: (идет после кода, указанного в вопросе)

  puts 'Updating the Company table...'
  streamer = Json::Streamer.parser(file_io: file, chunk_size: 1024)  # customize your chunk_size
  streamer.get(nesting_level: 1) do |company|
    (do your stuff with the API data here...)
  end
end
0 голосов
/ 13 июня 2018

Ваш фрагмент кода не указывает на то, что вы когда-либо закрывали GzipReader.Часто лучше обернуть IO в блоки, чтобы убедиться, что они закрыты соответствующим образом.Кроме того, метод open может быть не тем, который вам нужен, поэтому просто позвольте GzipReader обработать открытие файла для вас и просто отправить file_path.

Zlib::GzipReader.new(file_path) do |gz|
  output = gz.read
  @companies_array = JSON.parse(output)
end
...