amelioration(email): passe les jobs non prioritaire [appelons ça des bulk email], dans la queue de low_priority

This commit is contained in:
Martin 2023-10-18 07:10:26 +02:00
parent dbb68f29da
commit b69d4baaa2
26 changed files with 190 additions and 35 deletions

View file

@ -0,0 +1,14 @@
class PriorizedMailDeliveryJob < ActionMailer::MailDeliveryJob
def queue_name
mailer, action_name = @arguments
if mailer.constantize.critical_email?(action_name)
super
else
custom_queue
end
end
def custom_queue
ENV.fetch('BULK_EMAIL_QUEUE') { Rails.application.config.action_mailer.deliver_later_queue_name }
end
end

View file

@ -39,9 +39,7 @@ class AdministrateurMailer < ApplicationMailer
reply_to: CONTACT_EMAIL) reply_to: CONTACT_EMAIL)
end end
private def self.critical_email?(action_name)
def forced_delivery_for_action?
action_name == "activate_before_expiration" action_name == "activate_before_expiration"
end end
end end

View file

@ -20,4 +20,8 @@ class AdministrationMailer < ApplicationMailer
subject: subject, subject: subject,
reply_to: CONTACT_EMAIL) reply_to: CONTACT_EMAIL)
end end
def self.critical_email?(action_name)
false
end
end end

View file

@ -2,6 +2,7 @@ class ApplicationMailer < ActionMailer::Base
include MailerDolistConcern include MailerDolistConcern
include MailerMonitoringConcern include MailerMonitoringConcern
include BalancedDeliveryConcern include BalancedDeliveryConcern
include PriorityDeliveryConcern
helper :application # gives access to all helpers defined within `application_helper`. helper :application # gives access to all helpers defined within `application_helper`.
default from: "#{APPLICATION_NAME} <#{CONTACT_EMAIL}>" default from: "#{APPLICATION_NAME} <#{CONTACT_EMAIL}>"

View file

@ -19,4 +19,8 @@ class AvisMailer < ApplicationMailer
mail(to: email, subject: subject) mail(to: email, subject: subject)
end end
end end
def self.critical_email?(action_name)
false
end
end end

View file

@ -2,16 +2,16 @@ module BalancedDeliveryConcern
extend ActiveSupport::Concern extend ActiveSupport::Concern
included do included do
before_action :add_delivery_method, if: :forced_delivery? before_action :add_delivery_method, if: :forced_delivery_provider?
def critical_email?
self.class.critical_email?(action_name)
end
private private
def forced_delivery_for_action? def forced_delivery_provider?
false SafeMailer.forced_delivery_method.present? && critical_email?
end
def forced_delivery?
SafeMailer.forced_delivery_method.present? && forced_delivery_for_action?
end end
def add_delivery_method def add_delivery_method

View file

@ -0,0 +1,10 @@
module PriorityDeliveryConcern
extend ActiveSupport::Concern
included do
self.delivery_job = PriorizedMailDeliveryJob
def self.critical_email?(action_name)
raise NotImplementedError
end
end
end

View file

@ -6,6 +6,8 @@ class DeviseUserMailer < Devise::Mailer
include MailerDolistConcern include MailerDolistConcern
include MailerMonitoringConcern include MailerMonitoringConcern
include BalancedDeliveryConcern include BalancedDeliveryConcern
include PriorityDeliveryConcern
layout 'mailers/layout' layout 'mailers/layout'
def template_paths def template_paths
@ -19,7 +21,7 @@ class DeviseUserMailer < Devise::Mailer
super super
end end
def forced_delivery_for_action? def self.critical_email?(action_name)
true true
end end
end end

View file

@ -184,6 +184,10 @@ class DossierMailer < ApplicationMailer
end end
end end
def self.critical_email?(action_name)
false
end
protected protected
def prevent_perform_deliveries def prevent_perform_deliveries

View file

@ -22,6 +22,10 @@ class ExpertMailer < ApplicationMailer
mail(template_name: 'send_dossier_decision', to: email, subject: subject) mail(template_name: 'send_dossier_decision', to: email, subject: subject)
end end
def self.critical_email?(action_name)
false
end
end end
def decision_dossier(dossier) def decision_dossier(dossier)

