Задача: Поступают события от пользователей, каждое нужно верифицировать во внешнем источнике, но он отвечает не сразу.

Храните счётчик попыток для события, повторяйте только Pending с задержкой не меньше пяти секунд и завершайте обработку после OK или исчерпания трёх попыток. Error в примере считается окончательным отказом.

Короткий ответ

Что ответить на собеседовании

Храните счётчик попыток для события, повторяйте только Pending с задержкой не меньше пяти секунд и завершайте обработку после OK или исчерпания трёх попыток. Error в примере считается окончательным отказом.

Подробный разбор

Ответ с пояснениями

Условие

Задача: Поступают события от пользователей, каждое нужно верифицировать во внешнем источнике, но он отвечает не сразу.

Необходимо реализовать VerificationService который:

  • Принимает события от пользователя
  • Пытается верифицировать каждое, обращаясь к внешнему сервису
  • Если ответ PENDING, повторяет отправку данного события не раньше чем спустя 5 секунд
  • Максимум 3 попытки, после идентификатор события выводится в stdout со статусом FAILED
  • Успешно обработанные события выводятся в stdout со статусом VERIFIED

Шаблоны и заготовки внешних зависимостей уже реализованы:

  1. VerificationStatus
  2. Event
  3. VerificationResult
  4. IExternalSource

public enum VerificationStatus { OK, Pending, Error }

public record Event(string Id, string Payload);

public record VerificationResult(VerificationStatus Status, string? Message = null);

public interface IExternalSource { VerificationResult Verify(string eventId); }

public class VerificationService { private readonly IExternalSource _externalSource; private const int MaxAttempts = 3; private static readonly TimeSpan RetryDelay = TimeSpan.FromSeconds(5);

public VerificationService(IExternalSource externalSource)
{
    _externalSource = externalSource;
}

// TODO: реализовать

}

Ответ

Храните счётчик попыток для события, повторяйте только Pending с задержкой не меньше пяти секунд и завершайте обработку после OK или исчерпания трёх попыток. Error в примере считается окончательным отказом.

Метод можно добавить в заданный VerificationService:

public async Task ProcessAsync(Event evt, CancellationToken ct = default)
{
    if (evt == null) throw new ArgumentNullException(nameof(evt));
    for (int attempt = 1; attempt <= MaxAttempts; attempt++)
    {
        ct.ThrowIfCancellationRequested();
        VerificationResult result;
        try
        {
            result = _externalSource.Verify(evt.Id);
        }
        catch (OperationCanceledException) when (ct.IsCancellationRequested)
        {
            throw;
        }
        catch (Exception)
        {
            Console.WriteLine($"{evt.Id} FAILED");
            return;
        }
        if (result.Status == VerificationStatus.OK)
        {
            Console.WriteLine($"{evt.Id} VERIFIED");
            return;
        }
        if (result.Status != VerificationStatus.Pending || attempt == MaxAttempts)
            break;
        await Task.Delay(RetryDelay, ct);
    }
    Console.WriteLine($"{evt.Id} FAILED");
}

Нужны System, System.Threading и System.Threading.Tasks. Каждый входящий Event передаётся в ProcessAsync; вызывающая сторона ожидает Task и ограничивает число одновременных обработок. Между завершением Pending-ответа и следующим вызовом выдерживается пять секунд; после третьего ожидания уже нет.

Отмена прерывает обработку, а не печатает FAILED. Исходный Verify синхронный и может блокировать поток; Task.Delay не исправляет это. Для production предпочтителен async-контракт с таймаутом и долговечная очередь повторов. Политика повторов Error и исключений в условии не задана, здесь они терминальные.

ИИ-помощник для собеседований

Хочешь уверенно проходить собеседования?

Попробуй ИИ-помощник для собеседований: слышит вас и собеседника, анализирует экран, подсказывает ответы в реальном времени, работает без VPN и не попадает в захват экрана.

Подробнее