- Delete dead Notify Worker (NoOp handler) - Move 51 source files (endpoints, contracts, services, compat stores) - Transform namespaces from Notifier.WebService to Notify.WebService - Update DI registrations, WebSocket support, v2 endpoint mapping - Comment out notifier-web in compose, update gateway routes - Update architecture docs, port registry, rollout matrix - Notifier Worker stays as separate delivery engine container Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
92 lines
2.8 KiB
C#
92 lines
2.8 KiB
C#
|
|
using StellaOps.Notify.Models;
|
|
using System.Collections.Concurrent;
|
|
using System.Linq;
|
|
|
|
namespace StellaOps.Notify.WebService.Storage.Compat;
|
|
|
|
public interface INotifyQuietHoursRepository
|
|
{
|
|
Task<IReadOnlyList<NotifyQuietHoursSchedule>> ListAsync(
|
|
string tenantId,
|
|
string? channelId,
|
|
bool? enabledOnly,
|
|
CancellationToken cancellationToken = default);
|
|
|
|
Task<NotifyQuietHoursSchedule?> GetAsync(
|
|
string tenantId,
|
|
string scheduleId,
|
|
CancellationToken cancellationToken = default);
|
|
|
|
Task<NotifyQuietHoursSchedule> UpsertAsync(
|
|
NotifyQuietHoursSchedule schedule,
|
|
CancellationToken cancellationToken = default);
|
|
|
|
Task<bool> DeleteAsync(
|
|
string tenantId,
|
|
string scheduleId,
|
|
CancellationToken cancellationToken = default);
|
|
}
|
|
|
|
public sealed class InMemoryQuietHoursRepository : INotifyQuietHoursRepository
|
|
{
|
|
private readonly ConcurrentDictionary<string, ConcurrentDictionary<string, NotifyQuietHoursSchedule>> _store = new();
|
|
|
|
public Task<IReadOnlyList<NotifyQuietHoursSchedule>> ListAsync(
|
|
string tenantId,
|
|
string? channelId,
|
|
bool? enabledOnly,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
var items = ForTenant(tenantId).Values.AsEnumerable();
|
|
|
|
if (!string.IsNullOrWhiteSpace(channelId))
|
|
{
|
|
items = items.Where(s =>
|
|
string.Equals(s.ChannelId, channelId, StringComparison.OrdinalIgnoreCase));
|
|
}
|
|
|
|
if (enabledOnly is true)
|
|
{
|
|
items = items.Where(s => s.Enabled);
|
|
}
|
|
|
|
var result = items
|
|
.OrderBy(s => s.Name, StringComparer.OrdinalIgnoreCase)
|
|
.ToList();
|
|
|
|
return Task.FromResult<IReadOnlyList<NotifyQuietHoursSchedule>>(result);
|
|
}
|
|
|
|
public Task<NotifyQuietHoursSchedule?> GetAsync(
|
|
string tenantId,
|
|
string scheduleId,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
var items = ForTenant(tenantId);
|
|
items.TryGetValue(scheduleId, out var schedule);
|
|
return Task.FromResult(schedule);
|
|
}
|
|
|
|
public Task<NotifyQuietHoursSchedule> UpsertAsync(
|
|
NotifyQuietHoursSchedule schedule,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
var items = ForTenant(schedule.TenantId);
|
|
items[schedule.ScheduleId] = schedule;
|
|
return Task.FromResult(schedule);
|
|
}
|
|
|
|
public Task<bool> DeleteAsync(
|
|
string tenantId,
|
|
string scheduleId,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
var items = ForTenant(tenantId);
|
|
return Task.FromResult(items.TryRemove(scheduleId, out _));
|
|
}
|
|
|
|
private ConcurrentDictionary<string, NotifyQuietHoursSchedule> ForTenant(string tenantId) =>
|
|
_store.GetOrAdd(tenantId, _ => new ConcurrentDictionary<string, NotifyQuietHoursSchedule>());
|
|
}
|