Reviewed-on: #36
This commit is contained in:
commit
f72eb323ec
|
@ -1,5 +1,5 @@
|
|||
@page "/config"
|
||||
@inject AccessQueuePlayground.Services.IAccessQueueManager QueueManager
|
||||
@inject AccessQueuePlayground.Services.AccessQueueManager QueueManager
|
||||
@using BlazorBootstrap
|
||||
|
||||
<h3>Access Queue Configuration</h3>
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
@using AccessQueueService.Models;
|
||||
@using BlazorBootstrap
|
||||
|
||||
@inject IAccessQueueManager Manager
|
||||
@inject AccessQueueManager Manager
|
||||
|
||||
<PageTitle>AccessQueue Playground</PageTitle>
|
||||
@if (Config != null)
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
||||
}
|
||||
}
|
|
@ -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)
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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>();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue