ASP.NET core 2.1 application (Entity Framework) that consist of multiple web api endpoints. One of them is a "join" endpoint, where users can join a queue. Another is a "leave" endpoint, where users can leave the queue.
The queue has 10 available spots.
If all 10 spots are filled out, we throw a message back saying, "Queue is full."
If exactly 3 users has joined, we return true.
If the number of joined users is NOT 3 then we return false.
200 trigger-happy users are ready to join and leave different queues. They are all calling the "join" and "leave" endpoint concurrently.
This means that we have to handle the requests coming in is a sequential way, to be able to ensure that users are added and removed to the correct queues in a nice and controlled manner. (right?)
One option is to add the QueueService class as AddSingleton<> in the IServiceCollection and then make a lock() to ensure only one user at a time can enter. However, how do we when handle the dbContext, beacause it is registered as AddTransient<> or AddScoped<>?
Psedudo code for the join part:
public class QueueService
{
private readonly object _myLock = new object();
private readonly QueueContext _context;
public QueueService(QueueContext context)
{
_context = context;
}
public bool Join(int queueId, int userId)
{
lock (_myLock)
{
var numberOfUsersInQueue = _context.GetNumberOfUsersInQueue(queueId); <- Problem.
if (numberOfUsersInQueue >= 10)
{
throw new Exception("Queue is full.");
}
else
{
_context.AddUserToQueue(queueId, userId); <- Problem.
}
numberOfUsersInQueue = _context.GetNumberOfUsersInQueue(queueId); <- Problem.
if (numberOfUsersInQueue == 3)
{
return true;
}
}
return false;
}
}
Another option is to make the QueueService transient, but then I lose the state of the service, and a new instance is provided for every request, making the lock () pointless.
Questions:
[1] Should I handle the state of the queues in memory instead? If yes, how to align it with the database?
[2] Are there a brilliant pattern I have missed? Or how could I handle this differently?
Aucun commentaire:
Enregistrer un commentaire