Refactored DidDequeueUntilFull into a couple methods to make it more readable

This commit is contained in:
henry 2025-07-05 20:51:37 -04:00
parent 9865e722fd
commit a812acf67d
1 changed files with 49 additions and 20 deletions

View File

@ -61,28 +61,27 @@ namespace AccessQueueService.Data
return count; return count;
} }
public bool DidDequeueUntilFull(AccessQueueConfig config) private bool HasValidActiveUsersCache(AccessQueueConfig config, DateTime now)
{ {
var now = DateTime.UtcNow; return config.CacheMilliseconds.HasValue && _cachedActiveUsers.HasValue && (now - _cachedActiveUsersTime).TotalMilliseconds < config.CacheMilliseconds.Value;
var activeCutoff = now.AddSeconds(-config.ActivitySeconds.Value);
if (config.CacheMilliseconds.HasValue && _cachedActiveUsers.HasValue && (now - _cachedActiveUsersTime).TotalMilliseconds < config.CacheMilliseconds)
{
var numberOfActiveUsers = _cachedActiveUsers.Value;
var openSpots = config.CapacityLimit - numberOfActiveUsers;
if (openSpots <= 0)
{
return true;
} }
private int GetOpenSpots(AccessQueueConfig config, int activeUsers)
{
return config.CapacityLimit.Value - activeUsers;
} }
private int UpdateActiveUsersCache(DateTime now, DateTime activeCutoff)
{
_cachedActiveUsers = _accessTickets.Count(t => t.Value.ExpiresOn > now && t.Value.LastActive > activeCutoff); _cachedActiveUsers = _accessTickets.Count(t => t.Value.ExpiresOn > now && t.Value.LastActive > activeCutoff);
_cachedActiveUsersTime = now; _cachedActiveUsersTime = now;
var openSpotsNew = config.CapacityLimit - _cachedActiveUsers; return _cachedActiveUsers.GetValueOrDefault();
if (openSpotsNew <= 0)
{
return true;
} }
private int DequeueUsersUntilFull(int openSpots, DateTime now, DateTime activeCutoff, AccessQueueConfig config)
{
int filledSpots = 0; int filledSpots = 0;
while (filledSpots < openSpotsNew && _nowServing < _nextUnusedTicket) while (filledSpots < openSpots && _nowServing < _nextUnusedTicket)
{ {
if (_accessQueue.TryRemove(_nowServing++, out var nextUser)) if (_accessQueue.TryRemove(_nowServing++, out var nextUser))
{ {
@ -95,19 +94,49 @@ namespace AccessQueueService.Data
_accessTickets[nextUser.UserId] = new AccessTicket _accessTickets[nextUser.UserId] = new AccessTicket
{ {
UserId = nextUser.UserId, UserId = nextUser.UserId,
ExpiresOn = now.AddSeconds(config.ExpirationSeconds.Value), ExpiresOn = now.AddSeconds(config.ExpirationSeconds ?? 0),
LastActive = now LastActive = now
}; };
filledSpots++; filledSpots++;
} }
} }
return filledSpots;
}
public bool DidDequeueUntilFull(AccessQueueConfig config)
{
var now = DateTime.UtcNow;
if (!config.ActivitySeconds.HasValue || !config.ExpirationSeconds.HasValue || !config.CapacityLimit.HasValue)
{
throw new Exception("Required config values are not defined.");
}
var activeCutoff = now.AddSeconds(-config.ActivitySeconds.Value);
int activeUsers;
if (HasValidActiveUsersCache(config, now))
{
activeUsers = _cachedActiveUsers.GetValueOrDefault();
}
else
{
activeUsers = UpdateActiveUsersCache(now, activeCutoff);
}
var openSpots = GetOpenSpots(config, activeUsers);
if (openSpots <= 0)
{
return true;
}
int filledSpots = DequeueUsersUntilFull(openSpots, now, activeCutoff, config);
// Invalidate cache if any users were granted access // Invalidate cache if any users were granted access
if (filledSpots > 0) if (filledSpots > 0)
{ {
_cachedActiveUsers = null; _cachedActiveUsers = null;
_cachedActiveUsersTime = DateTime.MinValue; _cachedActiveUsersTime = DateTime.MinValue;
} }
return filledSpots == openSpotsNew; return filledSpots == openSpots;
} }
public AccessTicket? GetTicket(string userId) public AccessTicket? GetTicket(string userId)