From 781a5291b501bf7c1c49a7f61158ba10b3d5db47 Mon Sep 17 00:00:00 2001 From: "a.drazdou" Date: Sat, 8 Nov 2025 14:43:20 +0300 Subject: [PATCH 1/8] add redis --- docker-compose.yml | 10 +++- user-service/user-service-impl/pom.xml | 17 +++++- .../configuration/ConfigRedis.java | 53 +++++++++++++++++++ .../service/impl/UserServiceImpl.java | 14 +++++ .../src/main/resources/application.yml | 7 ++- 5 files changed, 97 insertions(+), 4 deletions(-) create mode 100644 user-service/user-service-impl/src/main/java/ru/project/iakov/userservice/configuration/ConfigRedis.java diff --git a/docker-compose.yml b/docker-compose.yml index 5c84ea7..ffff7c7 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -58,7 +58,6 @@ services: interval: 10s timeout: 10s retries: 5 - user-service: image: user-service:latest build: @@ -78,6 +77,13 @@ services: - KAFKA_BOOTSTRAP_SERVERS=kafka:9093 env_file: - .env - + redis: + image: redis:8.2.1 + restart: on-failure + ports: + - "6379:6379" + volumes: + - redis_data:/data volumes: pgdata: + redis_data: diff --git a/user-service/user-service-impl/pom.xml b/user-service/user-service-impl/pom.xml index 0587f22..f3f2f20 100644 --- a/user-service/user-service-impl/pom.xml +++ b/user-service/user-service-impl/pom.xml @@ -97,6 +97,8 @@ spring-boot-starter-hateoas + + org.springdoc @@ -132,5 +134,18 @@ spring-kafka + + + org.springframework.boot + spring-boot-starter-cache + 3.5.6 + + + + + org.springframework.boot + spring-boot-starter-data-redis + + - + \ No newline at end of file diff --git a/user-service/user-service-impl/src/main/java/ru/project/iakov/userservice/configuration/ConfigRedis.java b/user-service/user-service-impl/src/main/java/ru/project/iakov/userservice/configuration/ConfigRedis.java new file mode 100644 index 0000000..7220868 --- /dev/null +++ b/user-service/user-service-impl/src/main/java/ru/project/iakov/userservice/configuration/ConfigRedis.java @@ -0,0 +1,53 @@ +package ru.project.iakov.userservice.configuration; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.cache.CacheManager; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.cache.RedisCacheConfiguration; +import org.springframework.data.redis.cache.RedisCacheManager; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializationContext; +import org.springframework.data.redis.serializer.StringRedisSerializer; +import ru.project.iakov.userservice.domain.entity.User; + +import java.time.Duration; + +@EnableCaching +@Configuration +public class ConfigRedis { + + @Bean + public RedisTemplate redisTemplate(RedisConnectionFactory connectionFactory, + ObjectMapper objectMapper) { + RedisTemplate redisTemplate = new RedisTemplate<>(); + redisTemplate.setConnectionFactory(connectionFactory); + + redisTemplate.setKeySerializer(new StringRedisSerializer()); + + var serializer = new Jackson2JsonRedisSerializer<>(objectMapper,User.class); + redisTemplate.setValueSerializer(serializer); + + redisTemplate.afterPropertiesSet(); + return redisTemplate; + } + + @Bean + public CacheManager cacheManager(RedisConnectionFactory connectionFactory, + ObjectMapper objectMapper) { + var jsonSerializer = new Jackson2JsonRedisSerializer<>(objectMapper, User.class); + + RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig() + .entryTtl(Duration.ofMinutes(1)) + .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer())) + .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jsonSerializer)); + + return RedisCacheManager.builder(connectionFactory) + .cacheDefaults(config) + .transactionAware() + .build(); + } +} \ No newline at end of file diff --git a/user-service/user-service-impl/src/main/java/ru/project/iakov/userservice/service/impl/UserServiceImpl.java b/user-service/user-service-impl/src/main/java/ru/project/iakov/userservice/service/impl/UserServiceImpl.java index 2e04e57..b7f156a 100644 --- a/user-service/user-service-impl/src/main/java/ru/project/iakov/userservice/service/impl/UserServiceImpl.java +++ b/user-service/user-service-impl/src/main/java/ru/project/iakov/userservice/service/impl/UserServiceImpl.java @@ -2,6 +2,8 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import ru.project.iakov.userservice.domain.entity.User; @@ -31,6 +33,10 @@ public class UserServiceImpl implements UserService { private final UserMapper userMapper; private final KafkaSender kafkaSender; + @Cacheable( + value = "user", + key = "#id" + ) @Override public UserResponse findById(UUID id) { User user = userRepository.findById(id) @@ -80,6 +86,10 @@ public UserResponse createUser(UserRequest userRequest) { return userMapper.toResponse(savedUser); } + @CacheEvict( + value = "user", + key = "#id" + ) @Override @Transactional public UserResponse updateUser(UUID id, UserRequest userRequest) { @@ -105,6 +115,10 @@ public UserResponse updateUser(UUID id, UserRequest userRequest) { return userMapper.toResponse(updatedUser); } + @CacheEvict( + value = "user", + key = "#id" + ) @Override @Transactional public void deleteUser(UUID id) { diff --git a/user-service/user-service-impl/src/main/resources/application.yml b/user-service/user-service-impl/src/main/resources/application.yml index 5484fa9..d33ae88 100644 --- a/user-service/user-service-impl/src/main/resources/application.yml +++ b/user-service/user-service-impl/src/main/resources/application.yml @@ -12,6 +12,12 @@ spring: properties: hibernate: format_sql: true + data: + redis: + host: ${SPRING_REDIS_HOST:localhost} + port: ${SPRING_REDIS_PORT:6379} + cache: + type: redis liquibase: change-log: classpath:db/changelog/db.changelog-master.yaml jackson: @@ -28,7 +34,6 @@ spring: producer: key-serializer: org.apache.kafka.common.serialization.StringSerializer value-serializer: org.springframework.kafka.support.serializer.JsonSerializer - logging: level: ru.project.iakov.userservice.kafka: INFO From 87bd79ab3d2f7faa698e4760545ed4146a5f762a Mon Sep 17 00:00:00 2001 From: Iakov Lysenko Date: Sat, 8 Nov 2025 22:24:24 +0300 Subject: [PATCH 2/8] CI --- .github/workflows/ci.yml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..38d5633 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,23 @@ +name: Java CI with Maven + +on: + push: + pull_request: + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - name: Set up JDK 21 + uses: actions/setup-java@v4 + with: + java-version: '21' + distribution: 'temurin' + cache: maven + - name: Build with Maven + run: mvn -B package --file pom.xml + + - name: Update dependency graph + uses: advanced-security/maven-dependency-submission-action@571e99aab1055c2e71a1e2309b9691de18d6b7d6 From 28ba744691f72200889533b4cd7e65c7f33ca713 Mon Sep 17 00:00:00 2001 From: Iakov Lysenko Date: Sat, 8 Nov 2025 22:28:04 +0300 Subject: [PATCH 3/8] directory change CI --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 38d5633..05ff0a9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,6 +17,7 @@ jobs: distribution: 'temurin' cache: maven - name: Build with Maven + working-directory: user-service run: mvn -B package --file pom.xml - name: Update dependency graph From ee07e01626955c290dc8fe914ad8c4352f5ede4e Mon Sep 17 00:00:00 2001 From: Iakov Lysenko Date: Sat, 8 Nov 2025 22:34:09 +0300 Subject: [PATCH 4/8] graph directory changed CI --- .github/workflows/ci.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 05ff0a9..1ed3846 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,16 +9,20 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - name: Check Repository + uses: actions/checkout@v4 + - name: Set up JDK 21 uses: actions/setup-java@v4 with: java-version: '21' distribution: 'temurin' cache: maven + - name: Build with Maven working-directory: user-service run: mvn -B package --file pom.xml - name: Update dependency graph + working-directory: user-service uses: advanced-security/maven-dependency-submission-action@571e99aab1055c2e71a1e2309b9691de18d6b7d6 From 7a6bb92f52a7cdca52db01f50895872d297a0c64 Mon Sep 17 00:00:00 2001 From: Iakov Lysenko Date: Sat, 8 Nov 2025 22:35:13 +0300 Subject: [PATCH 5/8] Fix working directory for dependency graph update --- .github/workflows/ci.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1ed3846..c6f9bf0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,5 +24,6 @@ jobs: run: mvn -B package --file pom.xml - name: Update dependency graph - working-directory: user-service uses: advanced-security/maven-dependency-submission-action@571e99aab1055c2e71a1e2309b9691de18d6b7d6 + with: + working-directory: user-service From 3c4fbaad90f236dd81c63a6a5ea7651faac4be9c Mon Sep 17 00:00:00 2001 From: Iakov Lysenko Date: Sat, 8 Nov 2025 22:38:12 +0300 Subject: [PATCH 6/8] Update Maven dependency submission action version --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c6f9bf0..1402652 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,6 +24,6 @@ jobs: run: mvn -B package --file pom.xml - name: Update dependency graph - uses: advanced-security/maven-dependency-submission-action@571e99aab1055c2e71a1e2309b9691de18d6b7d6 + uses: advanced-security/maven-dependency-submission-action@v4 with: working-directory: user-service From 3608318ae58686ebf3c47c24ea57ed3875711eec Mon Sep 17 00:00:00 2001 From: Iakov Lysenko Date: Sat, 8 Nov 2025 22:42:32 +0300 Subject: [PATCH 7/8] update CI Replaced 'mvn package' with 'mvn clean verify' and updated workflow to upload test results. --- .github/workflows/ci.yml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1402652..966ed1f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,9 +21,10 @@ jobs: - name: Build with Maven working-directory: user-service - run: mvn -B package --file pom.xml + run: mvn -B clean verify - - name: Update dependency graph - uses: advanced-security/maven-dependency-submission-action@v4 - with: - working-directory: user-service + - name: Upload test results + uses: actions/upload-artifact@v4 + with: + name: test-results + path: user-service/target/surefire-reports/ From fe65fc937b512c8921083791f46ac1e258d6029b Mon Sep 17 00:00:00 2001 From: "a.drazdou" Date: Sat, 8 Nov 2025 14:43:20 +0300 Subject: [PATCH 8/8] add redis --- docker-compose.yml | 10 +++- user-service/user-service-impl/pom.xml | 17 +++++- .../configuration/ConfigRedis.java | 53 +++++++++++++++++++ .../service/impl/UserServiceImpl.java | 14 +++++ .../src/main/resources/application.yml | 7 ++- 5 files changed, 97 insertions(+), 4 deletions(-) create mode 100644 user-service/user-service-impl/src/main/java/ru/project/iakov/userservice/configuration/ConfigRedis.java diff --git a/docker-compose.yml b/docker-compose.yml index 5c84ea7..ffff7c7 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -58,7 +58,6 @@ services: interval: 10s timeout: 10s retries: 5 - user-service: image: user-service:latest build: @@ -78,6 +77,13 @@ services: - KAFKA_BOOTSTRAP_SERVERS=kafka:9093 env_file: - .env - + redis: + image: redis:8.2.1 + restart: on-failure + ports: + - "6379:6379" + volumes: + - redis_data:/data volumes: pgdata: + redis_data: diff --git a/user-service/user-service-impl/pom.xml b/user-service/user-service-impl/pom.xml index 0587f22..f3f2f20 100644 --- a/user-service/user-service-impl/pom.xml +++ b/user-service/user-service-impl/pom.xml @@ -97,6 +97,8 @@ spring-boot-starter-hateoas + + org.springdoc @@ -132,5 +134,18 @@ spring-kafka + + + org.springframework.boot + spring-boot-starter-cache + 3.5.6 + + + + + org.springframework.boot + spring-boot-starter-data-redis + + - + \ No newline at end of file diff --git a/user-service/user-service-impl/src/main/java/ru/project/iakov/userservice/configuration/ConfigRedis.java b/user-service/user-service-impl/src/main/java/ru/project/iakov/userservice/configuration/ConfigRedis.java new file mode 100644 index 0000000..7220868 --- /dev/null +++ b/user-service/user-service-impl/src/main/java/ru/project/iakov/userservice/configuration/ConfigRedis.java @@ -0,0 +1,53 @@ +package ru.project.iakov.userservice.configuration; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.cache.CacheManager; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.cache.RedisCacheConfiguration; +import org.springframework.data.redis.cache.RedisCacheManager; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializationContext; +import org.springframework.data.redis.serializer.StringRedisSerializer; +import ru.project.iakov.userservice.domain.entity.User; + +import java.time.Duration; + +@EnableCaching +@Configuration +public class ConfigRedis { + + @Bean + public RedisTemplate redisTemplate(RedisConnectionFactory connectionFactory, + ObjectMapper objectMapper) { + RedisTemplate redisTemplate = new RedisTemplate<>(); + redisTemplate.setConnectionFactory(connectionFactory); + + redisTemplate.setKeySerializer(new StringRedisSerializer()); + + var serializer = new Jackson2JsonRedisSerializer<>(objectMapper,User.class); + redisTemplate.setValueSerializer(serializer); + + redisTemplate.afterPropertiesSet(); + return redisTemplate; + } + + @Bean + public CacheManager cacheManager(RedisConnectionFactory connectionFactory, + ObjectMapper objectMapper) { + var jsonSerializer = new Jackson2JsonRedisSerializer<>(objectMapper, User.class); + + RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig() + .entryTtl(Duration.ofMinutes(1)) + .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer())) + .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jsonSerializer)); + + return RedisCacheManager.builder(connectionFactory) + .cacheDefaults(config) + .transactionAware() + .build(); + } +} \ No newline at end of file diff --git a/user-service/user-service-impl/src/main/java/ru/project/iakov/userservice/service/impl/UserServiceImpl.java b/user-service/user-service-impl/src/main/java/ru/project/iakov/userservice/service/impl/UserServiceImpl.java index 2e04e57..b7f156a 100644 --- a/user-service/user-service-impl/src/main/java/ru/project/iakov/userservice/service/impl/UserServiceImpl.java +++ b/user-service/user-service-impl/src/main/java/ru/project/iakov/userservice/service/impl/UserServiceImpl.java @@ -2,6 +2,8 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import ru.project.iakov.userservice.domain.entity.User; @@ -31,6 +33,10 @@ public class UserServiceImpl implements UserService { private final UserMapper userMapper; private final KafkaSender kafkaSender; + @Cacheable( + value = "user", + key = "#id" + ) @Override public UserResponse findById(UUID id) { User user = userRepository.findById(id) @@ -80,6 +86,10 @@ public UserResponse createUser(UserRequest userRequest) { return userMapper.toResponse(savedUser); } + @CacheEvict( + value = "user", + key = "#id" + ) @Override @Transactional public UserResponse updateUser(UUID id, UserRequest userRequest) { @@ -105,6 +115,10 @@ public UserResponse updateUser(UUID id, UserRequest userRequest) { return userMapper.toResponse(updatedUser); } + @CacheEvict( + value = "user", + key = "#id" + ) @Override @Transactional public void deleteUser(UUID id) { diff --git a/user-service/user-service-impl/src/main/resources/application.yml b/user-service/user-service-impl/src/main/resources/application.yml index 5484fa9..d33ae88 100644 --- a/user-service/user-service-impl/src/main/resources/application.yml +++ b/user-service/user-service-impl/src/main/resources/application.yml @@ -12,6 +12,12 @@ spring: properties: hibernate: format_sql: true + data: + redis: + host: ${SPRING_REDIS_HOST:localhost} + port: ${SPRING_REDIS_PORT:6379} + cache: + type: redis liquibase: change-log: classpath:db/changelog/db.changelog-master.yaml jackson: @@ -28,7 +34,6 @@ spring: producer: key-serializer: org.apache.kafka.common.serialization.StringSerializer value-serializer: org.springframework.kafka.support.serializer.JsonSerializer - logging: level: ru.project.iakov.userservice.kafka: INFO