#33 Remove single-use interfaces #36

Merged
henry merged 1 commits from remove-interfaces into main 2025-07-15 22:36:24 +00:00
13 changed files with 24 additions and 67 deletions

View File

@ -1,5 +1,5 @@
@page "/config"
@inject AccessQueuePlayground.Services.IAccessQueueManager QueueManager
@inject AccessQueuePlayground.Services.AccessQueueManager QueueManager
@using BlazorBootstrap
<h3>Access Queue Configuration</h3>

View File

@ -4,7 +4,7 @@
@using AccessQueueService.Models;
@using BlazorBootstrap
@inject IAccessQueueManager Manager
@inject AccessQueueManager Manager
<PageTitle>AccessQueue Playground</PageTitle>
@if (Config != null)

View File

@ -28,8 +28,8 @@ else
builder.Services.AddHttpClient();
builder.Services.AddSingleton<IAccessService, AccessQueueApiService>();
}
builder.Services.AddSingleton<IAccessQueueRepo, TakeANumberAccessQueueRepo>();
builder.Services.AddSingleton<IAccessQueueManager, AccessQueueManager>();
builder.Services.AddSingleton<AccessQueueRepository>();
builder.Services.AddSingleton<AccessQueueManager>();
builder.Services.AddHostedService<AccessQueueBackgroundService>();
var app = builder.Build();

View File

