avoid async report pattern and replace with simpler hijack

This commit is contained in:
Sam 2018-05-16 16:05:03 +10:00
parent 3864091f2d
commit 21e0b7c818
7 changed files with 51 additions and 128 deletions

View File

@ -16,7 +16,7 @@ export default Ember.Component.extend(AsyncReport, {
fetchReport() {
this._super();
let payload = { data: { async: true, facets: ["total", "prev30Days"] } };
let payload = { data: { cache: true, facets: ["total", "prev30Days"] } };
if (this.get("startDate")) {
payload.data.start_date = this.get("startDate").format("YYYY-MM-DD[T]HH:mm:ss.SSSZZ");
@ -31,13 +31,11 @@ export default Ember.Component.extend(AsyncReport, {
}
this.set("reports", Ember.Object.create());
this.set("reportKeys", []);
return Ember.RSVP.Promise.all(this.get("dataSources").map(dataSource => {
return ajax(dataSource, payload)
.then(response => {
this.set(`reports.${response.report.report_key}`, this.loadReport(response.report));
this.get("reportKeys").pushObject(response.report.report_key);
});
}));
}

View File

@ -41,7 +41,7 @@ export default Ember.Component.extend(AsyncReport, {
this._super();
let payload = {
data: { async: true, facets: ["prev_period"] }
data: { cache: true, facets: ["prev_period"] }
};
if (this.get("startDate")) {
@ -58,13 +58,11 @@ export default Ember.Component.extend(AsyncReport, {
}
this.set("reports", Ember.Object.create());
this.set("reportKeys", []);
return Ember.RSVP.Promise.all(this.get("dataSources").map(dataSource => {
return ajax(dataSource, payload)
.then(response => {
this.set(`reports.${response.report.report_key}`, this.loadReport(response.report));
this.get("reportKeys").pushObject(response.report.report_key);
});
}));
},

View File

@ -4,44 +4,12 @@ export default Ember.Mixin.create({
classNameBindings: ["isLoading"],
reports: null,
reportKeys: null,
isLoading: false,
dataSourceNames: "",
init() {
this._super();
this.set("reports", Ember.Object.create());
this.set("reportKeys", []);
this._channels = this.get("dataSources");
this._callback = (report) => {
if (this.get("reportKeys").includes(report.report_key)) {
Em.run.next(() => {
if (this.get("reportKeys").includes(report.report_key)) {
const previousReport = this.get(`reports.${report.report_key}`);
this.set(`reports.${report.report_key}`, this.loadReport(report, previousReport));
this.renderReport();
}
});
}
};
// in case we did not subscribe in time ensure we always grab the
// last thing on the channel
this.subscribe(-2);
},
subscribe(position) {
this._channels.forEach(channel => {
this.messageBus.subscribe(channel, this._callback, position);
});
},
unsubscribe() {
this._channels.forEach(channel => {
this.messageBus.unsubscribe(channel, this._callback);
});
},
@computed("dataSourceNames")
@ -49,21 +17,12 @@ export default Ember.Mixin.create({
return dataSourceNames.split(",").map(source => `/admin/reports/${source}`);
},
willDestroyElement() {
this._super();
this.unsubscribe();
},
didInsertElement() {
this._super();
Ember.run.later(this, function() {
this.fetchReport()
.finally(() => {
this.renderReport();
});
}, 500);
this.fetchReport()
.finally(() => {
this.renderReport();
});
},
didUpdateAttrs() {

View File

@ -32,18 +32,36 @@ class Admin::ReportsController < Admin::AdminController
limit = params[:limit].to_i
end
report = Report.find(report_type,
start_date: start_date,
end_date: end_date,
category_id: category_id,
group_id: group_id,
facets: facets,
limit: limit,
async: params[:async])
args = {
start_date: start_date,
end_date: end_date,
category_id: category_id,
group_id: group_id,
facets: facets,
limit: limit
}
raise Discourse::NotFound if report.blank?
report = nil
if (params[:cache])
report = Report.find_cached(report_type, args)
end
if report
return render_json_dump(report: report)
end
hijack do
report = Report.find(report_type, args)
raise Discourse::NotFound if report.blank?
if (params[:cache])
Report.cache(report, 35.minutes)
end
render_json_dump(report: report)
end
render_json_dump(report: report)
end
end

View File

@ -1,30 +0,0 @@
require_dependency 'report'
module Jobs
class RetrieveReport < Jobs::Base
sidekiq_options retry: false
def execute(args)
raise Discourse::InvalidParameters.new(:report_type) if !args['report_type']
type = args.delete('report_type')
report = Report.new(type)
report.start_date = (args['start_date'].present? ? args['start_date'].to_date : 30.days.ago).beginning_of_day
report.end_date = (args['end_date'].present? ? args['end_date'].to_date : start_date + 30.days).end_of_day
report.category_id = args['category_id'] if args['category_id']
report.group_id = args['group_id'] if args['group_id']
report.facets = args['facets'].map(&:to_sym) if args['facets']
report.limit = args['limit'].to_i if args['limit']
report.processing = false
report.average = args[:average] || false
report.percent = args[:percent] || false
Report.send("report_#{type}", report)
json = report.as_json
Discourse.cache.write(Report.cache_key(report), json, force: true, expires_in: 30.minutes)
MessageBus.publish("/admin/reports/#{type}", json, user_ids: User.staff.pluck(:id))
end
end
end

View File

@ -71,7 +71,7 @@ class Report
singleton_class.instance_eval { define_method("report_#{name}", &block) }
end
def self.find(type, opts = nil)
def self._get(type, opts = nil)
opts ||= {}
# Load the report
@ -80,26 +80,30 @@ class Report
report.end_date = opts[:end_date] if opts[:end_date]
report.category_id = opts[:category_id] if opts[:category_id]
report.group_id = opts[:group_id] if opts[:group_id]
report.async = opts[:async] || false
report.facets = opts[:facets] || [:total, :prev30Days]
report.limit = opts[:limit] if opts[:limit]
report.processing = false
report.average = opts[:average] || false
report.percent = opts[:percent] || false
report
end
def self.find_cached(type, opts = nil)
report = _get(type, opts)
Discourse.cache.read(cache_key(report))
end
def self.cache(report, duration)
Discourse.cache.write(Report.cache_key(report), report.as_json, force: true, expires_in: duration)
end
def self.find(type, opts = nil)
report = _get(type, opts)
report_method = :"report_#{type}"
if respond_to?(report_method)
cached_report = Discourse.cache.read(cache_key(report))
if report.async
if cached_report
return cached_report
else
Jobs.enqueue(:retrieve_report, opts.merge(report_type: type))
report.processing = true
end
else
send(report_method, report)
end
send(report_method, report)
elsif type =~ /_reqs$/
req_report(report, type.split(/_reqs$/)[0].to_sym)
else

View File

@ -1,24 +0,0 @@
require 'rails_helper'
require_dependency 'jobs/base'
describe Jobs::RetrieveReport do
it "correctly included full day in report" do
freeze_time '2016-02-03 10:00'.to_date
_topic = Fabricate(:topic)
args = {
report_type: :topics,
start_date: Time.now.beginning_of_day,
end_date: Time.now.end_of_day,
facets: [:total]
}.to_json
messages = MessageBus.track_publish("/admin/reports/topics") do
Jobs::RetrieveReport.new.execute(JSON.parse(args))
end
data = messages.first.data[:data]
expect(data).to eq([y: 1, x: Time.now.to_date])
end
end