using System; using System.Collections.Immutable; namespace StellaOps.Scheduler.Models; /// /// Shared helper for translating persisted documents into /// API-facing projections. /// public static class PolicyRunStatusFactory { public static PolicyRunStatus Create(PolicyRunJob job, DateTimeOffset nowUtc) { ArgumentNullException.ThrowIfNull(job); var status = MapExecutionStatus(job.Status); var queuedAt = job.QueuedAt ?? job.CreatedAt; var startedAt = job.SubmittedAt; var finishedAt = job.CompletedAt ?? job.CancelledAt; var metadata = job.Metadata ?? ImmutableSortedDictionary.Empty; var inputs = job.Inputs ?? PolicyRunInputs.Empty; var policyVersion = job.PolicyVersion ?? throw new InvalidOperationException($"Policy run job '{job.Id}' is missing policyVersion."); return new PolicyRunStatus( job.RunId ?? job.Id, job.TenantId, job.PolicyId, policyVersion, job.Mode, status, job.Priority, queuedAt, job.Status == PolicyRunJobStatus.Pending ? null : startedAt, finishedAt, PolicyRunStats.Empty, inputs, determinismHash: null, errorCode: null, error: job.Status == PolicyRunJobStatus.Failed ? job.LastError : null, attempts: job.AttemptCount, traceId: null, explainUri: null, metadata, cancellationRequested: job.CancellationRequested, cancellationRequestedAt: job.CancellationRequestedAt, cancellationReason: job.CancellationReason, SchedulerSchemaVersions.PolicyRunStatus); } private static PolicyRunExecutionStatus MapExecutionStatus(PolicyRunJobStatus status) => status switch { PolicyRunJobStatus.Pending => PolicyRunExecutionStatus.Queued, PolicyRunJobStatus.Dispatching => PolicyRunExecutionStatus.Running, PolicyRunJobStatus.Submitted => PolicyRunExecutionStatus.Running, PolicyRunJobStatus.Completed => PolicyRunExecutionStatus.Succeeded, PolicyRunJobStatus.Failed => PolicyRunExecutionStatus.Failed, PolicyRunJobStatus.Cancelled => PolicyRunExecutionStatus.Cancelled, _ => PolicyRunExecutionStatus.Queued }; }