View file

@ -18,4 +18,8 @@ class GroupeGestionnaireMailer < ApplicationMailer
mail(bcc: added_gestionnaire_emails, subject: subject) mail(bcc: added_gestionnaire_emails, subject: subject)
end end
def self.critical_email?(action_name)
false
end
end end

View file

@ -27,4 +27,8 @@ class GroupeInstructeurMailer < ApplicationMailer
mail(bcc: added_instructeur_emails, subject: subject) mail(bcc: added_instructeur_emails, subject: subject)
end end
def self.critical_email?(action_name)
false
end
end end

View file

@ -45,9 +45,7 @@ class InstructeurMailer < ApplicationMailer
mail(to: instructeur.email, subject: subject) mail(to: instructeur.email, subject: subject)
end end
private def self.critical_email?(action_name)
def forced_delivery_for_action?
action_name == "send_login_token" action_name == "send_login_token"
end end
end end

View file

@ -33,7 +33,7 @@ class InviteMailer < ApplicationMailer
reply_to: reply_to) reply_to: reply_to)
end end
def forced_delivery_for_action? def self.critical_email?(action_name)
true true
end end
end end

View file

@ -48,6 +48,10 @@ class NotificationMailer < ApplicationMailer
with(dossier: dossier).send_notification with(dossier: dossier).send_notification
end end
def self.critical_email?(action_name)
false
end
private private
def set_services_publics_plus def set_services_publics_plus

View file

@ -30,4 +30,8 @@ class PreactivateUsersMailer < ApplicationMailer
reply_to: CONTACT_EMAIL, reply_to: CONTACT_EMAIL,
body: body) body: body)
end end
def self.critical_email?(action_name)
false
end
end end

View file

@ -8,6 +8,10 @@ class ResendAttestationMailer < ApplicationMailer
mail(to: to, subject: subject, body: body(dossier)) mail(to: to, subject: subject, body: body(dossier))
end end
def self.critical_email?(action_name)
false
end
private private
def body(dossier) def body(dossier)

View file

@ -4,4 +4,8 @@ class SuperAdminMailer < ApplicationMailer
mail(to: to, subject: "Dolist report", body: "Ci-joint le rapport d'emails récents envoyés via Dolist.") mail(to: to, subject: "Dolist report", body: "Ci-joint le rapport d'emails récents envoyés via Dolist.")
end end
def self.critical_email?(action_name)
false
end
end end

View file

@ -67,7 +67,7 @@ class UserMailer < ApplicationMailer
mail(to: administrateur_or_instructeur.email, subject: subject) mail(to: administrateur_or_instructeur.email, subject: subject)
end end
def forced_delivery_for_action? def self.critical_email?(action_name)
['france_connect_merge_confirmation', "new_account_warning", "ask_for_merge", "invite_instructeur"].include?(action_name) ['france_connect_merge_confirmation', "new_account_warning", "ask_for_merge", "invite_instructeur"].include?(action_name)
end end
end end

View file

@ -236,3 +236,4 @@ DS_LOG_LEVEL='info'
# Admins group usage (gestionnaire de groupes d'administrateurs) # Admins group usage (gestionnaire de groupes d'administrateurs)
# can be removed if needed when EVERY PARTS of the feature will be merged / only used in routes.rb # can be removed if needed when EVERY PARTS of the feature will be merged / only used in routes.rb
ADMINS_GROUP_ENABLED="disabled" ADMINS_GROUP_ENABLED="disabled"
BULK_EMAIL_QUEUE="low_priority"

View file

@ -86,7 +86,7 @@ Rails.application.configure do
helo: ENV['HELO_ENABLED'] == 'enabled' ? 100 : 0, helo: ENV['HELO_ENABLED'] == 'enabled' ? 100 : 0,
letter_opener: ENV['HELO_ENABLED'] == 'enabled' ? 0 : 100 letter_opener: ENV['HELO_ENABLED'] == 'enabled' ? 0 : 100
} }
config.action_mailer.delivery_method = :balancer config.action_mailer.delivery_method = :letter_opener_web
config.action_mailer.default_url_options = { host: ENV.fetch("APP_HOST") } config.action_mailer.default_url_options = { host: ENV.fetch("APP_HOST") }
config.action_mailer.asset_host = "http://" + ENV.fetch("APP_HOST") config.action_mailer.asset_host = "http://" + ENV.fetch("APP_HOST")

