ASP.NET Core: вызовы очереди для фильтра действий из того же клиента - PullRequest
0 голосов
/ 07 декабря 2018

Сначала немного контекста: у нас есть два сервера, один для Identity Management (IdentityServer4) и другой с бизнес-логикой (API), когда любой из наших пользователей создает учетную запись на IdentityServer, который этот пользователь НЕ создает на сервере API.API должен отслеживать некоторую информацию о пользователе, поэтому мы написали ActionFilter, который проверяет, создан ли уже пользователь с таким идентификатором субъекта (предоставленный в JWT) в БД, если нет, фильтр создаст новый (новый пользователь).В большинстве случаев это работает просто отлично, когда клиенты совершают звонки в хорошем темпе (по одному за раз), но при запуске нашего клиентского приложения он совершает от 3 до 4 звонков одновременно, чтобы извлечь некоторые данные (из разных действий)и он выполняется почти одновременно на сервере, и из-за этого запрос A не знает, что делает запрос B, поэтому, если запрос A создает нового пользователя, запрос B не может знать об этом в то время (чтопользователь будет создан по запросу А), поэтому при проверке, был ли пользователь уже создан (или будет создан) для этого предметного идентификатора, он вернет false (пользователь не найден), потому что он действительно не существует в настоящее времяи это также создаст нового пользователя, и теперь у нас есть ДВА (или более) пользователя с тем же идентификатором субъекта

Итак, как мы можем поставить эти вызовы в очередь (по крайней мере, если другой вызов уже обрабатывается), чтобыпредотвратить такое поведение?

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

Фильтр действий

public async Task OnResourceExecutionAsync(ResourceExecutingContext context, ResourceExecutionDelegate next) {
    var subject = GetSubject(context);

    if (!await _userService.ExistAsync(subject)) {
        await _userService.CreateUserAsync(subject);
    }

    await next();
}
...