operationRun = $operationRun; } public function middleware(): array { return [new TrackOperationRun]; } /** * Execute the job. */ public function handle(RoleDefinitionsSyncService $syncService, AuditLogger $auditLogger): void { if (! $this->operationRun) { $this->fail(new RuntimeException('OperationRun context is required for SyncRoleDefinitionsJob.')); return; } $tenant = Tenant::query()->find($this->tenantId); if (! $tenant instanceof Tenant) { throw new RuntimeException('Tenant not found.'); } $auditLogger->log( tenant: $tenant, action: 'directory_role_definitions.sync.started', context: [ 'tenant_id' => (int) $tenant->getKey(), ], actorId: $this->operationRun->user_id, status: 'success', resourceType: 'operation_run', resourceId: (string) $this->operationRun->getKey(), ); $result = $syncService->sync($tenant); /** @var OperationRunService $opService */ $opService = app(OperationRunService::class); $outcome = 'succeeded'; if ($result['error_code'] !== null) { $outcome = 'failed'; } elseif ($result['safety_stop_triggered'] === true) { $outcome = 'partially_succeeded'; } $failures = []; if (is_string($result['error_code']) && $result['error_code'] !== '') { $failures[] = [ 'code' => $result['error_code'], 'message' => is_string($result['error_summary']) ? $result['error_summary'] : 'Role definitions sync failed.', ]; } $opService->updateRun( $this->operationRun, 'completed', $outcome, [ 'total' => $result['items_observed_count'], 'processed' => $result['items_observed_count'], 'updated' => $result['items_upserted_count'], 'failed' => $result['error_count'], ], $failures, ); $auditLogger->log( tenant: $tenant, action: $outcome === 'succeeded' ? 'directory_role_definitions.sync.succeeded' : ($outcome === 'partially_succeeded' ? 'directory_role_definitions.sync.partial' : 'directory_role_definitions.sync.failed'), context: [ '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'], 'finished_at' => CarbonImmutable::now('UTC')->toIso8601String(), ], actorId: $this->operationRun->user_id, status: $outcome === 'failed' ? 'failed' : 'success', resourceType: 'operation_run', resourceId: (string) $this->operationRun->getKey(), ); } }