View file

@ -1,32 +1,57 @@
RSpec.describe AdministrateurMailer, type: :mailer do RSpec.describe AdministrateurMailer, type: :mailer do
let(:procedure) { create(:procedure) } let(:procedure) { create(:procedure) }
let(:admin_email) { 'administrateur@email.fr' } let(:admin_email) { 'administrateur@email.fr' }
describe '.notify_procedure_expires_when_termine_forced' do describe '.notify_procedure_expires_when_termine_forced' do
subject { described_class.notify_procedure_expires_when_termine_forced(admin_email, procedure) } subject { described_class.notify_procedure_expires_when_termine_forced(admin_email, procedure) }
it { expect(subject.to).to eq([admin_email]) } it { expect(subject.to).to eq([admin_email]) }
it { expect(subject.subject).to include("La suppression automatique des dossiers a été activée sur la démarche") } it { expect(subject.subject).to include("La suppression automatique des dossiers a été activée sur la démarche") }
context 'when perform_later is called' do
let(:custom_queue) { 'low_priority' }
before { ENV['BULK_EMAIL_QUEUE'] = custom_queue }
it 'enqueues email is custom queue for low priority delivery' do
expect { subject.deliver_later }.to have_enqueued_job.on_queue(custom_queue)
end end
end
end
describe '.activate_before_expiration' do describe '.activate_before_expiration' do
let(:user) { create(:user, reset_password_sent_at: 2.days.ago) } let(:user) { create(:user, reset_password_sent_at: 2.days.ago) }
let(:token) { SecureRandom.hex } let(:token) { SecureRandom.hex }
subject { described_class.activate_before_expiration(user, token) }
context 'without SafeMailer configured' do context 'without SafeMailer configured' do
subject { described_class.activate_before_expiration(user, token) }
it { expect(subject[BalancerDeliveryMethod::FORCE_DELIVERY_METHOD_HEADER]&.value).to eq(nil) } it { expect(subject[BalancerDeliveryMethod::FORCE_DELIVERY_METHOD_HEADER]&.value).to eq(nil) }
end end
context 'with SafeMailer configured' do context 'with SafeMailer configured' do
let(:forced_delivery_method) { :kikoo } let(:forced_delivery_method) { :kikoo }
before { allow(SafeMailer).to receive(:forced_delivery_method).and_return(forced_delivery_method) } before { allow(SafeMailer).to receive(:forced_delivery_method).and_return(forced_delivery_method) }
subject { described_class.activate_before_expiration(user, token) }
it { expect(subject[BalancerDeliveryMethod::FORCE_DELIVERY_METHOD_HEADER]&.value).to eq(forced_delivery_method.to_s) } it { expect(subject[BalancerDeliveryMethod::FORCE_DELIVERY_METHOD_HEADER]&.value).to eq(forced_delivery_method.to_s) }
end end
context 'when perform_later is called' do
it 'enqueues email in default queue for high priority delivery' do
expect { subject.deliver_later }.to have_enqueued_job.on_queue(Rails.application.config.action_mailer.deliver_later_queue_name)
end
end
end end
describe '.notify_service_without_siret' do describe '.notify_service_without_siret' do
subject { described_class.notify_service_without_siret(admin_email) } subject { described_class.notify_service_without_siret(admin_email) }
it { expect(subject.to).to eq([admin_email]) } it { expect(subject.to).to eq([admin_email]) }
it { expect(subject.subject).to eq("Siret manquant sur un de vos services") } it { expect(subject.subject).to eq("Siret manquant sur un de vos services") }
it { expect(subject.body).to include("un de vos services n'a pas son siret renseigné") } it { expect(subject.body).to include("un de vos services n'a pas son siret renseigné") }
context 'when perform_later is called' do
let(:custom_queue) { 'low_priority' }
before { ENV['BULK_EMAIL_QUEUE'] = custom_queue }
it 'enqueues email is custom queue for low priority delivery' do
expect { subject.deliver_later }.to have_enqueued_job.on_queue(custom_queue)
end
end
end end
end end

