perf(appointment): batch-fetch pending payments in expiry loop (fix N+1)

AppointmentExpiryService ran one findPendingByAppointment query per expiring
booking. Add PaymentRepository::findPendingByAppointments (one IN query keyed
by appointment id) and use it. Test covers expiry + payment cancellation for
several appointments at once.
This commit is contained in:
hamed
2026-06-28 17:10:32 +03:30
parent 36b87e9817
commit e1740462b5
3 changed files with 87 additions and 1 deletions
@@ -29,12 +29,16 @@ class AppointmentExpiryService
$expired[$appointment->getUuid()] = $appointment;
}
// Fetch all pending payments for the expiring appointments in one query
// instead of one lookup per appointment (was N+1 in this scheduler loop).
$pendingByAppointment = $this->paymentRepo->findPendingByAppointments(array_values($expired));
$count = 0;
foreach ($expired as $appointment) {
$appointment->transitionTo(Appointment::STATUS_EXPIRED);
$this->appointmentRepo->save($appointment, false);
$payment = $this->paymentRepo->findPendingByAppointment($appointment);
$payment = $pendingByAppointment[$appointment->getId()] ?? null;
if ($payment !== null) {
$payment->setStatus(Payment::STATUS_CANCELED);
$this->paymentRepo->save($payment, false);