0
0
Fork 0
mirror of https://github.com/discourse/discourse.git synced 2026-08-05 19:38:04 +08:00
discourse/app/models/browser_pageview_referrer_daily_rollup.rb
Krzysztof Kotlarek 820ebddd65
FIX: Split browser pageview rollup source at the cutover date (#42013)
Previously, the pageview rollups picked a single event source globally:
beacon when the `dashboard_improvements` upcoming change was enabled,
piggyback otherwise — so enabling the change silently rebuilt historical
days from sparse beacon data, and disabling it discarded beacon-era
days.

This change replaces `BrowserPageviewEvent.rollup_source` with a
per-date condition based on `beacon_cutover_date`: days before the
cutover are aggregated from piggyback events and days from the cutover
onwards from beacon events, matching how the dashboard traffic chart
already splits its counters.
2026-07-24 14:56:36 +08:00

71 lines
2.3 KiB
Ruby
Vendored

# frozen_string_literal: true
class BrowserPageviewReferrerDailyRollup < ActiveRecord::Base
def self.aggregate(start_date:, end_date:)
start_date = start_date.to_date
end_date = end_date.to_date + 1
DB.exec(<<~SQL, start_date:, end_date:)
INSERT INTO browser_pageview_referrer_daily_rollups (date, normalized_referrer, count, logged_in_count)
SELECT
created_at::date AS date,
normalized_referrer,
COUNT(*) AS count,
COUNT(*) FILTER (WHERE user_id IS NOT NULL) AS logged_in_count
FROM browser_pageview_events
WHERE created_at >= :start_date
AND created_at < :end_date
AND #{BrowserPageviewEvent.rollup_source_condition}
GROUP BY date, normalized_referrer
ON CONFLICT (date, normalized_referrer) DO UPDATE
SET count = EXCLUDED.count,
logged_in_count = EXCLUDED.logged_in_count
SQL
end
def self.recompute(dates)
dates = Array(dates).map(&:to_date).uniq
return if dates.empty?
# The rollups are the permanent record, but their source events are pruned
# after a retention period (CleanUpBrowserPageviewEvents). Only rebuild
# dates that still have events so we never delete a rollup we can no longer
# reconstruct from events.
dates = DB.query_single(<<~SQL, dates:)
SELECT d.date
FROM unnest(ARRAY[:dates]::date[]) AS d(date)
WHERE EXISTS (
SELECT 1
FROM browser_pageview_events e
WHERE e.created_at >= d.date
AND e.created_at < d.date + 1
AND #{BrowserPageviewEvent.rollup_source_condition(table: "e")}
)
SQL
return if dates.empty?
transaction do
DB.exec(<<~SQL, dates: dates)
DELETE FROM browser_pageview_referrer_daily_rollups
WHERE date IN (:dates)
SQL
dates.each { |date| aggregate(start_date: date, end_date: date) }
end
end
end
# == Schema Information
#
# Table name: browser_pageview_referrer_daily_rollups
#
# id :bigint not null, primary key
# count :bigint not null
# date :date not null
# logged_in_count :bigint not null
# normalized_referrer :string(2000)
#
# Indexes
#
# idx_bprd_rollups_date_referrer_unique (date,normalized_referrer) UNIQUE NULLS NOT DISTINCT
#