test: enable Doctrine profiling in the test env and fix the N+1 it exposed
APP_DEBUG=0 in .env means doctrine.dbal.profiling, which defaults to %kernel.debug%, was off in tests too, so doctrine.debug_data_holder was never registered. Every test calling countQueries() errored out — all four N+1 regression tests had been dead for as long as they have existed. Turning profiling on for when@test brings the harness back. Three of the four passed immediately. The fourth was a real N+1: the service-coverage endpoint batch-fetched its ServiceItem entities to avoid one find() per row, but ServiceItem maps staffMembers as fetch: EAGER, so hydrating N items fired N extra collection loads and the batch bought nothing. Six coverage rows cost 11 queries where one row cost 6. ServiceItemRepository::findUuidsByIds() returns the id => uuid map as a scalar query, so no entity is hydrated and no eager collection is touched. Also adds the query-count assertion for next_available_at that could not be written while the harness was broken. Confirmed it fails against the previous per-day implementation (40 queries for 2 locations, 113 for 6) and passes now. Suite: 411 tests, 2 failures — both pre-existing and unrelated (LowTierFixesTest, PatientWalletSessionSettleTest). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -493,15 +493,10 @@ class InsuranceController extends BaseController
|
||||
|
||||
$rows = $this->serviceCoverageRepo->findByContract($contract->getId());
|
||||
|
||||
// Batch-fetch the referenced service items once instead of one find()
|
||||
// per coverage row (N+1).
|
||||
$itemIds = array_values(array_unique(array_map(fn($r) => $r->getServiceItemId(), $rows)));
|
||||
$uuidById = [];
|
||||
if ($itemIds !== []) {
|
||||
foreach ($this->serviceItemRepo->findBy(['id' => $itemIds]) as $item) {
|
||||
$uuidById[$item->getId()] = $item->getUuid();
|
||||
}
|
||||
}
|
||||
// یک کوئری اسکالر برای همهٔ uuidها. هیدریتکردن entity کافی نیست: رابطهٔ
|
||||
// EAGER staffMembers روی ServiceItem به ازای هر ردیف یک کوئری اضافه میزند.
|
||||
$itemIds = array_values(array_unique(array_map(fn($r) => $r->getServiceItemId(), $rows)));
|
||||
$uuidById = $this->serviceItemRepo->findUuidsByIds($itemIds);
|
||||
|
||||
$data = array_map(function ($r) use ($uuidById) {
|
||||
$row = $r->toArray();
|
||||
|
||||
Reference in New Issue
Block a user