Skip to content

Commit d1cf05b

Browse files
jhendersonthomasleese
authored andcommitted
Optimise offline session exporter
This PR significantly improves the performance of the offline session exporter. It addresses concerns that the "Record offline" function was taking too long (up to 10s) and if sessions get bigger (eg with flu) the threshold to cause timeouts will be reached, and it will not be possible for these spreadsheets to be generated by SAIS teams. While most sessions will have around 1,000 patients, community clinic sessions could potentially contain up to 60,000 patients. For this special case, we may need to implement a background job in the future to handle the export asynchronously, but hopefully, this optimisation should handle the vast majority of use cases. Key improvements: - Added comprehensive eager loading for all required associations - Cached vaccination records in memory with `to_a` to avoid repeated DB calls - Memoise `clinic_name_values` Performance impact based on 1236 patient sessions: - Total time: 6.45s → 2.47s (62% faster) - SQL queries: 10,649 → 77 (99.3% reduction) - SQL time: 1.83s → 0.30s (84% faster DB time) The most significant improvement came from eliminating repeated queries for parent relationships, location names, and programme lookups which were previously causing thousands of separate database calls.
1 parent 1288b96 commit d1cf05b

File tree

1 file changed

+26
-14
lines changed

1 file changed

+26
-14
lines changed

app/lib/reports/offline_session_exporter.rb

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -125,25 +125,35 @@ def columns
125125
end
126126

127127
def patient_sessions
128-
session
129-
.patient_sessions
130-
.includes(
131-
patient: [
132-
:consent_statuses,
133-
:school,
134-
{ vaccination_records: %i[batch performed_by_user vaccine] }
135-
],
136-
session: :programmes
137-
)
138-
.order_by_name
128+
@patient_sessions ||=
129+
session
130+
.patient_sessions
131+
.includes(
132+
patient: [
133+
:consent_statuses,
134+
:school,
135+
{ parent_relationships: :parent },
136+
{
137+
vaccination_records: %i[
138+
batch
139+
performed_by_user
140+
vaccine
141+
programme
142+
session
143+
]
144+
}
145+
],
146+
session: [{ programmes: :vaccines }, :location]
147+
)
148+
.order_by_name
139149
end
140150

141151
def consents
142152
@consents ||=
143153
Consent
144154
.where(patient_id: patient_sessions.select(:patient_id))
145155
.not_invalidated
146-
.includes(:parent, :patient)
156+
.includes(:parent, patient: { parent_relationships: :parent })
147157
.group_by(&:patient_id)
148158
.transform_values do
149159
it
@@ -206,7 +216,9 @@ def rows(patient_session:)
206216
}
207217

208218
vaccination_records =
209-
patient.vaccination_records.select { it.programme_id == programme.id }
219+
patient.vaccination_records.to_a.select do
220+
it.programme_id == programme.id
221+
end
210222

211223
if vaccination_records.any?
212224
vaccination_records.map do |vaccination_record|
@@ -409,7 +421,7 @@ def batch_numbers_range_for_programme(programme)
409421
end
410422

411423
def clinic_name_values
412-
@clinic_name_values =
424+
@clinic_name_values ||=
413425
Location
414426
.community_clinic
415427
.joins(:team)

0 commit comments

Comments
 (0)