View file

@ -2,15 +2,22 @@ RSpec.describe DeviseUserMailer, type: :mailer do
let(:user) { create(:user) } let(:user) { create(:user) }
let(:token) { SecureRandom.hex } let(:token) { SecureRandom.hex }
describe '.confirmation_instructions' do describe '.confirmation_instructions' do
context 'without SafeMailer configured' do
subject { described_class.confirmation_instructions(user, token, opts = {}) } subject { described_class.confirmation_instructions(user, token, opts = {}) }
context 'without SafeMailer configured' do
it { expect(subject[BalancerDeliveryMethod::FORCE_DELIVERY_METHOD_HEADER]&.value).to eq(nil) } it { expect(subject[BalancerDeliveryMethod::FORCE_DELIVERY_METHOD_HEADER]&.value).to eq(nil) }
end end
context 'with SafeMailer configured' do context 'with SafeMailer configured' do
let(:forced_delivery_method) { :kikoo } let(:forced_delivery_method) { :kikoo }
before { allow(SafeMailer).to receive(:forced_delivery_method).and_return(forced_delivery_method) } before { allow(SafeMailer).to receive(:forced_delivery_method).and_return(forced_delivery_method) }
subject { described_class.confirmation_instructions(user, token, opts = {}) }
it { expect(subject[BalancerDeliveryMethod::FORCE_DELIVERY_METHOD_HEADER]&.value).to eq(forced_delivery_method.to_s) } it { expect(subject[BalancerDeliveryMethod::FORCE_DELIVERY_METHOD_HEADER]&.value).to eq(forced_delivery_method.to_s) }
end end
context 'when perform_later is called' do
it 'enqueues email in default queue for high priority delivery' do
expect { subject.deliver_later }.to have_enqueued_job.on_queue(Rails.application.config.action_mailer.deliver_later_queue_name)
end
end
end end
end end

View file

@ -3,27 +3,40 @@ RSpec.describe InstructeurMailer, type: :mailer do
let(:sender) { create(:instructeur) } let(:sender) { create(:instructeur) }
let(:recipient) { create(:instructeur) } let(:recipient) { create(:instructeur) }
let(:dossier) { create(:dossier) } let(:dossier) { create(:dossier) }
subject { described_class.send_dossier(sender, dossier, recipient) } subject { described_class.send_dossier(sender, dossier, recipient) }
it { expect(subject.body).to include('Bonjour') } it { expect(subject.body).to include('Bonjour') }
context 'when perform_later is called' do
let(:custom_queue) { 'low_priority' }
before { ENV['BULK_EMAIL_QUEUE'] = custom_queue }
it 'enqueues email is custom queue for low priority delivery' do
expect { subject.deliver_later }.to have_enqueued_job.on_queue(custom_queue)
end
end
end end
describe '#send_login_token' do describe '#send_login_token' do
let(:user) { create(:instructeur) } let(:user) { create(:instructeur) }
let(:token) { SecureRandom.hex } let(:token) { SecureRandom.hex }
subject { described_class.send_login_token(user, token) }
context 'without SafeMailer configured' do context 'without SafeMailer configured' do
subject { described_class.send_login_token(user, token) }
it { expect(subject[BalancerDeliveryMethod::FORCE_DELIVERY_METHOD_HEADER]&.value).to eq(nil) } it { expect(subject[BalancerDeliveryMethod::FORCE_DELIVERY_METHOD_HEADER]&.value).to eq(nil) }
end end
context 'with SafeMailer configured' do context 'with SafeMailer configured' do
let(:forced_delivery_method) { :kikoo } let(:forced_delivery_method) { :kikoo }
before { allow(SafeMailer).to receive(:forced_delivery_method).and_return(forced_delivery_method) } before { allow(SafeMailer).to receive(:forced_delivery_method).and_return(forced_delivery_method) }
subject { described_class.send_login_token(user, token) }
it { expect(subject[BalancerDeliveryMethod::FORCE_DELIVERY_METHOD_HEADER]&.value).to eq(forced_delivery_method.to_s) } it { expect(subject[BalancerDeliveryMethod::FORCE_DELIVERY_METHOD_HEADER]&.value).to eq(forced_delivery_method.to_s) }
end end
context 'when perform_later is called' do
it 'enqueues email in default queue for high priority delivery' do
expect { subject.deliver_later }.to have_enqueued_job.on_queue(Rails.application.config.action_mailer.deliver_later_queue_name)
end
end
end end
describe '#last_week_overview' do describe '#last_week_overview' do
@ -62,5 +75,14 @@ RSpec.describe InstructeurMailer, type: :mailer do
expect(subject.body).to be_blank expect(subject.body).to be_blank
end end
end end
context 'when perform_later is called' do
let(:custom_queue) { 'low_priority' }
before { ENV['BULK_EMAIL_QUEUE'] = custom_queue }
it 'enqueues email is custom queue for low priority delivery' do
expect { subject.deliver_later }.to have_enqueued_job.on_queue(custom_queue)
end
end
end end
end end

