perf(usager): cache tabs with a simple and fast cache_key

Plutôt que d'include dans la cache_key tous les scopes utilisés par l'onglet,
(ce qui provquerait une requête par scope),
on le base simplement sur les dossiers & invitations.
Les deleted dossiers sont inclus indirectement car ça correspond à la
suppression (N-1) d'un dossier.
This commit is contained in:
Colin Darie 2023-11-30 15:37:18 +01:00
parent 9ac3775207
commit 75c22bc7d4
No known key found for this signature in database
GPG key ID: 8C76CADD40253590
2 changed files with 103 additions and 43 deletions

View file

@ -25,49 +25,50 @@
= render Dossiers::UserProcedureFilterComponent.new(procedures_for_select: @procedures_for_select)
- if @search_terms.blank?
%nav.fr-tabs{ role: 'navigation', 'aria-label': t('views.users.dossiers.secondary_menu') }
%ul.fr-tabs__list{ role: 'tablist' }
- if @user_dossiers.present?
= tab_item(t('pluralize.en_cours', count: @user_dossiers.count),
dossiers_path(statut: 'en-cours', procedure_id: params[:procedure_id]),
active: @statut == 'en-cours',
badge: number_with_html_delimiter(@user_dossiers.count))
- if @dossiers_traites.present?
// TODO: when renaming this tab in "Terminé", update notify_near_deletion_to_user email wording accordingly.
= tab_item(t('pluralize.traites', count: @dossiers_traites.count),
dossiers_path(statut: 'traites', procedure_id: params[:procedure_id]),
active: @statut == 'traites',
badge: number_with_html_delimiter(@dossiers_traites.count))
- cache([current_user.id, @statut, current_user.dossiers, current_user.dossiers_invites], expires_in: 1.hour) do
%nav.fr-tabs{ role: 'navigation', 'aria-label': t('views.users.dossiers.secondary_menu') }
%ul.fr-tabs__list{ role: 'tablist' }
- if @user_dossiers.present?
= tab_item(t('pluralize.en_cours', count: @user_dossiers.count),
dossiers_path(statut: 'en-cours', procedure_id: params[:procedure_id]),
active: @statut == 'en-cours',
badge: number_with_html_delimiter(@user_dossiers.count))
- if @dossiers_traites.present?
// TODO: when renaming this tab in "Terminé", update notify_near_deletion_to_user email wording accordingly.
= tab_item(t('pluralize.traites', count: @dossiers_traites.count),
dossiers_path(statut: 'traites', procedure_id: params[:procedure_id]),
active: @statut == 'traites',
badge: number_with_html_delimiter(@dossiers_traites.count))
- if @dossiers_invites.present?
= tab_item(t('pluralize.dossiers_invites', count: @dossiers_invites.count),
dossiers_path(statut: 'dossiers-invites', procedure_id: params[:procedure_id]),
active: @statut == 'dossiers-invites',
badge: number_with_html_delimiter(@dossiers_invites.count))
- if @dossiers_invites.present?
= tab_item(t('pluralize.dossiers_invites', count: @dossiers_invites.count),
dossiers_path(statut: 'dossiers-invites', procedure_id: params[:procedure_id]),
active: @statut == 'dossiers-invites',
badge: number_with_html_delimiter(@dossiers_invites.count))
- if @dossiers_close_to_expiration.count > 0
= tab_item(t('pluralize.dossiers_close_to_expiration', count: @dossiers_close_to_expiration.count),
dossiers_path(statut: 'dossiers-expirant', procedure_id: params[:procedure_id]),
active: @statut == 'dossiers-expirant',
badge: number_with_html_delimiter(@dossiers_close_to_expiration.count))
- if @dossiers_close_to_expiration.count > 0
= tab_item(t('pluralize.dossiers_close_to_expiration', count: @dossiers_close_to_expiration.count),
dossiers_path(statut: 'dossiers-expirant', procedure_id: params[:procedure_id]),
active: @statut == 'dossiers-expirant',
badge: number_with_html_delimiter(@dossiers_close_to_expiration.count))
- if @dossiers_supprimes_recemment.present?
= tab_item(t('pluralize.dossiers_supprimes_recemment', count: @dossiers_supprimes_recemment.count),
dossiers_path(statut: 'dossiers-supprimes-recemment', procedure_id: params[:procedure_id]),
active: @statut == 'dossiers-supprimes-recemment',
badge: number_with_html_delimiter(@dossiers_supprimes_recemment.count))
- if @dossiers_supprimes_recemment.present?
= tab_item(t('pluralize.dossiers_supprimes_recemment', count: @dossiers_supprimes_recemment.count),
dossiers_path(statut: 'dossiers-supprimes-recemment', procedure_id: params[:procedure_id]),
active: @statut == 'dossiers-supprimes-recemment',
badge: number_with_html_delimiter(@dossiers_supprimes_recemment.count))
- if @dossiers_supprimes_definitivement.present?
= tab_item(t('pluralize.dossiers_supprimes_definitivement', count: @dossiers_supprimes_definitivement.count),
dossiers_path(statut: 'dossiers-supprimes-definitivement', procedure_id: params[:procedure_id]),
active: @statut == 'dossiers-supprimes-definitivement',
badge: number_with_html_delimiter(@dossiers_supprimes_definitivement.count))
- if @dossiers_supprimes_definitivement.present?
= tab_item(t('pluralize.dossiers_supprimes_definitivement', count: @dossiers_supprimes_definitivement.count),
dossiers_path(statut: 'dossiers-supprimes-definitivement', procedure_id: params[:procedure_id]),
active: @statut == 'dossiers-supprimes-definitivement',
badge: number_with_html_delimiter(@dossiers_supprimes_definitivement.count))
- if @dossier_transferes.present?
= tab_item(t('pluralize.dossiers_transferes', count: @dossier_transferes.count),
dossiers_path(statut: 'dossiers-transferes', procedure_id: params[:procedure_id]),
active: @statut == 'dossiers-transferes',
badge: number_with_html_delimiter(@dossier_transferes.count))
- if @dossier_transferes.present?
= tab_item(t('pluralize.dossiers_transferes', count: @dossier_transferes.count),
dossiers_path(statut: 'dossiers-transferes', procedure_id: params[:procedure_id]),
active: @statut == 'dossiers-transferes',
badge: number_with_html_delimiter(@dossier_transferes.count))
.fr-container
.fr-grid-row.fr-grid-row--center

