mirror of
https://github.com/discourse/discourse.git
synced 2026-08-11 02:59:07 +08:00
Previously, the dashboard ran eligible pinned Data Explorer queries when users loaded report cards. This change runs eligible admin-only queries every 30 minutes and writes results to the cache
135 lines
4 KiB
Ruby
Vendored
135 lines
4 KiB
Ruby
Vendored
# frozen_string_literal: true
|
|
|
|
describe AdminDashboardCacheWarmer do
|
|
before { Discourse.cache.clear }
|
|
|
|
let(:prewarm_calls) { [] }
|
|
let(:prewarming_provider) do
|
|
calls = prewarm_calls
|
|
Class.new(AdminDashboard::Reports::SourceProvider) do
|
|
def self.source_name = "prewarming_source"
|
|
|
|
define_singleton_method(:resolve_many) do |identifiers, guardian:|
|
|
next {} if guardian.nil?
|
|
|
|
identifiers.each_with_object({}) do |identifier, reports|
|
|
reports[identifier] = AdminDashboard::Reports::ResolvedReport.new(
|
|
source: source_name,
|
|
identifier:,
|
|
title: identifier,
|
|
description: nil,
|
|
label: nil,
|
|
url: "",
|
|
)
|
|
end
|
|
end
|
|
|
|
define_singleton_method(:prewarm) do |identifiers, guardian:, filters:|
|
|
calls << { identifiers:, guardian:, filters: }
|
|
end
|
|
end
|
|
end
|
|
let(:failing_provider) do
|
|
Class.new(prewarming_provider) do
|
|
def self.source_name = "failing_source"
|
|
|
|
def self.prewarm(...)
|
|
raise StandardError, "prewarm failed"
|
|
end
|
|
end
|
|
end
|
|
let(:plugin) { Plugin::Instance.new }
|
|
|
|
before do
|
|
DiscoursePluginRegistry.register_admin_dashboard_report_source(prewarming_provider, plugin)
|
|
DiscoursePluginRegistry.register_admin_dashboard_report_source(failing_provider, plugin)
|
|
end
|
|
|
|
after do
|
|
DiscoursePluginRegistry._raw_admin_dashboard_report_sources.reject! do |entry|
|
|
[prewarming_provider, failing_provider].include?(entry[:value])
|
|
end
|
|
end
|
|
|
|
def warmed_signups(offset)
|
|
end_date = Time.zone.now.to_date + offset
|
|
|
|
Report.find_cached(
|
|
"signups",
|
|
facets: %i[prev_period],
|
|
start_date: (end_date - 29).beginning_of_day,
|
|
end_date: end_date.end_of_day,
|
|
)
|
|
end
|
|
|
|
describe ".call" do
|
|
it "warms the default window for the server date and the neighbouring days" do
|
|
described_class.call
|
|
|
|
expect(warmed_signups(-1)).to be_present
|
|
expect(warmed_signups(0)).to be_present
|
|
expect(warmed_signups(1)).to be_present
|
|
end
|
|
|
|
it "warms the reports backing the highlights and engagement KPIs" do
|
|
described_class.call
|
|
|
|
types =
|
|
described_class.report_specs.map do |spec|
|
|
Report.find_cached(spec[:type], spec[:opts].merge(described_class.windows.second))
|
|
end
|
|
|
|
expect(types).to all(be_present)
|
|
end
|
|
|
|
it "asks report providers to warm their pinned reports for each default window" do
|
|
AdminDashboardReport.create!(
|
|
source: prewarming_provider.source_name,
|
|
identifier: "report-id",
|
|
position: 0,
|
|
)
|
|
|
|
described_class.call
|
|
|
|
expect(prewarm_calls.map { |call| call[:identifiers] }).to eq(
|
|
Array.new(described_class.windows.size, ["report-id"]),
|
|
)
|
|
expect(prewarm_calls.map { |call| call[:guardian].user }).to all(eq(Discourse.system_user))
|
|
expect(prewarm_calls.map { |call| call[:filters] }).to eq(
|
|
described_class.windows.map do |window|
|
|
{
|
|
start_date: window[:start_date].to_date.iso8601,
|
|
end_date: window[:end_date].to_date.iso8601,
|
|
}
|
|
end,
|
|
)
|
|
end
|
|
|
|
it "continues warming core reports when a pinned provider raises" do
|
|
AdminDashboardReport.create!(
|
|
source: failing_provider.source_name,
|
|
identifier: "report-id",
|
|
position: 0,
|
|
)
|
|
|
|
described_class.call
|
|
|
|
expect([warmed_signups(-1), warmed_signups(0), warmed_signups(1)]).to all(be_present)
|
|
end
|
|
end
|
|
|
|
describe ".report_specs" do
|
|
it "requests the prev_period facet for KPI reports so keys match the dashboard" do
|
|
kpi_specs =
|
|
described_class.report_specs.reject { |spec| spec[:type] == "trust_level_pipeline" }
|
|
|
|
expect(kpi_specs.map { |spec| spec[:opts] }.uniq).to eq([{ facets: %i[prev_period] }])
|
|
expect(kpi_specs.map { |spec| spec[:type] }).to include(
|
|
"signups",
|
|
"dau_by_mau",
|
|
"new_contributors",
|
|
"daily_engaged_users",
|
|
)
|
|
end
|
|
end
|
|
end
|