View file

@ -1,9 +1,8 @@
RSpec.describe InviteMailer, type: :mailer do RSpec.describe InviteMailer, type: :mailer do
let(:deliver) { mailer.deliver_now } let(:deliver) { subject.deliver_now }
subject { InviteMailer.invite_user(invite) }
describe '.invite_user' do describe '.invite_user' do
let(:mailer) { InviteMailer.invite_user(invite) }
let(:invite) { create(:invite, user: create(:user)) } let(:invite) { create(:invite, user: create(:user)) }
it 'creates a target_user_link' do it 'creates a target_user_link' do
expect { deliver } expect { deliver }
@ -20,29 +19,34 @@ RSpec.describe InviteMailer, type: :mailer do
end end
begin begin
mailer.body subject.body
rescue => e rescue => e
nil nil
end end
mailer.body subject.body
expect(TargetedUserLink.where(target_model: invite, user: invite.user).count).to eq(1) expect(TargetedUserLink.where(target_model: invite, user: invite.user).count).to eq(1)
end end
end end
context 'without SafeMailer configured' do context 'without SafeMailer configured' do
it { expect(mailer[BalancerDeliveryMethod::FORCE_DELIVERY_METHOD_HEADER]&.value).to eq(nil) } it { expect(subject[BalancerDeliveryMethod::FORCE_DELIVERY_METHOD_HEADER]&.value).to eq(nil) }
end end
context 'with SafeMailer configured' do context 'with SafeMailer configured' do
let(:forced_delivery_method) { :kikoo } let(:forced_delivery_method) { :kikoo }
before { allow(SafeMailer).to receive(:forced_delivery_method).and_return(forced_delivery_method) } before { allow(SafeMailer).to receive(:forced_delivery_method).and_return(forced_delivery_method) }
it { expect(mailer[BalancerDeliveryMethod::FORCE_DELIVERY_METHOD_HEADER]&.value).to eq(forced_delivery_method.to_s) } it { expect(subject[BalancerDeliveryMethod::FORCE_DELIVERY_METHOD_HEADER]&.value).to eq(forced_delivery_method.to_s) }
end
context 'when perform_later is called' do
it 'enqueues email in default queue for high priority delivery' do
expect { invite }.to have_enqueued_job.on_queue(Rails.application.config.action_mailer.deliver_later_queue_name)
end
end end
end end
describe '.invite_guest' do describe '.invite_guest' do
let(:mailer) { InviteMailer.invite_guest(invite) }
let(:invite) { create(:invite, user: nil, email: 'kikoo@lol.fr') } let(:invite) { create(:invite, user: nil, email: 'kikoo@lol.fr') }
it 'creates a target_user_link' do it 'creates a target_user_link' do
@ -69,14 +73,20 @@ RSpec.describe InviteMailer, type: :mailer do
end end
begin begin
mailer.body subject.body
rescue => e rescue => e
nil nil
end end
mailer.body subject.body
expect(TargetedUserLink.where(target_model: invite, user: invite.user).count).to eq(1) expect(TargetedUserLink.where(target_model: invite, user: invite.user).count).to eq(1)
end end
end end
context 'when perform_later is called' do
it 'enqueues email in default queue for high priority delivery' do
expect { invite }.to have_enqueued_job.on_queue(Rails.application.config.action_mailer.deliver_later_queue_name)
end
end
end end
end end

