Fix race analytics: retry su unique violation in aggregazione heatmap.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-08-21 16:23:02 +02:00
co-authored by Cursor
parent 4573edfedc
commit 873e0ea55c
2 changed files with 41 additions and 16 deletions
+32 -15
View File
@@ -3,6 +3,7 @@
module Analytics
class Aggregate
BATCH = 500
UPSERT_RETRIES = 3
def call
loop do
@@ -45,13 +46,15 @@ module Analytics
now = Time.current
grouped.each do |(day, page_path, device, cell_x, cell_y), count|
cell = AnalyticsPageCell.find_or_initialize_by(
day: day, page_path: page_path, device: device, cell_x: cell_x, cell_y: cell_y
)
cell[counter_attr] = cell[counter_attr].to_i + count
cell.created_at ||= now
cell.updated_at = now
cell.save!
with_unique_retry do
cell = AnalyticsPageCell.find_or_initialize_by(
day: day, page_path: page_path, device: device, cell_x: cell_x, cell_y: cell_y
)
cell[counter_attr] = cell[counter_attr].to_i + count
cell.created_at ||= now
cell.updated_at = now
cell.save!
end
end
end
@@ -76,14 +79,28 @@ module Analytics
now = Time.current
grouped.each do |(day, page_path, device), vals|
stat = AnalyticsPageStat.find_or_initialize_by(day: day, page_path: page_path, device: device)
stat.pageview_count = stat.pageview_count.to_i + vals[:pageviews]
stat.scroll_samples = stat.scroll_samples.to_i + vals[:scroll_samples]
stat.scroll_sum_pct = stat.scroll_sum_pct.to_i + vals[:scroll_sum]
stat.max_scroll_pct = [stat.max_scroll_pct.to_i, vals[:max_scroll]].max
stat.created_at ||= now
stat.updated_at = now
stat.save!
with_unique_retry do
stat = AnalyticsPageStat.find_or_initialize_by(day: day, page_path: page_path, device: device)
stat.pageview_count = stat.pageview_count.to_i + vals[:pageviews]
stat.scroll_samples = stat.scroll_samples.to_i + vals[:scroll_samples]
stat.scroll_sum_pct = stat.scroll_sum_pct.to_i + vals[:scroll_sum]
stat.max_scroll_pct = [stat.max_scroll_pct.to_i, vals[:max_scroll]].max
stat.created_at ||= now
stat.updated_at = now
stat.save!
end
end
end
def with_unique_retry
attempts = 0
begin
attempts += 1
yield
rescue ActiveRecord::RecordNotUnique
raise if attempts >= UPSERT_RETRIES
retry
end
end
end