3

我有一个在 Heroku 上运行的 rails 应用程序。我正在尝试添加一个功能,让用户以 CSV 格式下载他们的一些数据。CSV 文件很大(~ 1-2 MB),而且生成速度很慢。为了不占用我的网络测功机,我将这些下载请求传递给工作测功机(使用 Resque),并在那里组装 CSV。我的 resque 工人看起来像这样。

class Downloader

  def self.perform(ids_to_download)
      models = Model.where(:id => ids_to_download)
      csv_data_for_client = models.to_csv 
  end

end

我想知道将 csv 文件发送回请求它的客户的最佳方式。

如果这段代码在 Rails 控制器中,这可以通过简单send_data csv_data_for_client的 . 不过,这种方法似乎不适用于 Resque 工作人员。

通过对 SO 和互联网上其他地方的研究,我似乎有几个选择。

  1. 直接从 Resque 工作人员发送数据(虽然我不确定这是否可能)
  2. 将数据保存到 heroku 文件系统,在控制器中检索它,然后使用send_data
  3. 将其保存到数据库(postgresql),在控制器中检索它,然后使用send_data

任何人都可以提供有关最佳方式的建议吗?谢谢。

4

1 回答 1

1

经过一番思考,我排除了选项 1 和 2。

Re 1,我不知道如何将 csv 文件从 Resque 工作人员直接发送到客户端。

Re 2,似乎也不可能将 csv 文件保存到 Heroku。Heroku 的文档说每个 dyno 都有自己的文件系统,并且这个文件系统只对拥有它的 dyno 可见。我的工人测功机无法读取或写入我的网络测功机的文件系统,反之亦然。所以这似乎也不是一个有前途的选择。

这给我留下了选项 3,将 csv 文件保存到我的 worker dyno 中的数据库中,然后检索它并将其发送到我的 web dyno 中的客户端。

我使用resque-status gem 为每个 csv 文件请求分配一个唯一的 id (uuid)。

我创建了一个简单的模型来保存生成的 csv 文件,并将其与其 uuid 相关联。

class DownloaderJobOutput < ActiveRecord::Base
  attr_accessible :file_to_download, :uuid
end

在我的 resque 工作人员中,构建 csv 文件后,我将其保存到我的数据库中。

class Downloader
  @queue = :trial_downloader_queue
  include Resque::Plugins::Status

  def perform
    models = Model.where(:id => options["trial_ids"])
    csv = models.to_csv
    DownloaderJobOutput.create!( :uuid => self.uuid, :file_to_download => csv )
  end
end

在作业执行期间,我从 Web 客户端对其进行轮询以跟踪其状态。完成后,我将其从数据库中取出并发送给客户端。

于 2013-06-29T22:22:39.767 回答