Есть несколько способов подойти к этому. Наиболее прямолинейным может быть реализация lock
вокруг части кода, которая вызывает _usersRepository.GetOrCreateUser(subject, context.Principal);
, которая обеспечила бы доступ только одной нити за раз к этой строке кода, предотвращая любые грязные чтения и дублирующие вставки.
Этот код будет выглядеть примерно так
public class CustomJwtBearerEvents : JwtBearerEvents
{
private readonly object _key = new object();
private IUsersRepository _usersRepository;
public CustomJwtBearerEvents(IUsersRepository usersRepository)
{
this._usersRepository = usersRepository;
}
public override async Task TokenValidated(TokenValidatedContext context)
{
var subject = context.Principal.FindFirstValue("user_id");
lock(_key)
{
var dbUser = await _usersRepository.GetOrCreateUser(subject, context.Principal);
}
// Populate custom claims
}
}
Как вы можете догадаться, это не будет наиболее эффективным, фактически заставляя каждый из ваших вызовов API ждать всех остальных вызовов fini sh.
Чтобы немного оптимизировать, вы можете подумать о добавлении GetUser()
метода к вашему IUsersRepository
, который можно использовать за пределами lock
ed части кода.
Это позволит выполнять любые запросы пользователей, которые уже существуют, без ожидания и блокировки кода только при создании нового пользователя.
public class CustomJwtBearerEvents : JwtBearerEvents
{
private readonly object _key = new object();
private IUsersRepository _usersRepository;
public CustomJwtBearerEvents(IUsersRepository usersRepository)
{
this._usersRepository = usersRepository;
}
public override async Task TokenValidated(TokenValidatedContext context)
{
var subject = context.Principal.FindFirstValue("user_id");
var dbUser = await _usersRepository.GetUser(subject, context.Principal);
if (dbUser is null)
{
lock(_key)
{
dbUser = await _usersRepository.GetOrCreateUser(subject, context.Principal);
}
}
// Populate custom claims
}
}
Все это говорит Microsoft.As pNet .Identity Framework отлично справляется с управлением внешними учетными записями пользователей, если вы заинтересованы в этом.
Вот ссылка на их документы по теме.