From 91afb0dd8e82216399a3a1ee760e95fdafdaf01f Mon Sep 17 00:00:00 2001 From: Henry Hobbs Date: Sat, 17 May 2025 22:26:58 -0400 Subject: [PATCH] Added ability to update config via API at runtime. wip on customizing config via UI --- .../Components/Pages/Home.razor | 4 +- .../Models/AccessQueueConfig.cs | 10 ----- .../Services/AccessQueueManager.cs | 10 ++--- .../Services/IAccessQueueManager.cs | 2 + .../Controllers/AccessController.cs | 13 ++++++ .../Models/AccessQueueConfig.cs | 15 +++++++ AccessQueueService/Services/AccessService.cs | 41 +++++++++++++------ AccessQueueService/Services/IAccessService.cs | 3 ++ 8 files changed, 69 insertions(+), 29 deletions(-) delete mode 100644 AccessQueuePlayground/Models/AccessQueueConfig.cs create mode 100644 AccessQueueService/Models/AccessQueueConfig.cs diff --git a/AccessQueuePlayground/Components/Pages/Home.razor b/AccessQueuePlayground/Components/Pages/Home.razor index fbfe951..3bc5f6e 100644 --- a/AccessQueuePlayground/Components/Pages/Home.razor +++ b/AccessQueuePlayground/Components/Pages/Home.razor @@ -1,6 +1,7 @@ @page "/" @using AccessQueuePlayground.Models @using AccessQueuePlayground.Services +@using AccessQueueService.Models; @using BlazorBootstrap @inject IAccessQueueManager Manager @@ -12,7 +13,8 @@

Expiration Seconds: @Config.ExpirationSeconds, Activity Seconds: @Config.ActivitySeconds, - Capacity Limit: @Config.CapacityLimit + Capacity Limit: @Config.CapacityLimit, + Rolling Expiration: @Config.RollingExpiration

}

