refactor(stock): make reservation expiration authoritative

This commit is contained in:
2026-08-25 15:28:17 -03:00
parent 00ec37d8a0
commit 1881cc1d4b
6 changed files with 52 additions and 64 deletions

View File

@@ -21,7 +21,7 @@ class ExpireStockReservationsService
) {}
/**
* @return array{purchases: int, cart_reservations: int}
* @return array{purchases: int, cart_reservations: int, orphan_reservations: int, failed: int}
*/
public function expireOverdue(): array
{
@@ -43,24 +43,24 @@ class ExpireStockReservationsService
->limit(self::BATCH_SIZE)
->pluck('id');
Log::channel('commands')->info('Stock reservation cleanup completed.', [
'command' => 'reservations:expire',
'expired_purchases' => $expiredPurchases,
'expired_cart_reservations' => $expiredCartItems,
'total_expired' => $expiredPurchases + $expiredCartItems,
]);
foreach ($reservationIds as $reservationId) {
$lastReservationId = (int) $reservationId;
return [
'purchases' => $expiredPurchases,
'cart_reservations' => $expiredCartItems,
];
} catch (Throwable $exception) {
Log::channel('commands')->error('Stock reservation cleanup failed.', [
'command' => 'reservations:expire',
'expired_purchases' => $expiredPurchases,
'expired_cart_reservations' => $expiredCartItems,
'exception' => $exception,
]);
try {
$owner = $this->expireReservation($lastReservationId);
if ($owner !== null) {
$summary[$owner]++;
}
} catch (Throwable $exception) {
$summary['failed']++;
Log::channel('commands')->error('Failed to expire overdue stock reservation.', [
'command' => 'reservations:expire',
'stock_reservation_id' => $lastReservationId,
'exception' => $exception,
]);
}
}
} while ($reservationIds->count() === self::BATCH_SIZE);
Log::channel('commands')->info('Stock reservation cleanup completed.', [
'command' => 'reservations:expire',
@@ -76,20 +76,6 @@ class ExpireStockReservationsService
return $summary;
}
public function expireIfOverdue(int $reservationId): bool
{
/** @var StockReservation|null $reservation */
$reservation = StockReservation::query()->find($reservationId);
if ($reservation?->status === StockReservation::STATUS_EXPIRED) {
return true;
}
if (! $this->isOverdue($reservation)) {
return false;
}
return $this->expireReservation($reservationId) !== null;
}
/** @return 'purchases'|'cart_reservations'|'orphan_reservations'|null */
private function expireReservation(int $reservationId): ?string
{
@@ -141,7 +127,7 @@ class ExpireStockReservationsService
$cart = Cart::query()
->whereKey($cartId)
->where('current_stock_reservation_id', $reservationId)
->where('status', Cart::STATUS_ACTIVE)
->where('status', 'active')
->lockForUpdate()
->first();
if ($cart === null) {
@@ -155,7 +141,6 @@ class ExpireStockReservationsService
}
$this->reservations->expire($reservation);
$cart->update(['status' => Cart::STATUS_EXPIRED]);
return 'cart_reservations';
});