I am trying to export database rows to CSV depending on the parameters user picks. These exports can take a while, so I'm using delayed_job to process them and upload them to S3. My controller looks like this:
def search
@books = visible_books.includes(:publisher)
@books = @books.where(contract_id: assigned_contract_ids) if assigned_subscriber.present?
@books = @books.unifilter(params, to_cents: ['total_cost'])
respond_to do |format|
format.json { export }
format.js { @books.paginate(params[:page], per: 50) }
end
end
def export
exportable_books = ExportableBooks.new(@books)
exportable_books.delay.upload
render json: { id: exportable_books.id }
end
Unfortunately, @books
can hold up to 10.000 rows, and when they are serialized to YAML for delayed_job, all those rows get loaded into memory, and then written to the database in YAML format. Is there a way to avoid that?
The problem is that delay
needs to serialize exportable_books
into the database and exportable_books
holds the complete result set of @books
.
Instead of that you should initialize ExportableBooks
just with the params
and assigned_contract_ids
, because that is much smaller when serialized. And then run the query in the upload
method.