Class: AdSpendAmazonReportPollWorker

Inherits:
Object
  • Object
show all
Includes:
Sidekiq::Job
Defined in:
app/workers/ad_spend_amazon_report_poll_worker.rb

Overview

Performs one Amazon Ads report-status sweep, records reports that completed,
and reschedules the remaining state. Every execution is short: waiting lives
in Redis, not in a Sidekiq thread. When this job belongs to an ad-spend batch,
each successor is registered in that same batch before the current job ends.

Defined Under Namespace

Classes: ReportExpired, ReportFailed

Constant Summary collapse

POLL_INTERVAL =

Max report age.

30.seconds
MAX_REPORT_AGE =

Constant.

2.hours

Instance Method Summary collapse

Instance Method Details

#perform(reports, start_date, end_date, batch_id = nil, started_at = nil, attempt = 1) ⇒ Object

Runs the job.

Parameters:

  • reports (Report)

    the reports to evaluate

  • start_date (Date)

    the start date

  • end_date (Date)

    the end date

  • batch_id (Integer, nil) (defaults to: nil)

    the batch id

  • started_at (Time, nil) (defaults to: nil)

    the started at

  • attempt (Integer) (defaults to: 1)

    the attempt to evaluate

Returns:

  • (Object)

    the result



35
36
37
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
72
73
74
75
76
77
78
79
# File 'app/workers/ad_spend_amazon_report_poll_worker.rb', line 35

def perform(reports, start_date, end_date, batch_id = nil, started_at = nil, attempt = 1)
  started_at = started_at.presence || Time.current.iso8601
  ensure_not_expired!(reports, started_at)

  pending = []
  completed = 0
  remaining = reports.dup
  until remaining.empty?
    report = remaining.shift
    result = Marketing::AdSpend::AmazonAdapter.poll_report(report, default_date: Date.parse(start_date))
    case result.fetch(:state)
    when :completed
      Marketing::AdSpend::Recorder.new(provider: 'amazon_ads', batch_id:).call(
        rows_by_date: result.fetch(:rows_by_date)
      )
      completed += 1
    when :pending
      pending << report
    when :failed
      retry_reports = pending + remaining
      report_progress(
        reports:, pending: retry_reports, completed:, start_date:, end_date:, started_at:, attempt:,
        action: 'failed'
      )
      if retry_reports.any?
        schedule_poll(
          retry_reports, start_date, end_date, batch_id, started_at, attempt + 1, POLL_INTERVAL
        )
      end
      raise ReportFailed, "Amazon Ads report #{report['report_id'] || report[:report_id]} failed"
    end
  end

  report_progress(reports:, pending:, completed:, start_date:, end_date:, started_at:, attempt:)
  schedule_poll(pending, start_date, end_date, batch_id, started_at, attempt + 1, POLL_INTERVAL) if pending.any?
rescue AmazonAds::ApiClient::ThrottledError
  Marketing::AdSpend::RunState.open_cooldown!
  delay = Marketing::AdSpend::RunState.cooldown_remaining.seconds
  retry_reports = pending + [report] + remaining
  report_progress(
    reports:, pending: retry_reports, completed:, start_date:, end_date:, started_at:, attempt:,
    action: 'throttled', retry_in_seconds: delay.to_i
  )
  schedule_poll(retry_reports, start_date, end_date, batch_id, started_at, attempt + 1, delay)
end