Skip to content

Commit 0ef0327

Browse files
authored
Cache triage status in database (#3268)
This introduces a new model, `Patient::TriageStatus`, which stores the triage status of a patient-programme pair in the database so it can queried and rendered quickly. Locally, I'm seeing the triage tab on sessions with 50,000 patients load almost instantly even when filtering on statuses. The session overview page has a slight improvement, but that will only load quickly once the other statuses are cached. I've decided not to implement a state machine as had been previously discussed, but this could be built on top of this change to enhancement the functionality. For now, this effectively caches the existing logic that runs on the fly to the database. I've also decided not to implement this using Rails callbacks and instead be explicit where the status is refreshed. This allows us to optimise for bulk refreshes, as is necessary when adding new programmes to sessions, running the seeds, or generally updating the status of an entire session. This follows up from #3263 which applies the same to the consents.
2 parents 155f6ac + b815421 commit 0ef0327

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+539
-394
lines changed

app/components/app_outcome_banner_component.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ def vaccination_record
5858
end
5959

6060
def triage
61-
@triage ||= patient.triage_outcome.latest[programme]
61+
@triage ||= patient.latest_triage(programme:)
6262
end
6363

6464
def session_attendance

app/components/app_patient_page_component.html.erb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,14 +72,14 @@
7272
) %>
7373
<% end %>
7474

75-
<% if patient.triage_outcome.all[programme].any? %>
75+
<% if patient.triages.exists?(programme:) %>
7676
<%= render AppCardComponent.new do |c| %>
7777
<% c.with_heading { "Triage notes" } %>
7878
<%= render AppTriageNotesComponent.new(patient_session:, programme:) %>
7979
<% end %>
8080
<% end %>
8181

82-
<% if helpers.policy(Triage).create? && patient.triage_outcome.required?(programme) %>
82+
<% if helpers.policy(Triage).create? && patient.triage_status(programme:).required? %>
8383
<%= render AppCardComponent.new do %>
8484
<%= render AppTriageFormComponent.new(
8585
patient_session:,

app/components/app_patient_session_search_result_card_component.rb

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -83,24 +83,25 @@ def action_required
8383
def status_tag
8484
return if context == :record
8585

86-
if context == :register
86+
case context
87+
when :register
8788
render AppRegisterStatusTagComponent.new(
8889
patient_session.register_outcome.status
8990
)
90-
elsif context == :consent
91+
when :consent
9192
statuses =
9293
patient_session.programmes.index_with do |programme|
9394
patient.consent_status(programme:).status
9495
end
9596
render AppProgrammeStatusTagsComponent.new(statuses, outcome: :consent)
96-
else
97-
outcome =
98-
case context
99-
when :triage
100-
patient.triage_outcome
101-
when :outcome
102-
patient_session.session_outcome
97+
when :triage
98+
statuses =
99+
patient_session.programmes.index_with do |programme|
100+
patient.triage_status(programme:).status
103101
end
102+
render AppProgrammeStatusTagsComponent.new(statuses, outcome: :triage)
103+
else
104+
outcome = patient_session.session_outcome
104105

105106
# ensure status is calculated for each programme
106107
patient_session.programmes.each { outcome.status[it] }

app/components/app_programme_session_table_component.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,9 @@ def no_response_percentage(session:)
4343
end
4444

4545
def triage_needed_count(session:)
46-
number_stat(session:) { it.patient.triage_outcome.required?(programme) }
46+
format_number(
47+
session.patient_sessions.has_triage_status(:required, programme:).count
48+
)
4749
end
4850

4951
def vaccinated_count(session:)

app/components/app_session_actions_component.rb

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,12 +62,10 @@ def consent_row(text, status:)
6262
end
6363

6464
def triage_required_row
65-
status = Patient::TriageOutcome::REQUIRED
65+
status = "required"
6666

6767
count =
68-
patient_sessions.count do
69-
it.patient.triage_outcome.status.values_at(*it.programmes).any?(status)
70-
end
68+
patient_sessions.has_triage_status(status, programme: programmes).count
7169

7270
return nil if count.zero?
7371

app/components/app_simple_status_banner_component.rb

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,11 @@ def description
5050
programme_name: programme.name
5151
}
5252

53-
if patient.triage_outcome.required?(programme)
53+
triage_status = patient.triage_status(programme:)
54+
55+
if triage_status.required?
5456
reasons = [
55-
if patient.consent_status(programme:).health_answers_require_follow_up?
57+
if triage_status.consent_requires_triage?
5658
I18n.t(
5759
:consent_needs_triage,
5860
scope: %i[
@@ -63,7 +65,7 @@ def description
6365
**options
6466
)
6567
end,
66-
if patient.triage_outcome.vaccination_history_needs_triage?(programme:)
68+
if triage_status.vaccination_history_requires_triage?
6769
I18n.t(
6870
:vaccination_partially_administered,
6971
scope: %i[
@@ -92,7 +94,7 @@ def who_refused
9294

9395
def nurse
9496
(
95-
patient.triage_outcome.all[programme] +
97+
patient.triages.includes(:performed_by).where(programme:) +
9698
patient.programme_outcome.all[programme]
9799
).max_by(&:updated_at)&.performed_by&.full_name
98100
end

app/components/app_triage_form_component.rb

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,7 @@ def initialize(
1616
@triage =
1717
triage ||
1818
Triage.new.tap do |t|
19-
if (
20-
latest_triage =
21-
patient_session.patient.triage_outcome.latest[programme]
22-
)
19+
if (latest_triage = patient_session.patient.latest_triage(programme:))
2320
t.status = latest_triage.status
2421
end
2522
end

app/controllers/concerns/triage_mailer_concern.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,18 +40,18 @@ def send_triage_confirmation(patient_session, consent)
4040
def vaccination_will_happen?(patient, consent)
4141
programme = consent.programme
4242
consent.triage_needed? &&
43-
patient.triage_outcome.safe_to_vaccinate?(programme)
43+
patient.triage_status(programme:).safe_to_vaccinate?
4444
end
4545

4646
def vaccination_wont_happen?(patient, consent)
4747
programme = consent.programme
4848
consent.triage_needed? &&
49-
patient.triage_outcome.do_not_vaccinate?(programme)
49+
patient.triage_status(programme:).do_not_vaccinate?
5050
end
5151

5252
def vaccination_at_clinic?(patient, consent)
5353
programme = consent.programme
5454
consent.triage_needed? &&
55-
patient.triage_outcome.delay_vaccination?(programme)
55+
patient.triage_status(programme:).delay_vaccination?
5656
end
5757
end

app/controllers/draft_consents_controller.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ def handle_confirm
6363
StatusUpdater.call(patient: @patient)
6464
end
6565

66-
set_patient_session # reload with new consents
66+
set_patient_session # reload with new statuses
6767

6868
send_triage_confirmation(@patient_session, @consent)
6969

app/controllers/patient_sessions_controller.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ def set_patient_session
5454
patient: {
5555
consents: %i[parent],
5656
parent_relationships: :parent,
57+
triage_statuses: :programme,
5758
triages: :performed_by,
5859
vaccination_records: {
5960
vaccine: :programme

0 commit comments

Comments
 (0)