在下载大型CSV大小文件作为后台进程时排队请求(延迟作业)



这在我的控制器中工作正常。

def export_list_sites_as_csv
    require "csv"
    csv_string = CSV.generate do |csv|
      csv << ["id","name", 'etc']
      @search.relation.not_archived.each do |site|
        csv << [site.id, site.name, site.etc]
      end
    end
    send_data csv_string,
              :type => 'text/csv',
              :filename => '_sites.csv',
              :disposition => 'attachment'
  end

@search变量取决于用户过滤器,在某种程度上会给 RAM 带来大量负载,UX 不好。因为其他请求将被搁置,直到当前请求得到服务。这也使我的系统挂起。因此,希望在后台进程运行,并在准备好下载后让用户知道。

当我尝试移动到模型时。

我收到一个错误 #<\Class:0x9f8bed0>send_data 的未定义方法"

我要搬到模型,因为我必须在上面调用延迟的工作。

首次处理 CSV 和延迟作业。

编辑:ActionController::Streaming仅在控制器中可用,所以其他方式? 更多的时候,这不会去任何地方。

正如D-Side的回答所说,我将不得不寻找其他方法。

编辑2:按照我能够做的 http://railscasts.com/episodes/171-delayed-job

class ExportCsv < Struct(:site_ids, :user_id)
def perform
    require "csv"
    sites = Site.where(id: site_ids)
    CSV.open("tmp/#{user_id}.csv", "w+") do |csv|
      csv <<  ["id","name", 'etc']
      sites.each do |site|
        csv << ....
      end
    end
  end

  def after(job)
    send_file(
      ....
      )
  end
end

如何在自定义类中使用ActionController::Streaming ExportCsvModel

编辑:

了解同步以及我如何处理这种情况,

答:http://imnithin.github.io/csv_download_with_delayed_job.html

你试图做的事情违背了延迟工作的目的。

当用户发出请求时,服务器应做出响应以完成请求。问题是,有些请求需要相当长的时间才能完成,用户必须坚持并等待完成。一个经典案例 - 大规模电子邮件传递,但正如您提到的,还有其他案例,例如数据套件生成。无论什么。完成所需的时间比用户等待的时间要长。

现在来了延迟工作。它执行某个操作,而无需响应查询的上下文。它不需要着急。但你不能只是为它打send_data耳光:它不会有任何查询来响应。相反,它应该将完成的工作的结果写入一些持久存储中。

你有很多方法可以做到这一点。

  • 当数据集准备就绪时,您可以通过电子邮件通知用户。您甚至可以将其附加到电子邮件中,但我不建议这样做:您不能依靠电子邮件提供商的准备来接受大量数据。改为创建用于下载数据集的链接并发送。
    • DelayedJob 需要渲染数据集,将其保存到文件中,获取链接并将其通过电子邮件发送给用户。
  • 将应用的某个部分(由模型、控制器和视图组成的公司)听起来像"已完成的请求",可能是用户个人资料的一部分。"启动"请求应指示用户稍后返回并查看该列表以获取结果。
    • 在请求完成后,延迟作业必须在该列表中输入一个条目。数据集的存储方式无关紧要,但您可以将其与上述方法相结合,将其保存到文件中并显示指向它的链接。

最新更新