Rails 4:解析大型csv文件
问题描述:
我有一个非常大的csv文件,我需要阅读,解析,然后向用户提供数据,以便他们可以进行调整/验证事物看起来是否正确。Rails 4:解析大型csv文件
该进程在本地运行,但是当部署到Heroku时,我遇到了Request Timeout
错误,因为解析需要很长时间。
2017-07-27T13:47:25.399387+00:00 heroku[router]: at=error code=H12 desc="Request timeout"
我知道我应该使用类似Resque,我已经使用了电子邮件,但我不知道如何使用它,如果我需要做额外的处理与返回的对象。
有人可以提供一个如何从Resque作业中访问返回对象的例子吗?
这是我的代码,第一个函数是在控制器中调用模型函数,然后在模型函数完成解析(这是需要这么长的过程)之后重定向。
def check_upload_file
@response = WeighIn.check_file(params[:file], params[:location])
@final = {}
@file = params[:file]
@client_names = []
@final[:success] = @response[:successful_entry]
@final[:name_fail] = @response[:name_error]
@final[:weigh_fail] = @response[:weigh_in_error]
@final[:location_id] = @response[:location_id]
# Need to mess with this to use 'include' and see if speed improves
@clients = Client.all.order("name ASC").select(:name)
@clients.each { |c| @client_names << c.name unless c.name.nil? }
render 'weigh_ins/preview'
end
def self.check_file(file, location_id)
status = {
name_error: [],
weigh_in_error: [],
successful_entry: [],
location_id: location_id
}
status[:file] = file.original_filename
options = {:key_mapping => @new_hash, :strings_as_keys => true, :keep_original_headers => true, :remove_unmapped_keys => true}
SmarterCSV.process(file.path, options) do |row|
hashed_row = row[0]
hashed_row[:unique_mb] = (location_id.to_s + hashed_row[:scale_id].to_s).to_i
hashed_row[:unique_scale] = (location_id.to_s + hashed_row[:scale_id].to_s).to_i
# Escape missing scale ids
next if hashed_row[:scale_id].nil?
client = Client.find_by(unique_scale: hashed_row[:unique_scale]) || Client.find_by(unique_mb: hashed_row[:unique_mb])
hashed_row = hashed_row.except!(:unique_mb)
# Handle missing client
if client.nil?
status[:name_error] << hashed_row
next
end
check_ins_with_no_weigh_ins = client.check_ins.with_no_weigh_ins
hashed_row[:client_id] = client.id
if check_ins_with_no_weigh_ins.length != 1
hashed_row[:empty_check_ins] = check_ins_with_no_weigh_ins.length
hashed_row[:check_ins] = client.check_ins.length
status[:weigh_in_error] << hashed_row
else
hashed_row[:check_in_id] = check_ins_with_no_weigh_ins.first.id
status[:successful_entry] << hashed_row
end
end
return status
end
答
我会做下列方式:
- 文件上传到S3(与Carrierwave或其它),以及路径的队列,如表或Redis的一个状态“存储待处理'
- 异步处理待处理内容(使用Resque或简单的cron作业)并将结果再次保存到s3(并将状态更新为“已处理”)。
- 向用户显示准备好的内容,您可能需要websocket。
或者,您可以在Heroku配置中查看是否可以在超时前调整持续时间。我不会推荐它。