find($this->bulkRunId); if (! $run || $run->status !== 'pending') { return; } $service->start($run); try { $chunkSize = 10; $itemCount = 0; $totalItems = $run->total_items ?: count($run->item_ids ?? []); $failureThreshold = (int) floor($totalItems / 2); foreach (($run->item_ids ?? []) as $policyId) { $itemCount++; try { $policy = Policy::query() ->whereKey($policyId) ->where('tenant_id', $run->tenant_id) ->first(); if (! $policy) { $service->recordFailure($run, (string) $policyId, 'Policy not found'); if ($run->failed > $failureThreshold) { $service->abort($run, 'Circuit breaker: more than 50% of items failed.'); if ($run->user) { Notification::make() ->title('Bulk Sync Aborted') ->body('Circuit breaker triggered: too many failures (>50%).') ->icon('heroicon-o-exclamation-triangle') ->danger() ->sendToDatabase($run->user) ->send(); } return; } continue; } if ($policy->ignored_at) { $service->recordSkippedWithReason($run, (string) $policyId, 'Policy is ignored locally'); continue; } $syncService->syncPolicy($run->tenant, $policy); $service->recordSuccess($run); } catch (Throwable $e) { $service->recordFailure($run, (string) $policyId, $e->getMessage()); if ($run->failed > $failureThreshold) { $service->abort($run, 'Circuit breaker: more than 50% of items failed.'); if ($run->user) { Notification::make() ->title('Bulk Sync Aborted') ->body('Circuit breaker triggered: too many failures (>50%).') ->icon('heroicon-o-exclamation-triangle') ->danger() ->sendToDatabase($run->user) ->send(); } return; } } if ($itemCount % $chunkSize === 0) { $run->refresh(); } } $service->complete($run); if ($run->user) { $message = "Synced {$run->succeeded} policies"; if ($run->skipped > 0) { $message .= " ({$run->skipped} skipped)"; } if ($run->failed > 0) { $message .= " ({$run->failed} failed)"; } $message .= '.'; Notification::make() ->title('Bulk Sync Completed') ->body($message) ->icon('heroicon-o-check-circle') ->success() ->sendToDatabase($run->user) ->send(); } } catch (Throwable $e) { $service->fail($run, $e->getMessage()); $run->refresh(); $run->load('user'); if ($run->user) { Notification::make() ->title('Bulk Sync Failed') ->body($e->getMessage()) ->icon('heroicon-o-x-circle') ->danger() ->sendToDatabase($run->user) ->send(); } throw $e; } } }