如何从Resque worker向客户端发送数据?

3

我在Heroku上运行了一个Rails应用程序。我正在尝试添加一个功能,允许用户以CSV格式下载一些数据。这些CSV文件相对较大(约1-2 MB),生成速度较慢。为了不占用我的Web dynos,我将这些下载请求传递给工作 dynos(使用Resque),并在那里组装CSV文件。我的Resque worker看起来像这样。

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发送
请问有人可以提供关于如何继续的建议吗?谢谢。
1个回答

1

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

关于选项1,我无法想出如何直接从Resque工作者向客户端发送csv文件。

关于选项2,似乎也不可能将csv文件保存到Heroku。Heroku的文档说每个dyno都有自己的文件系统,而且这个文件系统仅对拥有它的dyno可见。我的工作者dyno无法读取或写入我的Web dyno的文件系统,反之亦然。因此,这似乎也不是一个很有前途的选项。

那么只剩下选项3了,即在我的工作者dyno中将csv文件保存到我的数据库中,然后在我的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 客户端轮询它以跟踪其状态。当它完成时,我从数据库中取出它并将其发送给客户端。


只需使用Paperclip上传,如果它配置为上传到S3,则还应将文件的引用保存在数据库中。我尝试了这种方式,它的工作效果非常好。 - Passionate Engineer
哦,不错。我从没听说过Paperclip。我会去了解一下的。 - dB'

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接