Skip to content

Commit aca1638

Browse files
committed
Refactor SchoolConsentRemindersJob
This splits the job in to two separate jobs, one which runs on a schedule and for each session queues up a separate job which handles the process of sending the communications for a particular session. We're finding that the current job is unable to handle a high number of sessions and runs out of resources. Instead, by queuing a job for each session we can avoid the individual jobs being too resource hungry and gives us more flexibility in terms of running the jobs manually.
1 parent ce94518 commit aca1638

File tree

5 files changed

+121
-41
lines changed

5 files changed

+121
-41
lines changed
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# frozen_string_literal: true
2+
3+
class EnqueueSchoolConsentRemindersJob < ApplicationJob
4+
queue_as :notifications
5+
6+
def perform
7+
sessions =
8+
Session.send_consent_reminders.joins(:location).merge(Location.school)
9+
10+
sessions.find_each do |session|
11+
SendSchoolConsentRemindersJob.perform_later(session)
12+
end
13+
end
14+
end

app/jobs/school_consent_reminders_job.rb renamed to app/jobs/send_school_consent_reminders_job.rb

Lines changed: 28 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,35 @@
11
# frozen_string_literal: true
22

3-
class SchoolConsentRemindersJob < ApplicationJob
3+
class SendSchoolConsentRemindersJob < ApplicationJob
44
queue_as :notifications
55

6-
def perform
7-
sessions =
8-
Session
9-
.send_consent_reminders
10-
.joins(:location)
11-
.includes(:session_dates, :programmes, :patient_sessions, :location)
12-
.merge(Location.school)
13-
14-
sessions.find_each(batch_size: 1) do |session|
15-
next unless session.open_for_consent?
16-
17-
session.patient_sessions.each do |patient_session|
18-
ProgrammeGrouper
19-
.call(patient_session.programmes)
20-
.each_value do |programmes|
21-
next unless should_send_notification?(patient_session:, programmes:)
22-
23-
patient = patient_session.patient
24-
25-
sent_initial_reminder =
26-
programmes.all? do |programme|
27-
patient
28-
.consent_notifications
29-
.select { it.programmes.include?(programme) }
30-
.any?(&:initial_reminder?)
31-
end
32-
33-
ConsentNotification.create_and_send!(
34-
patient:,
35-
programmes:,
36-
session:,
37-
type:
38-
sent_initial_reminder ? :subsequent_reminder : :initial_reminder
39-
)
40-
end
41-
end
6+
def perform(session)
7+
return unless session.school? && session.open_for_consent?
8+
9+
session.patient_sessions.includes_programmes.find_each do |patient_session|
10+
ProgrammeGrouper
11+
.call(patient_session.programmes)
12+
.each_value do |programmes|
13+
next unless should_send_notification?(patient_session:, programmes:)
14+
15+
patient = patient_session.patient
16+
17+
sent_initial_reminder =
18+
programmes.all? do |programme|
19+
patient
20+
.consent_notifications
21+
.select { it.programmes.include?(programme) }
22+
.any?(&:initial_reminder?)
23+
end
24+
25+
ConsentNotification.create_and_send!(
26+
patient:,
27+
programmes:,
28+
session:,
29+
type:
30+
sent_initial_reminder ? :subsequent_reminder : :initial_reminder
31+
)
32+
end
4233
end
4334
end
4435

config/environments/production.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,9 +108,9 @@
108108
description:
109109
"Send school consent request emails to parents for each session"
110110
},
111-
consent_reminder: {
111+
school_consent_reminders: {
112112
cron: "every day at 9am",
113-
class: "SchoolConsentRemindersJob",
113+
class: "EnqueueSchoolConsentRemindersJob",
114114
description:
115115
"Send school consent reminder emails to parents for each session"
116116
},
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
# frozen_string_literal: true
2+
3+
describe EnqueueSchoolConsentRemindersJob do
4+
subject(:perform_now) { described_class.perform_now }
5+
6+
let(:programmes) { [create(:programme)] }
7+
let(:organisation) { create(:organisation, programmes:) }
8+
let(:location) { create(:school, organisation:) }
9+
10+
let(:dates) { [Date.new(2024, 1, 12), Date.new(2024, 1, 15)] }
11+
12+
let!(:session) do
13+
create(
14+
:session,
15+
dates:,
16+
send_consent_requests_at: dates.first - 3.weeks,
17+
days_before_consent_reminders: 7,
18+
location:,
19+
programmes:,
20+
organisation:
21+
)
22+
end
23+
24+
around { |example| travel_to(today) { example.run } }
25+
26+
context "two weeks before the first session" do
27+
let(:today) { dates.first - 2.weeks }
28+
29+
it "doesn't queue any jobs" do
30+
expect { perform_now }.not_to have_enqueued_job(
31+
SendSchoolConsentRemindersJob
32+
)
33+
end
34+
end
35+
36+
context "one week before the first session" do
37+
let(:today) { dates.first - 1.week }
38+
39+
it "queues a job for the session" do
40+
expect { perform_now }.to have_enqueued_job(
41+
SendSchoolConsentRemindersJob
42+
).with(session)
43+
end
44+
45+
context "when location is a generic clinic" do
46+
let(:location) { create(:generic_clinic, organisation:) }
47+
48+
it "doesn't queue any jobs" do
49+
expect { perform_now }.not_to have_enqueued_job(
50+
SendSchoolConsentRemindersJob
51+
)
52+
end
53+
end
54+
end
55+
56+
context "one week before the second session" do
57+
let(:today) { dates.last - 1.week }
58+
59+
it "queues a job for the session" do
60+
expect { perform_now }.to have_enqueued_job(
61+
SendSchoolConsentRemindersJob
62+
).with(session)
63+
end
64+
65+
context "when location is a generic clinic" do
66+
let(:location) { create(:generic_clinic, organisation:) }
67+
68+
it "doesn't queue any jobs" do
69+
expect { perform_now }.not_to have_enqueued_job(
70+
SendSchoolConsentRemindersJob
71+
)
72+
end
73+
end
74+
end
75+
end

spec/jobs/school_consent_reminders_job_spec.rb renamed to spec/jobs/send_school_consent_reminders_job_spec.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# frozen_string_literal: true
22

3-
describe SchoolConsentRemindersJob do
4-
subject(:perform_now) { described_class.perform_now }
3+
describe SendSchoolConsentRemindersJob do
4+
subject(:perform_now) { described_class.perform_now(session) }
55

66
let(:programmes) { [create(:programme)] }
77

0 commit comments

Comments
 (0)