Skip to content

Sprint 2#2

Open
Naz1anmak wants to merge 8 commits intodevelopfrom
feature/redis-cache-and-feign
Open

Sprint 2#2
Naz1anmak wants to merge 8 commits intodevelopfrom
feature/redis-cache-and-feign

Conversation

@Naz1anmak
Copy link
Copy Markdown
Owner

@Naz1anmak Naz1anmak commented Feb 10, 2026

Redis | FeignClient | Circuit breaker
PR сервиса обогащения данных tag-analytics-service

- Добавлен RedisCacheConfig для настройки кэширования
- Обновлён application.yml для конфигурации Redis
- Добавлены аннотации @Cacheable и @CacheEvict в сервисы для категорий, событий, тегов, пользователей и проектов
- Обновлён docker-compose.yml для запуска Redis
- Добавлен клиент TagAnalyticsClient для работы с API аналитики тегов
- Обновлён TagService для получения статистики тегов
- Изменён метод getTagByEvent в TagService для возврата TagWithStatsDto
- Добавлен новый DTO TagWithStatsDto для передачи данных о тегах с их статистикой
- Обновлён mappers для поддержки нового DTO
- Обновлён application.yml для добавления URL сервиса аналитики
- Добавлен класс TagAnalyticsFallback для обработки ошибок
- Обновлён TagAnalyticsClient с использованием fallback
- Настроены параметры Circuit Breaker в application.yml
- Добавлена зависимость spring-cloud-starter-circuitbreaker-resilience4j в build.gradle
Copilot AI review requested due to automatic review settings February 10, 2026 18:12
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

PR добавляет интеграции для Redis-кэша, Feign-клиента к сервису аналитики тегов и circuit breaker/retry (Resilience4j), а также расширяет контракт API, чтобы возвращать тег вместе со статистикой.

Changes:

  • Добавлен Redis-кэш (CacheManager + аннотации кэширования в сервисах).
  • Добавлен FeignClient TagAnalyticsClient с fallback и конфигурацией circuit breaker/retry.
  • Обновлён OpenAPI-контракт и DTO/маппинг для ответа TagWithStatsDto.

Reviewed changes

Copilot reviewed 23 out of 24 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
src/main/resources/openapi/openapi.yml Обновление ответа метода получения тега по событию + добавление схемы TagWithStatsDto
src/main/resources/application.yml Конфигурация Redis cache, Feign circuitbreaker, Resilience4j, URL сервиса tag-analytics
src/main/java/ru/practicum/eventhub/infrastructure/TagAnalyticsClient.java Feign-клиент для tag-analytics
src/main/java/ru/practicum/eventhub/infrastructure/fallback/TagAnalyticsFallback.java Fallback для недоступности tag-analytics
src/main/java/ru/practicum/eventhub/config/RedisCacheConfig.java Конфигурация RedisCacheManager и TTL
src/main/java/ru/practicum/eventhub/domain/service/impl/*ReadService.java Добавлены @Cacheable для чтений (users/tags/events/categories/userMetadata)
src/main/java/ru/practicum/eventhub/domain/service/impl/*ServiceImpl.java Добавлены @CachePut/@CacheEvict на update/delete (users/tags/events/categories/projects)
src/main/java/ru/practicum/eventhub/domain/service/impl/TagServiceImpl.java Вызов tag-analytics (incrementUsage/getStats) и возврат TagWithStatsDto
src/main/java/ru/practicum/eventhub/domain/service/TagService.java Сигнатура getTagByEvent теперь возвращает TagWithStatsDto
src/main/java/ru/practicum/eventhub/controller/EventTagController.java Эндпоинт getTagByEventId теперь возвращает TagWithStatsDto
src/main/java/ru/practicum/eventhub/api/mapper/TagMapper.java Добавлен маппинг в TagWithStatsDto
src/main/java/ru/practicum/eventhub/api/dto/response/TagWithStatsDto.java Новый DTO для тега со статистикой
src/main/java/ru/practicum/eventhub/api/dto/response/TagStatsDto.java Новый DTO статистики тега
src/main/java/ru/practicum/eventhub/EventHubApplication.java Включены @EnableCaching и @EnableFeignClients
build.gradle / gradle.properties Подключены зависимости cache/redis/feign/resilience4j и вынесены версии в gradle.properties
docker-compose.yml Добавлен сервис redis

@Naz1anmak Naz1anmak marked this pull request as draft February 10, 2026 20:01
- Добавлен класс CategoryCacheInvalidator для удаления кэша при удалении категории
- Добавлен класс CategoryCacheService для обновления кэша категорий
- Добавлен класс ProjectCacheIndexService для управления индексом проектов по категориям
- Обновлены методы в CategoryServiceImpl и ProjectServiceImpl для работы с кэшированием
- Обновлены DTO классы для соответствия изменениям
@Query("""
select t from Tag t
join t.events e
where t.id = :tagId and e.id in :eventIds
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Добавь for update skip locked

event = eventRepository.save(event);

Set<UUID> addedTagIds = event.getTags().stream().map(Tag::getId).collect(Collectors.toSet());
addedTagIds.removeAll(oldTagIds);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Не очень понял, а зачем удалять все старые?

for (UUID tagId : addedTagIds) {
relationIndexService.add(EVENT_TAG_RELATION, id, tagId);
}
eventCacheService.refresh(id);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Правильно ли я понял, что из-за составного ключа ты делаешь refresh ручной вместо CachePut?


retry:
instances:
tagAnalytics:
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Если не ошибаюсь, у тебя так как нейминг другой в feignclient это не будет работать либо прокинь в feignclient contextId = "tagAnalytics"

name varchar(100) not null unique,
description varchar(255),
category_id uuid not null references categories(id) on delete restrict,
category_id uuid not null references categories(id) on delete cascade,
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Миграции работают так, если ты прошел мр, фича раскатилась и на сервере применились миграции, если ты изменишь миграции, то поменяется хэшсумма, из-за чего приложение не встанет, у нас все также применяется правило 1 пр/мр - 1 миграция, также не добавил каскадирование на обновление

retry:
instances:
tagAnalytics:
maxAttempts: 3
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Сейчас ты ретраишь все подряд, к примеру 400-ки не надо ретраить, а сразу вернуть исключение, что такого объекта к примеру не существует, то есть все логические ошибки мы не ретраим, ретраим только 500-ки

- Обновлён конфиг для Feign клиента с добавлением кастомного ErrorDecoder
- Добавлены исключения для обработки ошибок TagAnalyticsClient
- Изменены пакеты для классов кэширования и сервисов
- Обновлены методы кэширования тегов для использования нового подхода
- Добавлены новые классы исключений для обработки ошибок
@Naz1anmak Naz1anmak force-pushed the feature/redis-cache-and-feign branch from f9e41e5 to d981c1c Compare February 18, 2026 21:26

@Override
public TagStatsDto getStats(UUID id) {
log.warn("Сервис Tag Analytics недоступен. Не удалось получить статистику для тега с id={}", id);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Если у тебя есть декодер и он у тебя возвращает исключение, не уверен, что это будет работать и вообще нужно, там должно быть нужное логгирование и верный ответ

eventCacheService.refresh(eventId);
tagCacheService.refresh(tagId);

tagAnalyticsClient.createIfAbsent(tag.getId());
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Вот сейчас у тебя тут две потенциальные ошибки
1-е, ты очень долго можешь держать открытой транзакцию это можно починить TransactionTemplate https://docs.spring.io/spring-framework/reference/data-access/transaction/programmatic.html
https://habr.com/ru/companies/otus/articles/431508/
2-е у тебя в бд другого сервиса могут создаться данные, а тут нет так мы получаем неконсистентность данных, поэтому давай реализуем с тобой сагу в реализации через оркестрацию
https://habr.com/ru/companies/otus/articles/751134/
https://habr.com/ru/articles/906166/
https://habr.com/ru/articles/427705/
https://habr.com/ru/companies/alfa/articles/759224/

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Также не вижу как данные ты отсюда получаешь и все в одну дто складываешь

tag = tagRepository.save(tag);

Set<UUID> eventIds = relationIndexService.getLeftIds(EVENT_TAG_RELATION, tagId);
tagCacheService.refreshCompositeCacheForTag(tagId, eventIds);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Также здесь можешь долго держать транзакцию

- Добавлен класс TagAnalyticsFacade для работы с Tag Analytics
- Реализован TagAnalyticsSagaOrchestrator для управления добавлением тегов к событиям
- Обновлены сервисы TagService и TagCacheService для использования нового фасада
- Изменены методы в контроллерах для работы с новыми классами
- Обновлены конфигурации Feign для работы с Tag Analytics
return eventMapper.toDto(event);
}

public void evict(UUID eventId) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Только сейчас заметил, все операции где участвует только один кэш - выносим в конфигурацию кэша, это тут не нужно

- Удалён ненужный CacheManager из EventCacheService
- Добавлены аннотации @cACHEpUT и @CacheEvict в EventServiceImpl
- Переименован метод createIfAbsent в incrementUsage в TagAnalyticsClient
- Обновлён метод sendAnalytics на incrementUsage в TagAnalyticsFacade
- Изменён возврат TagStatsDto в TagAnalyticsFallbackFactory
@Naz1anmak Naz1anmak marked this pull request as ready for review March 12, 2026 16:21
log.info("Обновлен кэш тега с id={} для всех связанных событий", tagId);
}

public void evictAll(UUID tagId) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Это тоже в конфиг можно вынести, общий метод, надо все общие методы убрать в конфиг и переисользовать их, без переопределения в будущем

@Service
@RequiredArgsConstructor
public class UserApplicationService {
public class UserPageMapper {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Сервис называется маппером но при это вызывает метод чтения и почему-то он в папке openapi хотя тут ничего нет связанно со сваггером

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Также убери папку кэш, я в архитектуре запутался ты ее сильно переусложнил, для кэша отдельный класс сервис не нужен

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Для саги также отдельный класс не нужен, сначала напиши в сервисе, если логика будет слишком сложная для него одного, потом будем разделять

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Только сейчас заметил в domain у нас только сущности, из domain все что не связано с сущностями

}

@Override
public void deleteTagAnalytics(UUID id) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Нам нужны только два метода, пост и гет, удали все ненужные методы

- Создан класс CompensationAction для хранения информации о компенсационных действиях
- Реализован CompensationService для обработки и сохранения компенсационных действий
- Добавлен CompensationScheduler для периодической обработки компенсаций
- Обновлены пакеты и импорты в нескольких классах
- Исправлены пути к классам и методам в соответствии с новой структурой
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ошибки не находятся в конфиге

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Убери вторую папку конфиг

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Это должно находиться в папке клиент

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Здесь тоже 2-я папка конфиг не нужна

@Scheduled(fixedDelay = 180000)
@Transactional
public void processCompensations() {
List<CompensationAction> actions = repository.findAll();
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Лучше доставай сразу с нужным статусом, иначе будешь доставать обработавшиеся, а это лишняя работа

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

И если пустое то сразу делай return

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Все шедулеры вынеси в отдельную папку

Tag tag = addTagLocal(eventId, tagId);
tagAdded = true;

TagStatsDto tagStatsDto = tagAnalyticsFacade.createTagAnalytics(tagId);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

По заданию для саги ты должен делать сохранение еще в локальную бд, не вижу этой операции

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants