diff --git a/README.md b/README.md index a5ef670..bbb7829 100644 --- a/README.md +++ b/README.md @@ -1,162 +1,132 @@ # Explore With Me (Исследуй со мной) -Приложение-афиша, позволяющее пользователям делиться информацией об интересных событиях и находить компанию для участия в них. Изначально проект был разработан в команде в рамках обучения в Яндекс Практикуме, а в настоящее время дорабатывается и расширяется как индивидуальный дипломный проект. +Приложение-афиша, позволяющее пользователям делиться информацией об интересных событиях и находить компанию для участия в них. Изначально проект был разработан в команде в рамках обучения в Яндекс Практикуме. + +В настоящее время проект развивается как индивидуальный дипломный проект, в рамках которого архитектура была переведена на современный микросервисный стек с использованием **Spring Cloud**. ## Оглавление +- [Архитектура](#архитектура) - [Технологии](#технологии) - [Структура проекта](#структура-проекта) - [API Спецификации](#api-спецификации) - [Начало работы](#начало-работы) - [Предварительные требования](#предварительные-требования) - [Сборка проекта](#сборка-проекта) - - [Запуск с использованием Docker Compose](#запуск-с-использованием-docker-compose) + - [Запуск с использованием Docker Compose (Рекомендуемый способ)](#запуск-с-использованием-docker-compose-рекомендуемый-способ) - [Локальный запуск для разработки (IntelliJ IDEA)](#локальный-запуск-для-разработки-intellij-idea) - - [Локальный запуск Stats Service](#локальный-запуск-stats-service-stats-server) - - [Локальный запуск Main Service](#локальный-запуск-main-service-main-service) - [Примеры использования API](#примеры-использования-api) - - [Публичные эндпоинты Событий, Категорий, Подборок](#публичные-эндпоинты-событий-категорий-подборок) - - [Публичные эндпоинты Комментариев](#публичные-эндпоинты-комментариев) - [Тестирование](#тестирование) - - [Юнит и Интеграционные тесты](#юнит-и-интеграционные-тесты) - - [Postman-тесты для Дополнительной Функциональности](#postman-тесты-для-дополнительной-функциональности) - [Реализованная Дополнительная Функциональность: Комментарии](#реализованная-дополнительная-функциональность-комментарии) - [История проекта и Автор](#история-проекта-и-автор) +## Архитектура + +Приложение построено на основе микросервисной архитектуры с использованием компонентов **Spring Cloud** для обеспечения отказоустойчивости, масштабируемости и централизованного управления. + +- **API Gateway (`gateway-server`)**: Единая точка входа для всех внешних запросов. Отвечает за маршрутизацию, балансировку нагрузки, а также реализует паттерны отказоустойчивости (Retries, Circuit Breaker с использованием Resilience4j). +- **Discovery Server (`discovery-server`)**: Сервер обнаружения сервисов (Netflix Eureka). Все микросервисы регистрируются в нем, что позволяет им динамически находить друг друга по имени, не используя статические IP-адреса и порты. +- **Config Server (`config-server`)**: Сервер конфигурации. Предоставляет централизованное управление конфигурацией для всех сервисов. Сами сервисы при запуске запрашивают свои настройки у Config Server. +- **Межсервисное взаимодействие**: Для коммуникации между `main-service` и `stats-server` используется декларативный HTTP-клиент **OpenFeign**, который интегрирован с Eureka для динамического обнаружения сервисов. + ## Технологии - Java 21 -- Spring Boot 3.4.5 +- Spring Boot 3.5.5 +- Spring Cloud (Gateway, Netflix Eureka, Config) +- OpenFeign, Resilience4j (межсервисное взаимодействие и отказоустойчивость) - Spring Data JPA, QueryDSL -- Spring MVC, Spring AOP (для интеграции со StatsClient) +- Spring MVC, Spring AOP (интеграция со StatsClient) - PostgreSQL 16.1 - Maven - Docker / Docker Compose -- Lombok -- MapStruct (для маппинга DTO) -- JUnit 5, Mockito -- Testcontainers -- Checkstyle, Spotbugs, Jacoco (для контроля качества кода) +- Lombok, MapStruct +- JUnit 5, Mockito, Testcontainers +- Checkstyle, Spotbugs, Jacoco (контроль качества кода) ## Структура проекта -Проект является многомодульным Maven-проектом и состоит из следующих основных частей: +Проект является многомодульным Maven-проектом и разделен на два логических слоя: `core` (бизнес-логика) и `infra` (инфраструктурные сервисы). -- `explore-with-me` (корневой POM) - - `ewm-common`: Общий модуль, содержащий классы, используемые как основным сервисом, так и сервисом статистики (например, `ApiError.java`, общие константы). - - `main-service`: Основной сервис приложения. Отвечает за бизнес-логику, управление пользователями, событиями, категориями, подборками и запросами на участие. Взаимодействует с `stats-client` для сбора статистики. - - `Dockerfile` - - `schema.sql` (для инициализации схемы БД `ewm_main_db`) - - `stats-service` (родительский POM для модулей статистики) - - `stats-dto`: Data Transfer Objects (DTO) для сервиса статистики. - * `stats-client`: HTTP-клиент для взаимодействия с API сервиса статистики (используется `main-service`). - * `stats-server`: Сервис статистики (сбор и предоставление данных о запросах к эндпоинтам). - * `Dockerfile` - * `schema.sql` (для инициализации схемы БД `ewm_stats_db`) +``` +explore-with-me/ +| +├── core/ (Модули, реализующие бизнес-логику приложения) +│ ├── ewm-common/ (Общий модуль для core-сервисов) +│ ├── main-service/ +│ └── stats-service/ +│ ├── stats-client/ +│ ├── stats-dto/ +│ └── stats-server/ +| +└── infra/ (Инфраструктурные сервисы Spring Cloud) + ├── config-server/ (Сервер конфигурации) + ├── discovery-server/ (Сервер обнаружения) + └── gateway-server/ (API-шлюз) +``` ## API Спецификации -Актуальные спецификации API, включая эндпоинты для реализованной дополнительной функциональности "Комментарии", можно найти в репозитории: +Спецификации API остаются без изменений, так как инфраструктурные преобразования не затронули публичный контракт сервисов. - **Основной сервис:** [`ewm-main-service-spec.json`](https://github.com/impatient0/java-plus-graduation/blob/main/ewm-main-service-spec.json) - * *Примечание: Оригинальная спецификация от Яндекс Практикума [здесь](https://raw.githubusercontent.com/yandex-praktikum/java-explore-with-me/main/ewm-main-service-spec.json) не включает эндпоинты для комментариев. Описание реализованных эндпоинтов для комментариев см. в разделе [Реализованная Дополнительная Функциональность: Комментарии](#реализованная-дополнительная-функциональность-комментарии).* - **Сервис статистики:** [`ewm-stats-service.json`](https://github.com/impatient0/java-plus-graduation/blob/main/ewm-stats-service-spec.json) -*Рекомендуется просматривать через Swagger Editor или аналогичный инструмент.* - ## Начало работы ### Предварительные требования -Для работы с проектом вам понадобятся: - - JDK 21 - Apache Maven 3.6+ - Docker и Docker Compose -- IntelliJ IDEA (рекомендуется) ### Сборка проекта -Для сборки всех модулей проекта (включая генерацию Q-типов QueryDSL и реализаций MapStruct) выполните: +Для сборки всех модулей проекта выполните команду в корневой директории: ```bash mvn clean install ``` -Эта команда также запустит статические анализаторы кода и юнит-тесты. -### Запуск с использованием Docker Compose +### Запуск с использованием Docker Compose (Рекомендуемый способ) -Это основной способ запуска всего приложения для проверки взаимодействия сервисов. +Это основной способ запуска всего приложения, который поднимает все 5 сервисов в правильном порядке. 1. **Соберите проект:** `mvn clean install` 2. **Запустите сервисы:** В корневой директории проекта выполните: ```bash - docker-compose up --build -d + docker-compose up --build ``` - - Сервис статистики (`stats-server`): `http://localhost:9090` - - Основной сервис (`main-service`): `http://localhost:8080` + Эта команда запустит: + - `discovery-server` + - `config-server` + - `stats-server` (и его БД) + - `main-service` (и его БД) + - `gateway-server` + +3. **Доступ к приложению:** + - **Единая точка входа (API Gateway):** `http://localhost:8080` + - **Eureka Dashboard:** `http://localhost:8761` -3. **Просмотр логов:** - ```bash - docker-compose logs -f main-service - docker-compose logs -f stats-server - ``` 4. **Остановка сервисов:** - ```bash - docker-compose down - ``` - Для удаления volumes (данных БД): ```bash docker-compose down -v ``` - *Примечание: При первом запуске `docker-compose up` скрипты `schema.sql` из каждого сервиса будут выполнены для создания таблиц в соответствующих базах данных.* ### Локальный запуск для разработки (IntelliJ IDEA) -#### Локальный запуск Stats Service (`stats-server`) - -Предусмотрен профиль запуска `stat-local` в IntelliJ IDEA. - -1. **База данных для `stats-server`:** Настройте локальный PostgreSQL согласно `stats-service/stats-server/src/main/resources/application-local.yml` (порт, имя БД, пользователь, пароль). - ```yaml - # stats-service/stats-server/src/main/resources/application-local.yml - spring: - datasource: - url: jdbc:postgresql://localhost:6543/ewm_stats_db # Пример - username: stats_user - password: stats_password - jpa: - hibernate: - ddl-auto: validate # Используется schema.sql из classpath (src/main/resources) - sql: - init: - mode: always # Для выполнения schema.sql при локальном запуске - ``` -2. **Запуск `StatsServerApplication`:** Используйте Run Configuration "stat-local" (VM options: `-Dspring.profiles.active=local`). - -#### Локальный запуск Main Service (`main-service`) - -Предусмотрен профиль запуска `main-local` в IntelliJ IDEA. - -1. **База данных для `main-service`:** Настройте локальный PostgreSQL согласно `main-service/src/main/resources/application-local.yml`. - ```yaml - # main-service/src/main/resources/application-local.yml - stats-server: - url: http://localhost:9090 # Если stats-server тоже запущен локально - - spring: - datasource: - url: jdbc:postgresql://localhost:5432/ewm_main_db # Пример - username: ewm_user - password: ewm_password - jpa: - hibernate: - ddl-auto: validate # Используется schema.sql из classpath - sql: - init: - mode: always # Для выполнения schema.sql при локальном запуске - ``` -2. **Запуск `MainServiceApplication`:** Используйте Run Configuration "main-local" (VM options: `-Dspring.profiles.active=local`). Убедитесь, что `stats-server` уже запущен (локально или в Docker), так как `main-service` от него зависит. +Локальный запуск требует ручного старта всех сервисов в правильной последовательности. Это полезно для отладки конкретного сервиса. + +**Важно:** Все сервисы (кроме `gateway-server` и `discovery-server`) запускаются на случайных портах и получают свою конфигурацию от `config-server`. + +**Порядок запуска:** + +1. **`discovery-server`**: Запустите `DiscoveryServerApplication`. Дождитесь полного старта. +2. **`config-server`**: Запустите `ConfigServerApplication`. Убедитесь, что он зарегистрировался в Eureka. +3. **`stats-server`** и **`main-service`**: Запустите профили `main-local` и `stats-local` (порядок между ними не важен). Они запустят приложения `MainServiceApplication` и `StatsServerApplication`, а также их БД. +4. **`gateway-server`**: Запустите `GatewayServerApplication`. + +После запуска всех сервисов **все API-запросы** должны направляться на порт API Gateway: `http://localhost:8080`. ## Примеры использования API diff --git a/compose.yaml b/compose.yaml index a5406f4..517b78a 100644 --- a/compose.yaml +++ b/compose.yaml @@ -1,17 +1,72 @@ services: + discovery-server: + build: infra/discovery-server + container_name: ewm-discovery-server-compose + hostname: discovery-server + ports: + - "8761:8761" + environment: + EUREKA_HOSTNAME: discovery-server + restart: unless-stopped + healthcheck: + test: [ "CMD-SHELL", "curl -f http://localhost:8761/actuator/health || exit 1" ] + interval: 5s + timeout: 3s + retries: 5 + start_period: 5s + + config-server: + build: infra/config-server + container_name: config-server + depends_on: + discovery-server: + condition: service_healthy + ports: + - "8888:8888" + restart: unless-stopped + healthcheck: + test: [ "CMD-SHELL", "curl -f http://localhost:8888/actuator/health | grep -q '\"eureka\":.*\"details\":{\"applications\":{\"CONFIG-SERVER\":1}}'" ] + interval: 5s + timeout: 5s + retries: 10 + start_period: 10s + environment: + EUREKA_URI: http://discovery-server:8761/eureka/ + PORT: 8888 + + gateway-server: + build: infra/gateway-server + container_name: gateway-server + depends_on: + discovery-server: + condition: service_healthy + config-server: + condition: service_healthy + ports: + - "8080:8080" + restart: unless-stopped + environment: + EUREKA_URI: http://discovery-server:8761/eureka/ + PORT: 8080 + stats-server: - build: stats-service/stats-server + build: core/stats-service/stats-server container_name: ewm-stats-server-compose depends_on: + discovery-server: + condition: service_healthy + config-server: + condition: service_healthy stats-db: condition: service_healthy ports: - "9090:9090" environment: - - SPRING_DATASOURCE_URL=jdbc:postgresql://stats-db:5432/ewm_stats_db - - SPRING_DATASOURCE_USERNAME=stats_user - - SPRING_DATASOURCE_PASSWORD=stats_password - - JAVA_OPTS=-Duser.timezone=UTC + EUREKA_URI: http://discovery-server:8761/eureka/ + SPRING_DATASOURCE_URL: jdbc:postgresql://stats-db:5432/ewm_stats_db + SPRING_DATASOURCE_USERNAME: stats_user + SPRING_DATASOURCE_PASSWORD: stats_password + JAVA_OPTS: -Duser.timezone=UTC stats-db: image: postgres:16.1 @@ -24,7 +79,7 @@ services: POSTGRES_DB: ewm_stats_db volumes: - stats_db_data:/var/lib/postgresql/data - - ./stats-service/stats-server/src/main/resources/schema.sql:/docker-entrypoint-initdb.d/01-schema.sql + - ./core/stats-service/stats-server/src/main/resources/schema.sql:/docker-entrypoint-initdb.d/01-schema.sql healthcheck: test: [ "CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB} -p 5432" ] interval: 10s @@ -33,20 +88,25 @@ services: start_period: 10s ewm-service: - build: main-service + build: core/main-service container_name: ewm-main-service-compose depends_on: + discovery-server: + condition: service_healthy + config-server: + condition: service_healthy ewm-db: condition: service_healthy stats-server: condition: service_started ports: - - "8080:8080" + - "8081:8081" environment: - - SPRING_DATASOURCE_URL=jdbc:postgresql://ewm-db:5432/ewm_main_db - - SPRING_DATASOURCE_USERNAME=ewm_user - - SPRING_DATASOURCE_PASSWORD=ewm_password - - JAVA_OPTS=-Duser.timezone=UTC + EUREKA_URI: http://discovery-server:8761/eureka/ + SPRING_DATASOURCE_URL: jdbc:postgresql://ewm-db:5432/ewm_main_db + SPRING_DATASOURCE_USERNAME: ewm_user + SPRING_DATASOURCE_PASSWORD: ewm_password + JAVA_OPTS: -Duser.timezone=UTC ewm-db: image: postgres:16.1 @@ -59,7 +119,7 @@ services: POSTGRES_DB: ewm_main_db volumes: - main_db_data:/var/lib/postgresql/data - - ./main-service/src/main/resources/schema.sql:/docker-entrypoint-initdb.d/01-schema.sql + - ./core/main-service/src/main/resources/schema.sql:/docker-entrypoint-initdb.d/01-schema.sql healthcheck: test: [ "CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB} -p 5432" ] interval: 10s diff --git a/ewm-common/pom.xml b/core/ewm-common/pom.xml similarity index 95% rename from ewm-common/pom.xml rename to core/ewm-common/pom.xml index c835673..684588d 100644 --- a/ewm-common/pom.xml +++ b/core/ewm-common/pom.xml @@ -5,7 +5,7 @@ 4.0.0 ru.practicum - explore-with-me + core 0.0.1-SNAPSHOT ../pom.xml diff --git a/ewm-common/src/main/java/ru/practicum/explorewithme/common/constants/DateTimeConstants.java b/core/ewm-common/src/main/java/ru/practicum/explorewithme/common/constants/DateTimeConstants.java similarity index 100% rename from ewm-common/src/main/java/ru/practicum/explorewithme/common/constants/DateTimeConstants.java rename to core/ewm-common/src/main/java/ru/practicum/explorewithme/common/constants/DateTimeConstants.java diff --git a/ewm-common/src/main/java/ru/practicum/explorewithme/common/error/ApiError.java b/core/ewm-common/src/main/java/ru/practicum/explorewithme/common/error/ApiError.java similarity index 100% rename from ewm-common/src/main/java/ru/practicum/explorewithme/common/error/ApiError.java rename to core/ewm-common/src/main/java/ru/practicum/explorewithme/common/error/ApiError.java diff --git a/main-service/Dockerfile b/core/main-service/Dockerfile similarity index 100% rename from main-service/Dockerfile rename to core/main-service/Dockerfile diff --git a/main-service/pom.xml b/core/main-service/pom.xml similarity index 82% rename from main-service/pom.xml rename to core/main-service/pom.xml index 1ac60b0..9d4e8da 100644 --- a/main-service/pom.xml +++ b/core/main-service/pom.xml @@ -5,8 +5,9 @@ 4.0.0 ru.practicum - explore-with-me + core 0.0.1-SNAPSHOT + ../pom.xml main-service @@ -17,10 +18,27 @@ org.springframework.boot spring-boot-starter-web + + org.springframework.cloud + spring-cloud-starter-netflix-eureka-client + + + org.springframework.cloud + spring-cloud-starter-config + org.springframework.boot spring-boot-starter-actuator + + org.springframework.cloud + spring-cloud-starter-openfeign + + + ru.practicum + stats-server + ${project.version} + ru.practicum stats-client diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/MainServiceApplication.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/MainServiceApplication.java similarity index 59% rename from main-service/src/main/java/ru/practicum/explorewithme/main/MainServiceApplication.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/MainServiceApplication.java index 7856da2..f97155b 100644 --- a/main-service/src/main/java/ru/practicum/explorewithme/main/MainServiceApplication.java +++ b/core/main-service/src/main/java/ru/practicum/explorewithme/main/MainServiceApplication.java @@ -2,11 +2,12 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.Import; -import ru.practicum.explorewithme.stats.client.config.StatsClientModuleConfiguration; +import org.springframework.cloud.client.discovery.EnableDiscoveryClient; +import org.springframework.cloud.openfeign.EnableFeignClients; @SpringBootApplication -@Import(StatsClientModuleConfiguration.class) +@EnableDiscoveryClient +@EnableFeignClients(basePackages = "ru.practicum.explorewithme.stats.client") public class MainServiceApplication { public static void main(String[] args) { SpringApplication.run(MainServiceApplication.class, args); diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/aspect/LogStatsHit.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/aspect/LogStatsHit.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/aspect/LogStatsHit.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/aspect/LogStatsHit.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/aspect/StatsHitAspect.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/aspect/StatsHitAspect.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/aspect/StatsHitAspect.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/aspect/StatsHitAspect.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/config/JpaAuditingConfig.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/config/JpaAuditingConfig.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/config/JpaAuditingConfig.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/config/JpaAuditingConfig.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/controller/admin/AdminCategoryController.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/controller/admin/AdminCategoryController.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/controller/admin/AdminCategoryController.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/controller/admin/AdminCategoryController.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/controller/admin/AdminCommentController.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/controller/admin/AdminCommentController.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/controller/admin/AdminCommentController.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/controller/admin/AdminCommentController.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/controller/admin/AdminCompilationController.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/controller/admin/AdminCompilationController.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/controller/admin/AdminCompilationController.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/controller/admin/AdminCompilationController.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/controller/admin/AdminEventController.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/controller/admin/AdminEventController.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/controller/admin/AdminEventController.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/controller/admin/AdminEventController.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/controller/admin/AdminUserController.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/controller/admin/AdminUserController.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/controller/admin/AdminUserController.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/controller/admin/AdminUserController.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/controller/priv/PrivateCommentController.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/controller/priv/PrivateCommentController.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/controller/priv/PrivateCommentController.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/controller/priv/PrivateCommentController.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/controller/priv/PrivateEventController.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/controller/priv/PrivateEventController.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/controller/priv/PrivateEventController.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/controller/priv/PrivateEventController.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/controller/priv/PrivateRequestController.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/controller/priv/PrivateRequestController.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/controller/priv/PrivateRequestController.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/controller/priv/PrivateRequestController.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/controller/pub/PublicCategoryController.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/controller/pub/PublicCategoryController.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/controller/pub/PublicCategoryController.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/controller/pub/PublicCategoryController.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/controller/pub/PublicCommentController.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/controller/pub/PublicCommentController.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/controller/pub/PublicCommentController.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/controller/pub/PublicCommentController.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/controller/pub/PublicCompilationController.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/controller/pub/PublicCompilationController.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/controller/pub/PublicCompilationController.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/controller/pub/PublicCompilationController.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/controller/pub/PublicEventController.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/controller/pub/PublicEventController.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/controller/pub/PublicEventController.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/controller/pub/PublicEventController.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/dto/CategoryDto.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/dto/CategoryDto.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/dto/CategoryDto.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/dto/CategoryDto.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/dto/CommentAdminDto.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/dto/CommentAdminDto.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/dto/CommentAdminDto.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/dto/CommentAdminDto.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/dto/CommentDto.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/dto/CommentDto.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/dto/CommentDto.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/dto/CommentDto.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/dto/CompilationDto.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/dto/CompilationDto.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/dto/CompilationDto.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/dto/CompilationDto.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/dto/EventFullDto.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/dto/EventFullDto.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/dto/EventFullDto.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/dto/EventFullDto.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/dto/EventRequestStatusUpdateRequestDto.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/dto/EventRequestStatusUpdateRequestDto.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/dto/EventRequestStatusUpdateRequestDto.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/dto/EventRequestStatusUpdateRequestDto.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/dto/EventRequestStatusUpdateResultDto.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/dto/EventRequestStatusUpdateResultDto.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/dto/EventRequestStatusUpdateResultDto.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/dto/EventRequestStatusUpdateResultDto.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/dto/EventShortDto.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/dto/EventShortDto.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/dto/EventShortDto.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/dto/EventShortDto.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/dto/NewCategoryDto.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/dto/NewCategoryDto.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/dto/NewCategoryDto.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/dto/NewCategoryDto.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/dto/NewCommentDto.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/dto/NewCommentDto.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/dto/NewCommentDto.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/dto/NewCommentDto.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/dto/NewCompilationDto.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/dto/NewCompilationDto.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/dto/NewCompilationDto.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/dto/NewCompilationDto.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/dto/NewEventDto.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/dto/NewEventDto.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/dto/NewEventDto.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/dto/NewEventDto.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/dto/NewUserRequestDto.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/dto/NewUserRequestDto.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/dto/NewUserRequestDto.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/dto/NewUserRequestDto.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/dto/ParticipationRequestDto.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/dto/ParticipationRequestDto.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/dto/ParticipationRequestDto.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/dto/ParticipationRequestDto.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/dto/UpdateCommentDto.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/dto/UpdateCommentDto.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/dto/UpdateCommentDto.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/dto/UpdateCommentDto.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/dto/UpdateCompilationRequestDto.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/dto/UpdateCompilationRequestDto.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/dto/UpdateCompilationRequestDto.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/dto/UpdateCompilationRequestDto.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/dto/UpdateEventAdminRequestDto.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/dto/UpdateEventAdminRequestDto.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/dto/UpdateEventAdminRequestDto.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/dto/UpdateEventAdminRequestDto.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/dto/UpdateEventUserRequestDto.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/dto/UpdateEventUserRequestDto.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/dto/UpdateEventUserRequestDto.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/dto/UpdateEventUserRequestDto.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/dto/UserDto.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/dto/UserDto.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/dto/UserDto.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/dto/UserDto.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/dto/UserShortDto.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/dto/UserShortDto.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/dto/UserShortDto.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/dto/UserShortDto.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/error/BusinessRuleViolationException.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/error/BusinessRuleViolationException.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/error/BusinessRuleViolationException.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/error/BusinessRuleViolationException.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/error/EntityAlreadyExistsException.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/error/EntityAlreadyExistsException.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/error/EntityAlreadyExistsException.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/error/EntityAlreadyExistsException.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/error/EntityDeletedException.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/error/EntityDeletedException.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/error/EntityDeletedException.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/error/EntityDeletedException.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/error/EntityNotFoundException.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/error/EntityNotFoundException.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/error/EntityNotFoundException.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/error/EntityNotFoundException.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/error/GlobalExceptionHandler.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/error/GlobalExceptionHandler.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/error/GlobalExceptionHandler.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/error/GlobalExceptionHandler.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/mapper/CategoryMapper.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/mapper/CategoryMapper.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/mapper/CategoryMapper.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/mapper/CategoryMapper.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/mapper/CommentMapper.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/mapper/CommentMapper.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/mapper/CommentMapper.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/mapper/CommentMapper.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/mapper/CompilationMapper.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/mapper/CompilationMapper.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/mapper/CompilationMapper.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/mapper/CompilationMapper.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/mapper/EventMapper.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/mapper/EventMapper.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/mapper/EventMapper.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/mapper/EventMapper.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/mapper/RequestMapper.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/mapper/RequestMapper.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/mapper/RequestMapper.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/mapper/RequestMapper.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/mapper/UserMapper.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/mapper/UserMapper.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/mapper/UserMapper.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/mapper/UserMapper.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/model/Category.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/model/Category.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/model/Category.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/model/Category.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/model/Comment.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/model/Comment.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/model/Comment.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/model/Comment.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/model/Compilation.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/model/Compilation.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/model/Compilation.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/model/Compilation.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/model/Event.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/model/Event.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/model/Event.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/model/Event.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/model/EventState.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/model/EventState.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/model/EventState.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/model/EventState.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/model/Location.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/model/Location.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/model/Location.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/model/Location.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/model/ParticipationRequest.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/model/ParticipationRequest.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/model/ParticipationRequest.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/model/ParticipationRequest.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/model/RequestStatus.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/model/RequestStatus.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/model/RequestStatus.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/model/RequestStatus.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/model/User.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/model/User.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/model/User.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/model/User.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/repository/CategoryRepository.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/repository/CategoryRepository.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/repository/CategoryRepository.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/repository/CategoryRepository.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/repository/CommentRepository.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/repository/CommentRepository.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/repository/CommentRepository.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/repository/CommentRepository.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/repository/CompilationRepository.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/repository/CompilationRepository.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/repository/CompilationRepository.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/repository/CompilationRepository.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/repository/EventRepository.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/repository/EventRepository.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/repository/EventRepository.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/repository/EventRepository.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/repository/RequestRepository.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/repository/RequestRepository.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/repository/RequestRepository.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/repository/RequestRepository.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/repository/UserRepository.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/repository/UserRepository.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/repository/UserRepository.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/repository/UserRepository.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/service/CategoryService.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/service/CategoryService.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/service/CategoryService.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/service/CategoryService.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/service/CategoryServiceImpl.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/service/CategoryServiceImpl.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/service/CategoryServiceImpl.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/service/CategoryServiceImpl.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/service/CommentService.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/service/CommentService.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/service/CommentService.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/service/CommentService.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/service/CommentServiceImpl.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/service/CommentServiceImpl.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/service/CommentServiceImpl.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/service/CommentServiceImpl.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/service/CompilationService.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/service/CompilationService.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/service/CompilationService.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/service/CompilationService.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/service/CompilationServiceImpl.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/service/CompilationServiceImpl.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/service/CompilationServiceImpl.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/service/CompilationServiceImpl.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/service/EventService.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/service/EventService.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/service/EventService.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/service/EventService.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/service/EventServiceImpl.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/service/EventServiceImpl.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/service/EventServiceImpl.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/service/EventServiceImpl.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/service/RequestService.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/service/RequestService.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/service/RequestService.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/service/RequestService.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/service/RequestServiceImpl.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/service/RequestServiceImpl.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/service/RequestServiceImpl.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/service/RequestServiceImpl.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/service/UserService.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/service/UserService.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/service/UserService.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/service/UserService.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/service/UserServiceImpl.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/service/UserServiceImpl.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/service/UserServiceImpl.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/service/UserServiceImpl.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/service/params/AdminCommentSearchParams.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/service/params/AdminCommentSearchParams.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/service/params/AdminCommentSearchParams.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/service/params/AdminCommentSearchParams.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/service/params/AdminEventSearchParams.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/service/params/AdminEventSearchParams.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/service/params/AdminEventSearchParams.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/service/params/AdminEventSearchParams.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/service/params/EventRequestStatusUpdateRequestParams.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/service/params/EventRequestStatusUpdateRequestParams.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/service/params/EventRequestStatusUpdateRequestParams.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/service/params/EventRequestStatusUpdateRequestParams.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/service/params/GetListUsersParameters.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/service/params/GetListUsersParameters.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/service/params/GetListUsersParameters.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/service/params/GetListUsersParameters.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/service/params/PublicCommentParameters.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/service/params/PublicCommentParameters.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/service/params/PublicCommentParameters.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/service/params/PublicCommentParameters.java diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/service/params/PublicEventSearchParams.java b/core/main-service/src/main/java/ru/practicum/explorewithme/main/service/params/PublicEventSearchParams.java similarity index 100% rename from main-service/src/main/java/ru/practicum/explorewithme/main/service/params/PublicEventSearchParams.java rename to core/main-service/src/main/java/ru/practicum/explorewithme/main/service/params/PublicEventSearchParams.java diff --git a/core/main-service/src/main/resources/application.yaml b/core/main-service/src/main/resources/application.yaml new file mode 100644 index 0000000..b7474dd --- /dev/null +++ b/core/main-service/src/main/resources/application.yaml @@ -0,0 +1,25 @@ +spring: + application: + name: main-service + profiles: + active: postgres + config: + import: "configserver:" + cloud: + config: + discovery: + enabled: true + serviceId: config-server + fail-fast: true + retry: + max-attempts: 10 + initial-interval: 1000 + useRandomPolicy: true + +eureka: + client: + serviceUrl: + defaultZone: ${EUREKA_URI:http://localhost:8761/eureka/} + instance: + instance-id: "${spring.application.name}:${random.value}" + leaseRenewalIntervalInSeconds: 10 \ No newline at end of file diff --git a/main-service/src/main/resources/schema.sql b/core/main-service/src/main/resources/schema.sql similarity index 100% rename from main-service/src/main/resources/schema.sql rename to core/main-service/src/main/resources/schema.sql diff --git a/main-service/src/test/java/ru/practicum/explorewithme/main/aspect/StatsHitAspectTest.java b/core/main-service/src/test/java/ru/practicum/explorewithme/main/aspect/StatsHitAspectTest.java similarity index 100% rename from main-service/src/test/java/ru/practicum/explorewithme/main/aspect/StatsHitAspectTest.java rename to core/main-service/src/test/java/ru/practicum/explorewithme/main/aspect/StatsHitAspectTest.java diff --git a/main-service/src/test/java/ru/practicum/explorewithme/main/controller/admin/AdminCategoryControllerTest.java b/core/main-service/src/test/java/ru/practicum/explorewithme/main/controller/admin/AdminCategoryControllerTest.java similarity index 100% rename from main-service/src/test/java/ru/practicum/explorewithme/main/controller/admin/AdminCategoryControllerTest.java rename to core/main-service/src/test/java/ru/practicum/explorewithme/main/controller/admin/AdminCategoryControllerTest.java diff --git a/main-service/src/test/java/ru/practicum/explorewithme/main/controller/admin/AdminCommentControllerTest.java b/core/main-service/src/test/java/ru/practicum/explorewithme/main/controller/admin/AdminCommentControllerTest.java similarity index 100% rename from main-service/src/test/java/ru/practicum/explorewithme/main/controller/admin/AdminCommentControllerTest.java rename to core/main-service/src/test/java/ru/practicum/explorewithme/main/controller/admin/AdminCommentControllerTest.java diff --git a/main-service/src/test/java/ru/practicum/explorewithme/main/controller/admin/AdminEventControllerTest.java b/core/main-service/src/test/java/ru/practicum/explorewithme/main/controller/admin/AdminEventControllerTest.java similarity index 100% rename from main-service/src/test/java/ru/practicum/explorewithme/main/controller/admin/AdminEventControllerTest.java rename to core/main-service/src/test/java/ru/practicum/explorewithme/main/controller/admin/AdminEventControllerTest.java diff --git a/main-service/src/test/java/ru/practicum/explorewithme/main/controller/admin/AdminUserControllerTest.java b/core/main-service/src/test/java/ru/practicum/explorewithme/main/controller/admin/AdminUserControllerTest.java similarity index 100% rename from main-service/src/test/java/ru/practicum/explorewithme/main/controller/admin/AdminUserControllerTest.java rename to core/main-service/src/test/java/ru/practicum/explorewithme/main/controller/admin/AdminUserControllerTest.java diff --git a/main-service/src/test/java/ru/practicum/explorewithme/main/controller/priv/PrivateCommentControllerTest.java b/core/main-service/src/test/java/ru/practicum/explorewithme/main/controller/priv/PrivateCommentControllerTest.java similarity index 100% rename from main-service/src/test/java/ru/practicum/explorewithme/main/controller/priv/PrivateCommentControllerTest.java rename to core/main-service/src/test/java/ru/practicum/explorewithme/main/controller/priv/PrivateCommentControllerTest.java diff --git a/main-service/src/test/java/ru/practicum/explorewithme/main/controller/priv/PrivateEventControllerTest.java b/core/main-service/src/test/java/ru/practicum/explorewithme/main/controller/priv/PrivateEventControllerTest.java similarity index 100% rename from main-service/src/test/java/ru/practicum/explorewithme/main/controller/priv/PrivateEventControllerTest.java rename to core/main-service/src/test/java/ru/practicum/explorewithme/main/controller/priv/PrivateEventControllerTest.java diff --git a/main-service/src/test/java/ru/practicum/explorewithme/main/controller/pub/PublicCategoryControllerTest.java b/core/main-service/src/test/java/ru/practicum/explorewithme/main/controller/pub/PublicCategoryControllerTest.java similarity index 100% rename from main-service/src/test/java/ru/practicum/explorewithme/main/controller/pub/PublicCategoryControllerTest.java rename to core/main-service/src/test/java/ru/practicum/explorewithme/main/controller/pub/PublicCategoryControllerTest.java diff --git a/main-service/src/test/java/ru/practicum/explorewithme/main/controller/pub/PublicCommentControllerTest.java b/core/main-service/src/test/java/ru/practicum/explorewithme/main/controller/pub/PublicCommentControllerTest.java similarity index 100% rename from main-service/src/test/java/ru/practicum/explorewithme/main/controller/pub/PublicCommentControllerTest.java rename to core/main-service/src/test/java/ru/practicum/explorewithme/main/controller/pub/PublicCommentControllerTest.java diff --git a/main-service/src/test/java/ru/practicum/explorewithme/main/controller/pub/PublicEventControllerTest.java b/core/main-service/src/test/java/ru/practicum/explorewithme/main/controller/pub/PublicEventControllerTest.java similarity index 100% rename from main-service/src/test/java/ru/practicum/explorewithme/main/controller/pub/PublicEventControllerTest.java rename to core/main-service/src/test/java/ru/practicum/explorewithme/main/controller/pub/PublicEventControllerTest.java diff --git a/main-service/src/test/java/ru/practicum/explorewithme/main/mapper/CategoryMapperTest.java b/core/main-service/src/test/java/ru/practicum/explorewithme/main/mapper/CategoryMapperTest.java similarity index 100% rename from main-service/src/test/java/ru/practicum/explorewithme/main/mapper/CategoryMapperTest.java rename to core/main-service/src/test/java/ru/practicum/explorewithme/main/mapper/CategoryMapperTest.java diff --git a/main-service/src/test/java/ru/practicum/explorewithme/main/mapper/CommentMapperTest.java b/core/main-service/src/test/java/ru/practicum/explorewithme/main/mapper/CommentMapperTest.java similarity index 100% rename from main-service/src/test/java/ru/practicum/explorewithme/main/mapper/CommentMapperTest.java rename to core/main-service/src/test/java/ru/practicum/explorewithme/main/mapper/CommentMapperTest.java diff --git a/main-service/src/test/java/ru/practicum/explorewithme/main/mapper/EventMapperTest.java b/core/main-service/src/test/java/ru/practicum/explorewithme/main/mapper/EventMapperTest.java similarity index 100% rename from main-service/src/test/java/ru/practicum/explorewithme/main/mapper/EventMapperTest.java rename to core/main-service/src/test/java/ru/practicum/explorewithme/main/mapper/EventMapperTest.java diff --git a/main-service/src/test/java/ru/practicum/explorewithme/main/mapper/UserMapperTest.java b/core/main-service/src/test/java/ru/practicum/explorewithme/main/mapper/UserMapperTest.java similarity index 100% rename from main-service/src/test/java/ru/practicum/explorewithme/main/mapper/UserMapperTest.java rename to core/main-service/src/test/java/ru/practicum/explorewithme/main/mapper/UserMapperTest.java diff --git a/main-service/src/test/java/ru/practicum/explorewithme/main/repository/EventRepositoryTest.java b/core/main-service/src/test/java/ru/practicum/explorewithme/main/repository/EventRepositoryTest.java similarity index 100% rename from main-service/src/test/java/ru/practicum/explorewithme/main/repository/EventRepositoryTest.java rename to core/main-service/src/test/java/ru/practicum/explorewithme/main/repository/EventRepositoryTest.java diff --git a/main-service/src/test/java/ru/practicum/explorewithme/main/service/CategoryServiceIntegrationTest.java b/core/main-service/src/test/java/ru/practicum/explorewithme/main/service/CategoryServiceIntegrationTest.java similarity index 100% rename from main-service/src/test/java/ru/practicum/explorewithme/main/service/CategoryServiceIntegrationTest.java rename to core/main-service/src/test/java/ru/practicum/explorewithme/main/service/CategoryServiceIntegrationTest.java diff --git a/main-service/src/test/java/ru/practicum/explorewithme/main/service/CommentServiceImplTest.java b/core/main-service/src/test/java/ru/practicum/explorewithme/main/service/CommentServiceImplTest.java similarity index 100% rename from main-service/src/test/java/ru/practicum/explorewithme/main/service/CommentServiceImplTest.java rename to core/main-service/src/test/java/ru/practicum/explorewithme/main/service/CommentServiceImplTest.java diff --git a/main-service/src/test/java/ru/practicum/explorewithme/main/service/CommentServiceIntegrationTest.java b/core/main-service/src/test/java/ru/practicum/explorewithme/main/service/CommentServiceIntegrationTest.java similarity index 100% rename from main-service/src/test/java/ru/practicum/explorewithme/main/service/CommentServiceIntegrationTest.java rename to core/main-service/src/test/java/ru/practicum/explorewithme/main/service/CommentServiceIntegrationTest.java diff --git a/main-service/src/test/java/ru/practicum/explorewithme/main/service/EventServiceImplTest.java b/core/main-service/src/test/java/ru/practicum/explorewithme/main/service/EventServiceImplTest.java similarity index 100% rename from main-service/src/test/java/ru/practicum/explorewithme/main/service/EventServiceImplTest.java rename to core/main-service/src/test/java/ru/practicum/explorewithme/main/service/EventServiceImplTest.java diff --git a/main-service/src/test/java/ru/practicum/explorewithme/main/service/EventServiceIntegrationTest.java b/core/main-service/src/test/java/ru/practicum/explorewithme/main/service/EventServiceIntegrationTest.java similarity index 100% rename from main-service/src/test/java/ru/practicum/explorewithme/main/service/EventServiceIntegrationTest.java rename to core/main-service/src/test/java/ru/practicum/explorewithme/main/service/EventServiceIntegrationTest.java diff --git a/main-service/src/test/java/ru/practicum/explorewithme/main/service/UserServiceIntegrationTest.java b/core/main-service/src/test/java/ru/practicum/explorewithme/main/service/UserServiceIntegrationTest.java similarity index 100% rename from main-service/src/test/java/ru/practicum/explorewithme/main/service/UserServiceIntegrationTest.java rename to core/main-service/src/test/java/ru/practicum/explorewithme/main/service/UserServiceIntegrationTest.java diff --git a/main-service/src/main/resources/application-mapper_test.yaml b/core/main-service/src/test/resources/application-mapper_test.yaml similarity index 100% rename from main-service/src/main/resources/application-mapper_test.yaml rename to core/main-service/src/test/resources/application-mapper_test.yaml diff --git a/main-service/src/main/resources/application-test.yaml b/core/main-service/src/test/resources/application-test.yaml similarity index 100% rename from main-service/src/main/resources/application-test.yaml rename to core/main-service/src/test/resources/application-test.yaml diff --git a/core/main-service/src/test/resources/application.yaml b/core/main-service/src/test/resources/application.yaml new file mode 100644 index 0000000..18b8a7c --- /dev/null +++ b/core/main-service/src/test/resources/application.yaml @@ -0,0 +1,15 @@ +spring: + cloud: + config: + enabled: false + discovery: + enabled: false + sql: + init: + mode: always + properties: + hibernate: + dialect: org.hibernate.dialect.PostgreSQLDialect +eureka: + client: + enabled: false \ No newline at end of file diff --git a/core/pom.xml b/core/pom.xml new file mode 100644 index 0000000..7d7ae9c --- /dev/null +++ b/core/pom.xml @@ -0,0 +1,27 @@ + + + 4.0.0 + + ru.practicum + explore-with-me + 0.0.1-SNAPSHOT + + + core + pom + + + 21 + 21 + UTF-8 + + + + main-service + stats-service + ewm-common + + + \ No newline at end of file diff --git a/stats-service/pom.xml b/core/stats-service/pom.xml similarity index 92% rename from stats-service/pom.xml rename to core/stats-service/pom.xml index d0e2a8a..eb35629 100644 --- a/stats-service/pom.xml +++ b/core/stats-service/pom.xml @@ -5,7 +5,7 @@ 4.0.0 ru.practicum - explore-with-me + core 0.0.1-SNAPSHOT diff --git a/stats-service/stats-client/pom.xml b/core/stats-service/stats-client/pom.xml similarity index 68% rename from stats-service/stats-client/pom.xml rename to core/stats-service/stats-client/pom.xml index aeda0c2..7b67e49 100644 --- a/stats-service/stats-client/pom.xml +++ b/core/stats-service/stats-client/pom.xml @@ -38,6 +38,25 @@ ewm-common ${project.version} + + org.springframework.cloud + spring-cloud-openfeign-core + + + com.squareup.okhttp3 + mockwebserver + test + + + org.springframework.cloud + spring-cloud-starter-contract-stub-runner + test + + + org.springframework.cloud + spring-cloud-commons + test + diff --git a/core/stats-service/stats-client/src/main/java/ru/practicum/explorewithme/stats/client/StatsClient.java b/core/stats-service/stats-client/src/main/java/ru/practicum/explorewithme/stats/client/StatsClient.java new file mode 100644 index 0000000..d803bf2 --- /dev/null +++ b/core/stats-service/stats-client/src/main/java/ru/practicum/explorewithme/stats/client/StatsClient.java @@ -0,0 +1,29 @@ +package ru.practicum.explorewithme.stats.client; + +import static ru.practicum.explorewithme.common.constants.DateTimeConstants.DATE_TIME_FORMAT_PATTERN; + +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.format.annotation.DateTimeFormat; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestParam; +import ru.practicum.explorewithme.stats.dto.EndpointHitDto; +import ru.practicum.explorewithme.stats.dto.ViewStatsDto; + +import java.time.LocalDateTime; +import java.util.List; + +@FeignClient(name = "stats-server") +public interface StatsClient { + + @PostMapping("/hit") + void saveHit(@RequestBody EndpointHitDto endpointHitDto); + + @GetMapping("/stats") + List getStats( + @RequestParam @DateTimeFormat(pattern = DATE_TIME_FORMAT_PATTERN) LocalDateTime start, + @RequestParam @DateTimeFormat(pattern = DATE_TIME_FORMAT_PATTERN) LocalDateTime end, + @RequestParam(value = "uris", required = false) List uris, + @RequestParam(value = "unique", defaultValue = "false") Boolean unique); +} diff --git a/stats-service/stats-client/src/main/java/ru/practicum/explorewithme/stats/client/StatsClientImpl.java b/core/stats-service/stats-client/src/main/java/ru/practicum/explorewithme/stats/client/StatsClientImpl.java similarity index 100% rename from stats-service/stats-client/src/main/java/ru/practicum/explorewithme/stats/client/StatsClientImpl.java rename to core/stats-service/stats-client/src/main/java/ru/practicum/explorewithme/stats/client/StatsClientImpl.java diff --git a/stats-service/stats-client/src/main/resources/application-local.yaml b/core/stats-service/stats-client/src/main/resources/application-local.yaml similarity index 100% rename from stats-service/stats-client/src/main/resources/application-local.yaml rename to core/stats-service/stats-client/src/main/resources/application-local.yaml diff --git a/stats-service/stats-client/src/main/resources/application.yaml b/core/stats-service/stats-client/src/main/resources/application.yaml similarity index 100% rename from stats-service/stats-client/src/main/resources/application.yaml rename to core/stats-service/stats-client/src/main/resources/application.yaml diff --git a/stats-service/stats-dto/pom.xml b/core/stats-service/stats-dto/pom.xml similarity index 100% rename from stats-service/stats-dto/pom.xml rename to core/stats-service/stats-dto/pom.xml diff --git a/stats-service/stats-dto/src/main/java/ru/practicum/explorewithme/stats/dto/EndpointHitDto.java b/core/stats-service/stats-dto/src/main/java/ru/practicum/explorewithme/stats/dto/EndpointHitDto.java similarity index 100% rename from stats-service/stats-dto/src/main/java/ru/practicum/explorewithme/stats/dto/EndpointHitDto.java rename to core/stats-service/stats-dto/src/main/java/ru/practicum/explorewithme/stats/dto/EndpointHitDto.java diff --git a/stats-service/stats-dto/src/main/java/ru/practicum/explorewithme/stats/dto/ViewStatsDto.java b/core/stats-service/stats-dto/src/main/java/ru/practicum/explorewithme/stats/dto/ViewStatsDto.java similarity index 100% rename from stats-service/stats-dto/src/main/java/ru/practicum/explorewithme/stats/dto/ViewStatsDto.java rename to core/stats-service/stats-dto/src/main/java/ru/practicum/explorewithme/stats/dto/ViewStatsDto.java diff --git a/stats-service/stats-dto/src/test/java/ru/practicum/explorewithme/stats/dto/EndpointHitDtoTest.java b/core/stats-service/stats-dto/src/test/java/ru/practicum/explorewithme/stats/dto/EndpointHitDtoTest.java similarity index 100% rename from stats-service/stats-dto/src/test/java/ru/practicum/explorewithme/stats/dto/EndpointHitDtoTest.java rename to core/stats-service/stats-dto/src/test/java/ru/practicum/explorewithme/stats/dto/EndpointHitDtoTest.java diff --git a/stats-service/stats-dto/src/test/java/ru/practicum/explorewithme/stats/dto/ViewStatsDtoTest.java b/core/stats-service/stats-dto/src/test/java/ru/practicum/explorewithme/stats/dto/ViewStatsDtoTest.java similarity index 100% rename from stats-service/stats-dto/src/test/java/ru/practicum/explorewithme/stats/dto/ViewStatsDtoTest.java rename to core/stats-service/stats-dto/src/test/java/ru/practicum/explorewithme/stats/dto/ViewStatsDtoTest.java diff --git a/stats-service/stats-server/Dockerfile b/core/stats-service/stats-server/Dockerfile similarity index 100% rename from stats-service/stats-server/Dockerfile rename to core/stats-service/stats-server/Dockerfile diff --git a/stats-service/stats-server/pom.xml b/core/stats-service/stats-server/pom.xml similarity index 83% rename from stats-service/stats-server/pom.xml rename to core/stats-service/stats-server/pom.xml index 278694f..3f6a3e6 100644 --- a/stats-service/stats-server/pom.xml +++ b/core/stats-service/stats-server/pom.xml @@ -11,12 +11,21 @@ stats-server + jar org.springframework.boot spring-boot-starter-web + + org.springframework.cloud + spring-cloud-starter-netflix-eureka-client + + + org.springframework.cloud + spring-cloud-starter-config + org.springframework.boot spring-boot-starter-data-jpa @@ -59,13 +68,19 @@ ru.practicum ewm-common - 0.0.1-SNAPSHOT + ${project.version} compile org.mockito mockito-inline + + ru.practicum + stats-client + ${project.version} + compile + diff --git a/stats-service/stats-server/src/main/java/ru/practicum/explorewithme/stats/server/StatsServerApplication.java b/core/stats-service/stats-server/src/main/java/ru/practicum/explorewithme/stats/server/StatsServerApplication.java similarity index 78% rename from stats-service/stats-server/src/main/java/ru/practicum/explorewithme/stats/server/StatsServerApplication.java rename to core/stats-service/stats-server/src/main/java/ru/practicum/explorewithme/stats/server/StatsServerApplication.java index 2a59295..328ea08 100644 --- a/stats-service/stats-server/src/main/java/ru/practicum/explorewithme/stats/server/StatsServerApplication.java +++ b/core/stats-service/stats-server/src/main/java/ru/practicum/explorewithme/stats/server/StatsServerApplication.java @@ -2,8 +2,10 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.client.discovery.EnableDiscoveryClient; @SpringBootApplication +@EnableDiscoveryClient public class StatsServerApplication { public static void main(String[] args) { diff --git a/stats-service/stats-server/src/main/java/ru/practicum/explorewithme/stats/server/controller/StatsController.java b/core/stats-service/stats-server/src/main/java/ru/practicum/explorewithme/stats/server/controller/StatsController.java similarity index 96% rename from stats-service/stats-server/src/main/java/ru/practicum/explorewithme/stats/server/controller/StatsController.java rename to core/stats-service/stats-server/src/main/java/ru/practicum/explorewithme/stats/server/controller/StatsController.java index 82f53cf..ed7ea30 100644 --- a/stats-service/stats-server/src/main/java/ru/practicum/explorewithme/stats/server/controller/StatsController.java +++ b/core/stats-service/stats-server/src/main/java/ru/practicum/explorewithme/stats/server/controller/StatsController.java @@ -16,6 +16,7 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestController; +import ru.practicum.explorewithme.stats.client.StatsClient; import ru.practicum.explorewithme.stats.dto.EndpointHitDto; import ru.practicum.explorewithme.stats.dto.ViewStatsDto; import ru.practicum.explorewithme.stats.server.service.StatsService; @@ -25,7 +26,7 @@ @RequiredArgsConstructor @Slf4j @SuppressWarnings("unused") -public class StatsController { +public class StatsController implements StatsClient { private final StatsService statsService; diff --git a/stats-service/stats-server/src/main/java/ru/practicum/explorewithme/stats/server/error/GlobalExceptionHandler.java b/core/stats-service/stats-server/src/main/java/ru/practicum/explorewithme/stats/server/error/GlobalExceptionHandler.java similarity index 100% rename from stats-service/stats-server/src/main/java/ru/practicum/explorewithme/stats/server/error/GlobalExceptionHandler.java rename to core/stats-service/stats-server/src/main/java/ru/practicum/explorewithme/stats/server/error/GlobalExceptionHandler.java diff --git a/stats-service/stats-server/src/main/java/ru/practicum/explorewithme/stats/server/mapper/EndpointHitMapper.java b/core/stats-service/stats-server/src/main/java/ru/practicum/explorewithme/stats/server/mapper/EndpointHitMapper.java similarity index 100% rename from stats-service/stats-server/src/main/java/ru/practicum/explorewithme/stats/server/mapper/EndpointHitMapper.java rename to core/stats-service/stats-server/src/main/java/ru/practicum/explorewithme/stats/server/mapper/EndpointHitMapper.java diff --git a/stats-service/stats-server/src/main/java/ru/practicum/explorewithme/stats/server/mapper/EndpointHitMapperImpl.java b/core/stats-service/stats-server/src/main/java/ru/practicum/explorewithme/stats/server/mapper/EndpointHitMapperImpl.java similarity index 100% rename from stats-service/stats-server/src/main/java/ru/practicum/explorewithme/stats/server/mapper/EndpointHitMapperImpl.java rename to core/stats-service/stats-server/src/main/java/ru/practicum/explorewithme/stats/server/mapper/EndpointHitMapperImpl.java diff --git a/stats-service/stats-server/src/main/java/ru/practicum/explorewithme/stats/server/model/EndpointHit.java b/core/stats-service/stats-server/src/main/java/ru/practicum/explorewithme/stats/server/model/EndpointHit.java similarity index 100% rename from stats-service/stats-server/src/main/java/ru/practicum/explorewithme/stats/server/model/EndpointHit.java rename to core/stats-service/stats-server/src/main/java/ru/practicum/explorewithme/stats/server/model/EndpointHit.java diff --git a/stats-service/stats-server/src/main/java/ru/practicum/explorewithme/stats/server/repository/StatsRepository.java b/core/stats-service/stats-server/src/main/java/ru/practicum/explorewithme/stats/server/repository/StatsRepository.java similarity index 100% rename from stats-service/stats-server/src/main/java/ru/practicum/explorewithme/stats/server/repository/StatsRepository.java rename to core/stats-service/stats-server/src/main/java/ru/practicum/explorewithme/stats/server/repository/StatsRepository.java diff --git a/stats-service/stats-server/src/main/java/ru/practicum/explorewithme/stats/server/service/StatsService.java b/core/stats-service/stats-server/src/main/java/ru/practicum/explorewithme/stats/server/service/StatsService.java similarity index 100% rename from stats-service/stats-server/src/main/java/ru/practicum/explorewithme/stats/server/service/StatsService.java rename to core/stats-service/stats-server/src/main/java/ru/practicum/explorewithme/stats/server/service/StatsService.java diff --git a/stats-service/stats-server/src/main/java/ru/practicum/explorewithme/stats/server/service/StatsServiceImpl.java b/core/stats-service/stats-server/src/main/java/ru/practicum/explorewithme/stats/server/service/StatsServiceImpl.java similarity index 100% rename from stats-service/stats-server/src/main/java/ru/practicum/explorewithme/stats/server/service/StatsServiceImpl.java rename to core/stats-service/stats-server/src/main/java/ru/practicum/explorewithme/stats/server/service/StatsServiceImpl.java diff --git a/core/stats-service/stats-server/src/main/resources/application.yaml b/core/stats-service/stats-server/src/main/resources/application.yaml new file mode 100644 index 0000000..cf15002 --- /dev/null +++ b/core/stats-service/stats-server/src/main/resources/application.yaml @@ -0,0 +1,25 @@ +spring: + application: + name: stats-server + profiles: + active: postgres + config: + import: "configserver:" + cloud: + config: + discovery: + enabled: true + serviceId: config-server + fail-fast: true + retry: + max-attempts: 10 + initial-interval: 1000 + useRandomPolicy: true + +eureka: + client: + serviceUrl: + defaultZone: ${EUREKA_URI:http://localhost:8761/eureka/} + instance: + instance-id: "${spring.application.name}:${random.value}" + leaseRenewalIntervalInSeconds: 10 diff --git a/stats-service/stats-server/src/main/resources/schema.sql b/core/stats-service/stats-server/src/main/resources/schema.sql similarity index 100% rename from stats-service/stats-server/src/main/resources/schema.sql rename to core/stats-service/stats-server/src/main/resources/schema.sql diff --git a/stats-service/stats-server/src/test/java/ru/practicum/explorewithme/stats/server/controller/StatsControllerTest.java b/core/stats-service/stats-server/src/test/java/ru/practicum/explorewithme/stats/server/controller/StatsControllerTest.java similarity index 100% rename from stats-service/stats-server/src/test/java/ru/practicum/explorewithme/stats/server/controller/StatsControllerTest.java rename to core/stats-service/stats-server/src/test/java/ru/practicum/explorewithme/stats/server/controller/StatsControllerTest.java diff --git a/stats-service/stats-server/src/test/java/ru/practicum/explorewithme/stats/server/controller/StatsServerIntegrationTest.java b/core/stats-service/stats-server/src/test/java/ru/practicum/explorewithme/stats/server/controller/StatsServerIntegrationTest.java similarity index 100% rename from stats-service/stats-server/src/test/java/ru/practicum/explorewithme/stats/server/controller/StatsServerIntegrationTest.java rename to core/stats-service/stats-server/src/test/java/ru/practicum/explorewithme/stats/server/controller/StatsServerIntegrationTest.java diff --git a/stats-service/stats-server/src/test/java/ru/practicum/explorewithme/stats/server/repository/StatsRepositoryTest.java b/core/stats-service/stats-server/src/test/java/ru/practicum/explorewithme/stats/server/repository/StatsRepositoryTest.java similarity index 100% rename from stats-service/stats-server/src/test/java/ru/practicum/explorewithme/stats/server/repository/StatsRepositoryTest.java rename to core/stats-service/stats-server/src/test/java/ru/practicum/explorewithme/stats/server/repository/StatsRepositoryTest.java diff --git a/stats-service/stats-server/src/test/java/ru/practicum/explorewithme/stats/server/service/StatsServiceImplTest.java b/core/stats-service/stats-server/src/test/java/ru/practicum/explorewithme/stats/server/service/StatsServiceImplTest.java similarity index 100% rename from stats-service/stats-server/src/test/java/ru/practicum/explorewithme/stats/server/service/StatsServiceImplTest.java rename to core/stats-service/stats-server/src/test/java/ru/practicum/explorewithme/stats/server/service/StatsServiceImplTest.java diff --git a/core/stats-service/stats-server/src/test/resources/application.yaml b/core/stats-service/stats-server/src/test/resources/application.yaml new file mode 100644 index 0000000..689e431 --- /dev/null +++ b/core/stats-service/stats-server/src/test/resources/application.yaml @@ -0,0 +1,9 @@ +spring: + cloud: + config: + enabled: false + discovery: + enabled: false +eureka: + client: + enabled: false \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml deleted file mode 100644 index be96142..0000000 --- a/docker-compose.yml +++ /dev/null @@ -1,14 +0,0 @@ -services: - stats-server: - ports: - - "9090:9090" - - stats-db: - image: postgres:16.1 - - ewm-service: - ports: - - "8080:8080" - - ewm-db: - image: postgres:16.1 diff --git a/infra/config-server/Dockerfile b/infra/config-server/Dockerfile new file mode 100644 index 0000000..0ff1817 --- /dev/null +++ b/infra/config-server/Dockerfile @@ -0,0 +1,5 @@ +FROM eclipse-temurin:21-jre-jammy +VOLUME /tmp +ARG JAR_FILE=target/*.jar +COPY ${JAR_FILE} app.jar +ENTRYPOINT ["sh", "-c", "java ${JAVA_OPTS} -jar /app.jar"] \ No newline at end of file diff --git a/infra/config-server/pom.xml b/infra/config-server/pom.xml new file mode 100644 index 0000000..41078ba --- /dev/null +++ b/infra/config-server/pom.xml @@ -0,0 +1,46 @@ + + + 4.0.0 + + ru.practicum + infra + 0.0.1-SNAPSHOT + ../pom.xml + + + config-server + jar + + + 21 + 21 + UTF-8 + + + + + org.springframework.cloud + spring-cloud-config-server + + + org.springframework.boot + spring-boot-starter-actuator + + + org.springframework.cloud + spring-cloud-starter-netflix-eureka-client + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + \ No newline at end of file diff --git a/infra/config-server/src/main/java/ru/practicum/explorewithme/infra/configserver/ConfigServerApplication.java b/infra/config-server/src/main/java/ru/practicum/explorewithme/infra/configserver/ConfigServerApplication.java new file mode 100644 index 0000000..950b013 --- /dev/null +++ b/infra/config-server/src/main/java/ru/practicum/explorewithme/infra/configserver/ConfigServerApplication.java @@ -0,0 +1,17 @@ +package ru.practicum.explorewithme.infra.configserver; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.client.discovery.EnableDiscoveryClient; +import org.springframework.cloud.config.server.EnableConfigServer; + +@EnableConfigServer +@SpringBootApplication +@EnableDiscoveryClient +public class ConfigServerApplication { + + public static void main(String[] args) { + SpringApplication.run(ConfigServerApplication.class, args); + } + +} \ No newline at end of file diff --git a/infra/config-server/src/main/resources/application.yaml b/infra/config-server/src/main/resources/application.yaml new file mode 100644 index 0000000..2fe93a1 --- /dev/null +++ b/infra/config-server/src/main/resources/application.yaml @@ -0,0 +1,34 @@ +server: + port: ${PORT:0} + +spring: + application: + name: config-server + profiles: + active: native + cloud: + config: + server: + native: + searchLocations: + - classpath:config + - classpath:config/{application} + +eureka: + client: + serviceUrl: + defaultZone: ${EUREKA_URI:http://localhost:8761/eureka/} + + instance: + prefer-ip-address: true + +management: + endpoint: + health: + show-details: always + probes: + enabled: true + endpoints: + web: + exposure: + include: health, info \ No newline at end of file diff --git a/stats-service/stats-server/src/main/resources/application.yaml b/infra/config-server/src/main/resources/config/application-postgres.yaml similarity index 70% rename from stats-service/stats-server/src/main/resources/application.yaml rename to infra/config-server/src/main/resources/config/application-postgres.yaml index c599416..51d04d2 100644 --- a/stats-service/stats-server/src/main/resources/application.yaml +++ b/infra/config-server/src/main/resources/config/application-postgres.yaml @@ -1,9 +1,4 @@ -server: - port: 9090 - spring: - application: - name: stats-server jpa: hibernate: ddl-auto: validate @@ -14,4 +9,7 @@ spring: driver-class-name: org.postgresql.Driver sql: init: - mode: always \ No newline at end of file + mode: always + properties: + hibernate: + dialect: org.hibernate.dialect.PostgreSQLDialect \ No newline at end of file diff --git a/infra/config-server/src/main/resources/config/application.yaml b/infra/config-server/src/main/resources/config/application.yaml new file mode 100644 index 0000000..0dec9e2 --- /dev/null +++ b/infra/config-server/src/main/resources/config/application.yaml @@ -0,0 +1,25 @@ +management: + endpoint: + health: + probes: + enabled: true + health: + livenessstate: + enabled: true + readinessstate: + enabled: true + endpoints: + web: + exposure: + include: health,info,prometheus + +eureka: + instance: + health-check-url-path: /actuator/health/readiness + lease-renewal-interval-in-seconds: 5 + lease-expiration-duration-in-seconds: 15 + + client: + healthcheck: + enabled: true + registry-fetch-interval-seconds: 5 \ No newline at end of file diff --git a/infra/config-server/src/main/resources/config/gateway-server/application.yaml b/infra/config-server/src/main/resources/config/gateway-server/application.yaml new file mode 100644 index 0000000..b7045cc --- /dev/null +++ b/infra/config-server/src/main/resources/config/gateway-server/application.yaml @@ -0,0 +1,101 @@ +server: + port: ${PORT:8080} + +spring: + cloud: + gateway: + server: + webflux: + discovery: + locator: + enabled: false + default-filters: + - name: Retry + args: + retries: 3 + statuses: + - SERVICE_UNAVAILABLE # 503 + - BAD_GATEWAY # 502 + - GATEWAY_TIMEOUT # 504 + methods: + - GET + backoff: + firstBackoff: 25ms + maxBackoff: 300ms + factor: 2 + basedOnPreviousValue: false + + - name: CircuitBreaker + args: + name: default-breaker + fallbackUri: forward:/service-fallback + routes: + - id: main-service-admin-route + uri: lb://main-service + predicates: + - Path=/admin/** + + - id: main-service-users-route + uri: lb://main-service + predicates: + - Path=/users/** + + - id: main-service-categories-route + uri: lb://main-service + predicates: + - Path=/categories/** + + - id: main-service-events-route + uri: lb://main-service + predicates: + - Path=/events/** + + - id: main-service-compilations-route + uri: lb://main-service + predicates: + - Path=/compilations/** + loadbalancer: + enabled: true + retry: + enabled: false # no retry cascades + cache: + enabled: true + ttl: 30s + +resilience4j: + circuitbreaker: + configs: + default: + slidingWindowType: COUNT_BASED + slidingWindowSize: 20 + failureRateThreshold: 50 + waitDurationInOpenState: 10s + permittedNumberOfCallsInHalfOpenState: 3 + slowCallRateThreshold: 50 + slowCallDurationThreshold: 2s + + instances: + default-breaker: + baseConfig: default + + timelimiter: + configs: + default: + timeoutDuration: 4s + +management: + endpoints: + web: + exposure: + include: health,info,gateway + endpoint: + health: + probes: + enabled: true + gateway: + enabled: true + health: + livenessstate: + enabled: true + readinessstate: + enabled: true \ No newline at end of file diff --git a/main-service/src/main/resources/application-local.yaml b/infra/config-server/src/main/resources/config/main-service/application-local.yaml similarity index 91% rename from main-service/src/main/resources/application-local.yaml rename to infra/config-server/src/main/resources/config/main-service/application-local.yaml index 43b09bd..951b000 100644 --- a/main-service/src/main/resources/application-local.yaml +++ b/infra/config-server/src/main/resources/config/main-service/application-local.yaml @@ -1,3 +1,6 @@ +server: + port: 8081 + stats-server: url: http://localhost:9090 diff --git a/infra/config-server/src/main/resources/config/main-service/application.yaml b/infra/config-server/src/main/resources/config/main-service/application.yaml new file mode 100644 index 0000000..46eac2f --- /dev/null +++ b/infra/config-server/src/main/resources/config/main-service/application.yaml @@ -0,0 +1,2 @@ +server: + port: 0 \ No newline at end of file diff --git a/stats-service/stats-server/src/main/resources/application-local.yaml b/infra/config-server/src/main/resources/config/stats-server/application-local.yaml similarity index 94% rename from stats-service/stats-server/src/main/resources/application-local.yaml rename to infra/config-server/src/main/resources/config/stats-server/application-local.yaml index 6b0b01a..77331d7 100644 --- a/stats-service/stats-server/src/main/resources/application-local.yaml +++ b/infra/config-server/src/main/resources/config/stats-server/application-local.yaml @@ -1,3 +1,6 @@ +server: + port: 9090 + spring: datasource: url: jdbc:postgresql://localhost:6543/ewm_stats_db diff --git a/infra/config-server/src/main/resources/config/stats-server/application.yaml b/infra/config-server/src/main/resources/config/stats-server/application.yaml new file mode 100644 index 0000000..46eac2f --- /dev/null +++ b/infra/config-server/src/main/resources/config/stats-server/application.yaml @@ -0,0 +1,2 @@ +server: + port: 0 \ No newline at end of file diff --git a/infra/discovery-server/Dockerfile b/infra/discovery-server/Dockerfile new file mode 100644 index 0000000..0ff1817 --- /dev/null +++ b/infra/discovery-server/Dockerfile @@ -0,0 +1,5 @@ +FROM eclipse-temurin:21-jre-jammy +VOLUME /tmp +ARG JAR_FILE=target/*.jar +COPY ${JAR_FILE} app.jar +ENTRYPOINT ["sh", "-c", "java ${JAVA_OPTS} -jar /app.jar"] \ No newline at end of file diff --git a/infra/discovery-server/pom.xml b/infra/discovery-server/pom.xml new file mode 100644 index 0000000..700311c --- /dev/null +++ b/infra/discovery-server/pom.xml @@ -0,0 +1,42 @@ + + + 4.0.0 + + ru.practicum + infra + 0.0.1-SNAPSHOT + ../pom.xml + + + discovery-server + + + 21 + 21 + UTF-8 + + + + + org.springframework.cloud + spring-cloud-starter-netflix-eureka-server + + + + org.springframework.boot + spring-boot-starter-actuator + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + \ No newline at end of file diff --git a/infra/discovery-server/src/main/java/ru/practicum/explorewithme/infra/discovery/EurekaServerApp.java b/infra/discovery-server/src/main/java/ru/practicum/explorewithme/infra/discovery/EurekaServerApp.java new file mode 100644 index 0000000..8072d18 --- /dev/null +++ b/infra/discovery-server/src/main/java/ru/practicum/explorewithme/infra/discovery/EurekaServerApp.java @@ -0,0 +1,15 @@ +package ru.practicum.explorewithme.infra.discovery; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; + +@SpringBootApplication +@EnableEurekaServer +public class EurekaServerApp { + + public static void main(String[] args) { + SpringApplication.run(EurekaServerApp.class, args); + } + +} diff --git a/infra/discovery-server/src/main/resources/application.yaml b/infra/discovery-server/src/main/resources/application.yaml new file mode 100644 index 0000000..5dbd41c --- /dev/null +++ b/infra/discovery-server/src/main/resources/application.yaml @@ -0,0 +1,15 @@ +server: + port: 8761 + +eureka: + instance: + hostname: ${EUREKA_HOSTNAME:localhost} + client: + registerWithEureka: false + fetchRegistry: false + serviceUrl: + defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ + +spring: + application: + name: discovery-server \ No newline at end of file diff --git a/infra/gateway-server/Dockerfile b/infra/gateway-server/Dockerfile new file mode 100644 index 0000000..0ff1817 --- /dev/null +++ b/infra/gateway-server/Dockerfile @@ -0,0 +1,5 @@ +FROM eclipse-temurin:21-jre-jammy +VOLUME /tmp +ARG JAR_FILE=target/*.jar +COPY ${JAR_FILE} app.jar +ENTRYPOINT ["sh", "-c", "java ${JAVA_OPTS} -jar /app.jar"] \ No newline at end of file diff --git a/infra/gateway-server/pom.xml b/infra/gateway-server/pom.xml new file mode 100644 index 0000000..dc78b14 --- /dev/null +++ b/infra/gateway-server/pom.xml @@ -0,0 +1,69 @@ + + + 4.0.0 + + ru.practicum + infra + 0.0.1-SNAPSHOT + ../pom.xml + + + gateway-server + jar + + + 21 + 21 + UTF-8 + + + + + org.springframework.cloud + spring-cloud-starter-gateway-server-webflux + + + + org.springframework.boot + spring-boot-starter-webflux + + + + org.springframework.cloud + spring-cloud-starter-netflix-eureka-client + + + + org.springframework.cloud + spring-cloud-starter-config + + + + org.springframework.cloud + spring-cloud-starter-circuitbreaker-reactor-resilience4j + + + + org.springframework.boot + spring-boot-starter-actuator + + + + org.projectlombok + lombok + provided + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + \ No newline at end of file diff --git a/infra/gateway-server/src/main/java/ru/practicum/explorewithme/infra/gateway/GatewayApplication.java b/infra/gateway-server/src/main/java/ru/practicum/explorewithme/infra/gateway/GatewayApplication.java new file mode 100644 index 0000000..a5cb128 --- /dev/null +++ b/infra/gateway-server/src/main/java/ru/practicum/explorewithme/infra/gateway/GatewayApplication.java @@ -0,0 +1,14 @@ +package ru.practicum.explorewithme.infra.gateway; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.client.discovery.EnableDiscoveryClient; + +@SpringBootApplication +@EnableDiscoveryClient +public class GatewayApplication { + + public static void main(String[] args) { + SpringApplication.run(GatewayApplication.class, args); + } +} diff --git a/infra/gateway-server/src/main/java/ru/practicum/explorewithme/infra/gateway/controller/FallbackController.java b/infra/gateway-server/src/main/java/ru/practicum/explorewithme/infra/gateway/controller/FallbackController.java new file mode 100644 index 0000000..5f7bdfe --- /dev/null +++ b/infra/gateway-server/src/main/java/ru/practicum/explorewithme/infra/gateway/controller/FallbackController.java @@ -0,0 +1,19 @@ +package ru.practicum.explorewithme.infra.gateway.controller; + +import java.util.HashMap; +import java.util.Map; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import reactor.core.publisher.Mono; + +@RestController +public class FallbackController { + + @RequestMapping("/service-fallback") + public Mono> serviceFallback() { + Map response = new HashMap<>(); + response.put("status", "error"); + response.put("message", "The requested service is currently unavailable. Please try again later."); + return Mono.just(response); + } +} diff --git a/infra/gateway-server/src/main/resources/application.yaml b/infra/gateway-server/src/main/resources/application.yaml new file mode 100644 index 0000000..bcba139 --- /dev/null +++ b/infra/gateway-server/src/main/resources/application.yaml @@ -0,0 +1,23 @@ +spring: + application: + name: gateway-server + config: + import: "configserver:" + cloud: + config: + discovery: + enabled: true + serviceId: config-server + fail-fast: true + retry: + max-attempts: 10 + initial-interval: 1000 + useRandomPolicy: true + +eureka: + client: + serviceUrl: + defaultZone: ${EUREKA_URI:http://localhost:8761/eureka/} + instance: + instance-id: "${spring.application.name}:${random.value}" + leaseRenewalIntervalInSeconds: 10 diff --git a/infra/pom.xml b/infra/pom.xml new file mode 100644 index 0000000..d7b7927 --- /dev/null +++ b/infra/pom.xml @@ -0,0 +1,26 @@ + + + 4.0.0 + + ru.practicum + explore-with-me + 0.0.1-SNAPSHOT + + + infra + pom + + config-server + discovery-server + gateway-server + + + + 21 + 21 + UTF-8 + + + \ No newline at end of file diff --git a/main-service/src/main/resources/application.yaml b/main-service/src/main/resources/application.yaml deleted file mode 100644 index 3b1d899..0000000 --- a/main-service/src/main/resources/application.yaml +++ /dev/null @@ -1,20 +0,0 @@ -server: - port: 8080 - -stats-server: - url: http://stats-server:9090 - -spring: - application: - name: main-service - jpa: - hibernate: - ddl-auto: validate - datasource: - url: ${SPRING_DATASOURCE_URL} - username: ${SPRING_DATASOURCE_USERNAME} - password: ${SPRING_DATASOURCE_PASSWORD} - driver-class-name: org.postgresql.Driver - sql: - init: - mode: always \ No newline at end of file diff --git a/pom.xml b/pom.xml index 216701c..c3176a1 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ org.springframework.boot spring-boot-starter-parent - 3.4.5 + 3.5.5 @@ -20,7 +20,8 @@ UTF-8 21 - 3.4.5 + 3.5.5 + 2025.0.0 4.12.0 1.21.0 5.14.2 @@ -31,10 +32,9 @@ - stats-service - main-service - ewm-common - + infra + core + @@ -45,6 +45,13 @@ pom import + + org.springframework.cloud + spring-cloud-dependencies + ${spring-cloud.version} + pom + import + org.postgresql postgresql diff --git a/stats-service/stats-client/src/main/java/ru/practicum/explorewithme/stats/client/StatsClient.java b/stats-service/stats-client/src/main/java/ru/practicum/explorewithme/stats/client/StatsClient.java deleted file mode 100644 index 99911b0..0000000 --- a/stats-service/stats-client/src/main/java/ru/practicum/explorewithme/stats/client/StatsClient.java +++ /dev/null @@ -1,13 +0,0 @@ -package ru.practicum.explorewithme.stats.client; - -import ru.practicum.explorewithme.stats.dto.EndpointHitDto; -import ru.practicum.explorewithme.stats.dto.ViewStatsDto; - -import java.time.LocalDateTime; -import java.util.List; - -public interface StatsClient { - void saveHit(EndpointHitDto endpointHitDto); - - List getStats(LocalDateTime start, LocalDateTime end, List uris, Boolean unique); -} diff --git a/stats-service/stats-client/src/main/java/ru/practicum/explorewithme/stats/client/config/StatsClientModuleConfiguration.java b/stats-service/stats-client/src/main/java/ru/practicum/explorewithme/stats/client/config/StatsClientModuleConfiguration.java deleted file mode 100644 index 3058b14..0000000 --- a/stats-service/stats-client/src/main/java/ru/practicum/explorewithme/stats/client/config/StatsClientModuleConfiguration.java +++ /dev/null @@ -1,9 +0,0 @@ -package ru.practicum.explorewithme.stats.client.config; - -import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.Configuration; - -@Configuration -@ComponentScan("ru.practicum.explorewithme.stats.client") -public class StatsClientModuleConfiguration { -} \ No newline at end of file diff --git a/stats-service/stats-client/src/test/java/ru/practicum/explorewithme/stats/client/StatsClientTest.java b/stats-service/stats-client/src/test/java/ru/practicum/explorewithme/stats/client/StatsClientTest.java deleted file mode 100644 index 75a70f2..0000000 --- a/stats-service/stats-client/src/test/java/ru/practicum/explorewithme/stats/client/StatsClientTest.java +++ /dev/null @@ -1,445 +0,0 @@ -package ru.practicum.explorewithme.stats.client; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.springframework.test.web.client.match.MockRestRequestMatchers.content; -import static org.springframework.test.web.client.match.MockRestRequestMatchers.jsonPath; -import static org.springframework.test.web.client.match.MockRestRequestMatchers.method; -import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo; -import static org.springframework.test.web.client.response.MockRestResponseCreators.withServerError; -import static org.springframework.test.web.client.response.MockRestResponseCreators.withStatus; -import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess; - -import java.time.LocalDateTime; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; -import org.springframework.http.HttpMethod; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.test.web.client.MockRestServiceServer; -import org.springframework.web.client.RestClient; -import org.springframework.web.client.RestClientException; -import org.springframework.web.client.RestTemplate; -import ru.practicum.explorewithme.stats.dto.EndpointHitDto; -import ru.practicum.explorewithme.stats.dto.ViewStatsDto; - -@DisplayName("Тесты для StatsClientImpl") -class StatsClientTest { - - private RestTemplate restTemplate; - private MockRestServiceServer mockServer; - private StatsClientImpl statsClient; - private final String baseUrl = "http://stats-server:9090"; - - @BeforeEach - void setUp() { - restTemplate = new RestTemplate(); - mockServer = MockRestServiceServer.createServer(restTemplate); - - // Создаем RestClient на основе RestTemplate - RestClient restClient = RestClient.builder(restTemplate) - .baseUrl(baseUrl) - .build(); - - statsClient = new StatsClientImpl(restClient); - } - - @Nested - @DisplayName("Тесты метода saveHit") - class SaveHitTests { - @Test - @DisplayName("Успешное сохранение статистики") - void saveHit_successful() { - // Подготовка тестовых данных - LocalDateTime timestamp = LocalDateTime.now(); - EndpointHitDto hitDto = new EndpointHitDto( - "service", - "/test", - "192.168.0.1", - timestamp - ); - - // Настройка ожидания и ответа сервера - mockServer.expect(requestTo(baseUrl + "/hit")) - .andExpect(method(HttpMethod.POST)) - .andExpect(content().contentType(MediaType.APPLICATION_JSON)) - .andExpect(jsonPath("$.app").value("service")) - .andExpect(jsonPath("$.uri").value("/test")) - .andExpect(jsonPath("$.ip").value("192.168.0.1")) - .andRespond(withStatus(HttpStatus.CREATED)); - - // Вызов тестируемого метода - assertDoesNotThrow( - () -> statsClient.saveHit(hitDto), - "Метод saveHit должен успешно выполниться без исключений" - ); - - // Проверка выполнения всех ожиданий - mockServer.verify(); - } - - @Test - @DisplayName("Обработка ошибки сервера при сохранении") - void saveHit_throwsExceptionWhenFails() { - // Подготовка тестовых данных - EndpointHitDto hitDto = new EndpointHitDto( - "service", - "/test", - "192.168.0.1", - LocalDateTime.now() - ); - - // Настройка ожидания и ответа сервера с ошибкой 500 - mockServer.expect(requestTo(baseUrl + "/hit")) - .andExpect(method(HttpMethod.POST)) - .andRespond(withServerError()); - - // Вызов тестируемого метода и проверка исключения - Exception exception = assertThrows( - RestClientException.class, - () -> statsClient.saveHit(hitDto), - "Должно быть выброшено исключение при ошибке сервера" - ); - - assertThat(exception.getMessage()) - .as("Сообщение об ошибке должно содержать информацию о проблеме") - .contains("500"); - - // Проверка выполнения всех ожиданий - mockServer.verify(); - } - - @Test - @DisplayName("Обработка клиентской ошибки (400 Bad Request)") - void saveHit_handlesBadRequest() { - // Подготовка тестовых данных с некорректными значениями - EndpointHitDto hitDto = new EndpointHitDto( - "", // Пустое значение приведет к ошибке валидации - "/test", - "192.168.0.1", - LocalDateTime.now() - ); - - // Настройка ожидания и ответа сервера с ошибкой 400 - mockServer.expect(requestTo(baseUrl + "/hit")) - .andExpect(method(HttpMethod.POST)) - .andRespond(withStatus(HttpStatus.BAD_REQUEST) - .contentType(MediaType.APPLICATION_JSON) - .body("{\"error\":\"Validation failed\"}")); - - // Вызов тестируемого метода и проверка исключения - Exception exception = assertThrows( - RestClientException.class, - () -> statsClient.saveHit(hitDto), - "Должно быть выброшено исключение при ошибке валидации" - ); - - assertThat(exception.getMessage()) - .as("Сообщение об ошибке должно содержать информацию о коде статуса") - .contains("400"); - - // Проверка выполнения всех ожиданий - mockServer.verify(); - } - - @Test - @DisplayName("Обработка null в качестве параметра") - void saveHit_handlesNullParameter() { - // Вызов метода с null-параметром - Exception exception = assertThrows( - NullPointerException.class, - () -> statsClient.saveHit(null), - "Должно быть выброшено исключение при null-параметре" - ); - - // Проверка, что мок-сервер не получил запроса - // Это означает, что исключение произошло до обращения к серверу - mockServer.verify(); - } - } - - @Nested - @DisplayName("Тесты метода getStats") - class GetStatsTests { - @Test - @DisplayName("Успешное получение статистики") - void getStats_successful() { - // Подготовка тестовых данных с использованием LocalDateTime - LocalDateTime start = LocalDateTime.of(2023, 1, 1, 0, 0, 0); - LocalDateTime end = LocalDateTime.of(2023, 12, 31, 23, 59, 59); - List uris = Arrays.asList("/event/1", "/event/2"); - Boolean unique = true; - - String expectedResponseJson = - "[{\"app\":\"app1\",\"uri\":\"/event/1\",\"hits\":10}," + - "{\"app\":\"app1\",\"uri\":\"/event/2\",\"hits\":5}]"; - - // Форматированные строки для URL - String formattedStart = "2023-01-01%2000:00:00"; - String formattedEnd = "2023-12-31%2023:59:59"; - - // Формирование URL для запроса - String url = baseUrl + "/stats" + - "?start=" + formattedStart + - "&end=" + formattedEnd + - "&uris=/event/1" + - "&uris=/event/2" + - "&unique=" + unique; - - // Настройка ожидания и ответа сервера - mockServer.expect(requestTo(url)) - .andExpect(method(HttpMethod.GET)) - .andRespond(withSuccess(expectedResponseJson, MediaType.APPLICATION_JSON)); - - // Вызов тестируемого метода - List result = statsClient.getStats(start, end, uris, unique); - - // Проверка результата - assertThat(result) - .as("Результат должен содержать 2 элемента") - .hasSize(2); - - assertThat(result.get(0).getApp()) - .as("Первый элемент должен иметь правильное значение app") - .isEqualTo("app1"); - - assertThat(result.get(0).getUri()) - .as("Первый элемент должен иметь правильное значение uri") - .isEqualTo("/event/1"); - - assertThat(result.get(0).getHits()) - .as("Первый элемент должен иметь правильное значение hits") - .isEqualTo(10L); - - assertThat(result.get(1).getUri()) - .as("Второй элемент должен иметь правильное значение uri") - .isEqualTo("/event/2"); - - assertThat(result.get(1).getHits()) - .as("Второй элемент должен иметь правильное значение hits") - .isEqualTo(5L); - - // Проверка выполнения всех ожиданий - mockServer.verify(); - } - - @Test - @DisplayName("Получение статистики с пустым списком URI") - void getStats_withEmptyUris() { - // Подготовка тестовых данных с использованием LocalDateTime - LocalDateTime start = LocalDateTime.of(2023, 1, 1, 0, 0, 0); - LocalDateTime end = LocalDateTime.of(2023, 12, 31, 23, 59, 59); - List uris = Collections.emptyList(); - Boolean unique = false; - - String expectedResponseJson = "[{\"app\":\"app1\",\"uri\":\"all\",\"hits\":15}]"; - - // Форматированные строки для URL - String formattedStart = "2023-01-01%2000:00:00"; - String formattedEnd = "2023-12-31%2023:59:59"; - - // Формирование URL для запроса - String url = baseUrl + "/stats" + - "?start=" + formattedStart + - "&end=" + formattedEnd + - "&unique=" + unique; - - // Настройка ожидания и ответа сервера - mockServer.expect(requestTo(url)) - .andExpect(method(HttpMethod.GET)) - .andRespond(withSuccess(expectedResponseJson, MediaType.APPLICATION_JSON)); - - // Вызов тестируемого метода - List result = statsClient.getStats(start, end, uris, unique); - - // Проверка результата - assertThat(result) - .as("Результат должен содержать 1 элемент") - .hasSize(1); - - assertThat(result.get(0).getApp()) - .as("Элемент должен иметь правильное значение app") - .isEqualTo("app1"); - - assertThat(result.get(0).getUri()) - .as("Элемент должен иметь правильное значение uri") - .isEqualTo("all"); - - assertThat(result.get(0).getHits()) - .as("Элемент должен иметь правильное значение hits") - .isEqualTo(15L); - - // Проверка выполнения всех ожиданий - mockServer.verify(); - } - - @Test - @DisplayName("Получение статистики с null вместо списка URI") - void getStats_withNullUris() { - // Подготовка тестовых данных с использованием LocalDateTime - LocalDateTime start = LocalDateTime.of(2023, 1, 1, 0, 0, 0); - LocalDateTime end = LocalDateTime.of(2023, 12, 31, 23, 59, 59); - List uris = null; - Boolean unique = false; - - String expectedResponseJson = "[{\"app\":\"app1\",\"uri\":\"all\",\"hits\":15}]"; - - // Форматированные строки для URL - String formattedStart = "2023-01-01%2000:00:00"; - String formattedEnd = "2023-12-31%2023:59:59"; - - // URL без параметров uris - String url = baseUrl + "/stats" + - "?start=" + formattedStart + - "&end=" + formattedEnd + - "&unique=" + unique; - - // Настройка ожидания и ответа сервера - mockServer.expect(requestTo(url)) - .andExpect(method(HttpMethod.GET)) - .andRespond(withSuccess(expectedResponseJson, MediaType.APPLICATION_JSON)); - - // Вызов тестируемого метода - List result = statsClient.getStats(start, end, uris, unique); - - // Проверка результата - assertThat(result) - .as("Результат должен содержать 1 элемент") - .hasSize(1); - - assertThat(result.get(0).getUri()) - .as("Элемент должен иметь правильное значение uri") - .isEqualTo("all"); - - // Проверка выполнения всех ожиданий - mockServer.verify(); - } - - @Test - @DisplayName("Получение статистики с null вместо флага unique") - void getStats_withNullUniqueFlag() { - // Подготовка тестовых данных с использованием LocalDateTime - LocalDateTime start = LocalDateTime.of(2023, 1, 1, 0, 0, 0); - LocalDateTime end = LocalDateTime.of(2023, 12, 31, 23, 59, 59); - List uris = Collections.singletonList("/event/1"); - Boolean unique = null; - - String expectedResponseJson = "[{\"app\":\"app1\",\"uri\":\"/event/1\",\"hits\":10}]"; - - // Форматированные строки для URL - String formattedStart = "2023-01-01%2000:00:00"; - String formattedEnd = "2023-12-31%2023:59:59"; - - // URL с null в качестве unique - String url = baseUrl + "/stats" + - "?start=" + formattedStart + - "&end=" + formattedEnd + - "&uris=/event/1"; - - // Настройка ожидания и ответа сервера - mockServer.expect(requestTo(url)) - .andExpect(method(HttpMethod.GET)) - .andRespond(withSuccess(expectedResponseJson, MediaType.APPLICATION_JSON)); - - // Вызов тестируемого метода - List result = statsClient.getStats(start, end, uris, unique); - - // Проверка результата - assertThat(result) - .as("Результат должен содержать 1 элемент") - .hasSize(1); - - assertThat(result.get(0).getUri()) - .as("Элемент должен иметь правильное значение uri") - .isEqualTo("/event/1"); - - // Проверка выполнения всех ожиданий - mockServer.verify(); - } - - @Test - @DisplayName("Обработка ошибки сервера при получении статистики") - void getStats_throwsExceptionWhenFails() { - // Подготовка тестовых данных с использованием LocalDateTime - LocalDateTime start = LocalDateTime.of(2023, 1, 1, 0, 0, 0); - LocalDateTime end = LocalDateTime.of(2023, 12, 31, 23, 59, 59); - List uris = Arrays.asList("/event/1", "/event/2"); - Boolean unique = true; - - // Форматированные строки для URL - String formattedStart = "2023-01-01%2000:00:00"; - String formattedEnd = "2023-12-31%2023:59:59"; - - // Формирование URL для запроса - String url = baseUrl + "/stats" + - "?start=" + formattedStart + - "&end=" + formattedEnd + - "&uris=/event/1" + - "&uris=/event/2" + - "&unique=" + unique; - - // Настройка ожидания и ответа сервера с ошибкой - mockServer.expect(requestTo(url)) - .andExpect(method(HttpMethod.GET)) - .andRespond(withServerError()); - - // Вызов тестируемого метода и проверка исключения - Exception exception = assertThrows( - RestClientException.class, - () -> statsClient.getStats(start, end, uris, unique), - "Должно быть выброшено исключение при ошибке сервера" - ); - - assertThat(exception.getMessage()) - .as("Сообщение об ошибке должно содержать информацию о проблеме") - .contains("500"); - - // Проверка выполнения всех ожиданий - mockServer.verify(); - } - - @Test - @DisplayName("Получение пустого массива в ответе") - void getStats_emptyResponse() { - // Подготовка тестовых данных с использованием LocalDateTime - LocalDateTime start = LocalDateTime.of(2023, 1, 1, 0, 0, 0); - LocalDateTime end = LocalDateTime.of(2023, 12, 31, 23, 59, 59); - List uris = Arrays.asList("/non-existent/1", "/non-existent/2"); - Boolean unique = true; - - // Форматированные строки для URL - String formattedStart = "2023-01-01%2000:00:00"; - String formattedEnd = "2023-12-31%2023:59:59"; - - // Формирование URL - String url = baseUrl + "/stats" + - "?start=" + formattedStart + - "&end=" + formattedEnd + - "&uris=/non-existent/1" + - "&uris=/non-existent/2" + - "&unique=" + unique; - - // Настройка ожидания и ответа сервера с пустым массивом - mockServer.expect(requestTo(url)) - .andExpect(method(HttpMethod.GET)) - .andRespond(withSuccess("[]", MediaType.APPLICATION_JSON)); - - // Вызов тестируемого метода - List result = statsClient.getStats(start, end, uris, unique); - - // Проверка, что результат - пустой список - assertThat(result) - .as("Результат должен быть пустым списком") - .isEmpty(); - - // Проверка выполнения всех ожиданий - mockServer.verify(); - } - } -} \ No newline at end of file