159 lines
5.3 KiB
C#
159 lines
5.3 KiB
C#
|
|
using StellaOps.Scheduler.Models;
|
|
using StellaOps.Scheduler.Persistence.Postgres.Repositories;
|
|
using System.Collections.Concurrent;
|
|
using System.Collections.Immutable;
|
|
|
|
namespace StellaOps.Scheduler.WebService.Schedules;
|
|
|
|
internal sealed class InMemoryScheduleRepository : IScheduleRepository
|
|
{
|
|
private readonly ConcurrentDictionary<string, Schedule> _schedules = new(StringComparer.Ordinal);
|
|
|
|
public Task UpsertAsync(
|
|
Schedule schedule,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
_schedules[schedule.Id] = schedule;
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
public Task<Schedule?> GetAsync(
|
|
string tenantId,
|
|
string scheduleId,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
if (_schedules.TryGetValue(scheduleId, out var schedule) &&
|
|
string.Equals(schedule.TenantId, tenantId, StringComparison.Ordinal))
|
|
{
|
|
return Task.FromResult<Schedule?>(schedule);
|
|
}
|
|
|
|
return Task.FromResult<Schedule?>(null);
|
|
}
|
|
|
|
public Task<IReadOnlyList<Schedule>> ListAsync(
|
|
string tenantId,
|
|
ScheduleQueryOptions? options = null,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
options ??= new ScheduleQueryOptions();
|
|
|
|
var query = _schedules.Values
|
|
.Where(schedule => string.Equals(schedule.TenantId, tenantId, StringComparison.Ordinal));
|
|
|
|
if (!options.IncludeDisabled)
|
|
{
|
|
query = query.Where(schedule => schedule.Enabled);
|
|
}
|
|
|
|
var result = query
|
|
.OrderBy(schedule => schedule.Name, StringComparer.Ordinal)
|
|
.Take(options.Limit ?? int.MaxValue)
|
|
.ToArray();
|
|
|
|
return Task.FromResult<IReadOnlyList<Schedule>>(result);
|
|
}
|
|
|
|
public Task<bool> SoftDeleteAsync(
|
|
string tenantId,
|
|
string scheduleId,
|
|
string deletedBy,
|
|
DateTimeOffset deletedAt,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
if (_schedules.TryGetValue(scheduleId, out var schedule) &&
|
|
string.Equals(schedule.TenantId, tenantId, StringComparison.Ordinal))
|
|
{
|
|
_schedules.TryRemove(scheduleId, out _);
|
|
return Task.FromResult(true);
|
|
}
|
|
|
|
return Task.FromResult(false);
|
|
}
|
|
}
|
|
|
|
internal sealed class InMemoryRunSummaryService : IRunSummaryService
|
|
{
|
|
private readonly ConcurrentDictionary<(string TenantId, string ScheduleId), RunSummaryProjection> _summaries = new();
|
|
|
|
public Task<RunSummaryProjection> ProjectAsync(Run run, CancellationToken cancellationToken = default)
|
|
{
|
|
var scheduleId = run.ScheduleId ?? string.Empty;
|
|
var updatedAt = run.FinishedAt ?? run.StartedAt ?? run.CreatedAt;
|
|
|
|
var counters = new RunSummaryCounters(
|
|
Total: 0,
|
|
Planning: 0,
|
|
Queued: 0,
|
|
Running: 0,
|
|
Completed: 0,
|
|
Error: 0,
|
|
Cancelled: 0,
|
|
TotalDeltas: 0,
|
|
TotalNewCriticals: 0,
|
|
TotalNewHigh: 0,
|
|
TotalNewMedium: 0,
|
|
TotalNewLow: 0);
|
|
|
|
var projection = new RunSummaryProjection(
|
|
run.TenantId,
|
|
scheduleId,
|
|
updatedAt,
|
|
null,
|
|
ImmutableArray<RunSummarySnapshot>.Empty,
|
|
counters);
|
|
|
|
_summaries[(run.TenantId, scheduleId)] = projection;
|
|
return Task.FromResult(projection);
|
|
}
|
|
|
|
public Task<RunSummaryProjection?> GetAsync(string tenantId, string scheduleId, CancellationToken cancellationToken = default)
|
|
{
|
|
_summaries.TryGetValue((tenantId, scheduleId), out var projection);
|
|
return Task.FromResult<RunSummaryProjection?>(projection);
|
|
}
|
|
|
|
public Task<IReadOnlyList<RunSummaryProjection>> ListAsync(string tenantId, CancellationToken cancellationToken = default)
|
|
{
|
|
var projections = _summaries.Values
|
|
.Where(summary => string.Equals(summary.TenantId, tenantId, StringComparison.Ordinal))
|
|
.ToArray();
|
|
return Task.FromResult<IReadOnlyList<RunSummaryProjection>>(projections);
|
|
}
|
|
}
|
|
|
|
internal sealed class InMemorySchedulerAuditService : ISchedulerAuditService
|
|
{
|
|
private readonly TimeProvider _timeProvider;
|
|
private readonly StellaOps.Determinism.IGuidProvider _guidProvider;
|
|
|
|
public InMemorySchedulerAuditService(
|
|
TimeProvider? timeProvider = null,
|
|
StellaOps.Determinism.IGuidProvider? guidProvider = null)
|
|
{
|
|
_timeProvider = timeProvider ?? TimeProvider.System;
|
|
_guidProvider = guidProvider ?? StellaOps.Determinism.SystemGuidProvider.Instance;
|
|
}
|
|
|
|
public Task<AuditRecord> WriteAsync(SchedulerAuditEvent auditEvent, CancellationToken cancellationToken = default)
|
|
{
|
|
var occurredAt = auditEvent.OccurredAt ?? _timeProvider.GetUtcNow();
|
|
var record = new AuditRecord(
|
|
auditEvent.AuditId ?? $"audit_{_guidProvider.NewGuid():N}",
|
|
auditEvent.TenantId,
|
|
auditEvent.Category,
|
|
auditEvent.Action,
|
|
occurredAt,
|
|
auditEvent.Actor,
|
|
auditEvent.EntityId,
|
|
auditEvent.ScheduleId,
|
|
auditEvent.RunId,
|
|
auditEvent.CorrelationId,
|
|
auditEvent.Metadata?.ToImmutableSortedDictionary(StringComparer.OrdinalIgnoreCase) ?? ImmutableSortedDictionary<string, string>.Empty,
|
|
auditEvent.Message);
|
|
|
|
return Task.FromResult(record);
|
|
}
|
|
}
|