@ -6,10 +6,10 @@ namespace AccessQueuePlayground.Services
{
public class AccessQueueBackgroundService : BackgroundService
{
private readonly IAccessQueueManager _accessQueueManager;
private readonly AccessQueueManager _accessQueueManager;
private readonly IConfiguration _config;
public AccessQueueBackgroundService(IAccessQueueManager accessQueueManager, IConfiguration config)
public AccessQueueBackgroundService(AccessQueueManager accessQueueManager, IConfiguration config)
{
_accessQueueManager = accessQueueManager;
_config = config;

View File

@ -6,7 +6,7 @@ using Microsoft.Extensions.Configuration;
namespace AccessQueuePlayground.Services
{
public class AccessQueueManager : IAccessQueueManager
public class AccessQueueManager
{
private readonly IAccessService _accessService;
private readonly IConfiguration _config;

View File

@ -1,20 +0,0 @@
using AccessQueuePlayground.Models;
using AccessQueueService.Models;
namespace AccessQueuePlayground.Services
{
public interface IAccessQueueManager
{
public event Action? StatusUpdated;
public AccessQueueConfig GetConfig();
public void UpdateConfig(AccessQueueConfig config);
public Task RecalculateStatus();
public AccessQueueManagerStatus GetStatus();
public Guid AddUser(bool isActive);
public void SetUserActive(Guid userId, bool isActive);
public void RevokeAccess(Guid userId);
public void RevokeAllAccess();
public void Reset();
}
}

View File

@ -6,7 +6,7 @@ using Microsoft.Extensions.Configuration;
namespace AccessQueueService.Data
{
public class TakeANumberAccessQueueRepo : IAccessQueueRepo
public class AccessQueueRepository
{
private ConcurrentDictionary<string, AccessTicket> _accessTickets = new();
private ConcurrentDictionary<string, ulong> _queueNumbers = new();
@ -189,7 +189,7 @@ namespace AccessQueueService.Data
return JsonSerializer.Serialize(state);
}
public static TakeANumberAccessQueueRepo FromState(string stateJson)
public static AccessQueueRepository FromState(string stateJson)
{
var state = JsonSerializer.Deserialize<TakeANumberAccessQueueRepoState?>(stateJson);
if (state?.AccessTickets == null || state?.AccessQueue == null)

View File

@ -1,21 +0,0 @@
using System.Runtime.Serialization;
using AccessQueueService.Models;
using Microsoft.Extensions.Configuration;
namespace AccessQueueService.Data
{
public interface IAccessQueueRepo
{
public string ToState();
public int GetUnexpiredTicketsCount();
public int GetActiveTicketsCount(DateTime activeCutoff);
public int GetQueueCount();
public AccessTicket? GetTicket(string userId);
public void UpsertTicket(AccessTicket ticket);
public int GetRequestsAhead(string userId);
public void Enqueue(AccessTicket ticket);
public int DeleteExpiredTickets();
public bool RemoveUser(string userId);
public bool DidDequeueUntilFull(AccessQueueConfig config);
}
}

View File

@ -17,7 +17,7 @@ builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddSingleton<IAccessService, AccessService>();
builder.Services.AddSingleton<IAccessQueueRepo>(sp =>
builder.Services.AddSingleton<AccessQueueRepository>(sp =>
{
string? filePath = builder.Configuration.GetValue<string>("AccessQueue:BackupFilePath");
if (!string.IsNullOrWhiteSpace(filePath) && File.Exists(filePath))
@ -25,14 +25,14 @@ builder.Services.AddSingleton<IAccessQueueRepo>(sp =>
try
{
var json = File.ReadAllText(filePath);
return TakeANumberAccessQueueRepo.FromState(json);
return AccessQueueRepository.FromState(json);
}
catch (Exception ex)
{
Console.WriteLine($"Failed to load state from {filePath}. Error message: {ex.Message}");
}
}
return new TakeANumberAccessQueueRepo();
return new AccessQueueRepository();
});
builder.Services.AddHostedService<AccessCleanupBackgroundService>();
builder.Services.AddHostedService<AccessQueueSerializerService>();

View File

@ -5,11 +5,11 @@ namespace AccessQueueService.Services
{
public class AccessQueueSerializerService : BackgroundService
{
private readonly IAccessQueueRepo _accessRepo;
private readonly AccessQueueRepository _accessRepo;
private readonly IConfiguration _config;
private readonly ILogger<AccessQueueSerializerService> _logger;
public AccessQueueSerializerService(IAccessQueueRepo accessRepo, IConfiguration config, ILogger<AccessQueueSerializerService> logger)
public AccessQueueSerializerService(AccessQueueRepository accessRepo, IConfiguration config, ILogger<AccessQueueSerializerService> logger)
{
_accessRepo = accessRepo;
_config = config;

View File

@ -8,12 +8,12 @@ namespace AccessQueueService.Services
public class AccessService : IAccessService
{
private readonly IConfiguration _configuration;
private readonly IAccessQueueRepo _accessQueueRepo;
private readonly AccessQueueRepository _accessQueueRepo;
private readonly ILogger<AccessService> _logger;
private readonly SemaphoreSlim _queueLock = new(1, 1);
private AccessQueueConfig _config;
public AccessService(IConfiguration configuration, IAccessQueueRepo accessQueueRepo, ILogger<AccessService> logger)
public AccessService(IConfiguration configuration, AccessQueueRepository accessQueueRepo, ILogger<AccessService> logger)
{
_configuration = configuration;
_accessQueueRepo = accessQueueRepo;

View File

@ -14,7 +14,7 @@ namespace AccessQueueServiceTests
{
public class AccessQueueRepoTests
{
private readonly TakeANumberAccessQueueRepo _repo;
private readonly AccessQueueRepository _repo;
private readonly AccessQueueConfig _simpleConfig = new()
{
ExpirationSeconds = 60,
@ -42,7 +42,7 @@ namespace AccessQueueServiceTests
public AccessQueueRepoTests()
{
_repo = new TakeANumberAccessQueueRepo();
_repo = new AccessQueueRepository();
}
private List<AccessTicket> GetSimpleTicketList() => new()
@ -313,7 +313,7 @@ namespace AccessQueueServiceTests
_repo.Enqueue(ticketWithoutAccess);
string stateJson = _repo.ToState();
var deserializedRepo = TakeANumberAccessQueueRepo.FromState(stateJson);
var deserializedRepo = AccessQueueRepository.FromState(stateJson);
Assert.Equal(1, deserializedRepo.GetUnexpiredTicketsCount());
Assert.Equal(1, deserializedRepo.GetQueueCount());

View File

@ -16,7 +16,6 @@ namespace AccessQueueServiceTests
const int ACT_MILLIS = 1000 * ACT_SECONDS;
const int CAP_LIMIT = 5;
const int BULK_COUNT = 10000;
const int CACHE_MILLIS = 1000;
private readonly AccessService _accessService;
public AccessServiceTests()
@ -26,14 +25,13 @@ namespace AccessQueueServiceTests
{ "AccessQueue:ExpirationSeconds", $"{EXP_SECONDS}" },
{ "AccessQueue:ActivitySeconds", $"{ACT_SECONDS}" },
{ "AccessQueue:CapacityLimit", $"{CAP_LIMIT}" },
{ "AccessQueue:RollingExpiration", "true" },
{ "AccessQueue:CacheMilliseconds", $"{CACHE_MILLIS}" }
{ "AccessQueue:RollingExpiration", "true" }
};
var configuration = new ConfigurationBuilder()
.AddInMemoryCollection(inMemorySettings)
.Build();
var accessQueueRepo = new TakeANumberAccessQueueRepo();
var accessQueueRepo = new AccessQueueRepository();
var loggerFactory = LoggerFactory.Create(builder => builder.AddConsole());
var logger = loggerFactory.CreateLogger<AccessService>();
_accessService = new AccessService(configuration, accessQueueRepo, logger);
@ -89,9 +87,9 @@ namespace AccessQueueServiceTests
Assert.NotNull(response);
Assert.Null(response.ExpiresOn);
Assert.True(response.RequestsAhead == CAP_LIMIT);
Assert.Equal(CAP_LIMIT, _accessService.UnexpiredTicketsCount);
Assert.Equal(CAP_LIMIT, _accessService.ActiveTicketsCount);
Assert.Equal(CAP_LIMIT + 1, _accessService.QueueCount);
Assert.Equal(5, _accessService.UnexpiredTicketsCount);
Assert.Equal(5, _accessService.ActiveTicketsCount);
Assert.Equal(6, _accessService.QueueCount);
}