137 lines
4.5 KiB
C#
137 lines
4.5 KiB
C#
using System.Collections.Concurrent;
|
|
using System.Collections.Generic;
|
|
using System.Collections.Immutable;
|
|
using System.Linq;
|
|
using StellaOps.Scheduler.Models;
|
|
using StellaOps.Scheduler.Persistence.Postgres.Repositories;
|
|
|
|
namespace StellaOps.Scheduler.WebService.Runs;
|
|
|
|
internal sealed class InMemoryRunRepository : IRunRepository
|
|
{
|
|
private readonly ConcurrentDictionary<string, Run> _runs = new(StringComparer.Ordinal);
|
|
|
|
public Task InsertAsync(
|
|
Run run,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
ArgumentNullException.ThrowIfNull(run);
|
|
_runs[run.Id] = run;
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
public Task<bool> UpdateAsync(
|
|
Run run,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
ArgumentNullException.ThrowIfNull(run);
|
|
|
|
if (!_runs.TryGetValue(run.Id, out var existing))
|
|
{
|
|
return Task.FromResult(false);
|
|
}
|
|
|
|
if (!string.Equals(existing.TenantId, run.TenantId, StringComparison.Ordinal))
|
|
{
|
|
return Task.FromResult(false);
|
|
}
|
|
|
|
_runs[run.Id] = run;
|
|
return Task.FromResult(true);
|
|
}
|
|
|
|
public Task<Run?> GetAsync(
|
|
string tenantId,
|
|
string runId,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(tenantId))
|
|
{
|
|
throw new ArgumentException("Tenant id must be provided.", nameof(tenantId));
|
|
}
|
|
|
|
if (string.IsNullOrWhiteSpace(runId))
|
|
{
|
|
throw new ArgumentException("Run id must be provided.", nameof(runId));
|
|
}
|
|
|
|
if (_runs.TryGetValue(runId, out var run) && string.Equals(run.TenantId, tenantId, StringComparison.Ordinal))
|
|
{
|
|
return Task.FromResult<Run?>(run);
|
|
}
|
|
|
|
return Task.FromResult<Run?>(null);
|
|
}
|
|
|
|
public Task<IReadOnlyList<Run>> ListAsync(
|
|
string tenantId,
|
|
RunQueryOptions? options = null,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(tenantId))
|
|
{
|
|
throw new ArgumentException("Tenant id must be provided.", nameof(tenantId));
|
|
}
|
|
|
|
options ??= new RunQueryOptions();
|
|
|
|
IEnumerable<Run> query = _runs.Values
|
|
.Where(run => string.Equals(run.TenantId, tenantId, StringComparison.Ordinal));
|
|
|
|
if (!string.IsNullOrWhiteSpace(options.ScheduleId))
|
|
{
|
|
query = query.Where(run => string.Equals(run.ScheduleId, options.ScheduleId, StringComparison.Ordinal));
|
|
}
|
|
|
|
if (!options.States.IsDefaultOrEmpty)
|
|
{
|
|
var allowed = options.States.ToImmutableHashSet();
|
|
query = query.Where(run => allowed.Contains(run.State));
|
|
}
|
|
|
|
if (options.CreatedAfter is { } createdAfter)
|
|
{
|
|
query = query.Where(run => run.CreatedAt > createdAfter);
|
|
}
|
|
|
|
if (options.Cursor is { } cursor)
|
|
{
|
|
query = options.SortAscending
|
|
? query.Where(run => run.CreatedAt > cursor.CreatedAt ||
|
|
(run.CreatedAt == cursor.CreatedAt &&
|
|
string.Compare(run.Id, cursor.RunId, StringComparison.Ordinal) > 0))
|
|
: query.Where(run => run.CreatedAt < cursor.CreatedAt ||
|
|
(run.CreatedAt == cursor.CreatedAt &&
|
|
string.Compare(run.Id, cursor.RunId, StringComparison.Ordinal) < 0));
|
|
}
|
|
|
|
query = options.SortAscending
|
|
? query.OrderBy(run => run.CreatedAt).ThenBy(run => run.Id, StringComparer.Ordinal)
|
|
: query.OrderByDescending(run => run.CreatedAt).ThenByDescending(run => run.Id, StringComparer.Ordinal);
|
|
|
|
var limit = options.Limit is { } specified && specified > 0 ? specified : 50;
|
|
var result = query.Take(limit).ToArray();
|
|
return Task.FromResult<IReadOnlyList<Run>>(result);
|
|
}
|
|
|
|
public Task<IReadOnlyList<Run>> ListByStateAsync(
|
|
RunState state,
|
|
int limit = 50,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
if (limit <= 0)
|
|
{
|
|
throw new ArgumentOutOfRangeException(nameof(limit), limit, "Limit must be greater than zero.");
|
|
}
|
|
|
|
var result = _runs.Values
|
|
.Where(run => run.State == state)
|
|
.OrderBy(run => run.CreatedAt)
|
|
.ThenBy(run => run.Id, StringComparer.Ordinal)
|
|
.Take(limit)
|
|
.ToArray();
|
|
|
|
return Task.FromResult<IReadOnlyList<Run>>(result);
|
|
}
|
|
}
|