2017-07-27 101 views
1

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

回答

0

我會做下列方式:

  • 文件上傳到S3(與Carrierwave或其它),以及路徑的隊列,如表或Redis的一個狀態「存儲待處理'
  • 異步處理待處理內容(使用Resque或簡單的cron作業)並將結果再次保存到s3(並將狀態更新爲「已處理」)。
  • 向用戶顯示準備好的內容,您可能需要websocket。

或者,您可以在Heroku配置中查看是否可以在超時前調整持續時間。我不會推薦它。