Class: ConversionRetrySweepWorker

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

Overview

Daily sweep that re-enqueues failed-but-not-yet-reported CAPI conversions
for Pinterest and OpenAI Ads (ChatGPT).

Why we need this. Pinterest's and OpenAI Ads' conversion reporters
both persist a row in <provider>_conversion_meta whenever a send is
attempted — result: :failed on transport / validation / 4xx errors,
plus the upstream error message. The dispatch workers
(PinterestConversionWorker, OpenaiAdsConversionWorker) only fire on
Order#after_transition any => :invoiced and on
OpportunityFollowedUpHandler, so a transient failure (rate limit,
upstream outage, the Faraday-positional-args bug fixed in AppSignal
#5214) ends with the meta carrying result: :failed and
reported_at: nil forever — the conversion is silently lost.

This worker scans for that exact state and re-enqueues each record
through its provider-specific worker. The reporter's already_reported
guard (checks reported_at, not attempted_at) lets the retry
proceed cleanly; if the previous failure was transient the retry
succeeds and reported_at is stamped, lifting it out of this sweep's
scope for future runs. Sidekiq's unique-jobs middleware dedupes
overlapping enqueues.

Parity with Google. GoogleOfflineConversionRetryWorker does the
equivalent thing for the Google reporter (different reporter shape, so
its own worker). Both share the 7-day cutoff convention — a quote that
attempted to send a week ago and never succeeded is almost certainly
permanent debt, not retry candidate; keep noise out of AppSignal.

Constant Summary collapse

CUTOFF =

How far back to look. Older failures are treated as permanent and
stop appearing in the sweep — matches Google's 7-day window.

7.days
BATCH_SIZE =

Pull DB rows in batches so a backlog of thousands doesn't load
everything at once.

200
PROVIDERS =

Each entry: column (the JSONB column on Order/Opportunity), worker
(the Sidekiq class to re-enqueue against), name (for log messages).

[
  { name: 'Pinterest',  worker: 'PinterestConversionWorker', column: 'pinterest_conversion_meta' },
  { name: 'OpenAI Ads', worker: 'OpenaiAdsConversionWorker', column: 'openai_ads_conversion_meta' }
].freeze

Instance Method Summary collapse

Instance Method Details

#performObject



55
56
57
58
59
60
# File 'app/workers/conversion_retry_sweep_worker.rb', line 55

def perform
  PROVIDERS.each do |provider|
    retry_failed(provider, Order,       'order')
    retry_failed(provider, Opportunity, 'opportunity')
  end
end