consolidation of some of the modules, localization fixes, product advisories work, qa work
This commit is contained in:
@@ -0,0 +1,158 @@
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user