with(['tenant', 'evidenceSnapshot.items'])->find($this->environmentReviewId); $operationRun = OperationRun::query()->find($this->operationRunId); if (! $review instanceof EnvironmentReview || ! $operationRun instanceof OperationRun || ! $review->tenant) { return; } if ((string) $operationRun->status === OperationRunStatus::Completed->value) { return; } $adapterChange = $adapterRunReconciler->reconcileOperationRun($operationRun); if (($adapterChange['applied'] ?? false) === true) { return; } $operationRuns->updateRun($operationRun, OperationRunStatus::Running->value, OperationRunOutcome::Pending->value); $review->update(['status' => EnvironmentReviewStatus::Draft->value]); try { $review = $service->compose($review); $summary = is_array($review->summary) ? $review->summary : []; $operationRuns->updateRun( $operationRun, status: OperationRunStatus::Completed->value, outcome: OperationRunOutcome::Succeeded->value, summaryCounts: [ 'created' => 1, 'finding_count' => (int) ($summary['finding_count'] ?? 0), 'report_count' => (int) ($summary['report_count'] ?? 0), 'operation_count' => (int) ($summary['operation_count'] ?? 0), 'errors_recorded' => 0, ], ); } catch (Throwable $throwable) { $adapterChange = $adapterRunReconciler->reconcileOperationRun($operationRun); if (($adapterChange['applied'] ?? false) === true) { return; } if ($throwable instanceof QueryException && $this->isUniqueViolation($throwable)) { $result = ReconciliationResult::attentionRequired( reasonCode: LifecycleReconciliationReason::AdapterOutOfSync->value, reasonMessage: 'TenantPilot found matching review activity, but it could not be resolved automatically.', evidence: [ 'adapter' => EnvironmentReviewComposeDecision::ADAPTER, 'exception_class' => class_basename($throwable), 'workspace_id' => (int) $operationRun->workspace_id, 'managed_environment_id' => (int) $operationRun->managed_environment_id, 'fingerprint' => (string) data_get($operationRun->context, 'review_fingerprint', ''), ], ); $operationRuns->updateRunWithReconciliation( run: $operationRun, status: (string) $result->status, outcome: (string) $result->outcome, summaryCounts: $result->summaryCounts, failures: $result->failures, reasonCode: $result->reasonCode, reasonMessage: $result->reasonMessage, source: 'adapter_reconciler', evidence: $result->evidence, adapter: EnvironmentReviewComposeDecision::ADAPTER, decision: $result->decision, related: $result->related, ); return; } if ($review->isMutable() && (int) ($review->operation_run_id ?? 0) === (int) $operationRun->getKey()) { $review->update([ 'status' => EnvironmentReviewStatus::Failed->value, 'summary' => array_merge(is_array($review->summary) ? $review->summary : [], [ 'error' => RunFailureSanitizer::sanitizeMessage($throwable->getMessage()), ]), ]); } $operationRuns->updateRun( $operationRun, status: OperationRunStatus::Completed->value, outcome: OperationRunOutcome::Failed->value, failures: [ [ 'code' => 'environment_review_compose.failed', 'message' => $throwable->getMessage(), ], ], ); throw $throwable; } } private function isUniqueViolation(QueryException $exception): bool { return in_array(($exception->errorInfo[0] ?? null), ['23505', '23000'], true); } }