Run reports in background

This commit is contained in:
Matt-Yorkley
2023-05-02 21:13:16 +01:00
committed by Maikel Linke
parent ced959ad6a
commit a3ef604797
8 changed files with 84 additions and 31 deletions

View File

@@ -22,6 +22,13 @@ module Admin
def show
@report = report_class.new(spree_current_user, params, render: render_data?)
@background_reports = OpenFoodNetwork::FeatureToggle
.enabled?(:background_reports, spree_current_user)
if @background_reports && request.post?
return background(report_format)
end
if params[:report_format].present?
export_report
else
@@ -34,12 +41,12 @@ module Admin
private
def export_report
send_data render_report_as(report_format), filename: report_filename
send_data @report.render_as(report_format), filename: report_filename
end
def show_report
assign_view_data
@table = render_report_as(:html) if render_data?
@table = @report.render_as(:html) if render_data?
render "show"
end
@@ -56,21 +63,21 @@ module Admin
request.post?
end
def render_report_as(format)
if OpenFoodNetwork::FeatureToggle.enabled?(:background_reports, spree_current_user)
@blob = ReportBlob.create_for_upload_later!(report_filename)
ReportJob.perform_later(
report_class, spree_current_user, params, format, @blob
)
Timeout.timeout(max_wait_time) do
sleep 1 until @blob.content_stored?
end
def background(format)
@blob = ReportBlob.create_for_upload_later!(report_filename)
# This result has been rendered by Rails in safe mode already.
@blob.result.html_safe # rubocop:disable Rails/OutputSafety
else
@report.render_as(format)
end
ReportJob.perform_later(
report_class, spree_current_user, params, format, @blob, SessionChannel.for_request(request)
)
render cable_ready: cable_car.
inner_html(
selector: "#report-table",
html: render_to_string(partial: "admin/reports/loading")
).scroll_into_view(
selector: "#report-table",
block: "start"
)
end
def render_timeout_error
@@ -84,17 +91,5 @@ module Admin
end
render "show"
end
def max_wait_time
# This value is used by rack-timeout and nginx, usually 30 seconds in
# staging and production:
server_timeout = ENV.fetch("RACK_TIMEOUT_SERVICE_TIMEOUT", "15").to_f
# Zero disables the timeout:
return 0 if server_timeout.zero?
# We want to time out earlier than nginx:
server_timeout - 2.seconds
end
end
end

View File

@@ -7,4 +7,11 @@ class ApplicationJob < ActiveJob::Base
# Most jobs are safe to ignore if the underlying records are no longer available
# discard_on ActiveJob::DeserializationError
private
def enable_active_storage_urls
ActiveStorage::Current.url_options ||=
Rails.application.config.action_controller.default_url_options
end
end

View File

@@ -2,9 +2,14 @@
# Renders a report and stores it in a given blob.
class ReportJob < ApplicationJob
include CableReady::Broadcaster
delegate :render, to: ActionController::Base
before_perform :enable_active_storage_urls
NOTIFICATION_TIME = 5.seconds
def perform(report_class, user, params, format, blob)
def perform(report_class, user, params, format, blob, channel = nil)
start_time = Time.zone.now
report = report_class.new(user, params, render: true)
@@ -14,6 +19,8 @@ class ReportJob < ApplicationJob
execution_time = Time.zone.now - start_time
email_result(user, blob) if execution_time > NOTIFICATION_TIME
broadcast_result(channel, format, blob) if channel
end
def email_result(user, blob)
@@ -22,4 +29,17 @@ class ReportJob < ApplicationJob
blob: blob,
).report_ready.deliver_later
end
def broadcast_result(channel, format, blob)
cable_ready[channel].inner_html(
selector: "#report-table",
html: actioncable_content(format, blob)
).broadcast
end
def actioncable_content(format, blob)
return blob.result if format.to_sym == :html
render(partial: "admin/reports/download", locals: { file_url: blob.expiring_service_url })
end
end

View File

@@ -0,0 +1,2 @@
.download
= link_to t("admin.reports.download.button"), file_url, target: "_blank", class: "button icon icon-file"

View File

@@ -0,0 +1,2 @@
.loading
= render partial: "components/admin_spinner"

View File

@@ -3,7 +3,9 @@
- content_for :minimal_js, true if @background_reports
= form_for @report.search, :url => url_for do |f|
- options = @background_reports ? { data: { remote: "true" } } : {}
= form_for @report.search, { url: url_for }.merge(options) do |f|
%fieldset.no-border-bottom.print-hidden
%legend{ align: 'center'}= t(:report_filters)
= render partial: "admin/reports/filters/#{@report_type}", locals: { f: f }
@@ -24,4 +26,6 @@
%button.btn-print.icon-print{ onclick: "window.print()"}= t(:report_print)
= t(@error, link: link_to(t(".report_link_label"), @error_url)) if @error
= @table
#report-table
= @table

View File

@@ -60,3 +60,24 @@ table.report__table {
margin: 0 !important;
width: 120px;
}
#report-table {
margin-bottom: 4em;
.loading, .download {
text-align: center;
height: 2em;
padding: 4em;
width: 100%;
.spinner {
font-size: 4em;
color: $spree-blue;
opacity: 0.3;
}
.button {
font-size: 1.25em;
}
}
}

View File

@@ -1469,6 +1469,8 @@ en:
pack_by_customer: Pack By Customer
pack_by_supplier: Pack By Supplier
pack_by_product: Pack By Product
download:
button: "Download Report"
show:
report_taking_longer: >
Sorry, this report took too long to process.