From cf2aefe6c34576a1997390307d2cb527ef8fd34c Mon Sep 17 00:00:00 2001 From: backdev-1 Date: Thu, 21 May 2026 16:06:47 +0700 Subject: [PATCH] dev add cache for search --- build.gradle | 4 +++ .../ru/soune/nocopy/NoCopyApplication.java | 2 ++ .../nocopy/configuration/CacheConfig.java | 30 +++++++++++++++++++ .../nocopy/handler/GlobalSearchHandler.java | 9 ------ .../service/search/SearchImageService.java | 20 +++++++++---- 5 files changed, 50 insertions(+), 15 deletions(-) create mode 100644 src/main/java/ru/soune/nocopy/configuration/CacheConfig.java diff --git a/build.gradle b/build.gradle index bd3fb74..2384c39 100644 --- a/build.gradle +++ b/build.gradle @@ -77,6 +77,10 @@ dependencies { implementation 'org.springframework.cloud:spring-cloud-starter-openfeign:4.1.0' implementation 'io.github.resilience4j:resilience4j-spring-boot3:2.2.0' + + //cache + implementation("org.springframework.boot:spring-boot-starter-cache:4.0.6") + implementation 'com.github.ben-manes.caffeine:caffeine' } tasks.named('test') { diff --git a/src/main/java/ru/soune/nocopy/NoCopyApplication.java b/src/main/java/ru/soune/nocopy/NoCopyApplication.java index 0c9c534..f4c5bef 100644 --- a/src/main/java/ru/soune/nocopy/NoCopyApplication.java +++ b/src/main/java/ru/soune/nocopy/NoCopyApplication.java @@ -2,10 +2,12 @@ package ru.soune.nocopy; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cache.annotation.EnableCaching; import org.springframework.scheduling.annotation.EnableScheduling; @SpringBootApplication @EnableScheduling +@EnableCaching public class NoCopyApplication { public static void main(String[] args) { diff --git a/src/main/java/ru/soune/nocopy/configuration/CacheConfig.java b/src/main/java/ru/soune/nocopy/configuration/CacheConfig.java new file mode 100644 index 0000000..54a1d07 --- /dev/null +++ b/src/main/java/ru/soune/nocopy/configuration/CacheConfig.java @@ -0,0 +1,30 @@ +package ru.soune.nocopy.configuration; + +import com.github.benmanes.caffeine.cache.Caffeine; +import org.springframework.cache.CacheManager; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.cache.caffeine.CaffeineCacheManager; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.util.concurrent.TimeUnit; + +@Configuration +@EnableCaching +public class CacheConfig { + + @Bean + public CacheManager cacheManager() { + CaffeineCacheManager cacheManager = new CaffeineCacheManager( + "imageSearch", "parsedImages"); + + cacheManager.setCaffeine(Caffeine.newBuilder() + .maximumSize(10000) + .expireAfterWrite(1, TimeUnit.HOURS) + .recordStats() + ); + + return cacheManager; + } + +} diff --git a/src/main/java/ru/soune/nocopy/handler/GlobalSearchHandler.java b/src/main/java/ru/soune/nocopy/handler/GlobalSearchHandler.java index 35fba6c..a6e7820 100644 --- a/src/main/java/ru/soune/nocopy/handler/GlobalSearchHandler.java +++ b/src/main/java/ru/soune/nocopy/handler/GlobalSearchHandler.java @@ -6,21 +6,12 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import ru.soune.nocopy.dto.BaseRequest; import ru.soune.nocopy.dto.BaseResponse; -import ru.soune.nocopy.dto.MessageCode; import ru.soune.nocopy.dto.search.GlobalSearchStatisticsRequest; import ru.soune.nocopy.dto.search.GlobalSearchStatisticsResponse; -import ru.soune.nocopy.entity.company.Company; import ru.soune.nocopy.entity.user.AuthToken; -import ru.soune.nocopy.entity.user.User; import ru.soune.nocopy.repository.AuthTokenRepository; -import ru.soune.nocopy.repository.UserRepository; -import ru.soune.nocopy.service.CompanyService; import ru.soune.nocopy.service.search.GlobalSearchStatisticsService; -import ru.soune.nocopy.service.user.UserService; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; import java.util.Optional; @Slf4j diff --git a/src/main/java/ru/soune/nocopy/service/search/SearchImageService.java b/src/main/java/ru/soune/nocopy/service/search/SearchImageService.java index 32ac438..b806122 100644 --- a/src/main/java/ru/soune/nocopy/service/search/SearchImageService.java +++ b/src/main/java/ru/soune/nocopy/service/search/SearchImageService.java @@ -4,6 +4,8 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.DeserializationFeature; import jakarta.annotation.PostConstruct; +import org.springframework.cache.annotation.Cacheable; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import okhttp3.*; import org.springframework.beans.factory.annotation.Value; @@ -24,18 +26,13 @@ import java.util.concurrent.*; @Slf4j @Service - +@RequiredArgsConstructor public class SearchImageService { private final ObjectMapper objectMapper; private final SearchProperties searchProperties; - public SearchImageService(SearchProperties searchProperties) { - this.searchProperties = searchProperties; - this.objectMapper = new ObjectMapper(); - } - @Value("${yandex.api-key}") private String apiKey; @@ -57,6 +54,11 @@ public class SearchImageService { objectMapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true); } + @Cacheable( + value = "reverseImageSearch", + key = "#fileEntity.id + '_' + #engine + '_' + #searchType", + unless = "#result == null || #result.isEmpty()" + ) public String searchReverseByPublicUrl(FileEntity fileEntity, String engine, String searchType) throws IOException, TimeoutException { @@ -153,6 +155,12 @@ public class SearchImageService { } } + @Cacheable( + value = "parsedImages", + key = "#searchApiJson + '_' + #findType", + condition = "#searchApiJson != null && #searchApiJson.length() > 0", + unless = "#result == null || #result.isEmpty()" + ) public List getAllImagesWithoutPagination(String searchApiJson, String findType) throws IOException { JsonNode root = objectMapper.readTree(searchApiJson);