View file

@ -1,5 +1,5 @@
RSpec.describe UserMailer, type: :mailer do RSpec.describe UserMailer, type: :mailer do
let(:user) { build(:user) } let(:user) { create(:user) }
describe '.new_account_warning' do describe '.new_account_warning' do
subject { described_class.new_account_warning(user) } subject { described_class.new_account_warning(user) }
@ -25,6 +25,12 @@ RSpec.describe UserMailer, type: :mailer do
before { allow(SafeMailer).to receive(:forced_delivery_method).and_return(forced_delivery_method) } before { allow(SafeMailer).to receive(:forced_delivery_method).and_return(forced_delivery_method) }
it { expect(subject[BalancerDeliveryMethod::FORCE_DELIVERY_METHOD_HEADER]&.value).to eq(forced_delivery_method.to_s) } it { expect(subject[BalancerDeliveryMethod::FORCE_DELIVERY_METHOD_HEADER]&.value).to eq(forced_delivery_method.to_s) }
end end
context 'when perform_later is called' do
it 'enqueues email in default queue for high priority delivery' do
expect { subject.deliver_later }.to have_enqueued_job.on_queue(Rails.application.config.action_mailer.deliver_later_queue_name)
end
end
end end
describe '.ask_for_merge' do describe '.ask_for_merge' do
@ -44,6 +50,12 @@ RSpec.describe UserMailer, type: :mailer do
before { allow(SafeMailer).to receive(:forced_delivery_method).and_return(forced_delivery_method) } before { allow(SafeMailer).to receive(:forced_delivery_method).and_return(forced_delivery_method) }
it { expect(subject[BalancerDeliveryMethod::FORCE_DELIVERY_METHOD_HEADER]&.value).to eq(forced_delivery_method.to_s) } it { expect(subject[BalancerDeliveryMethod::FORCE_DELIVERY_METHOD_HEADER]&.value).to eq(forced_delivery_method.to_s) }
end end
context 'when perform_later is called' do
it 'enqueues email in default queue for high priority delivery' do
expect { subject.deliver_later }.to have_enqueued_job.on_queue(Rails.application.config.action_mailer.deliver_later_queue_name)
end
end
end end
describe '.france_connect_merge_confirmation' do describe '.france_connect_merge_confirmation' do
@ -64,6 +76,12 @@ RSpec.describe UserMailer, type: :mailer do
before { allow(SafeMailer).to receive(:forced_delivery_method).and_return(forced_delivery_method) } before { allow(SafeMailer).to receive(:forced_delivery_method).and_return(forced_delivery_method) }
it { expect(subject[BalancerDeliveryMethod::FORCE_DELIVERY_METHOD_HEADER]&.value).to eq(forced_delivery_method.to_s) } it { expect(subject[BalancerDeliveryMethod::FORCE_DELIVERY_METHOD_HEADER]&.value).to eq(forced_delivery_method.to_s) }
end end
context 'when perform_later is called' do
it 'enqueues email in default queue for high priority delivery' do
expect { subject.deliver_later }.to have_enqueued_job.on_queue(Rails.application.config.action_mailer.deliver_later_queue_name)
end
end
end end
describe '.send_archive' do describe '.send_archive' do
@ -84,5 +102,14 @@ RSpec.describe UserMailer, type: :mailer do
it { expect(subject.body).to have_link('Consulter mes archives', href: admin_procedure_archives_url(procedure)) } it { expect(subject.body).to have_link('Consulter mes archives', href: admin_procedure_archives_url(procedure)) }
it { expect(subject.body).to have_link("#{procedure.id} #{procedure.libelle}", href: admin_procedure_url(procedure)) } it { expect(subject.body).to have_link("#{procedure.id} #{procedure.libelle}", href: admin_procedure_url(procedure)) }
end end
context 'when perform_later is called' do
let(:role) { create(:administrateur) }
let(:custom_queue) { 'low_priority' }
before { ENV['BULK_EMAIL_QUEUE'] = custom_queue }
it 'enqueues email is custom queue for low priority delivery' do
expect { subject.deliver_later }.to have_enqueued_job.on_queue(custom_queue)
end
end
end end
end end