Назад к вопросам
OZON
Middle+
5
Реализовать метод который заполняет полное имя пользователя из хранилища (IDbRepository или ICacheRepository) и прокидывает обогащенное событие дальше(IEventSaver) Необходимо добиться максимальной производительности В кеше содержится 99.9% актуальных данных изначальный порядок событий при сохранении можно нарушать public async Task Enrich(IEnumerable<UserEvent> events) { }
Компании, где спрашивали
Ответ от нейросети
sobes.tech AI
Для максимальной производительности при обогащении событий именами пользователей из кеша и базы можно:
- Сначала попытаться получить данные из кеша (ICacheRepository) для всех пользователей.
- Для тех, кого нет в кеше (0.1%), сделать пакетный запрос в базу (IDbRepository).
- Обновить кеш новыми данными, если нужно.
- Обогатить события полным именем.
- Поскольку порядок можно нарушать, можно обрабатывать события параллельно.
Пример реализации:
public async Task Enrich(IEnumerable<UserEvent> events)
{
var eventList = events.ToList();
var userIds = eventList.Select(e => e.UserId).Distinct().ToList();
// Пытаемся получить из кеша
var cachedUsers = await cacheRepository.GetUsersAsync(userIds);
var missingUserIds = userIds.Except(cachedUsers.Select(u => u.Id)).ToList();
// Запрашиваем недостающих из базы
var dbUsers = missingUserIds.Any() ? await dbRepository.GetUsersAsync(missingUserIds) : new List<User>();
// Обновляем кеш
if (dbUsers.Any())
{
await cacheRepository.SetUsersAsync(dbUsers);
}
// Объединяем данные
var allUsers = cachedUsers.Concat(dbUsers).ToDictionary(u => u.Id);
// Обогащаем события и сохраняем
var tasks = eventList.Select(async e =>
{
if (allUsers.TryGetValue(e.UserId, out var user))
{
e.FullName = user.FullName;
}
await eventSaver.SaveAsync(e);
});
await Task.WhenAll(tasks);
}
Такой подход минимизирует обращения к базе, использует кеш максимально эффективно и позволяет параллельно сохранять обогащённые события.