2

https://devcenter.heroku.com/articles/request-timeout


ドキュメントによると、30 秒とタイムアウト エラーが発生します。

CSV ファイルをアップロードして解析し、データベースに保存しています。これらのファイルの 1 つは、サイズが 1.7MB で、37000 行あります。

このプロセスの処理には少し時間がかかり、確かに 30 秒以上かかります。

これらの場合、どうすればよいですか?どのようなオプションがありますか?

require 'csv'

class DatabaseImporterController < ApplicationController
  def index
  end

  def import
    # Receive the uploaded CSV file and import to the database.
    csv_file = params[:csv_file].tempfile

    i = 0
    CSV.foreach(csv_file) do |row|
      # Structure for CSV file: Year, Make, Model, Trim
      if i > 0 then
        make = Make.find_or_create_by_name(row[1])
        model = make.model.create(:year => row[0], :name => row[2], :trim => row[3])
      end

      i += 1
    end
    redirect_to :action => 'list'
  end

  def list
    @models = Model.all
  end
end
4

1 に答える 1

4

コントローラーで CSV ファイルを処理する代わりに、アップロードされたファイルの場所を含む通知をキューにプッシュします。次に、ワーカー dynoにその処理を処理させます。

特に無料の 1 つの dyno 層に固執しようとしている場合は、もう少し料金がかかりますが、これはスケーラブルな設計です (そのため、HTTP 処理に 30 秒のタイムアウトがあると思います)。

もう 1 つの方法は、データをテーブルに直接プッシュし、ストアド プロシージャを非同期的に実行することです。これにより、作業が Postgres にプッシュされ、HTTP スレッドが処理されなくなり、リクエストが 30 秒の制限時間内に置かれる可能性があります。

アプリケーション全体をわざわざ再構築する前に、テストを実行して、Heroku がlibpq-asynchを無効にしていないことを確認する必要があります。

上記のコードで大きなコストがかかるのは、Make.find_or_create_by_name37,000 の個別の呼び出しです - 入力例によると - SELECT と、CSV の各行の INSERT の可能性があります。libpq-asynch がオプションでない場合は、一度に 100 行または 1000 行のバッチでこの機能を実行するストアド プロシージャを作成する必要があります。これにより、コントローラー コードがデータベースへのラウンド トリップをあまり行わなくなります。Postgres は、行タイプの配列だけでなく、従来の序数インデックス スタイルの配列もサポートしているため、実際には思ったよりもはるかに簡単です。

于 2012-12-30T05:04:47.883 に答える