docbrown/app/services/billboard_event_rollup.rb
Ben Halpern e7fc1bb0ce
Add article id and geolocation info to billboard events (#20329)
* Add article id and geolocation info to billboard events

* Confirm destroyed in rollup
2023-11-09 12:43:23 -05:00

92 lines
2.3 KiB
Ruby

class BillboardEventRollup
ATTRIBUTES_PRESERVED = %i[user_id display_ad_id category context_type created_at].freeze
ATTRIBUTES_DESTROYED = %i[id counts_for updated_at article_id geolocation].freeze
class EventAggregator
Compact = Struct.new(:events, :user_id, :billboard_id, :category, :context_type) do
def to_h
super.except(:events).merge({ counts_for: events.sum(&:counts_for) })
end
end
def initialize
@aggregator = Hash.new do |level1, user_id|
level1[user_id] = Hash.new do |level2, billboard_id|
level2[billboard_id] = Hash.new do |level3, category|
level3[category] = Hash.new do |level4, context_type|
level4[context_type] = []
end
end
end
end
end
def <<(event)
@aggregator[event.user_id][event.billboard_id][event.category][event.context_type] << event
end
def each
@aggregator.each_pair do |user_id, grouped_by_user_id|
grouped_by_user_id.each_pair do |billboard_id, grouped_by_billboard_id|
grouped_by_billboard_id.each_pair do |category, grouped_by_category|
grouped_by_category.each_pair do |context_type, events|
next unless events.size > 1
yield Compact.new(events, user_id, billboard_id, category, context_type)
end
end
end
end
end
private
attr_reader :aggregator
end
def self.rollup(date, relation: BillboardEvent)
new(relation: relation).rollup(date)
end
def initialize(relation:)
@aggregator = EventAggregator.new
@relation = relation
end
attr_reader :aggregator, :relation
def rollup(date)
created = []
rows = relation.where(created_at: date.all_day)
aggregate_into_groups(rows).each do |compacted_events|
created << compact_records(date, compacted_events)
end
created
end
private
def aggregate_into_groups(rows)
rows.in_batches.each_record do |event|
aggregator << event
end
aggregator
end
def compact_records(date, compacted)
result = nil
relation.transaction do
result = relation.create!(compacted.to_h) do |event|
event.created_at = date
end
relation.where(id: compacted.events).delete_all
end
result
end
end