我可以将 http 流与 axlsx_rails 一起使用以避免 large/time 密集查询的超时问题吗?

Can I use http streaming with axlsx_rails to avoid timeout issue with large/time intensive query?

我正在使用 Rails 4.2.5 中的 axlsx_rails Ruby gem 生成一个 Excel 文件让用户下载他们的数据。

我的 index.xlsx.axlsx 模板中有这个:

wb = xlsx_package.workbook

wb.add_worksheet(name: 'Transactions') do |sheet|

  sheet.add_row ["Date", "Vendor Name", "Account",
             "Transaction Category",
             "Amount Spent", "Description"]

  @transactions.find_each(batch_size: 100) do |transaction|
    sheet.add_row [transaction.transaction_date,
      transaction.vendor_name,
      transaction.account.account_name,
      transaction.transaction_category.name,
      transaction.amount,
      transaction.description]
  end
end

如果有足够的数据,页面在返回 Excel 文件之前超时。有没有办法在处理过程中使用 HTTP 流发送回结果,而不是等到整个 transactions.find_each 循环完成?

我看到代码 here 使用 response.stream.write:

response.headers['Content-Type'] = 'text/event-stream'
10.times {
  response.stream.write "This is a test message"
  sleep 1
}
response.stream.close

这种方法看起来很有希望,但我不知道如何将 response.stream.write 集成到 axlsx_rails 模板中。有办法吗?

这是我的第一个 Stack Overflow 问题 - 对任何失礼表示歉意,并感谢您提供的任何想法。

欢迎来到 SO,乔。

我在评论中问过,但也许最好回答并解释一下。

简短的回答是,是的,如果可以渲染,则始终可以进行流式传输(尽管有时性能结果参差不齐)。

但是,如果您直接引用文件,它就不起作用。即,http://someurl.com/reports/mycustomreport.xlsx

rails 中的流式传输并不是默认情况下构建的。但不用担心,您 "should" 仍然可以解决您的问题,前提是您希望节省的时间仅用于渲染。

在您的控制器中(* 以后请注意,当您询问渲染操作时,提供您的控制器操作代码会有所帮助 *)您应该能够执行类似于以下操作的操作:

def report
  @transactions = current_user.transactions.all
  respond_to do |format|
    format.html { render xlsx: 'report', stream: true}
  end
end

可能有助于对您的加载进行完整性检查。在您的日志中,作为 200 响应的一部分,您应该得到如下内容:

在 506 毫秒内完成 200 OK(视图:494.6 毫秒 | ActiveRecord:2.8 毫秒)

如果活动记录数太高,或高于视图数,此解决方案可能不适用于您的查询,并且按照建议,这可能需要线程化或发送到作业。

即使可以直播,我也不认为会更快。问题是 Axlsx 在您完成构建之前不会生成您的电子表格。而 axlsx_rails 只是包装了这个过程,所以它也无济于事。因此,不会有部分电子表格以位形式提供服务,延迟也会一样长。

您应该硬着头皮尝试 Sidekiq(非常快)或其他一些作业调度程序。然后您可以立即 return 请求并在后台生成电子表格。您将必须进行某种监视或通知以获取生成的报告,或者使用 javascript ping 回另一个 url,当在呈现完成时设置标志时转发到新页面。你的电话那里。

当您需要发送电子邮件以响应请求时,拥有作业调度程序也非常方便;响应可以 return 立即而不是等待电子邮件完成。有了调度程序后,您会发现它的更多用途。

如果您选择作业调度程序,axlsx_rails 会让您 use your template to generate the attachment, or you can create your own view context to generate the file. Or for a really bare bones way of rendering the template, see this test