diff --git a/AccessQueuePlayground/Models/AccessQueueConfig.cs b/AccessQueuePlayground/Models/AccessQueueConfig.cs deleted file mode 100644 index 3bf62ef..0000000 --- a/AccessQueuePlayground/Models/AccessQueueConfig.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace AccessQueuePlayground.Models -{ - public class AccessQueueConfig - { - public int ActivitySeconds { get; set; } - public int ExpirationSeconds { get; set; } - public int CapacityLimit { get; set; } - - } -} diff --git a/AccessQueuePlayground/Services/AccessQueueManager.cs b/AccessQueuePlayground/Services/AccessQueueManager.cs index d3237bb..5bad7e2 100644 --- a/AccessQueuePlayground/Services/AccessQueueManager.cs +++ b/AccessQueuePlayground/Services/AccessQueueManager.cs @@ -29,12 +29,12 @@ namespace AccessQueuePlayground.Services public AccessQueueStatus GetStatus() => _status; - public AccessQueueConfig GetConfig() => new AccessQueueConfig + public AccessQueueConfig GetConfig() => _accessService.GetConfiguration(); + + public void UpdateConfig(AccessQueueConfig config) { - ActivitySeconds = _config.GetValue("AccessQueue:ActivitySeconds"), - ExpirationSeconds = _config.GetValue("AccessQueue:ExpirationSeconds"), - CapacityLimit = _config.GetValue("AccessQueue:CapacityLimit") - }; + _accessService.UpdateConfiguration(config); + } public Guid AddUser() { diff --git a/AccessQueuePlayground/Services/IAccessQueueManager.cs b/AccessQueuePlayground/Services/IAccessQueueManager.cs index 5c16ff1..015dbd8 100644 --- a/AccessQueuePlayground/Services/IAccessQueueManager.cs +++ b/AccessQueuePlayground/Services/IAccessQueueManager.cs @@ -1,4 +1,5 @@ using AccessQueuePlayground.Models; +using AccessQueueService.Models; namespace AccessQueuePlayground.Services { @@ -6,6 +7,7 @@ namespace AccessQueuePlayground.Services { public event Action? StatusUpdated; public AccessQueueConfig GetConfig(); + public void UpdateConfig(AccessQueueConfig config); public Task RecalculateStatus(); public AccessQueueStatus GetStatus(); public Guid AddUser(); diff --git a/AccessQueueService/Controllers/AccessController.cs b/AccessQueueService/Controllers/AccessController.cs index f9fcc05..d1f4786 100644 --- a/AccessQueueService/Controllers/AccessController.cs +++ b/AccessQueueService/Controllers/AccessController.cs @@ -28,5 +28,18 @@ namespace AccessQueueService.Controllers { return await _accessService.RevokeAccess(id); } + + [HttpGet("configuration")] + public ActionResult GetConfiguration() + { + return Ok(_accessService.GetConfiguration()); + } + + [HttpPost("configuration")] + public IActionResult UpdateConfiguration([FromBody] AccessQueueConfig config) + { + _accessService.PatchConfiguration(config); + return NoContent(); + } } } diff --git a/AccessQueueService/Models/AccessQueueConfig.cs b/AccessQueueService/Models/AccessQueueConfig.cs new file mode 100644 index 0000000..413caca --- /dev/null +++ b/AccessQueueService/Models/AccessQueueConfig.cs @@ -0,0 +1,15 @@ +namespace AccessQueueService.Models +{ + public class AccessQueueConfig + { + public int? CapacityLimit { get; set; } + public int? ActivitySeconds { get; set; } + public int? ExpirationSeconds { get; set; } + public bool? RollingExpiration { get; set; } + + public AccessQueueConfig Clone() + { + return (AccessQueueConfig)this.MemberwiseClone(); + } + } +} diff --git a/AccessQueueService/Services/AccessService.cs b/AccessQueueService/Services/AccessService.cs index 65d0f9a..891ab88 100644 --- a/AccessQueueService/Services/AccessService.cs +++ b/AccessQueueService/Services/AccessService.cs @@ -12,37 +12,52 @@ namespace AccessQueueService.Services private readonly ILogger _logger; private readonly SemaphoreSlim _queueLock = new(1, 1); - private readonly int EXP_SECONDS; - private readonly int ACT_SECONDS; - private readonly int CAPACITY_LIMIT; - private readonly bool ROLLING_EXPIRATION; + private AccessQueueConfig _config; public AccessService(IConfiguration configuration, IAccessQueueRepo accessQueueRepo, ILogger logger) { _configuration = configuration; _accessQueueRepo = accessQueueRepo; _logger = logger; - EXP_SECONDS = _configuration.GetValue("AccessQueue:ExpirationSeconds"); - ACT_SECONDS = _configuration.GetValue("AccessQueue:ActivitySeconds"); - CAPACITY_LIMIT = _configuration.GetValue("AccessQueue:CapacityLimit"); - ROLLING_EXPIRATION = _configuration.GetValue("AccessQueue:RollingExpiration"); + _config = new AccessQueueConfig + { + ExpirationSeconds = _configuration.GetValue("AccessQueue:ExpirationSeconds"), + ActivitySeconds = _configuration.GetValue("AccessQueue:ActivitySeconds"), + CapacityLimit = _configuration.GetValue("AccessQueue:CapacityLimit"), + RollingExpiration = _configuration.GetValue("AccessQueue:RollingExpiration") + }; + } + public AccessQueueConfig GetConfiguration() => _config.Clone(); + public void UpdateConfiguration(AccessQueueConfig config) + { + _config = config.Clone(); + } + public void PatchConfiguration(AccessQueueConfig partialConfig) + { + if (partialConfig.CapacityLimit.HasValue) _config.CapacityLimit = partialConfig.CapacityLimit.Value; + if (partialConfig.ActivitySeconds.HasValue) _config.ActivitySeconds = partialConfig.ActivitySeconds.Value; + if (partialConfig.ExpirationSeconds.HasValue) _config.ExpirationSeconds = partialConfig.ExpirationSeconds.Value; + if (partialConfig.RollingExpiration.HasValue) _config.RollingExpiration = partialConfig.RollingExpiration.Value; } public int UnexpiredTicketsCount => _accessQueueRepo.GetUnexpiredTicketsCount(); - public int ActiveTicketsCount => _accessQueueRepo.GetActiveTicketsCount(DateTime.UtcNow.AddSeconds(-_configuration.GetValue("AccessQueue:ActivitySeconds"))); + public int ActiveTicketsCount => _accessQueueRepo.GetActiveTicketsCount(DateTime.UtcNow.AddSeconds(-_config.ActivitySeconds.Value)); public int QueueCount => _accessQueueRepo.GetQueueCount(); public async Task RequestAccess(string userId) { await _queueLock.WaitAsync(); try { - var hasCapacity = !_accessQueueRepo.DidDequeueUntilFull(ACT_SECONDS, EXP_SECONDS, CAPACITY_LIMIT); + var hasCapacity = !_accessQueueRepo.DidDequeueUntilFull( + _config.ActivitySeconds.Value, + _config.ExpirationSeconds.Value, + _config.CapacityLimit.Value); var existingTicket = _accessQueueRepo.GetTicket(userId); if (existingTicket != null && existingTicket.ExpiresOn > DateTime.UtcNow) { // Already has access var expiresOn = existingTicket.ExpiresOn; - if (ROLLING_EXPIRATION) + if (_config.RollingExpiration.Value) { - expiresOn = DateTime.UtcNow.AddSeconds(EXP_SECONDS); + expiresOn = DateTime.UtcNow.AddSeconds(_config.ExpirationSeconds.Value); } _accessQueueRepo.UpsertTicket(new AccessTicket { @@ -62,7 +77,7 @@ namespace AccessQueueService.Services var accessTicket = new AccessTicket { UserId = userId, - ExpiresOn = DateTime.UtcNow.AddSeconds(EXP_SECONDS), + ExpiresOn = DateTime.UtcNow.AddSeconds(_config.ExpirationSeconds.Value), LastActive = DateTime.UtcNow }; _accessQueueRepo.UpsertTicket(accessTicket); diff --git a/AccessQueueService/Services/IAccessService.cs b/AccessQueueService/Services/IAccessService.cs index 6b94042..35cdf3c 100644 --- a/AccessQueueService/Services/IAccessService.cs +++ b/AccessQueueService/Services/IAccessService.cs @@ -7,5 +7,8 @@ namespace AccessQueueService.Services public Task RequestAccess(string userId); public Task RevokeAccess(string userId); public Task DeleteExpiredTickets(); + public AccessQueueConfig GetConfiguration(); + public void UpdateConfiguration(AccessQueueConfig config); + public void PatchConfiguration(AccessQueueConfig partialConfig); } }