with('tenant')->find($this->snapshotId); $operationRun = OperationRun::query()->find($this->operationRunId); if (! $snapshot instanceof EvidenceSnapshot || ! $operationRun instanceof OperationRun || ! $snapshot->tenant) { return; } $operationRuns->updateRun($operationRun, OperationRunStatus::Running->value, OperationRunOutcome::Pending->value); $snapshot->update(['status' => EvidenceSnapshotStatus::Generating->value]); try { $payload = $service->buildSnapshotPayload($snapshot->tenant); $previousActive = EvidenceSnapshot::query() ->where('tenant_id', (int) $snapshot->tenant_id) ->where('workspace_id', (int) $snapshot->workspace_id) ->where('status', EvidenceSnapshotStatus::Active->value) ->whereKeyNot((int) $snapshot->getKey()) ->first(); $snapshot->items()->delete(); foreach ($payload['items'] as $item) { $snapshot->items()->create([ 'tenant_id' => (int) $snapshot->tenant_id, 'workspace_id' => (int) $snapshot->workspace_id, 'dimension_key' => $item['dimension_key'], 'state' => $item['state'], 'required' => $item['required'], 'source_kind' => $item['source_kind'], 'source_record_type' => $item['source_record_type'], 'source_record_id' => $item['source_record_id'], 'source_fingerprint' => $item['source_fingerprint'], 'measured_at' => $item['measured_at'], 'freshness_at' => $item['freshness_at'], 'summary_payload' => $item['summary_payload'], 'sort_order' => $item['sort_order'], ]); } if ($previousActive instanceof EvidenceSnapshot && $previousActive->fingerprint !== $payload['fingerprint']) { $previousActive->update([ 'status' => EvidenceSnapshotStatus::Superseded->value, ]); } $snapshot->update([ 'fingerprint' => $payload['fingerprint'], 'previous_fingerprint' => $previousActive?->fingerprint, 'status' => EvidenceSnapshotStatus::Active->value, 'completeness_state' => $payload['completeness'], 'generated_at' => now(), 'summary' => $payload['summary'], ]); $operationRuns->updateRun( $operationRun, status: OperationRunStatus::Completed->value, outcome: OperationRunOutcome::Succeeded->value, summaryCounts: [ 'created' => 1, 'finding_count' => (int) ($payload['summary']['finding_count'] ?? 0), 'report_count' => (int) ($payload['summary']['report_count'] ?? 0), 'operation_count' => (int) ($payload['summary']['operation_count'] ?? 0), 'errors_recorded' => 0, ], ); } catch (Throwable $throwable) { $snapshot->update([ 'status' => EvidenceSnapshotStatus::Failed->value, 'summary' => [ 'error' => $throwable->getMessage(), ], ]); $operationRuns->updateRun( $operationRun, status: OperationRunStatus::Completed->value, outcome: OperationRunOutcome::Failed->value, failures: [ [ 'code' => 'evidence_snapshot_generation.failed', 'message' => $throwable->getMessage(), ], ], ); throw $throwable; } } }