perf(search): ignore search_terms columns, use raw sql instead
This commit is contained in:
parent
cb3581dd79
commit
2e763d5e92
13 changed files with 92 additions and 41 deletions
|
@ -3,6 +3,5 @@ class DossierUpdateSearchTermsJob < ApplicationJob
|
|||
|
||||
def perform(dossier)
|
||||
dossier.update_search_terms
|
||||
dossier.save!(touch: false)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -71,7 +71,6 @@ module DossierCloneConcern
|
|||
touch(:last_champ_updated_at)
|
||||
end
|
||||
reload
|
||||
update_search_terms_later
|
||||
editing_fork.destroy_editing_fork!
|
||||
end
|
||||
|
||||
|
|
|
@ -2,10 +2,10 @@ module DossierSearchableConcern
|
|||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
before_save :update_search_terms
|
||||
after_commit :update_search_terms_later
|
||||
|
||||
def update_search_terms
|
||||
self.search_terms = [
|
||||
search_terms = [
|
||||
user&.email,
|
||||
*champs_public.flat_map(&:search_terms),
|
||||
*etablissement&.search_terms,
|
||||
|
@ -13,7 +13,11 @@ module DossierSearchableConcern
|
|||
individual&.prenom
|
||||
].compact_blank.join(' ')
|
||||
|
||||
self.private_search_terms = champs_private.flat_map(&:search_terms).compact_blank.join(' ')
|
||||
private_search_terms = champs_private.flat_map(&:search_terms).compact_blank.join(' ')
|
||||
|
||||
sql = "UPDATE dossiers SET search_terms = :search_terms, private_search_terms = :private_search_terms WHERE id = :id"
|
||||
sanitized_sql = self.class.sanitize_sql_array([sql, search_terms:, private_search_terms:, id:])
|
||||
self.class.connection.execute(sanitized_sql)
|
||||
end
|
||||
|
||||
def update_search_terms_later
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
class Dossier < ApplicationRecord
|
||||
self.ignored_columns += [:re_instructed_at]
|
||||
self.ignored_columns += [:re_instructed_at, :search_terms, :private_search_terms]
|
||||
|
||||
include DossierCloneConcern
|
||||
include DossierCorrectableConcern
|
||||
|
|
|
@ -27,6 +27,8 @@ describe RechercheController, type: :controller do
|
|||
dossier_with_expert.champs_private[0].value = "Dossier B is incomplete"
|
||||
dossier_with_expert.champs_private[1].value = "Dossier B is invalid"
|
||||
dossier_with_expert.save!
|
||||
|
||||
perform_enqueued_jobs(only: DossierUpdateSearchTermsJob)
|
||||
end
|
||||
|
||||
describe 'GET #index' do
|
||||
|
|
|
@ -1,15 +1,21 @@
|
|||
RSpec.describe DossierUpdateSearchTermsJob, type: :job do
|
||||
let(:dossier) { create(:dossier) }
|
||||
let(:champ_public) { dossier.champs_public.first }
|
||||
let(:champ_private) { dossier.champs_private.first }
|
||||
|
||||
subject(:perform_job) { described_class.perform_now(dossier) }
|
||||
subject(:perform_job) { described_class.perform_now(dossier.reload) }
|
||||
|
||||
context 'with an update' do
|
||||
before do
|
||||
create(:champ_text, dossier: dossier, value: "un nouveau champ")
|
||||
create(:champ_text, dossier:, value: "un nouveau champ")
|
||||
create(:champ_text, dossier:, value: "private champ", private: true)
|
||||
end
|
||||
|
||||
it { expect { perform_job }.to change { dossier.reload.search_terms }.to(/un nouveau champ/) }
|
||||
it "update search terms columns" do
|
||||
perform_job
|
||||
|
||||
sql = "SELECT search_terms, private_search_terms FROM dossiers WHERE id = :id"
|
||||
sanitized_sql = Dossier.sanitize_sql_array([sql, id: dossier.id])
|
||||
result = Dossier.connection.execute(sanitized_sql).first
|
||||
|
||||
expect(result['search_terms']).to match(/un nouveau champ/)
|
||||
expect(result['private_search_terms']).to match(/private champ/)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -45,11 +45,19 @@ RSpec.describe DossierCloneConcern do
|
|||
it { expect(new_dossier.last_champ_updated_at).to be_nil }
|
||||
it { expect(new_dossier.last_commentaire_updated_at).to be_nil }
|
||||
it { expect(new_dossier.motivation).to be_nil }
|
||||
it { expect(new_dossier.private_search_terms).to eq("") }
|
||||
it { expect(new_dossier.processed_at).to be_nil }
|
||||
it { expect(new_dossier.search_terms).to match(dossier.user.email) }
|
||||
it { expect(new_dossier.termine_close_to_expiration_notice_sent_at).to be_nil }
|
||||
it { expect(new_dossier.dossier_transfer_id).to be_nil }
|
||||
|
||||
it "update search terms" do
|
||||
new_dossier
|
||||
perform_enqueued_jobs(only: DossierUpdateSearchTermsJob)
|
||||
sql = "SELECT search_terms, private_search_terms FROM dossiers where id = :id"
|
||||
result = Dossier.connection.execute(Dossier.sanitize_sql_array([sql, id: new_dossier.id])).first
|
||||
|
||||
expect(result["search_terms"]).to match(dossier.user.email)
|
||||
expect(result["private_search_terms"]).to eq("")
|
||||
end
|
||||
end
|
||||
|
||||
context 'copies some attributes' do
|
||||
|
|
|
@ -13,15 +13,23 @@ describe DossierSearchableConcern do
|
|||
let(:france_connect_information) { build(:france_connect_information, given_name: 'Chris', family_name: 'Harrisson') }
|
||||
let(:user) { build(:user, france_connect_informations: [france_connect_information]) }
|
||||
|
||||
let(:result) do
|
||||
Dossier.connection.execute(
|
||||
Dossier.sanitize_sql_array(["SELECT search_terms, private_search_terms FROM dossiers WHERE id = :id", id: dossier.id])
|
||||
).first
|
||||
end
|
||||
|
||||
before do
|
||||
champ_public.update_attribute(:value, "champ public")
|
||||
champ_private.update_attribute(:value, "champ privé")
|
||||
|
||||
dossier.update_search_terms
|
||||
perform_enqueued_jobs(only: DossierUpdateSearchTermsJob)
|
||||
end
|
||||
|
||||
it { expect(dossier.search_terms).to eq("#{user.email} champ public #{etablissement.entreprise_siren} #{etablissement.entreprise_numero_tva_intracommunautaire} #{etablissement.entreprise_forme_juridique} #{etablissement.entreprise_forme_juridique_code} #{etablissement.entreprise_nom_commercial} #{etablissement.entreprise_raison_sociale} #{etablissement.entreprise_siret_siege_social} #{etablissement.entreprise_nom} #{etablissement.entreprise_prenom} #{etablissement.association_rna} #{etablissement.association_titre} #{etablissement.association_objet} #{etablissement.siret} #{etablissement.naf} #{etablissement.libelle_naf} #{etablissement.adresse} #{etablissement.code_postal} #{etablissement.localite} #{etablissement.code_insee_localite}") }
|
||||
it { expect(dossier.private_search_terms).to eq('champ privé') }
|
||||
it "update columns" do
|
||||
expect(result["search_terms"]).to eq("#{user.email} champ public #{etablissement.entreprise_siren} #{etablissement.entreprise_numero_tva_intracommunautaire} #{etablissement.entreprise_forme_juridique} #{etablissement.entreprise_forme_juridique_code} #{etablissement.entreprise_nom_commercial} #{etablissement.entreprise_raison_sociale} #{etablissement.entreprise_siret_siege_social} #{etablissement.entreprise_nom} #{etablissement.entreprise_prenom} #{etablissement.association_rna} #{etablissement.association_titre} #{etablissement.association_objet} #{etablissement.siret} #{etablissement.naf} #{etablissement.libelle_naf} #{etablissement.adresse} #{etablissement.code_postal} #{etablissement.localite} #{etablissement.code_insee_localite}")
|
||||
expect(result["private_search_terms"]).to eq('champ privé')
|
||||
end
|
||||
|
||||
context 'with an update' do
|
||||
before do
|
||||
|
@ -31,11 +39,12 @@ describe DossierSearchableConcern do
|
|||
)
|
||||
|
||||
perform_enqueued_jobs(only: DossierUpdateSearchTermsJob)
|
||||
dossier.reload
|
||||
end
|
||||
|
||||
it { expect(dossier.search_terms).to include('nouvelle valeur publique') }
|
||||
it { expect(dossier.private_search_terms).to include('nouvelle valeur privee') }
|
||||
it "update columns" do
|
||||
expect(result["search_terms"]).to include('nouvelle valeur publique')
|
||||
expect(result["private_search_terms"]).to include('nouvelle valeur privee')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -899,7 +899,7 @@ describe Dossier, type: :model do
|
|||
dossier.procedure.update_column(:web_hook_url, '/webhook.json')
|
||||
|
||||
expect {
|
||||
dossier.update_column(:search_terms, 'bonjour')
|
||||
dossier.update_column(:conservation_extension, 'P1W')
|
||||
}.to_not have_enqueued_job(WebHookJob)
|
||||
|
||||
expect {
|
||||
|
@ -907,7 +907,7 @@ describe Dossier, type: :model do
|
|||
}.to have_enqueued_job(WebHookJob).with(dossier.procedure.id, dossier.id, 'en_construction', anything)
|
||||
|
||||
expect {
|
||||
dossier.update_column(:search_terms, 'bonjour2')
|
||||
dossier.update_column(:conservation_extension, 'P2W')
|
||||
}.to_not have_enqueued_job(WebHookJob)
|
||||
|
||||
expect {
|
||||
|
|
|
@ -15,23 +15,33 @@ describe DossierSearchService do
|
|||
before do
|
||||
instructeur_1.assign_to_procedure(procedure_1)
|
||||
instructeur_2.assign_to_procedure(procedure_2)
|
||||
|
||||
# create dossier before performing jobs
|
||||
# because let!() syntax is executed after "before" callback
|
||||
dossier_0
|
||||
dossier_1
|
||||
dossier_2
|
||||
dossier_3
|
||||
dossier_archived
|
||||
|
||||
perform_enqueued_jobs(only: DossierUpdateSearchTermsJob)
|
||||
end
|
||||
|
||||
let(:procedure_1) { create(:procedure, :published, administrateur: administrateur_1) }
|
||||
let(:procedure_2) { create(:procedure, :published, administrateur: administrateur_2) }
|
||||
|
||||
let!(:dossier_0) { create(:dossier, state: Dossier.states.fetch(:brouillon), procedure: procedure_1, user: create(:user, email: 'brouillon@clap.fr')) }
|
||||
let(:dossier_0) { create(:dossier, state: Dossier.states.fetch(:brouillon), procedure: procedure_1, user: create(:user, email: 'brouillon@clap.fr')) }
|
||||
|
||||
let!(:etablissement_1) { create(:etablissement, entreprise_raison_sociale: 'OCTO Academy', siret: '41636169600051') }
|
||||
let!(:dossier_1) { create(:dossier, :en_construction, procedure: procedure_1, user: create(:user, email: 'contact@test.com'), etablissement: etablissement_1) }
|
||||
let(:etablissement_1) { create(:etablissement, entreprise_raison_sociale: 'OCTO Academy', siret: '41636169600051') }
|
||||
let(:dossier_1) { create(:dossier, :en_construction, procedure: procedure_1, user: create(:user, email: 'contact@test.com'), etablissement: etablissement_1) }
|
||||
|
||||
let!(:etablissement_2) { create(:etablissement, entreprise_raison_sociale: 'Plop octo', siret: '41816602300012') }
|
||||
let!(:dossier_2) { create(:dossier, :en_construction, procedure: procedure_1, user: create(:user, email: 'plop@gmail.com'), etablissement: etablissement_2) }
|
||||
let(:etablissement_2) { create(:etablissement, entreprise_raison_sociale: 'Plop octo', siret: '41816602300012') }
|
||||
let(:dossier_2) { create(:dossier, :en_construction, procedure: procedure_1, user: create(:user, email: 'plop@gmail.com'), etablissement: etablissement_2) }
|
||||
|
||||
let!(:etablissement_3) { create(:etablissement, entreprise_raison_sociale: 'OCTO Technology', siret: '41816609600051') }
|
||||
let!(:dossier_3) { create(:dossier, :en_construction, procedure: procedure_2, user: create(:user, email: 'peace@clap.fr'), etablissement: etablissement_3) }
|
||||
let(:etablissement_3) { create(:etablissement, entreprise_raison_sociale: 'OCTO Technology', siret: '41816609600051') }
|
||||
let(:dossier_3) { create(:dossier, :en_construction, procedure: procedure_2, user: create(:user, email: 'peace@clap.fr'), etablissement: etablissement_3) }
|
||||
|
||||
let!(:dossier_archived) { create(:dossier, :en_construction, procedure: procedure_1, archived: true, user: create(:user, email: 'archived@clap.fr')) }
|
||||
let(:dossier_archived) { create(:dossier, :en_construction, procedure: procedure_1, archived: true, user: create(:user, email: 'archived@clap.fr')) }
|
||||
|
||||
describe 'search is empty' do
|
||||
let(:terms) { '' }
|
||||
|
@ -99,6 +109,16 @@ describe DossierSearchService do
|
|||
describe '#matching_dossiers_for_user' do
|
||||
subject { liste_dossiers }
|
||||
|
||||
before do
|
||||
dossier_0
|
||||
dossier_0b
|
||||
dossier_1
|
||||
dossier_2
|
||||
dossier_3
|
||||
dossier_archived
|
||||
perform_enqueued_jobs(only: DossierUpdateSearchTermsJob)
|
||||
end
|
||||
|
||||
let(:liste_dossiers) do
|
||||
described_class.matching_dossiers_for_user(terms, user_1)
|
||||
end
|
||||
|
@ -109,19 +129,19 @@ describe DossierSearchService do
|
|||
let(:procedure_1) { create(:procedure, :published) }
|
||||
let(:procedure_2) { create(:procedure, :published) }
|
||||
|
||||
let!(:dossier_0) { create(:dossier, state: Dossier.states.fetch(:brouillon), procedure: procedure_1, user: user_1) }
|
||||
let!(:dossier_0b) { create(:dossier, state: Dossier.states.fetch(:brouillon), procedure: procedure_1, user: user_2) }
|
||||
let(:dossier_0) { create(:dossier, state: Dossier.states.fetch(:brouillon), procedure: procedure_1, user: user_1) }
|
||||
let(:dossier_0b) { create(:dossier, state: Dossier.states.fetch(:brouillon), procedure: procedure_1, user: user_2) }
|
||||
|
||||
let!(:etablissement_1) { create(:etablissement, entreprise_raison_sociale: 'OCTO Academy', siret: '41636169600051') }
|
||||
let!(:dossier_1) { create(:dossier, state: Dossier.states.fetch(:en_construction), procedure: procedure_1, user: user_1, etablissement: etablissement_1) }
|
||||
let(:etablissement_1) { create(:etablissement, entreprise_raison_sociale: 'OCTO Academy', siret: '41636169600051') }
|
||||
let(:dossier_1) { create(:dossier, state: Dossier.states.fetch(:en_construction), procedure: procedure_1, user: user_1, etablissement: etablissement_1) }
|
||||
|
||||
let!(:etablissement_2) { create(:etablissement, entreprise_raison_sociale: 'Plop octo', siret: '41816602300012') }
|
||||
let!(:dossier_2) { create(:dossier, state: Dossier.states.fetch(:en_construction), procedure: procedure_1, user: user_1, etablissement: etablissement_2) }
|
||||
let(:etablissement_2) { create(:etablissement, entreprise_raison_sociale: 'Plop octo', siret: '41816602300012') }
|
||||
let(:dossier_2) { create(:dossier, state: Dossier.states.fetch(:en_construction), procedure: procedure_1, user: user_1, etablissement: etablissement_2) }
|
||||
|
||||
let!(:etablissement_3) { create(:etablissement, entreprise_raison_sociale: 'OCTO Technology', siret: '41816609600051') }
|
||||
let!(:dossier_3) { create(:dossier, state: Dossier.states.fetch(:en_construction), procedure: procedure_2, user: user_1, etablissement: etablissement_3) }
|
||||
let(:etablissement_3) { create(:etablissement, entreprise_raison_sociale: 'OCTO Technology', siret: '41816609600051') }
|
||||
let(:dossier_3) { create(:dossier, state: Dossier.states.fetch(:en_construction), procedure: procedure_2, user: user_1, etablissement: etablissement_3) }
|
||||
|
||||
let!(:dossier_archived) { create(:dossier, state: Dossier.states.fetch(:en_construction), procedure: procedure_1, archived: true, user: user_1) }
|
||||
let(:dossier_archived) { create(:dossier, state: Dossier.states.fetch(:en_construction), procedure: procedure_1, archived: true, user: user_1) }
|
||||
|
||||
describe 'search is empty' do
|
||||
let(:terms) { '' }
|
||||
|
|
|
@ -134,6 +134,8 @@ describe 'The routing with rules', js: true do
|
|||
user_send_dossier(litteraire_user, 'littéraire')
|
||||
user_send_dossier(artistique_user, 'artistique')
|
||||
|
||||
perform_enqueued_jobs(only: DossierUpdateSearchTermsJob)
|
||||
|
||||
# the litteraires instructeurs only manage the litteraires dossiers
|
||||
register_instructeur_and_log_in(victor.email)
|
||||
click_on procedure.libelle
|
||||
|
|
|
@ -162,6 +162,7 @@ describe 'Invitations' do
|
|||
before do
|
||||
navigate_to_invited_dossier(invite)
|
||||
visit dossiers_path
|
||||
perform_enqueued_jobs(only: DossierUpdateSearchTermsJob)
|
||||
end
|
||||
|
||||
it "can search by id and it displays the dossier" do
|
||||
|
|
|
@ -268,6 +268,7 @@ describe 'user access to the list of their dossiers', js: true do
|
|||
context 'when it matches multiple dossiers' do
|
||||
let!(:dossier_with_champs) { create(:dossier, :with_populated_champs, :en_construction, user: user) }
|
||||
before do
|
||||
perform_enqueued_jobs(only: DossierUpdateSearchTermsJob)
|
||||
find('.fr-search-bar .fr-btn').click
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in a new issue