-
-
Notifications
You must be signed in to change notification settings - Fork 3.3k
Don't stream CSV in development #3535
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
there should be a option for that |
I'm not sure what you're saying @timoschilling. |
@seanlinsley I mean we should do it this way: inheritable_setting :stream_csv, Rails.env.development? || Rails.env.test?
if active_admin_config.stream_csv
self.response_body = block['']
else
self.response_body = Enumerator.new &block
end The main reason is, I want the ability/possibility to test the streaming in dev and test env
|
I only took this approach because I couldn't figure out how to get the |
The stack trace after a request times out looks like this:
Maybe the only proper solution is to patch Rails / Rack. |
You can emulate the current behavior (returning the exception) except without the wait time with this: self.response_body = Enumerator.new do |receiver|
begin
yield receiver
rescue => e
receiver << {
exception: e.class.to_s, message: e.message, backtrace: e.backtrace
}.to_json
end
end |
I know the problem with stream error handling, and there is no solution for it at the moment. Your PR is a good workaround, but there should be a solution (the |
Another approach is to use $ git diff
diff --git a/lib/active_admin/csv_builder.rb b/lib/active_admin/csv_builder.rb
index 2d5b154..ea09284 100644
--- a/lib/active_admin/csv_builder.rb
+++ b/lib/active_admin/csv_builder.rb
@@ -39,20 +39,18 @@ module ActiveAdmin
@columns << Column.new(name, @resource, column_transitive_options.merge(options), block)
end
- def build(view_context, receiver)
+ def build(view_context, stream)
options = ActiveAdmin.application.csv_options.merge self.options
columns = exec_columns view_context
if options.delete(:column_names) { true }
- receiver << CSV.generate_line(columns.map{ |c| encode c.name, options }, options)
+ stream.write CSV.generate_line(columns.map{ |c| encode c.name, options }, options)
end
view_context.send(:collection).find_each do |resource|
resource = view_context.send :apply_decorator, resource
- receiver << CSV.generate_line(build_row(resource, columns, options), options)
+ stream.write CSV.generate_line(build_row(resource, columns, options), options)
end
-
- receiver
end
def exec_columns(view_context = nil)
diff --git a/lib/active_admin/resource_controller/streaming.rb b/lib/active_admin/resource_controller/streaming.rb
index c9e8cc0..2d04c99 100644
--- a/lib/active_admin/resource_controller/streaming.rb
+++ b/lib/active_admin/resource_controller/streaming.rb
@@ -8,6 +8,10 @@ module ActiveAdmin
#
module Streaming
+ def self.included(klass)
+ klass.send :include, ActionController::Live
+ end
+
def index
super do |format|
format.csv { stream_csv }
@@ -17,14 +21,17 @@ module ActiveAdmin
protected
- def stream_resource(&block)
+ def stream_resource
headers['X-Accel-Buffering'] = 'no'
headers['Cache-Control'] = 'no-cache'
- if Rails.env.development? || Rails.env.test?
- self.response_body = block['']
+ yield response.stream
+ response.stream.close
+ rescue
+ if Rails.env.development?
+ raise
else
- self.response_body = Enumerator.new &block
+ response.stream.close
end
end |
Using Do you want to cat of Rails 3.2 in general or only for CSV or only for CSV streaming? But I think your workaround is good enough, we should just add the config option, so can we set it to `true for specific streaming test. |
What do you think about a |
I've never heard of teams straying from:
Are custom environment names really that common? Also: it seems like we'd only want this behavior in development, not in test. Also: do you have any tests that expect a certain behavior (streaming or not) from CSV exports? Could you post an example here? |
Yes custom environment names really happen, some developers use things like I don't have tests for streaming, but in a ActiveAdmin test I want to test the stream and not the download. # To make debugging easier, by default only stream in staging & production
setting :stream_not_in, ['development'] looks like the best option |
Please also include somekind of documentation. |
@dmitry whats the best way in your eyes? |
|
Sure, but the pro part of that restriction is that the user don't need to change it for other envs |
I'm not ready to commit them yet, but here are some changes I had locally: $ git diff
diff --git a/lib/active_admin/application.rb b/lib/active_admin/application.rb
index 63ebc60..e00f6aa 100644
--- a/lib/active_admin/application.rb
+++ b/lib/active_admin/application.rb
@@ -104,8 +104,8 @@ module ActiveAdmin
:email,
:to_s ]
- # To make debugging easier, by default only stream in staging & production
- setting :stream_in, ['production', 'staging']
+ # To make debugging easier, by default don't stream in development
+ setting :disable_streaming, ['development']
# == Deprecated Settings
diff --git a/lib/active_admin/resource_controller/streaming.rb b/lib/active_admin/resource_controller/streaming.rb
index 356e780..56bd4dc 100644
--- a/lib/active_admin/resource_controller/streaming.rb
+++ b/lib/active_admin/resource_controller/streaming.rb
@@ -21,12 +21,11 @@ module ActiveAdmin
headers['X-Accel-Buffering'] = 'no'
headers['Cache-Control'] = 'no-cache'
- # To make debugging easier, by default only stream in staging/production
- case Rails.env
- when *ActiveAdmin.application.stream_in
- self.response_body = Enumerator.new &block
- else
+ # To make debugging easier, by default don't stream in development
+ if ActiveAdmin.application.disable_streaming.include? Rails.env
self.response_body = block['']
+ else
+ self.response_body = Enumerator.new &block
end
end |
👍 |
Maybe we should name it |
@seanlinsley can you finish this PR? |
ac1f5b6
to
249f8ed
Compare
Ah nevermind, I was missing a line after rebasing. |
This enables any exceptions to bubble up, instead of waiting until the request times out before sending back any data. This also lets you use in-browser debuggers, like better_errors.
249f8ed
to
cdc7a2a
Compare
local dev uses the last Rails version in the list. Until #4177 is resolved, Rails 5 / master can’t be the default
cdc7a2a
to
2f96673
Compare
This is ready for review. |
Don't stream CSV in development
This enables any exceptions to bubble up, instead of waiting until the request times out before sending back any data. This also lets you use in-browser debuggers, like better_errors.
TODO: add tests