2

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


根据他们的文档,30 秒和超时错误触发。

我正在上传并解析一个 CSV 文件以保存到我的数据库中。其中一个文件大小为 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 层,但这是一个可扩展的设计(这就是为什么我认为 HTTP 处理有 30 秒的超时)。

另一种方法是将数据直接推送到表中并异步执行存储过程。这会将工作推到 Postgres 来处理 HTTP 线程,并且可能会将您的请求置于 30 秒的时间限制之下,尽管对于较大的文件,您可能会违反此上限。

在您重新构建整个应用程序之前,您需要运行一个测试以确保 Heroku 没有禁用libpq-asynch

上面代码中的最大成本是Make.find_or_create_by_name分别调用 37,000 个 - 根据您的示例输入 - SELECT 并且可能为 CSV 中的每一行调用一个 INSERT。如果 libpq-asynch 不是一个选项,您将不得不创建一个存储过程,该过程将一次以 100 或 1000 行的批次执行此功能 - 这样您的控制器代码就不会对数据库进行如此多的往返。Postgres 支持经典的序数索引样式的数组以及行类型的数组,所以这实际上比听起来要痛苦得多。

于 2012-12-30T05:04:47.883 回答