$itemIds * @param array $context */ public function __construct( public int $tenantId, public int $userId, public array $itemIds, ?OperationRun $operationRun = null, public array $context = [], ) { $this->operationRun = $operationRun; $this->itemIds = $this->normalizeItemIds($itemIds); } /** * @return array */ public function middleware(): array { return []; } public function handle(OperationRunService $runs): void { if (! $this->operationRun instanceof OperationRun) { throw new RuntimeException('OperationRun is required for bulk orchestrator jobs.'); } $this->operationRun->refresh(); if ($this->operationRun->status === 'completed') { return; } $runs->updateRun($this->operationRun, 'running'); $runs->incrementSummaryCounts($this->operationRun, ['total' => count($this->itemIds)]); $chunkSize = (int) config('tenantpilot.bulk_operations.chunk_size', 10); $chunkSize = max(1, $chunkSize); foreach (array_chunk($this->itemIds, $chunkSize) as $chunk) { foreach ($chunk as $itemId) { dispatch($this->makeWorkerJob($itemId)); } } } abstract protected function makeWorkerJob(string $itemId): ShouldQueue; /** * @param array $itemIds * @return array */ protected function normalizeItemIds(array $itemIds): array { $normalized = []; foreach ($itemIds as $itemId) { if (is_int($itemId)) { $itemId = (string) $itemId; } if (! is_string($itemId)) { continue; } $itemId = trim($itemId); if ($itemId === '') { continue; } $normalized[] = $itemId; } $normalized = array_values(array_unique($normalized)); sort($normalized); return $normalized; } }