Цель: падение Redis или Kafka не должно ронять пользовательские запросы — кэш-промах вместо 500, write-off проходит даже без Kafka.
Зависимость: CACHE-1, KAFKA-1.
Что сделать
- Подключить
resilience4j-spring-boot3, обернуть обращения к Redis и к Kafka-продюсеру в @CircuitBreaker + @TimeLimiter (короткие таймауты, чтобы не висеть на недоступном бэкенде).
- Redis down →
fallbackMethod читает из БД (трактуем как cache miss), запрос отдаёт 200, а не 500.
- Kafka down → отправка
LowStockAlertEvent не валит транзакцию write-off; событие либо дропается с логом, либо складывается в outbox/локальную очередь (выбрать; ср. REL-6).
@CircuitBreaker(name = "itemCache", fallbackMethod = "getByIdFromDb")
public ItemCardResponse getById(Long id) { ... }
- Стретч: настроить
slidingWindow, порог открытия, half-open пробные вызовы; не расписывать все три состояния — дать конфиг и точки fallback.
Acceptance criteria
Цель: падение Redis или Kafka не должно ронять пользовательские запросы — кэш-промах вместо 500, write-off проходит даже без Kafka.
Зависимость: CACHE-1, KAFKA-1.
Что сделать
resilience4j-spring-boot3, обернуть обращения к Redis и к Kafka-продюсеру в@CircuitBreaker+@TimeLimiter(короткие таймауты, чтобы не висеть на недоступном бэкенде).fallbackMethodчитает из БД (трактуем как cache miss), запрос отдаёт 200, а не 500.LowStockAlertEventне валит транзакцию write-off; событие либо дропается с логом, либо складывается в outbox/локальную очередь (выбрать; ср. REL-6).slidingWindow, порог открытия,half-openпробные вызовы; не расписывать все три состояния — дать конфиг и точки fallback.Acceptance criteria
GET /api/items/{id}отвечает 200 (данные из БД), не 500.POST /api/movements/write-offуспешно меняет остаток.OPEN(видно в/actuator/healthили логах).