【问题标题】:Rails 4: Parsing large csv fileRails 4:解析大型 csv 文件
【发布时间】:2018-01-03 12:59:59
【问题描述】:

我有一个非常大的 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

【问题讨论】:

    标签: ruby-on-rails csv ruby-on-rails-4 heroku resque


    【解决方案1】:

    我会这样做:

    • 将文件上传到 s3(使用 Carrierwave 或其他),并将路径存储在类似队列的表中或状态为“待定”的 Redis 中
    • 异步处理待处理的内容(使用 Resque 或简单的 cron 作业)并将结果再次保存到 s3(并将状态更新为“已处理”)。
    • 在准备就绪后向用户显示已处理的内容,您可能需要 websockets。

    或者,您可以深入研究 Heroku 配置,看看是否可以调整超时前的持续时间。不过我不会推荐它。

    【讨论】:

      猜你喜欢
      • 2018-12-09
      • 2012-07-13
      • 2013-05-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-20
      • 2020-01-09
      • 2013-10-19
      相关资源
      最近更新 更多