Conversation
- Добавлен 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
There was a problem hiding this comment.
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 |
src/main/java/ru/practicum/eventhub/domain/service/impl/ProjectServiceImpl.java
Outdated
Show resolved
Hide resolved
src/main/java/ru/practicum/eventhub/service/impl/CategoryServiceImpl.java
Show resolved
Hide resolved
src/main/java/ru/practicum/eventhub/domain/service/impl/EventServiceImpl.java
Show resolved
Hide resolved
src/main/java/ru/practicum/eventhub/config/RedisCacheConfig.java
Outdated
Show resolved
Hide resolved
src/main/java/ru/practicum/eventhub/infrastructure/fallback/TagAnalyticsFallback.java
Outdated
Show resolved
Hide resolved
- Добавлен класс 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 |
| event = eventRepository.save(event); | ||
|
|
||
| Set<UUID> addedTagIds = event.getTags().stream().map(Tag::getId).collect(Collectors.toSet()); | ||
| addedTagIds.removeAll(oldTagIds); |
There was a problem hiding this comment.
Не очень понял, а зачем удалять все старые?
| for (UUID tagId : addedTagIds) { | ||
| relationIndexService.add(EVENT_TAG_RELATION, id, tagId); | ||
| } | ||
| eventCacheService.refresh(id); |
There was a problem hiding this comment.
Правильно ли я понял, что из-за составного ключа ты делаешь refresh ручной вместо CachePut?
src/main/resources/application.yml
Outdated
|
|
||
| retry: | ||
| instances: | ||
| tagAnalytics: |
There was a problem hiding this comment.
Если не ошибаюсь, у тебя так как нейминг другой в 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, |
There was a problem hiding this comment.
Миграции работают так, если ты прошел мр, фича раскатилась и на сервере применились миграции, если ты изменишь миграции, то поменяется хэшсумма, из-за чего приложение не встанет, у нас все также применяется правило 1 пр/мр - 1 миграция, также не добавил каскадирование на обновление
| retry: | ||
| instances: | ||
| tagAnalytics: | ||
| maxAttempts: 3 |
There was a problem hiding this comment.
Сейчас ты ретраишь все подряд, к примеру 400-ки не надо ретраить, а сразу вернуть исключение, что такого объекта к примеру не существует, то есть все логические ошибки мы не ретраим, ретраим только 500-ки
- Обновлён конфиг для Feign клиента с добавлением кастомного ErrorDecoder - Добавлены исключения для обработки ошибок TagAnalyticsClient - Изменены пакеты для классов кэширования и сервисов - Обновлены методы кэширования тегов для использования нового подхода - Добавлены новые классы исключений для обработки ошибок
f9e41e5 to
d981c1c
Compare
|
|
||
| @Override | ||
| public TagStatsDto getStats(UUID id) { | ||
| log.warn("Сервис Tag Analytics недоступен. Не удалось получить статистику для тега с id={}", id); |
There was a problem hiding this comment.
Если у тебя есть декодер и он у тебя возвращает исключение, не уверен, что это будет работать и вообще нужно, там должно быть нужное логгирование и верный ответ
| eventCacheService.refresh(eventId); | ||
| tagCacheService.refresh(tagId); | ||
|
|
||
| tagAnalyticsClient.createIfAbsent(tag.getId()); |
There was a problem hiding this comment.
Вот сейчас у тебя тут две потенциальные ошибки
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/
There was a problem hiding this comment.
Также не вижу как данные ты отсюда получаешь и все в одну дто складываешь
| tag = tagRepository.save(tag); | ||
|
|
||
| Set<UUID> eventIds = relationIndexService.getLeftIds(EVENT_TAG_RELATION, tagId); | ||
| tagCacheService.refreshCompositeCacheForTag(tagId, eventIds); |
There was a problem hiding this comment.
Также здесь можешь долго держать транзакцию
- Добавлен класс TagAnalyticsFacade для работы с Tag Analytics - Реализован TagAnalyticsSagaOrchestrator для управления добавлением тегов к событиям - Обновлены сервисы TagService и TagCacheService для использования нового фасада - Изменены методы в контроллерах для работы с новыми классами - Обновлены конфигурации Feign для работы с Tag Analytics
| return eventMapper.toDto(event); | ||
| } | ||
|
|
||
| public void evict(UUID eventId) { |
There was a problem hiding this comment.
Только сейчас заметил, все операции где участвует только один кэш - выносим в конфигурацию кэша, это тут не нужно
- Удалён ненужный CacheManager из EventCacheService - Добавлены аннотации @cACHEpUT и @CacheEvict в EventServiceImpl - Переименован метод createIfAbsent в incrementUsage в TagAnalyticsClient - Обновлён метод sendAnalytics на incrementUsage в TagAnalyticsFacade - Изменён возврат TagStatsDto в TagAnalyticsFallbackFactory
| log.info("Обновлен кэш тега с id={} для всех связанных событий", tagId); | ||
| } | ||
|
|
||
| public void evictAll(UUID tagId) { |
There was a problem hiding this comment.
Это тоже в конфиг можно вынести, общий метод, надо все общие методы убрать в конфиг и переисользовать их, без переопределения в будущем
| @Service | ||
| @RequiredArgsConstructor | ||
| public class UserApplicationService { | ||
| public class UserPageMapper { |
There was a problem hiding this comment.
Сервис называется маппером но при это вызывает метод чтения и почему-то он в папке openapi хотя тут ничего нет связанно со сваггером
There was a problem hiding this comment.
Также убери папку кэш, я в архитектуре запутался ты ее сильно переусложнил, для кэша отдельный класс сервис не нужен
There was a problem hiding this comment.
Для саги также отдельный класс не нужен, сначала напиши в сервисе, если логика будет слишком сложная для него одного, потом будем разделять
There was a problem hiding this comment.
Только сейчас заметил в domain у нас только сущности, из domain все что не связано с сущностями
| } | ||
|
|
||
| @Override | ||
| public void deleteTagAnalytics(UUID id) { |
There was a problem hiding this comment.
Нам нужны только два метода, пост и гет, удали все ненужные методы
- Создан класс CompensationAction для хранения информации о компенсационных действиях - Реализован CompensationService для обработки и сохранения компенсационных действий - Добавлен CompensationScheduler для периодической обработки компенсаций - Обновлены пакеты и импорты в нескольких классах - Исправлены пути к классам и методам в соответствии с новой структурой
| @Scheduled(fixedDelay = 180000) | ||
| @Transactional | ||
| public void processCompensations() { | ||
| List<CompensationAction> actions = repository.findAll(); |
There was a problem hiding this comment.
Лучше доставай сразу с нужным статусом, иначе будешь доставать обработавшиеся, а это лишняя работа
| Tag tag = addTagLocal(eventId, tagId); | ||
| tagAdded = true; | ||
|
|
||
| TagStatsDto tagStatsDto = tagAnalyticsFacade.createTagAnalytics(tagId); |
There was a problem hiding this comment.
По заданию для саги ты должен делать сохранение еще в локальную бд, не вижу этой операции
Redis | FeignClient | Circuit breaker
PR сервиса обогащения данных tag-analytics-service