#8 use string type for ID to make implementation more agnostic to different ID types
This commit is contained in:
parent
a540221b7f
commit
18a5a64d4e
|
@ -63,7 +63,7 @@ namespace AccessQueuePlayground.Services
|
|||
{
|
||||
if (user.Active)
|
||||
{
|
||||
user.LatestResponse = await _accessService.RequestAccess(user.Id);
|
||||
user.LatestResponse = await _accessService.RequestAccess(user.Id.ToString());
|
||||
if (user.LatestResponse?.HasAccess ?? false)
|
||||
{
|
||||
newStatus.AccessUsers.Add(user);
|
||||
|
@ -95,7 +95,7 @@ namespace AccessQueuePlayground.Services
|
|||
var user = _users[userId];
|
||||
user.Active = false;
|
||||
user.LatestResponse = null;
|
||||
_accessService.RevokeAccess(userId);
|
||||
_accessService.RevokeAccess(userId.ToString());
|
||||
}
|
||||
|
||||
public void RevokeAllAccess()
|
||||
|
|
|
@ -17,14 +17,14 @@ namespace AccessQueueService.Controllers
|
|||
|
||||
[HttpGet]
|
||||
[Route("{id}")]
|
||||
public async Task<AccessResponse> Get(Guid id)
|
||||
public async Task<AccessResponse> Get(string id)
|
||||
{
|
||||
return await _accessService.RequestAccess(id);
|
||||
}
|
||||
|
||||
[HttpDelete]
|
||||
[Route("{id}")]
|
||||
public async Task<bool> Delete(Guid id)
|
||||
public async Task<bool> Delete(string id)
|
||||
{
|
||||
return await _accessService.RevokeAccess(id);
|
||||
}
|
||||
|
|
|
@ -8,12 +8,12 @@ namespace AccessQueueService.Data
|
|||
public int GetUnexpiredTicketsCount();
|
||||
public int GetActiveTicketsCount(DateTime activeCutoff);
|
||||
public int GetQueueCount();
|
||||
public AccessTicket? GetTicket(Guid userId);
|
||||
public AccessTicket? GetTicket(string userId);
|
||||
public void UpsertTicket(AccessTicket ticket);
|
||||
public int GetRequestsAhead(Guid userId);
|
||||
public int GetRequestsAhead(string userId);
|
||||
public void Enqueue(AccessTicket ticket);
|
||||
public int DeleteExpiredTickets();
|
||||
public bool RemoveUser(Guid userId);
|
||||
public bool RemoveUser(string userId);
|
||||
public bool DidDequeueUntilFull(int activeSeconds, int expirationSeconds, int capacityLimit);
|
||||
|
||||
|
||||
|
|
|
@ -5,8 +5,8 @@ namespace AccessQueueService.Data
|
|||
{
|
||||
public class TakeANumberAccessQueueRepo : IAccessQueueRepo
|
||||
{
|
||||
private readonly Dictionary<Guid, AccessTicket> _accessTickets = [];
|
||||
private readonly Dictionary<Guid, ulong> _queueNumbers = [];
|
||||
private readonly Dictionary<string, AccessTicket> _accessTickets = [];
|
||||
private readonly Dictionary<string, ulong> _queueNumbers = [];
|
||||
private readonly Dictionary<ulong, AccessTicket> _accessQueue = [];
|
||||
|
||||
private ulong _nowServing = 0;
|
||||
|
@ -16,7 +16,7 @@ namespace AccessQueueService.Data
|
|||
public int GetActiveTicketsCount(DateTime activeCutoff) => _accessTickets
|
||||
.Count(t => t.Value.ExpiresOn > DateTime.UtcNow && t.Value.LastActive > activeCutoff);
|
||||
public int GetQueueCount() => (int)(_nextUnusedTicket - _nowServing);
|
||||
public int GetRequestsAhead(Guid userId)
|
||||
public int GetRequestsAhead(string userId)
|
||||
{
|
||||
if(_queueNumbers.TryGetValue(userId, out var queueNumber))
|
||||
{
|
||||
|
@ -50,7 +50,7 @@ namespace AccessQueueService.Data
|
|||
return count;
|
||||
}
|
||||
|
||||
public void RemoveUser(Guid userId)
|
||||
public void RemoveUser(string userId)
|
||||
{
|
||||
_accessTickets.Remove(userId);
|
||||
}
|
||||
|
@ -90,7 +90,7 @@ namespace AccessQueueService.Data
|
|||
return filledSpots == openSpots;
|
||||
}
|
||||
|
||||
public AccessTicket? GetTicket(Guid userId)
|
||||
public AccessTicket? GetTicket(string userId)
|
||||
{
|
||||
return _accessTickets.TryGetValue(userId, out var ticket) ? ticket : null;
|
||||
}
|
||||
|
@ -100,7 +100,7 @@ namespace AccessQueueService.Data
|
|||
_accessTickets[ticket.UserId] = ticket;
|
||||
}
|
||||
|
||||
bool IAccessQueueRepo.RemoveUser(Guid userId)
|
||||
bool IAccessQueueRepo.RemoveUser(string userId)
|
||||
{
|
||||
if(_queueNumbers.TryGetValue(userId, out var queueNumber))
|
||||
{
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
{
|
||||
public class AccessTicket
|
||||
{
|
||||
public Guid UserId { get; set; }
|
||||
public string UserId { get; set; }
|
||||
public DateTime ExpiresOn { get; set; }
|
||||
public DateTime LastActive { get; set; }
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ namespace AccessQueueService.Services
|
|||
public int UnexpiredTicketsCount => _accessQueueRepo.GetUnexpiredTicketsCount();
|
||||
public int ActiveTicketsCount => _accessQueueRepo.GetActiveTicketsCount(DateTime.UtcNow.AddSeconds(-_configuration.GetValue<int>("AccessQueue:ActivitySeconds")));
|
||||
public int QueueCount => _accessQueueRepo.GetQueueCount();
|
||||
public async Task<AccessResponse> RequestAccess(Guid userId)
|
||||
public async Task<AccessResponse> RequestAccess(string userId)
|
||||
{
|
||||
await _queueLock.WaitAsync();
|
||||
try
|
||||
|
@ -93,7 +93,7 @@ namespace AccessQueueService.Services
|
|||
}
|
||||
}
|
||||
|
||||
public async Task<bool> RevokeAccess(Guid userId)
|
||||
public async Task<bool> RevokeAccess(string userId)
|
||||
{
|
||||
await _queueLock.WaitAsync();
|
||||
try
|
||||
|
|
|
@ -4,8 +4,8 @@ namespace AccessQueueService.Services
|
|||
{
|
||||
public interface IAccessService
|
||||
{
|
||||
public Task<AccessResponse> RequestAccess(Guid userId);
|
||||
public Task<bool> RevokeAccess(Guid userId);
|
||||
public Task<AccessResponse> RequestAccess(string userId);
|
||||
public Task<bool> RevokeAccess(string userId);
|
||||
public int DeleteExpiredTickets();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ namespace AccessQueueServiceTests
|
|||
[Fact]
|
||||
public async Task RequestAccess_ShouldGrantAccess_WhenCapacityIsAvailable()
|
||||
{
|
||||
var userId = Guid.NewGuid();
|
||||
var userId = "user";
|
||||
|
||||
var response = await _accessService.RequestAccess(userId);
|
||||
|
||||
|
@ -56,7 +56,7 @@ namespace AccessQueueServiceTests
|
|||
[Fact]
|
||||
public async Task RequestAccess_ShouldReturnAccessResponse_WhenUserAlreadyHasTicket()
|
||||
{
|
||||
var userId = Guid.NewGuid();
|
||||
var userId = "user";
|
||||
await _accessService.RequestAccess(userId);
|
||||
|
||||
var response = await _accessService.RequestAccess(userId);
|
||||
|
@ -74,9 +74,9 @@ namespace AccessQueueServiceTests
|
|||
{
|
||||
for (int i = 0; i < CAP_LIMIT * 2; i++) // Fill double capacity
|
||||
{
|
||||
await _accessService.RequestAccess(Guid.NewGuid());
|
||||
await _accessService.RequestAccess(Guid.NewGuid().ToString());
|
||||
}
|
||||
var userId = Guid.NewGuid();
|
||||
var userId = "user";
|
||||
|
||||
var response = await _accessService.RequestAccess(userId);
|
||||
|
||||
|
@ -92,7 +92,7 @@ namespace AccessQueueServiceTests
|
|||
[Fact]
|
||||
public async Task RevokeAccess_ShouldReturnTrue_WhenUserHasAccess()
|
||||
{
|
||||
var userId = Guid.NewGuid();
|
||||
var userId = "user";
|
||||
await _accessService.RequestAccess(userId);
|
||||
|
||||
var result = await _accessService.RevokeAccess(userId);
|
||||
|
@ -103,7 +103,7 @@ namespace AccessQueueServiceTests
|
|||
[Fact]
|
||||
public async Task RevokeAccess_ShouldReturnFalse_WhenUserDoesNotHaveAccess()
|
||||
{
|
||||
var userId = Guid.NewGuid();
|
||||
var userId = "user";
|
||||
|
||||
var result = await _accessService.RevokeAccess(userId);
|
||||
|
||||
|
@ -113,12 +113,12 @@ namespace AccessQueueServiceTests
|
|||
[Fact]
|
||||
public async Task RequestAccess_ShouldQueueUser_AfterAccessRevoked()
|
||||
{
|
||||
var userId = Guid.NewGuid();
|
||||
var userId = "user";
|
||||
await _accessService.RequestAccess(userId);
|
||||
|
||||
for (int i = 0; i < CAP_LIMIT; i++) // Fill remaining slots
|
||||
{
|
||||
await _accessService.RequestAccess(Guid.NewGuid());
|
||||
await _accessService.RequestAccess(Guid.NewGuid().ToString());
|
||||
}
|
||||
|
||||
var response = await _accessService.RequestAccess(userId); // Request access before revoking
|
||||
|
@ -136,9 +136,9 @@ namespace AccessQueueServiceTests
|
|||
{
|
||||
for (int i = 0; i < CAP_LIMIT; i++) // Fill slots without awaiting
|
||||
{
|
||||
_ = _accessService.RequestAccess(Guid.NewGuid());
|
||||
_ = _accessService.RequestAccess(Guid.NewGuid().ToString());
|
||||
}
|
||||
var response = await _accessService.RequestAccess(Guid.NewGuid()); // Request access before revoking
|
||||
var response = await _accessService.RequestAccess(Guid.NewGuid().ToString()); // Request access before revoking
|
||||
Assert.NotNull(response);
|
||||
Assert.False(response.HasAccess);
|
||||
}
|
||||
|
@ -146,7 +146,7 @@ namespace AccessQueueServiceTests
|
|||
[Fact]
|
||||
public async Task RequestAccess_ShouldUpdateExpirationTime_WhenRollingExpirationTrue()
|
||||
{
|
||||
var userId = Guid.NewGuid();
|
||||
var userId = "user";
|
||||
var initialResponse = await _accessService.RequestAccess(userId);
|
||||
await Task.Delay(ACT_MILLIS);
|
||||
var updatedResponse = await _accessService.RequestAccess(userId);
|
||||
|
@ -158,9 +158,9 @@ namespace AccessQueueServiceTests
|
|||
{
|
||||
for (int i = 0; i < CAP_LIMIT; i++)
|
||||
{
|
||||
await _accessService.RequestAccess(Guid.NewGuid());
|
||||
await _accessService.RequestAccess(Guid.NewGuid().ToString());
|
||||
}
|
||||
var userId = Guid.NewGuid();
|
||||
var userId = "user";
|
||||
var response = await _accessService.RequestAccess(userId);
|
||||
Assert.False(response.HasAccess);
|
||||
await Task.Delay(ACT_MILLIS);
|
||||
|
@ -171,13 +171,13 @@ namespace AccessQueueServiceTests
|
|||
[Fact]
|
||||
public async Task RequestAccess_ShouldRevokeAccess_WhenExpired()
|
||||
{
|
||||
var userId = Guid.NewGuid();
|
||||
var userId = "user";
|
||||
var response = await _accessService.RequestAccess(userId);
|
||||
Assert.True(response.HasAccess);
|
||||
await Task.Delay(EXP_MILLIS);
|
||||
for (int i = 0; i < CAP_LIMIT; i++)
|
||||
{
|
||||
await _accessService.RequestAccess(Guid.NewGuid());
|
||||
await _accessService.RequestAccess(Guid.NewGuid().ToString());
|
||||
}
|
||||
response = await _accessService.RequestAccess(userId);
|
||||
Assert.False(response.HasAccess);
|
||||
|
@ -186,13 +186,13 @@ namespace AccessQueueServiceTests
|
|||
[Fact]
|
||||
public async Task RequestAccess_ShouldRetailAccess_WhenNotExpired()
|
||||
{
|
||||
var userId = Guid.NewGuid();
|
||||
var userId = "user";
|
||||
var response = await _accessService.RequestAccess(userId);
|
||||
Assert.True(response.HasAccess);
|
||||
await Task.Delay(ACT_MILLIS);
|
||||
for (int i = 0; i < CAP_LIMIT; i++)
|
||||
{
|
||||
response = await _accessService.RequestAccess(Guid.NewGuid());
|
||||
response = await _accessService.RequestAccess(Guid.NewGuid().ToString());
|
||||
Assert.True(response.HasAccess);
|
||||
}
|
||||
response = await _accessService.RequestAccess(userId);
|
||||
|
@ -202,11 +202,11 @@ namespace AccessQueueServiceTests
|
|||
[Fact]
|
||||
public async Task RequestAccess_ShouldProcessBulkRequests()
|
||||
{
|
||||
var userId = Guid.NewGuid();
|
||||
var userId = "user";
|
||||
await _accessService.RequestAccess(userId);
|
||||
for (int i = 0; i < BULK_COUNT; i++)
|
||||
{
|
||||
_ = _accessService.RequestAccess(Guid.NewGuid());
|
||||
_ = _accessService.RequestAccess(Guid.NewGuid().ToString());
|
||||
}
|
||||
var response = await _accessService.RequestAccess(userId);
|
||||
Assert.NotNull(response);
|
||||
|
@ -220,15 +220,14 @@ namespace AccessQueueServiceTests
|
|||
for (int i = 0; i < CAP_LIMIT; i++)
|
||||
{
|
||||
var elapsed = DateTime.UtcNow - start;
|
||||
Console.WriteLine($"Elapsed time: {elapsed.TotalSeconds} s: Adding {i}");
|
||||
await _accessService.RequestAccess(Guid.NewGuid());
|
||||
await _accessService.RequestAccess(Guid.NewGuid().ToString());
|
||||
await Task.Delay(ACT_MILLIS / CAP_LIMIT);
|
||||
}
|
||||
var users = new[]
|
||||
{
|
||||
Guid.NewGuid(),
|
||||
Guid.NewGuid(),
|
||||
Guid.NewGuid()
|
||||
"user1",
|
||||
"user2",
|
||||
"user3"
|
||||
};
|
||||
|
||||
await _accessService.RequestAccess(users[0]);
|
||||
|
@ -250,12 +249,12 @@ namespace AccessQueueServiceTests
|
|||
{
|
||||
for (int i = 0; i < CAP_LIMIT; i++)
|
||||
{
|
||||
await _accessService.RequestAccess(Guid.NewGuid());
|
||||
await _accessService.RequestAccess(Guid.NewGuid().ToString());
|
||||
}
|
||||
|
||||
var id1 = Guid.NewGuid();
|
||||
var id2 = Guid.NewGuid();
|
||||
var id3 = Guid.NewGuid();
|
||||
var id1 = "user1";
|
||||
var id2 = "user2";
|
||||
var id3 = "user3";
|
||||
|
||||
var response1 = await _accessService.RequestAccess(id1);
|
||||
var response2 = await _accessService.RequestAccess(id2);
|
||||
|
|
Loading…
Reference in New Issue