operationRun = $operationRun; } public function middleware(): array { return [new TrackOperationRun]; } public function handle(EntraGroupSyncService $syncService, AuditLogger $auditLogger): void { if (! $this->operationRun) { $this->fail(new RuntimeException('OperationRun context is required for EntraGroupSyncJob.')); return; } $tenant = Tenant::query()->find($this->tenantId); if (! $tenant instanceof Tenant) { throw new RuntimeException('Tenant not found.'); } /** @var OperationRunService $opService */ $opService = app(OperationRunService::class); if ($this->operationRun->status === 'queued') { $opService->updateRun($this->operationRun, 'running'); } $auditLogger->log( tenant: $tenant, action: 'directory_groups.sync.started', context: [ 'selection_key' => $this->selectionKey, 'slot_key' => $this->slotKey, ], actorId: $this->operationRun->user_id, status: 'success', resourceType: 'operation_run', resourceId: (string) $this->operationRun->getKey(), ); $result = $syncService->sync($tenant, $this->selectionKey); $terminalStatus = 'succeeded'; if ($result['error_code'] !== null) { $terminalStatus = 'failed'; } elseif ($result['safety_stop_triggered'] === true) { $terminalStatus = 'partial'; } $opOutcome = match ($terminalStatus) { 'succeeded' => OperationRunOutcome::Succeeded->value, 'partial' => OperationRunOutcome::PartiallySucceeded->value, default => OperationRunOutcome::Failed->value, }; $failures = []; if (is_string($result['error_code']) && $result['error_code'] !== '') { $failures[] = [ 'code' => $result['error_code'], 'message' => is_string($result['error_summary']) ? $result['error_summary'] : 'Directory groups sync failed.', ]; } $opService->updateRun( $this->operationRun, 'completed', $opOutcome, [ 'total' => (int) $result['items_observed_count'], 'processed' => (int) $result['items_observed_count'], 'updated' => (int) $result['items_upserted_count'], 'failed' => (int) $result['error_count'], ], $failures, ); $auditLogger->log( tenant: $tenant, action: $terminalStatus === 'succeeded' ? 'directory_groups.sync.succeeded' : ($terminalStatus === 'partial' ? 'directory_groups.sync.partial' : 'directory_groups.sync.failed'), context: [ 'selection_key' => $this->selectionKey, 'slot_key' => $this->slotKey, 'pages_fetched' => $result['pages_fetched'], 'items_observed_count' => $result['items_observed_count'], 'items_upserted_count' => $result['items_upserted_count'], 'error_code' => $result['error_code'], 'error_category' => $result['error_category'], ], actorId: $this->operationRun->user_id, status: $terminalStatus === 'failed' ? 'failed' : 'success', resourceType: 'operation_run', resourceId: (string) $this->operationRun->getKey(), ); } }