Class: MicrosoftAdsTokenRefreshWorker

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

Overview

Proactively refreshes the system-level Microsoft Advertising OAuth token every
45 minutes (scheduled in config/sidekiq_production_schedule.yml).

Microsoft access tokens are short-lived (~1 hour) — the same as YouTube's, so
this uses the same every-45-minute cadence rather than the daily cadence that
suits Pinterest's long-lived token. MicrosoftAds::OauthService#access_token!
still refreshes lazily on demand as a safety net, but a daily-only refresh left
the token Expired ~23 hours a day (it lives ~1h), which looks broken on the
admin dashboard and forces a synchronous refresh on the first upload after an
idle gap. Refreshing proactively keeps it Active. It also:

  1. keeps the long-lived refresh token exercised (Microsoft may rotate it
    on use, and the new value is persisted by the OAuth service), and
  2. surfaces an invalidated grant (revoked consent, changed password,
    removed app permission) proactively via
    OauthCredential#record_refresh_failure! — alerting the connecting
    admin rather than waiting for the next campaign sync or conversion
    upload to fail.

Instance Method Summary collapse

Instance Method Details

#performObject

Runs the job.

Returns:

  • (Object)

    the result



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'app/workers/microsoft_ads_token_refresh_worker.rb', line 31

def perform
  # Advisory lock guards against concurrent refreshes (scheduler overlap,
  # Sidekiq retry, manual enqueue). Microsoft may rotate the refresh token
  # on use, so two overlapping runs could invalidate each other.
  # timeout_seconds: 0 — if another run holds the lock, skip; it has it covered.
  OauthCredential.with_advisory_lock('microsoft_ads_token_refresh', timeout_seconds: 0) do
    credentials = OauthCredential.where(provider: MicrosoftAds::OauthService::PROVIDER)

    if credentials.none?
      Rails.logger.info('[MicrosoftAdsTokenRefreshWorker] No Microsoft Advertising credential — nothing to refresh')
      next
    end

    credentials.find_each { |cred| refresh_credential(cred) }
  end
end