Restructure solution layout by module

This commit is contained in:
master
2025-10-28 15:10:40 +02:00
parent 95daa159c4
commit d870da18ce
4103 changed files with 192899 additions and 187024 deletions

View File

@@ -0,0 +1,185 @@
using System;
using System.Collections.Immutable;
using System.Text.Json.Serialization;
namespace StellaOps.Scheduler.Models;
public sealed record PolicyRunJob(
string SchemaVersion,
string Id,
string TenantId,
string PolicyId,
int? PolicyVersion,
PolicyRunMode Mode,
PolicyRunPriority Priority,
int PriorityRank,
string? RunId,
string? RequestedBy,
string? CorrelationId,
ImmutableSortedDictionary<string, string>? Metadata,
PolicyRunInputs Inputs,
DateTimeOffset? QueuedAt,
PolicyRunJobStatus Status,
int AttemptCount,
DateTimeOffset? LastAttemptAt,
string? LastError,
DateTimeOffset CreatedAt,
DateTimeOffset UpdatedAt,
DateTimeOffset AvailableAt,
DateTimeOffset? SubmittedAt,
DateTimeOffset? CompletedAt,
string? LeaseOwner,
DateTimeOffset? LeaseExpiresAt,
bool CancellationRequested,
DateTimeOffset? CancellationRequestedAt,
string? CancellationReason,
DateTimeOffset? CancelledAt)
{
public string SchemaVersion { get; init; } = SchedulerSchemaVersions.EnsurePolicyRunJob(SchemaVersion);
public string Id { get; init; } = Validation.EnsureId(Id, nameof(Id));
public string TenantId { get; init; } = Validation.EnsureTenantId(TenantId, nameof(TenantId));
public string PolicyId { get; init; } = Validation.EnsureSimpleIdentifier(PolicyId, nameof(PolicyId));
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public int? PolicyVersion { get; init; } = EnsurePolicyVersion(PolicyVersion);
public PolicyRunMode Mode { get; init; } = Mode;
public PolicyRunPriority Priority { get; init; } = Priority;
public int PriorityRank { get; init; } = PriorityRank >= 0 ? PriorityRank : GetPriorityRank(Priority);
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? RunId { get; init; } = NormalizeRunId(RunId);
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? RequestedBy { get; init; } = Validation.TrimToNull(RequestedBy);
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? CorrelationId { get; init; } = Validation.TrimToNull(CorrelationId);
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public ImmutableSortedDictionary<string, string>? Metadata { get; init; } = NormalizeMetadata(Metadata);
public PolicyRunInputs Inputs { get; init; } = Inputs ?? throw new ArgumentNullException(nameof(Inputs));
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public DateTimeOffset? QueuedAt { get; init; } = Validation.NormalizeTimestamp(QueuedAt);
public PolicyRunJobStatus Status { get; init; } = Status;
public int AttemptCount { get; init; } = Validation.EnsureNonNegative(AttemptCount, nameof(AttemptCount));
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public DateTimeOffset? LastAttemptAt { get; init; } = Validation.NormalizeTimestamp(LastAttemptAt);
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? LastError { get; init; } = Validation.TrimToNull(LastError);
public DateTimeOffset CreatedAt { get; init; } = NormalizeTimestamp(CreatedAt, nameof(CreatedAt));
public DateTimeOffset UpdatedAt { get; init; } = NormalizeTimestamp(UpdatedAt, nameof(UpdatedAt));
public DateTimeOffset AvailableAt { get; init; } = NormalizeTimestamp(AvailableAt, nameof(AvailableAt));
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public DateTimeOffset? SubmittedAt { get; init; } = Validation.NormalizeTimestamp(SubmittedAt);
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public DateTimeOffset? CompletedAt { get; init; } = Validation.NormalizeTimestamp(CompletedAt);
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? LeaseOwner { get; init; } = Validation.TrimToNull(LeaseOwner);
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public DateTimeOffset? LeaseExpiresAt { get; init; } = Validation.NormalizeTimestamp(LeaseExpiresAt);
public bool CancellationRequested { get; init; } = CancellationRequested;
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public DateTimeOffset? CancellationRequestedAt { get; init; } = Validation.NormalizeTimestamp(CancellationRequestedAt);
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? CancellationReason { get; init; } = Validation.TrimToNull(CancellationReason);
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public DateTimeOffset? CancelledAt { get; init; } = Validation.NormalizeTimestamp(CancelledAt);
public PolicyRunRequest ToPolicyRunRequest(DateTimeOffset fallbackQueuedAt)
{
var queuedAt = QueuedAt ?? fallbackQueuedAt;
return new PolicyRunRequest(
TenantId,
PolicyId,
Mode,
Inputs,
Priority,
RunId,
PolicyVersion,
RequestedBy,
queuedAt,
CorrelationId,
Metadata);
}
private static int? EnsurePolicyVersion(int? value)
{
if (value is not null && value <= 0)
{
throw new ArgumentOutOfRangeException(nameof(PolicyVersion), value, "Policy version must be positive.");
}
return value;
}
private static string? NormalizeRunId(string? runId)
{
var trimmed = Validation.TrimToNull(runId);
return trimmed is null ? null : Validation.EnsureId(trimmed, nameof(runId));
}
private static ImmutableSortedDictionary<string, string>? NormalizeMetadata(ImmutableSortedDictionary<string, string>? metadata)
{
if (metadata is null || metadata.Count == 0)
{
return null;
}
var builder = ImmutableSortedDictionary.CreateBuilder<string, string>(StringComparer.Ordinal);
foreach (var (key, value) in metadata)
{
var normalizedKey = Validation.TrimToNull(key);
var normalizedValue = Validation.TrimToNull(value);
if (normalizedKey is null || normalizedValue is null)
{
continue;
}
builder[normalizedKey.ToLowerInvariant()] = normalizedValue;
}
return builder.Count == 0 ? null : builder.ToImmutable();
}
private static int GetPriorityRank(PolicyRunPriority priority)
=> priority switch
{
PolicyRunPriority.Emergency => 2,
PolicyRunPriority.High => 1,
_ => 0
};
private static DateTimeOffset NormalizeTimestamp(DateTimeOffset value, string propertyName)
{
var normalized = Validation.NormalizeTimestamp(value);
if (normalized == default)
{
throw new ArgumentException($"{propertyName} must be a valid timestamp.", propertyName);
}
return normalized;
}
}