Retry как ограниченный декоратор
Повторять только явно временную ошибку чтения
Реализуй декоратор Reader. Он повторяет только RetryableFailure и делает не более maxAttempts вызовов всего, включая первый. Значение maxAttempts < 1 должно отклоняться при создании. Успех сразу возвращается; последняя временная ошибка и все другие исключения выходят наружу.
Операция read по договору безопасна для повтора. Задержки и backoff в этой маленькой задаче опущены; это не рекомендуемый сетевой retry-loop для production. Вызовы декоратора не разделяют счётчик попыток.
Проверки fake Reader: успех с первого раза; временная ошибка → успех; три временные ошибки при лимите 3; обычная IllegalStateException; CancellationException на первой попытке. В двух последних случаях повторов нет.
Основа: Decorator из draft/patterns.md, retry из draft/M++.md.
Сохранённый код превышает предел редактора. Скачай его перед сбросом; исходная запись сохранена.
Контракт Reader сохранён, а декоратор добавляет политику повторов. Перехватывается только RetryableFailure: отмена и ошибки программирования не маскируются. Счётчик локальный для каждого вызова. Для настоящей сети нужны ограничения времени, backoff и явная оценка идемпотентности.
Декораторы можно собирать через DI. Если добавить логирование снаружи retry, оно увидит одну операцию; внутри — отдельные попытки. Делегирование Kotlin, DI.
Статически разобраны все ветви; Kotlin-запуск не выполнялся.