diff --git a/config/features.yml b/config/features.yml index fdeee335e78..da3db4377d4 100644 --- a/config/features.yml +++ b/config/features.yml @@ -1872,6 +1872,9 @@ features: show_yellow_ribbon_table: actor_type: user description: Used to show yellow ribbon table in Comparison Tool + banner_update_alternative_banners: + actor_type: user + description: Used to toggle the DB updating of alternative banners banner_use_alternative_banners: actor_type: user description: Used to toggle use of alternative banners. diff --git a/lib/periodic_jobs.rb b/lib/periodic_jobs.rb index 526efe95789..fa405255039 100644 --- a/lib/periodic_jobs.rb +++ b/lib/periodic_jobs.rb @@ -48,6 +48,9 @@ # Checks status of Flipper features expected to be enabled and alerts to Slack if any are not enabled mgr.register('0 2,9,16 * * 1-5', 'AppealsApi::FlipperStatusAlert') + # Update alternative Banners data every 10 minutes + mgr.register('*/10 * * * *', 'Banners::UpdateAll') + # Update static data cache mgr.register('0 0 * * *', 'Crm::TopicsDataJob') diff --git a/modules/banners/app/sidekiq/banners/update_all_job.rb b/modules/banners/app/sidekiq/banners/update_all_job.rb new file mode 100644 index 00000000000..85de00945f8 --- /dev/null +++ b/modules/banners/app/sidekiq/banners/update_all_job.rb @@ -0,0 +1,56 @@ +# frozen_string_literal: true + +module Banners + class UpdateAllJob + include Sidekiq::Job + + STATSD_KEY_PREFIX = 'banners.sidekiq.update_all_banners' + + sidekiq_options retry: 5 + + sidekiq_retries_exhausted do |msg, _ex| + job_id = msg['jid'] + job_class = msg['class'] + error_class = msg['error_class'] + error_message = msg['error_message'] + + StatsD.increment("#{STATSD_KEY_PREFIX}.exhausted") + + message = "#{job_class} retries exhausted" + Rails.logger.error(message, { job_id:, error_class:, error_message: }) + rescue => e + Rails.logger.error( + "Failure in #{job_class}#sidekiq_retries_exhausted", + { + messaged_content: e.message, + job_id:, + pre_exhaustion_failure: { + error_class:, + error_message: + } + } + ) + + raise e + end + + def perform + return unless enabled? + + Banners.update_all + rescue Banners::Updater::BannerDataFetchError => e + StatsD.increment("#{STATSD_KEY_PREFIX}.banner_data_fetch_error") + Rails.logger.error( + 'Banner data fetch failed', + { error_message: e.message, error_class: e.class.name } + ) + raise e # Re-raise to trigger Sidekiq retries + end + + private + + def enabled? + Flipper.enabled?(:banner_update_alternative_banners) + end + end +end diff --git a/modules/banners/lib/banners/updater.rb b/modules/banners/lib/banners/updater.rb index ab03d162f1b..01eac1a2d8f 100644 --- a/modules/banners/lib/banners/updater.rb +++ b/modules/banners/lib/banners/updater.rb @@ -7,6 +7,8 @@ module Banners class Updater STATSD_KEY_PREFIX = 'banners.updater' + class BannerDataFetchError < StandardError; end + # If banners are to be added in the future, include them here by adding # another #update_{type_of}_banners method for #perform to call def self.perform @@ -70,8 +72,8 @@ def vamcs_banner_data begin JSON.parse(response.body).dig('data', 'nodeQuery', 'entities') - rescue JSON::ParserError - [] + rescue JSON::ParserError => e + raise BannerDataFetchError, "Failed to parse VAMC banner data: #{e.message}" end end end diff --git a/modules/banners/spec/lib/updater_spec.rb b/modules/banners/spec/lib/updater_spec.rb index 325bc99e687..4c84f47ad81 100644 --- a/modules/banners/spec/lib/updater_spec.rb +++ b/modules/banners/spec/lib/updater_spec.rb @@ -70,8 +70,8 @@ context 'when response is invalid JSON' do let(:response_body) { 'invalid json' } - it 'returns empty array' do - expect(updater.send(:vamcs_banner_data)).to eq([]) + it 'returns an error' do + expect { updater.send(:vamcs_banner_data) }.to raise_error(Banners::Updater::BannerDataFetchError) end end end