Heroku:通过 rake 任务解压 Gzip 文件失败
Heroku: Unpacking a Gzip file through a rake task fails
我正在使用 Rails 5.2 和 ruby 2.5.1 并将我的应用程序部署到Heroku。
我 运行 在尝试 运行 本地 rake 任务时遇到了问题。该任务调用一个 API,它以 *.gz
文件响应,保存它,压缩,然后使用检索到的 JSON 填充数据库,最后删除 *.gz
文件。任务 运行 在开发中很顺利,但在生产中调用时。打印到控制台的最后一行是 'Unzipping the file...',所以我猜问题出自 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
有没有其他人运行遇到类似的问题并且知道如何让它工作?
您的代码片段并未表明您曾经关闭过 GzipReader。通常最好将 IO 包装在块中以确保它们被正确关闭。此外,open
方法可能不是您想要的方法,因此只需让 GzipReader 为您打开文件并发送 file_path
即可。
Zlib::GzipReader.new(file_path) do |gz|
output = gz.read
@companies_array = JSON.parse(output)
end
问题与内存限制有关,而不是 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
我正在使用 Rails 5.2 和 ruby 2.5.1 并将我的应用程序部署到Heroku。
我 运行 在尝试 运行 本地 rake 任务时遇到了问题。该任务调用一个 API,它以 *.gz
文件响应,保存它,压缩,然后使用检索到的 JSON 填充数据库,最后删除 *.gz
文件。任务 运行 在开发中很顺利,但在生产中调用时。打印到控制台的最后一行是 'Unzipping the file...',所以我猜问题出自 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
有没有其他人运行遇到类似的问题并且知道如何让它工作?
您的代码片段并未表明您曾经关闭过 GzipReader。通常最好将 IO 包装在块中以确保它们被正确关闭。此外,open
方法可能不是您想要的方法,因此只需让 GzipReader 为您打开文件并发送 file_path
即可。
Zlib::GzipReader.new(file_path) do |gz|
output = gz.read
@companies_array = JSON.parse(output)
end
问题与内存限制有关,而不是 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