0
0
Fork 0
mirror of https://github.com/discourse/discourse.git synced 2026-08-05 21:16:17 +08:00
discourse/spec/models/user_visit_daily_rollup_spec.rb
Alan Guo Xiang Tan 395077a745
PERF: Use daily rollups for DAU/MAU reports (#41958)
DAU/MAU reports previously calculated every requested date from the full
user visit history, so dashboard requests became slower as that history
grew.

Persist the daily DAU and trailing-30-day MAU values and have the shared
report read only those rollups. The scheduled job builds all existing
history on its first successful run, then refreshes yesterday and today
every three hours. Replacements are atomic, so a failed calculation
leaves the previous report data intact.
2026-07-24 09:52:40 +08:00

50 lines
1.7 KiB
Ruby
Vendored

# frozen_string_literal: true
RSpec.describe UserVisitDailyRollup do
fab!(:visitor, :user)
before { freeze_time(Time.zone.local(2026, 7, 23, 12)) }
describe ".fetch" do
it "returns existing rows in date order and omits dates without rows" do
described_class.create!(date: 2.days.ago, dau: 1, mau: 3)
described_class.create!(date: Time.zone.today, dau: 2, mau: 4)
rows = described_class.fetch(start_date: 2.days.ago, end_date: Time.zone.today)
expect(rows).to eq(
[
{ "date" => 2.days.ago.to_date, "dau" => 1, "mau" => 3 },
{ "date" => Time.zone.today, "dau" => 2, "mau" => 4 },
],
)
end
end
describe ".aggregate" do
it "stores the same daily values as the established calculation" do
visitor.user_visits.create!(visited_at: Time.zone.today)
historical_visitor = Fabricate(:user)
historical_visitor.user_visits.create!(visited_at: 10.days.ago)
expected = UserVisit.count_by_active_users(10.days.ago, Time.zone.today)
described_class.aggregate(start_date: 10.days.ago, end_date: Time.zone.today)
expect(described_class.fetch(start_date: 10.days.ago, end_date: Time.zone.today)).to eq(
expected,
)
end
it "keeps existing report data when a refresh fails" do
existing = described_class.create!(date: Time.zone.today, dau: 3, mau: 4)
described_class.stubs(:insert_all!).raises(ActiveRecord::StatementInvalid)
visitor.user_visits.create!(visited_at: Time.zone.today)
expect do
described_class.aggregate(start_date: Time.zone.today, end_date: Time.zone.today)
end.to raise_error(ActiveRecord::StatementInvalid)
expect(existing.reload).to have_attributes(dau: 3, mau: 4)
end
end
end