Class: SeoBatchPollWorker
- Inherits:
-
Object
- Object
- SeoBatchPollWorker
- Includes:
- Sidekiq::Job
- 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 |
# File 'app/workers/seo_batch_poll_worker.rb', line 28 def perform(batch_job_id, = {}) attempt = (['attempt'] || [: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.}" 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.}") end end |