Skip to content

Instantly share code, notes, and snippets.

@njakobsen
Last active November 5, 2021 02:28
Show Gist options
  • Save njakobsen/6257887 to your computer and use it in GitHub Desktop.
Save njakobsen/6257887 to your computer and use it in GitHub Desktop.
Live stream a database dump (or any other STDOUT) using Rails 4. Why would you want this? If you have a large database dump and want to avoid storing it in memory as Rails streams it. This allows pipe the dump directly into the http response instead of storing it as a file, sending it, and then deleting it. Let me know what you think! I've teste…
class DatabaseController < ApplicationController
def database_dump
database = Rails.configuration.database_configuration[Rails.env]["database"]
send_file_headers!(:type => 'application/octet-stream', :filename => "#{database}_#{Time.now.to_s(:human)}.backup")
pipe = IO.popen("pg_dump '#{database}' -F c")
stream = response.stream
while (line = pipe.gets)
stream.write line
sleep 0.0001 # HACK: Prevent server instance from sleeping forever if client disconnects during download
end
rescue IOError
# Client Disconnected
ensure
pipe.close
response.stream.close
end
# Code that allows us to only mix in the live methods if we're accessing the desired action
def dispatch(name, *args)
extend ActionController::Live if name.to_s == 'database_dump'
super
end
end
@matthewd
Copy link

matthewd commented Jun 1, 2014

@njakobsen btw, you probably don't want to use gets here: I imagine read(n) will be much more efficient. Most of the "lines" you see are going to be pretty tiny.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment