wip - trying to move expensive alculation to background
This commit is contained in:
parent
7b34b55197
commit
b1b1b44e0f
|
@ -26,6 +26,19 @@ builder.Services.AddHostedService<AccessQueueBackgroundService>();
|
||||||
|
|
||||||
var app = builder.Build();
|
var app = builder.Build();
|
||||||
|
|
||||||
|
// Configure TakeANumberAccessQueueRepo active users cache
|
||||||
|
using (var scope = app.Services.CreateScope())
|
||||||
|
{
|
||||||
|
var config = scope.ServiceProvider.GetRequiredService<IConfiguration>();
|
||||||
|
var repo = scope.ServiceProvider.GetRequiredService<IAccessQueueRepo>() as TakeANumberAccessQueueRepo;
|
||||||
|
if (repo != null)
|
||||||
|
{
|
||||||
|
int activeSeconds = config.GetValue<int>("AccessQueue:ActivitySeconds", 2);
|
||||||
|
int updateInterval = config.GetValue<int>("AccessQueue:ActiveUsersUpdateIntervalSeconds", 2);
|
||||||
|
repo.ConfigureActiveUsersCache(activeSeconds, updateInterval);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Configure the HTTP request pipeline.
|
// Configure the HTTP request pipeline.
|
||||||
if (!app.Environment.IsDevelopment())
|
if (!app.Environment.IsDevelopment())
|
||||||
{
|
{
|
||||||
|
|
|
@ -6,13 +6,14 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"AccessQueue": {
|
"AccessQueue": {
|
||||||
"CapacityLimit": 3, // Maximum number of active users
|
"CapacityLimit": 3,
|
||||||
"ActivitySeconds": 2, // Time since last access before a user is considered inactive
|
"ActivitySeconds": 2,
|
||||||
"ExpirationSeconds": 10, // 12 hours - Time before a user access is revoked
|
"ExpirationSeconds": 10,
|
||||||
"RollingExpiration": true // Whether to extend expiration time on access
|
"RollingExpiration": true,
|
||||||
|
"ActiveUsersUpdateIntervalSeconds": 2
|
||||||
},
|
},
|
||||||
"AccessQueuePlayground": {
|
"AccessQueuePlayground": {
|
||||||
"RefreshRateMilliseconds": 200 // How often to re-request access and update the UI
|
"RefreshRateMilliseconds": 200
|
||||||
},
|
},
|
||||||
"AllowedHosts": "*"
|
"AllowedHosts": "*"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using AccessQueueService.Models;
|
using AccessQueueService.Models;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
namespace AccessQueueService.Data
|
namespace AccessQueueService.Data
|
||||||
{
|
{
|
||||||
|
@ -12,6 +13,12 @@ namespace AccessQueueService.Data
|
||||||
private ulong _nowServing = 0;
|
private ulong _nowServing = 0;
|
||||||
private ulong _nextUnusedTicket = 0;
|
private ulong _nextUnusedTicket = 0;
|
||||||
|
|
||||||
|
private int _cachedActiveUsers = 0;
|
||||||
|
private int _activeSeconds = 60; // default, can be set from config
|
||||||
|
private Timer? _activeUsersUpdateTimer;
|
||||||
|
private int _activeUsersUpdateIntervalSeconds = 10; // default, can be set from config
|
||||||
|
private readonly object _activeUsersLock = new();
|
||||||
|
|
||||||
public int GetUnexpiredTicketsCount() => _accessTickets.Count(t => t.Value.ExpiresOn > DateTime.UtcNow);
|
public int GetUnexpiredTicketsCount() => _accessTickets.Count(t => t.Value.ExpiresOn > DateTime.UtcNow);
|
||||||
public int GetActiveTicketsCount(DateTime activeCutoff) => _accessTickets
|
public int GetActiveTicketsCount(DateTime activeCutoff) => _accessTickets
|
||||||
.Count(t => t.Value.ExpiresOn > DateTime.UtcNow && t.Value.LastActive > activeCutoff);
|
.Count(t => t.Value.ExpiresOn > DateTime.UtcNow && t.Value.LastActive > activeCutoff);
|
||||||
|
@ -54,7 +61,8 @@ namespace AccessQueueService.Data
|
||||||
{
|
{
|
||||||
var now = DateTime.UtcNow;
|
var now = DateTime.UtcNow;
|
||||||
var activeCutoff = now.AddSeconds(-activeSeconds);
|
var activeCutoff = now.AddSeconds(-activeSeconds);
|
||||||
var numberOfActiveUsers = _accessTickets.Count(t => t.Value.ExpiresOn > now && t.Value.LastActive > activeCutoff);
|
// Use cached value instead of recalculating
|
||||||
|
var numberOfActiveUsers = GetCachedActiveUsers();
|
||||||
var openSpots = capacityLimit - numberOfActiveUsers;
|
var openSpots = capacityLimit - numberOfActiveUsers;
|
||||||
if(openSpots <= 0)
|
if(openSpots <= 0)
|
||||||
{
|
{
|
||||||
|
@ -104,5 +112,33 @@ namespace AccessQueueService.Data
|
||||||
}
|
}
|
||||||
return _accessTickets.Remove(userId);
|
return _accessTickets.Remove(userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void ConfigureActiveUsersCache(int activeSeconds, int updateIntervalSeconds)
|
||||||
|
{
|
||||||
|
_activeSeconds = activeSeconds;
|
||||||
|
_activeUsersUpdateIntervalSeconds = updateIntervalSeconds;
|
||||||
|
_activeUsersUpdateTimer?.Dispose();
|
||||||
|
_activeUsersUpdateTimer = new Timer(_ => UpdateActiveUsersCache(), null, 0, _activeUsersUpdateIntervalSeconds * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateActiveUsersCache()
|
||||||
|
{
|
||||||
|
var now = DateTime.UtcNow;
|
||||||
|
var activeCutoff = now.AddSeconds(-_activeSeconds);
|
||||||
|
int count = 0;
|
||||||
|
lock (_activeUsersLock)
|
||||||
|
{
|
||||||
|
count = _accessTickets.Count(t => t.Value.ExpiresOn > now && t.Value.LastActive > activeCutoff);
|
||||||
|
_cachedActiveUsers = count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetCachedActiveUsers()
|
||||||
|
{
|
||||||
|
lock (_activeUsersLock)
|
||||||
|
{
|
||||||
|
return _cachedActiveUsers;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,19 @@ builder.Services.AddHostedService<AccessCleanupBackgroundService>();
|
||||||
|
|
||||||
var app = builder.Build();
|
var app = builder.Build();
|
||||||
|
|
||||||
|
// Configure TakeANumberAccessQueueRepo active users cache
|
||||||
|
using (var scope = app.Services.CreateScope())
|
||||||
|
{
|
||||||
|
var config = scope.ServiceProvider.GetRequiredService<IConfiguration>();
|
||||||
|
var repo = scope.ServiceProvider.GetRequiredService<IAccessQueueRepo>() as TakeANumberAccessQueueRepo;
|
||||||
|
if (repo != null)
|
||||||
|
{
|
||||||
|
int activeSeconds = config.GetValue<int>("AccessQueue:ActivitySeconds", 900);
|
||||||
|
int updateInterval = config.GetValue<int>("AccessQueue:ActiveUsersUpdateIntervalSeconds", 10);
|
||||||
|
repo.ConfigureActiveUsersCache(activeSeconds, updateInterval);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (app.Environment.IsDevelopment())
|
if (app.Environment.IsDevelopment())
|
||||||
{
|
{
|
||||||
app.UseSwagger();
|
app.UseSwagger();
|
||||||
|
|
|
@ -28,7 +28,8 @@
|
||||||
"ActivitySeconds": 900,
|
"ActivitySeconds": 900,
|
||||||
"ExpirationSeconds": 43200,
|
"ExpirationSeconds": 43200,
|
||||||
"RollingExpiration": true,
|
"RollingExpiration": true,
|
||||||
"CleanupIntervalSeconds": 60
|
"CleanupIntervalSeconds": 60,
|
||||||
|
"ActiveUsersUpdateIntervalSeconds": 10
|
||||||
},
|
},
|
||||||
"AllowedHosts": "*"
|
"AllowedHosts": "*"
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue