mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-03-13 04:00:21 +00:00
Store reports with Active Storage
This will enable us to offer download links and clean them up automatically.
This commit is contained in:
@@ -57,8 +57,9 @@ module Admin
|
||||
|
||||
def render_report_as(format)
|
||||
if OpenFoodNetwork::FeatureToggle.enabled?(:background_reports, spree_current_user)
|
||||
blob = ReportJob.create_blob!
|
||||
job = ReportJob.perform_later(
|
||||
report_class, spree_current_user, params, format
|
||||
report_class, spree_current_user, params, format, blob
|
||||
)
|
||||
Timeout.timeout(max_wait_time) do
|
||||
sleep 1 until job.done?
|
||||
|
||||
@@ -1,15 +1,29 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# Renders a report and saves it to a temporary file.
|
||||
# Renders a report and stores it in a given blob.
|
||||
class ReportJob < ApplicationJob
|
||||
def perform(report_class, user, params, format)
|
||||
def self.create_blob!
|
||||
# ActiveStorage discourages modifying a blob later but we need a blob
|
||||
# before we know anything about the report file. It enables us to use the
|
||||
# same blob in the controller to read the result.
|
||||
ActiveStorage::Blob.create_before_direct_upload!(
|
||||
filename: "tbd",
|
||||
byte_size: 0,
|
||||
checksum: "0",
|
||||
content_type: "application/octet-stream",
|
||||
).tap do |blob|
|
||||
ActiveStorage::PurgeJob.set(wait: 1.month).perform_later(blob)
|
||||
end
|
||||
end
|
||||
|
||||
def perform(report_class, user, params, format, blob)
|
||||
report = report_class.new(user, params, render: true)
|
||||
result = report.render_as(format)
|
||||
write(result)
|
||||
write(result, blob)
|
||||
end
|
||||
|
||||
def done?
|
||||
@done ||= File.file?(filename)
|
||||
@done ||= blob.reload.checksum != "0"
|
||||
end
|
||||
|
||||
def result
|
||||
@@ -18,17 +32,17 @@ class ReportJob < ApplicationJob
|
||||
|
||||
private
|
||||
|
||||
def write(result)
|
||||
File.write(filename, result, mode: "wb")
|
||||
def write(result, blob)
|
||||
io = StringIO.new(result)
|
||||
blob.upload(io, identify: false)
|
||||
blob.save!
|
||||
end
|
||||
|
||||
def read_result
|
||||
File.read(filename)
|
||||
ensure
|
||||
File.unlink(filename)
|
||||
blob.download
|
||||
end
|
||||
|
||||
def filename
|
||||
Rails.root.join("tmp/report-#{job_id}")
|
||||
def blob
|
||||
arguments[4]
|
||||
end
|
||||
end
|
||||
|
||||
@@ -3,12 +3,13 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe ReportJob do
|
||||
let(:report_args) { [report_class, user, params, format] }
|
||||
let(:report_args) { [report_class, user, params, format, blob] }
|
||||
let(:report_class) { Reporting::Reports::UsersAndEnterprises::Base }
|
||||
let(:user) { enterprise.owner }
|
||||
let(:enterprise) { create(:enterprise) }
|
||||
let(:params) { {} }
|
||||
let(:format) { :csv }
|
||||
let(:blob) { ReportJob.create_blob! }
|
||||
|
||||
it "generates a report" do
|
||||
job = perform_enqueued_jobs(only: ReportJob) do
|
||||
|
||||
Reference in New Issue
Block a user