View file

@ -3,15 +3,15 @@ describe 'users/dossiers/index', type: :view do
let(:dossier_brouillon) { create(:dossier, state: Dossier.states.fetch(:brouillon), user: user) }
let(:dossier_en_construction) { create(:dossier, state: Dossier.states.fetch(:en_construction), user: user) }
let(:dossier_termine) { create(:dossier, state: Dossier.states.fetch(:accepte), user: user) }
let(:user_dossiers) { [dossier_brouillon, dossier_en_construction, dossier_termine] }
let(:dossiers_invites) { [] }
let(:user_dossiers) { Kaminari.paginate_array([dossier_brouillon, dossier_en_construction, dossier_termine]).page(1) }
let(:statut) { 'en-cours' }
let(:filter) { DossiersFilter.new(user, ActionController::Parameters.new(random_param: 'random_param')) }
before do
before do |config|
allow(view).to receive(:new_demarche_url).and_return('#')
allow(controller).to receive(:current_user) { user }
assign(:user_dossiers, Kaminari.paginate_array(user_dossiers).page(1))
assign(:user_dossiers, user_dossiers)
assign(:dossiers_invites, Kaminari.paginate_array(dossiers_invites).page(1))
assign(:dossiers_supprimes_recemment, Kaminari.paginate_array(user_dossiers).page(1))
assign(:dossiers_supprimes_definitivement, Kaminari.paginate_array(user_dossiers).page(1))
@ -22,7 +22,8 @@ describe 'users/dossiers/index', type: :view do
assign(:statut, statut)
assign(:filter, filter)
assign(:all_dossiers_uniq_procedures_count, 0)
render
render if !config.metadata[:caching]
end
it 'affiche les dossiers' do
@ -56,7 +57,7 @@ describe 'users/dossiers/index', type: :view do
end
context 'quand il ny a aucun dossier' do
let(:user_dossiers) { [] }
let(:user_dossiers) { [] }
let(:dossiers_invites) { [] }
it 'naffiche pas la table' do
@ -101,4 +102,62 @@ describe 'users/dossiers/index', type: :view do
expect(rendered).to have_text("Supprimer le dossier")
end
end
context 'caching', caching: true do
it "works" do
expect(user_dossiers).to receive(:present?).once
2.times { render; user.reload }
end
it "cache key depends on statut" do
expect(user_dossiers).to receive(:present?).twice
render
assign(:statut, "termines")
user.reload
render
end
it "cache key depends on dossier updated_at" do
expect(user_dossiers).to receive(:present?).twice
render
dossier_termine.touch
user.reload
render
end
it "cache key depends on dossiers list" do
render
expect(rendered).to have_text(/3\s+en cours/)
assign(:user_dossiers, Kaminari.paginate_array(user_dossiers.concat([create(:dossier, :en_construction, user: user)])).page(1))
user.reload
render
expect(rendered).to have_text(/4\s+en cours/)
end
it "cache key dpeends on dossier invites" do
expect(user_dossiers).to receive(:present?).twice
render
create(:invite, user:)
user.reload
render
end
it "cache key depends on dossier deletion" do
expect(user_dossiers).to receive(:present?).twice
render
dossier_termine.expired_keep_track_and_destroy!
user.reload
render
end
end
end