where('received_at', '<', $now->copy()->subDays((int) config('webhooks.request_retention_days', 7))) ->delete(); $this->pruneEndpointLimits(); $deletedEndpoints = $this->deleteExpiredAnonymousEndpoints($now); $this->info("Deleted {$deletedRequests} old requests and {$deletedEndpoints} expired endpoints."); return self::SUCCESS; } private function pruneEndpointLimits(): void { WebhookEndpoint::query() ->select('id') ->chunkById(100, function (Collection $endpoints): void { foreach ($endpoints as $endpoint) { $requestIds = WebhookRequest::query() ->whereBelongsTo($endpoint, 'endpoint') ->select('id') ->orderByDesc('received_at') ->orderByDesc('id') ->skip((int) config('webhooks.max_requests_per_endpoint', 1000)) ->take(1_000_000_000) ->pluck('id'); if ($requestIds->isNotEmpty()) { WebhookRequest::query()->whereKey($requestIds)->delete(); } } }); } private function deleteExpiredAnonymousEndpoints(Carbon $now): int { return WebhookEndpoint::query() ->public() ->whereNull('user_id') ->whereNotNull('expires_at') ->where('expires_at', '<', $now) ->delete(); } }