where('status', StockReservation::STATUS_ACTIVE) ->whereNotNull('expires_at') ->where('expires_at', '<=', now()) ->where('id', '>', $lastReservationId) ->whereHas('currentCart', fn ($query) => $query->where('status', 'active')) ->whereDoesntHave('purchase', fn ($query) => $query->whereIn('status', [ Purchase::STATUS_CREATED, Purchase::STATUS_PENDING_PAYMENT, Purchase::STATUS_IN_REVIEW, ])) ->orderBy('id') ->limit(500) ->pluck('id'); foreach ($reservationIds as $reservationId) { $lastReservationId = (int) $reservationId; if ($this->expireReservation($lastReservationId)) { $expired++; } } } while ($reservationIds->count() === 500); return $expired; } private function expireReservation(int $reservationId): bool { $cartId = Cart::query() ->where('current_stock_reservation_id', $reservationId) ->where('status', 'active') ->value('id'); if ($cartId === null) { return false; } return DB::transaction(function () use ($cartId, $reservationId): bool { /** @var Cart|null $cart */ $cart = Cart::query() ->whereKey($cartId) ->where('current_stock_reservation_id', $reservationId) ->where('status', 'active') ->lockForUpdate() ->first(); if ($cart === null) { return false; } /** @var StockReservation|null $reservation */ $reservation = StockReservation::query()->lockForUpdate()->find($reservationId); if ($reservation === null || $reservation->status !== StockReservation::STATUS_ACTIVE || $reservation->expires_at === null || $reservation->expires_at->isFuture()) { return false; } $this->reservations->expire($reservation); return true; }); } }