Skip to content

Commit

Permalink
Merge pull request #11276 from tchak/fix-repetition-migration-task-again
Browse files Browse the repository at this point in the history
[Tech] Encore une tentative d'améliorer la perf de la tache de migration des champs
  • Loading branch information
tchak authored Feb 13, 2025
2 parents 996aaa7 + 0aa836c commit 085dec5
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,30 +8,47 @@ class T20241202migrateNonFillableAndRepetitionChampsTask < MaintenanceTasks::Tas
include StatementsHelpersConcern

def collection
Dossier.includes(champs: [], revision: { revision_types_de_champ: { parent_type_de_champ: [], types_de_champ: [] }, types_de_champ_public: [], types_de_champ_private: [], types_de_champ: [] })
Dossier.select(:id, :revision_id)
end

def process(dossier)
Dossier.no_touching do
champ_to_remove_ids = dossier
.champs
.filter { !_1.row? && (_1.repetition? || _1.header_section? || _1.explication?) }
.map(&:id)
dossier.champs.where(id: champ_to_remove_ids).destroy_all

create_rows(dossier)
end
# ici on peut faire un delete_all car les champs concernés n'ont pas de cascade
Champ.where(dossier_id: dossier.id, type: ['Champs::HeaderSectionChamp', 'Champs::ExplicationChamp'])
.or(Champ.where(dossier_id: dossier.id, type: 'Champs::RepetitionChamp', row_id: Champ::NULL_ROW_ID))
.delete_all

create_rows(dossier.id, dossier.revision_id)
end

def create_rows(dossier)
repetitions = dossier.revision.types_de_champ.filter(&:repetition?)
existing_row_ids = dossier.champs.filter(&:row?).to_set(&:row_id)
def create_rows(dossier_id, revision_id)
# les row_ids qui sont déjà persistés en base
persisted_row_ids = Champs::RepetitionChamp.where(dossier_id:).where.not(row_id: Champ::NULL_ROW_ID).pluck(:row_id)

first_child_stable_id_by_row_id = Champ.where(dossier_id:)
.where.not(type: 'Champs::RepetitionChamp')
.where.not(row_id: Champ::NULL_ROW_ID)
.where.not(row_id: persisted_row_ids)
.pluck(:row_id, :stable_id)
.to_h

return if first_child_stable_id_by_row_id.empty?

coordinates_for_revision_id = ProcedureRevisionTypeDeChamp.joins(:type_de_champ).where(revision_id:)
coordinates = coordinates_for_revision_id
.where(types_de_champ: { type_champ: 'repetition' })
.or(coordinates_for_revision_id.where.not(parent_id: nil))
.pluck(:id, :stable_id, :parent_id, :private)
coordinate_parent_id_by_stable_id = coordinates.index_by(&:second).transform_values(&:third)
type_de_champ_attributes_by_id = coordinates.index_by(&:first).transform_values { { stable_id: _1.second, private: _1.last } }

now = Time.zone.now
row_attributes = { created_at: now, updated_at: now, dossier_id: dossier.id }
new_rows = repetitions.flat_map do |type_de_champ|
row_ids = dossier.repetition_row_ids(type_de_champ).to_set - existing_row_ids
row_ids.map { type_de_champ.params_for_champ.merge(row_id: _1, **row_attributes) }
row_attributes = { type: 'Champs::RepetitionChamp', created_at: now, updated_at: now, dossier_id: }
new_rows = first_child_stable_id_by_row_id.filter_map do |row_id, child_stable_id|
parent_id = coordinate_parent_id_by_stable_id[child_stable_id]
type_de_champ_attributes = type_de_champ_attributes_by_id[parent_id]
type_de_champ_attributes&.merge(row_id:, **row_attributes)
end

Champ.insert_all!(new_rows) if new_rows.present?
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ module Maintenance
header_section, explication, _, repetition = dossier.revision.types_de_champ_public
dossier.champs.create(**header_section.params_for_champ)
dossier.champs.create(**explication.params_for_champ)
dossier.champs.create(**repetition.params_for_champ)
dossier.champs.create(**repetition.params_for_champ, row_id: Champ::NULL_ROW_ID)
dossier.reload
}

Expand All @@ -23,16 +23,23 @@ module Maintenance

describe "create rows" do
subject(:process) { described_class.process(dossier) }
let(:procedure) { create(:procedure, types_de_champ_public: [{ type: :repetition, children: [{}] }]) }
let(:dossier) { create(:dossier, :with_populated_champs, procedure:) }
let(:procedure) do
create(:procedure,
types_de_champ_public: [{ type: :repetition, stable_id: 99, children: [{}, {}] }, { type: :repetition, children: [{}] }],
types_de_champ_private: [{ type: :repetition, children: [{}] }])
end
let(:dossier) { create(:dossier, :with_populated_champs, :with_populated_annotations, procedure:) }

before {
dossier.champs.filter(&:row?).each(&:destroy!)
repetition_1_rows, repetition_2_rows = dossier.champs.filter(&:public?).filter(&:row?).partition { _1.stable_id == 99 }
repetition_1_rows.each(&:destroy!)
repetition_2_rows.first.discard!
dossier.champs.filter(&:private?).find(&:row?).destroy!
dossier.reload
}

it { expect { subject }.not_to change { dossier.reload.updated_at } }
it { expect { subject }.to change { dossier.champs.where(type: 'Champs::RepetitionChamp').count }.by(2) }
it { expect { subject }.to change { dossier.champs.where(type: 'Champs::RepetitionChamp').count }.from(3).to(6) }
end
end
end

0 comments on commit 085dec5

Please sign in to comment.