Запретить параллельные запросы контроллера от пользователя - PullRequest
0 голосов
/ 21 сентября 2019

У меня есть действие Controller в моем проекте ASP.Net MVC, которое не должно выполняться одновременно одним и тем же пользователем.Когда пользователь отправляет запрос № 1, а во время выполнения запроса № 1 все остальные запросы должны быть отклонены.Эта логика должна основываться на пользователе.

Я написал некоторый код и думаю, что он может работать

Поскольку у меня есть проблемы с тестированием на localhost, и это чувствительная часть моего сайта, я был бы очень признателенЕсли бы вы могли просмотреть код и дать мне обратную связь!

ОБНОВЛЕНИЕ

Я опубликовал приведенный ниже код в производство, и у меня был один случай, когда пользователь создал блокировку и не разблокировал,Я не знаю, где проблема.

Контроллер

public class LockTestController : Controller
    {
        public string Submit(int userId)
        {
            try
            {
                if (TransactionLockRepository.HasLock(userId))
                    return DateTime.Now + $"Err: UserId {userId} already requested already ";

                //todo: do important stuff an user should not execute concurrently

                TransactionLockRepository.RemoveLock(userId);
                return DateTime.Now + " Submit successfully. UserId: " + userId + " ";
            }
            catch (Exception e)
            {
                TransactionLockRepository.RemoveLock(userId);
                Debug.WriteLine(e);
                return  DateTime.Now + " Error " + e;
            }
        }
    }

LockRepository

public static class TransactionLockRepository
    {
        private static readonly ConcurrentBag<int> UserLocks = new ConcurrentBag<int>();
        private static readonly object _lockInsert = new object();
        private static readonly object _lockRemove = new object();

        public static bool HasLock(int userId)
        {
            lock (_lockInsert)
            {
                var i = userId;
                var hasLock = UserLocks.TryPeek(out i);
                if (hasLock)
                    return true;
                UserLocks.Add(userId);
                return false;
            }
        }

        public static bool RemoveLock(int userId)
        {
            lock (_lockRemove)
            {
                var i = userId;
                UserLocks.TryTake(out i);
                return i == userId;
            }
        }
    }

Я ожидаю, что запросы блокируются только тогда, когда userId находится в репозитории блокировки.Другие пользователи не должны быть затронуты

1 Ответ

1 голос
/ 21 сентября 2019

Не думаю, что это будет работать постоянно.Что если два запроса на действие вызывают метод HasLock одновременно?и два запроса последовательно устанавливают переменную hasLock в false перед выполнением строки кода UserLocks.Add(userId);.В этом случае вам может понадобиться использовать блокировку внутри метода HasLock:

private static object _lockObj = new object();
public static bool HasLock(int userId)
{
   lock(_lockObj)    
   {
     var i = userId;
     var hasLock = UserLocks.TryPeek(out i);
     if (hasLock)
         return true;
     UserLocks.Add(userId);
     return false;
   }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...