fix(jobs): resolve channel service class by name in SendReplyJob

CHANNEL_SERVICES held frozen references to service class objects, captured
when SendReplyJob was first autoloaded. In test env (cache_classes=false),
Zeitwerk reloads triggered between specs (notably by request specs)
replaced the constants with new class objects, leaving the hash pointing
to the stale ones. RSpec stubs applied to the current constant were then
bypassed when the job called service_class.new(...) through the stale
reference, causing flaky CI failures in spec/jobs/send_reply_job_spec.rb
when sharded together with V2::ReportBuilder + Captain::Preferences specs.

Storing class names as strings and resolving via constantize per call
fixes this and is the standard Rails autoload-safe pattern.
This commit is contained in:
gabrieljablonski 2026-04-17 21:24:29 -03:00
parent 35ea658548
commit b0e7688aad

View File

@ -2,17 +2,17 @@ class SendReplyJob < ApplicationJob
queue_as :high
CHANNEL_SERVICES = {
'Channel::TwitterProfile' => ::Twitter::SendOnTwitterService,
'Channel::TwilioSms' => ::Twilio::SendOnTwilioService,
'Channel::Line' => ::Line::SendOnLineService,
'Channel::Telegram' => ::Telegram::SendOnTelegramService,
'Channel::Whatsapp' => ::Whatsapp::SendOnWhatsappService,
'Channel::Sms' => ::Sms::SendOnSmsService,
'Channel::Instagram' => ::Instagram::SendOnInstagramService,
'Channel::Tiktok' => ::Tiktok::SendOnTiktokService,
'Channel::Email' => ::Email::SendOnEmailService,
'Channel::WebWidget' => ::Messages::SendEmailNotificationService,
'Channel::Api' => ::Messages::SendEmailNotificationService
'Channel::TwitterProfile' => '::Twitter::SendOnTwitterService',
'Channel::TwilioSms' => '::Twilio::SendOnTwilioService',
'Channel::Line' => '::Line::SendOnLineService',
'Channel::Telegram' => '::Telegram::SendOnTelegramService',
'Channel::Whatsapp' => '::Whatsapp::SendOnWhatsappService',
'Channel::Sms' => '::Sms::SendOnSmsService',
'Channel::Instagram' => '::Instagram::SendOnInstagramService',
'Channel::Tiktok' => '::Tiktok::SendOnTiktokService',
'Channel::Email' => '::Email::SendOnEmailService',
'Channel::WebWidget' => '::Messages::SendEmailNotificationService',
'Channel::Api' => '::Messages::SendEmailNotificationService'
}.freeze
def perform(message_id)
@ -21,10 +21,10 @@ class SendReplyJob < ApplicationJob
return send_on_facebook_page(message) if channel_name == 'Channel::FacebookPage'
service_class = CHANNEL_SERVICES[channel_name]
return unless service_class
service_class_name = CHANNEL_SERVICES[channel_name]
return unless service_class_name
service_class.new(message: message).perform
service_class_name.constantize.new(message: message).perform
end
private