Heroku、私はあなたをストリーム!
問題:CSVまたは他の形式としてエクスポートされたコンテンツのタイムアウト.
これは、CSV、XLSX、PDFなどのような形式でページにエクスポート機能を持っている非常に一般的な機能です.
これは以下のような単純なものです.
サーバは一定量の秒後にタイムアウトエラーに応答し、ファイルを生成しているリクエストを停止します.
paasのようなherokuでは、この時間制限は、生成された内容の30秒である.また、出力の各々の新しい断片の間に55 ''の別のタイムアウトがあります.公式情報を引用する
RailsはActionController ::LIVEでこの種の出力生成を処理するためにストリーミング機能を持っているようです.また、Rails Edge(将来のV 7)には、この機能を達成するように見えるCount - sendSense Streamメソッドがあります.したがって、私はコントローラの懸念に私の柵5.2 APPにそれをコピーして、CSV形式の論理を変更可能な各々の方法を実装するためにCSV生成ロジックを変えました.
最後に修正されたヘッダをオーバーライドするまでは動作しませんでした.this issue discussionを参照.
コントローラの完全なコードです.
今すぐあなたのアプリケーションのストリームのようなデータを大量にストリームすることができます!
私はHeroku appでこのアプリを展開しているコードはthis github repoにあります.
余分なパフォーマンスのヒント.ActiveRecordを使ってDBからレコードを取得する際には、Count Countの代わりにCount Countを使います.
これがあなたのために役に立つならば、知らせてください.
ハッピーレールハッキング!
これは、CSV、XLSX、PDFなどのような形式でページにエクスポート機能を持っている非常に一般的な機能です.
これは以下のような単純なものです.
def index
@records = ...
respond_to do |format|
format.html # index.html
format.csv { some_csv_generation_code }
end
end
しかし、ある日、ユーザーが多くの情報をダウンロードしようとすると、エラーが発生し始めます.サーバは一定量の秒後にタイムアウトエラーに応答し、ファイルを生成しているリクエストを停止します.
paasのようなherokuでは、この時間制限は、生成された内容の30秒である.また、出力の各々の新しい断片の間に55 ''の別のタイムアウトがあります.公式情報を引用する
An application has an initial 30 second window to respond with a single byte back to the client. However, each byte transmitted thereafter (either received from the client or sent by your application) resets a rolling 55 second window. If no data is sent during the 55 second window, the connection will be terminated.
RailsはActionController ::LIVEでこの種の出力生成を処理するためにストリーミング機能を持っているようです.また、Rails Edge(将来のV 7)には、この機能を達成するように見えるCount - sendSense Streamメソッドがあります.したがって、私はコントローラの懸念に私の柵5.2 APPにそれをコピーして、CSV形式の論理を変更可能な各々の方法を実装するためにCSV生成ロジックを変えました.
最後に修正されたヘッダをオーバーライドするまでは動作しませんでした.this issue discussionを参照.
コントローラの完全なコードです.
require 'content_disposition'
module Streamable
extend ActiveSupport::Concern
include ActionController::Live
# Almost verbatim copy of new Rails 7 method.
# See https://edgeapi.rubyonrails.org/classes/ActionController/Live.html#method-i-send_stream
def send_stream(filename:, disposition: 'attachment', type: nil)
response.headers['Content-Type'] =
(type.is_a?(Symbol) ? Mime[type].to_s : type) ||
Mime::Type.lookup_by_extension(File.extname(filename).downcase.delete('.')) ||
'application/octet-stream'
response.headers['Content-Disposition'] = ContentDisposition.format(disposition: disposition, filename: filename)
# with rails 6 remove content_disposition gem and use:
# ActionDispatch::Http::ContentDisposition.format(disposition: disposition, filename: filename)
# Extra: needed for streaming
response.headers['Last-Modified'] = Time.now.httpdate
yield response.stream
ensure
response.stream.close
end
end
5 .X私はContent - Dispositionヘッダを設定するために余分な宝石を必要としました.gem 'content_disposition', '~> 1.0' # Not needed on Rails 6
遅いダミーデータを生成するコントローラのテスト例class ExporterController < ApplicationController
include Streameable
def index
respond_to do |format|
format.html # index.html
format.js # index.js
format.csv do
send_stream(attachment_opts) do |stream|
stream.write "email_address,updated_at\n"
50.times.each do |i|
line = "pepe_#{i}@acme.com,#{Time.zone.now}\n"
stream.write line
puts line
sleep 1 # force slow response
end
end
end
end
end
private
def attachment_opts
{
filename: "data_#{Time.zone.now.to_i}.csv",
disposition: 'attachment',
type: 'text/csv'
}
end
end
最後に、curlのようなものを使用すると、2番目目で出力される出力が表示されます.curl -i http://localhost:3000/exporter
今すぐあなたのアプリケーションのストリームのようなデータを大量にストリームすることができます!
私はHeroku appでこのアプリを展開しているコードはthis github repoにあります.
余分なパフォーマンスのヒント.ActiveRecordを使ってDBからレコードを取得する際には、Count Countの代わりにCount Countを使います.
これがあなたのために役に立つならば、知らせてください.
ハッピーレールハッキング!
Reference
この問題について(Heroku、私はあなたをストリーム!), 我々は、より多くの情報をここで見つけました https://dev.to/megatux/heroku-i-stream-you-4mdbテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol