Приложение ASP.NET core 2.1 (Entity Framework), состоящее из нескольких конечных точек веб-API.
Одной из них является конечная точка «соединения», где пользователи могут присоединиться к очереди.
Еще одна конечная точка «выхода», где пользователи могут покинуть очередь.
В очереди 10 доступных мест.
Если все 10 мест заполнены, мы возвращаем сообщение «Очередь заполнена».
Если ровно 3 пользователя присоединились, мы возвращаем true.
Если количество присоединившихся пользователей НЕ равно 3, мы возвращаем false.
200 счастливых пользователей триггера готовы присоединиться и покинуть разные очереди. Все они одновременно вызывают конечную точку "соединения" и "выхода".
Это означает, что мы должны обрабатывать поступающие запросы последовательным образом, чтобы обеспечить возможность добавления и удаления пользователей в правильные очереди удобным и контролируемым образом. (Правильно?)
Один из вариантов - добавить класс QueueService
как AddSingleton<>
в IServiceCollection
, а затем сделать lock()
, чтобы обеспечить доступ только одному пользователю за раз. Однако как мы можем обрабатывать dbContext
, поскольку он зарегистрирован как AddTransient<>
или AddScoped<>
?
Psedudo код для присоединяемой части:
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;
}
}
Другой вариант - сделать QueueService
кратковременным, но тогда я потеряю состояние службы, и для каждого запроса предоставляется новый экземпляр, что делает lock () бессмысленным.
Вопросы:
[1] Должен ли я вместо этого обрабатывать состояние очередей в памяти? Если да, как выровнять его с базой данных?
[2] Есть ли блестящий образец, который я пропустил? Или как я могу справиться с этим по-другому?