Class: Marketing::AdSpend::Recorder
- Inherits:
-
Object
- Object
- Marketing::AdSpend::Recorder
- Defined in:
- app/services/marketing/ad_spend/recorder.rb
Overview
Idempotently records normalized provider rows against campaign Sources.
Kept separate from the polling worker so report state transitions do not
also own Source lookup and data-point persistence policy.
Constant Summary collapse
- METRICS =
Adapter row key →
source_metric_typeenum value. Adapters that don't
supply a key return nil for it, and SourceDataPoint.bulk_record!
compacts those away rather than writing a zero.salesis the platform's OWN attributed revenue. Only the Amazon adapter
fills it, because Amazon is the only provider whose orders cannot reach a
campaign throughinvoices— see AmazonAdapter.
Everywhere else, return is read from acquisition, not from the platform. { spend: :ad_spend, clicks: :ad_clicks, impressions: :ad_impressions, conversions: :ad_conversions, sales: :ad_sales }.freeze
- METRIC_KEYS =
Metric keys an adapter row may carry; all-zero rows are skipped.
METRICS.keys.freeze
Instance Method Summary collapse
-
#call(rows_by_date:) ⇒ Hash
Persistence counts for logging/metrics.
-
#initialize(provider:, batch_id: nil, logger: Rails.logger) ⇒ Recorder
constructor
A new instance of Recorder.
Constructor Details
#initialize(provider:, batch_id: nil, logger: Rails.logger) ⇒ Recorder
Returns a new instance of Recorder.
30 31 32 33 34 |
# File 'app/services/marketing/ad_spend/recorder.rb', line 30 def initialize(provider:, batch_id: nil, logger: Rails.logger) @provider = provider @batch_id = batch_id @logger = logger end |
Instance Method Details
#call(rows_by_date:) ⇒ Hash
Returns persistence counts for logging/metrics.
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
# File 'app/services/marketing/ad_spend/recorder.rb', line 38 def call(rows_by_date:) sources = Source.where(campaign_provider: @provider) .where.not(campaign_external_id: nil) .pluck(:campaign_external_id, :id) .to_h recorded = 0 unmatched = Set.new rows_by_date.each do |date, rows| rows.each do |row| next if METRIC_KEYS.all? { |key| row[key].to_f.zero? } source_id = sources[row[:external_id]] unless source_id unmatched << row[:external_id] next end SourceDataPoint.bulk_record!( source_id:, date: date.to_date, batch_id: @batch_id, metrics: METRICS.to_h { |row_key, metric| [metric, row[row_key]] } ) recorded += 1 end end @logger.info( "[AdSpend::Recorder] #{@provider}: #{recorded} campaign-days recorded, " \ "#{unmatched.size} unmatched" ) { recorded:, unmatched: unmatched.size } end |