Class: SeoBatchPollWorker

Inherits:
Object
  • Object
show all
Includes:
Sidekiq::Worker
Defined in:
app/workers/seo_batch_poll_worker.rb

Overview

Phase 2b: Poll the Batch API for completion.

Routes to the correct provider (Gemini or Anthropic) based on the
SeoBatchJob's model. Re-enqueues itself with exponential backoff
until the batch reaches a terminal state, then enqueues
SeoBatchResultsWorker to process results.

Polling schedule (exponential backoff):
2 min -> 4 min -> 8 min -> 15 min (capped)

Max polling duration: 24 hours (provider batch expiry limit).

Usage:
SeoBatchPollWorker.perform_async(batch_job_id)
SeoBatchPollWorker.perform_async(batch_job_id, { 'attempt' => 3 })

Constant Summary collapse

MAX_POLL_ATTEMPTS =

~24 hours at 15-min intervals

120
MIN_BACKOFF_SECONDS =

2 minutes

120
MAX_BACKOFF_SECONDS =

15 minutes

900

Instance Method Summary collapse

Instance Method Details

#perform(batch_job_id, options = {}) ⇒ Object



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'app/workers/seo_batch_poll_worker.rb', line 28

def perform(batch_job_id, options = {})
  options = options.with_indifferent_access
  attempt = (options[:attempt] || 1).to_i

  batch_job = SeoBatchJob.find(batch_job_id)

  unless batch_job.processing?
    log_info "Batch job #{batch_job_id} is #{batch_job.status} — stopping poll"
    return
  end

  if attempt > MAX_POLL_ATTEMPTS
    batch_job.mark_failed!("Polling timed out after #{MAX_POLL_ATTEMPTS} attempts")
    log_error "Polling timed out for batch job #{batch_job_id}"
    return
  end

  if batch_job.gemini?
    poll_gemini(batch_job, attempt)
  else
    poll_anthropic(batch_job, attempt)
  end
rescue Seo::GeminiBatchClient::BatchError, Seo::AnthropicBatchClient::BatchError => e
  log_error "Poll failed: #{e.message}"
  if attempt < MAX_POLL_ATTEMPTS
    self.class.perform_in(MAX_BACKOFF_SECONDS, batch_job_id, { 'attempt' => attempt + 1 })
  else
    batch_job.mark_failed!("Poll error after #{attempt} attempts: #{e.message}")
  end
end