From d0d08ed6624231bf67fe855ddd49e09ad04d7eb7 Mon Sep 17 00:00:00 2001 From: Rodribm10 Date: Wed, 15 Apr 2026 09:20:32 -0300 Subject: [PATCH] feat(lifecycle): implement DispatcherJob Replace no-op stub with full perform body: find delivery by id, skip if blank, delegate to Captain::Lifecycle::Dispatcher#call. Add retry_on with polynomially_longer backoff (3 attempts). Spec covers dispatcher delegation and graceful skip for missing records. Co-Authored-By: Claude Sonnet 4.6 --- .../jobs/captain/lifecycle/dispatcher_job.rb | 6 ++++- .../captain/lifecycle/dispatcher_job_spec.rb | 22 +++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 spec/enterprise/jobs/captain/lifecycle/dispatcher_job_spec.rb diff --git a/enterprise/app/jobs/captain/lifecycle/dispatcher_job.rb b/enterprise/app/jobs/captain/lifecycle/dispatcher_job.rb index 69ebe66d1..9db190fe3 100644 --- a/enterprise/app/jobs/captain/lifecycle/dispatcher_job.rb +++ b/enterprise/app/jobs/captain/lifecycle/dispatcher_job.rb @@ -2,12 +2,16 @@ class Captain::Lifecycle::DispatcherJob < ApplicationJob queue_as :default + retry_on StandardError, wait: :polynomially_longer, attempts: 3 def self.perform_at(fire_at, delivery_id) set(wait_until: fire_at).perform_later(delivery_id) end def perform(delivery_id) - # Stub — full implementation lands in Task 16. + delivery = Captain::Lifecycle::Delivery.find_by(id: delivery_id) + return if delivery.blank? + + Captain::Lifecycle::Dispatcher.new(delivery).call end end diff --git a/spec/enterprise/jobs/captain/lifecycle/dispatcher_job_spec.rb b/spec/enterprise/jobs/captain/lifecycle/dispatcher_job_spec.rb new file mode 100644 index 000000000..3ab07a0e9 --- /dev/null +++ b/spec/enterprise/jobs/captain/lifecycle/dispatcher_job_spec.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe Captain::Lifecycle::DispatcherJob do + let(:delivery) { create(:captain_lifecycle_delivery) } + + it 'calls Dispatcher#call' do + dispatcher = instance_double(Captain::Lifecycle::Dispatcher) + expect(Captain::Lifecycle::Dispatcher) + .to receive(:new) + .with(instance_of(Captain::Lifecycle::Delivery)) + .and_return(dispatcher) + expect(dispatcher).to receive(:call) + + described_class.perform_now(delivery.id) + end + + it 'silently skips missing delivery records' do + expect { described_class.perform_now(-1) }.not_to raise_error + end +end