From 4a6ebf06f5005a95ea06025f193745f3774a1144 Mon Sep 17 00:00:00 2001 From: seokjin8678 Date: Tue, 16 Apr 2024 23:26:37 +0900 Subject: [PATCH 1/7] =?UTF-8?q?feat:=20SchoolFestivalsV2QueryService,=20Sc?= =?UTF-8?q?hoolFestivalsV2QueryDslRepository=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 페이징 적용하지 않고 학교에 대한 축제 목록 조회 --- .../v2/SchoolFestivalsV2QueryService.java | 29 +++ .../SchoolFestivalsV2QueryDslRepository.java | 64 ++++++ .../v2/SchoolFestivalsV2QueryServiceTest.java | 185 ++++++++++++++++++ 3 files changed, 278 insertions(+) create mode 100644 backend/src/main/java/com/festago/school/application/v2/SchoolFestivalsV2QueryService.java create mode 100644 backend/src/main/java/com/festago/school/repository/v2/SchoolFestivalsV2QueryDslRepository.java create mode 100644 backend/src/test/java/com/festago/school/application/v2/SchoolFestivalsV2QueryServiceTest.java diff --git a/backend/src/main/java/com/festago/school/application/v2/SchoolFestivalsV2QueryService.java b/backend/src/main/java/com/festago/school/application/v2/SchoolFestivalsV2QueryService.java new file mode 100644 index 000000000..cca3feb59 --- /dev/null +++ b/backend/src/main/java/com/festago/school/application/v2/SchoolFestivalsV2QueryService.java @@ -0,0 +1,29 @@ +package com.festago.school.application.v2; + +import com.festago.school.dto.v1.SchoolFestivalV1Response; +import com.festago.school.repository.v2.SchoolFestivalsV2QueryDslRepository; +import java.time.Clock; +import java.time.LocalDate; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@RequiredArgsConstructor +@Transactional(readOnly = true) +public class SchoolFestivalsV2QueryService { + + private final SchoolFestivalsV2QueryDslRepository schoolFestivalsV1QueryDslRepository; + private final Clock clock; + + public List findFestivalsBySchoolId(Long schoolId) { + LocalDate now = LocalDate.now(clock); + return schoolFestivalsV1QueryDslRepository.findFestivalsBySchoolId(schoolId, now); + } + + public List findPastFestivalsBySchoolId(Long schoolId) { + LocalDate now = LocalDate.now(clock); + return schoolFestivalsV1QueryDslRepository.findPastFestivalsBySchoolId(schoolId, now); + } +} diff --git a/backend/src/main/java/com/festago/school/repository/v2/SchoolFestivalsV2QueryDslRepository.java b/backend/src/main/java/com/festago/school/repository/v2/SchoolFestivalsV2QueryDslRepository.java new file mode 100644 index 000000000..00b1775ae --- /dev/null +++ b/backend/src/main/java/com/festago/school/repository/v2/SchoolFestivalsV2QueryDslRepository.java @@ -0,0 +1,64 @@ +package com.festago.school.repository.v2; + +import static com.festago.festival.domain.QFestival.festival; +import static com.festago.festival.domain.QFestivalQueryInfo.festivalQueryInfo; + +import com.festago.common.querydsl.QueryDslHelper; +import com.festago.school.dto.v1.QSchoolFestivalV1Response; +import com.festago.school.dto.v1.SchoolFestivalV1Response; +import java.time.LocalDate; +import java.util.Comparator; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Repository; + +@Repository +@RequiredArgsConstructor +public class SchoolFestivalsV2QueryDslRepository { + + private final QueryDslHelper queryDslHelper; + + public List findFestivalsBySchoolId( + Long schoolId, + LocalDate today + ) { + return queryDslHelper.select( + new QSchoolFestivalV1Response( + festival.id, + festival.name, + festival.startDate, + festival.endDate, + festival.thumbnail, + festivalQueryInfo.artistInfo + ) + ) + .from(festival) + .leftJoin(festivalQueryInfo).on(festivalQueryInfo.festivalId.eq(festival.id)) + .where(festival.school.id.eq(schoolId).and(festival.endDate.goe(today))) + .stream() + .sorted(Comparator.comparing(SchoolFestivalV1Response::startDate)) + .toList(); + } + + public List findPastFestivalsBySchoolId( + Long schoolId, + LocalDate today + ) { + return queryDslHelper.select( + new QSchoolFestivalV1Response( + festival.id, + festival.name, + festival.startDate, + festival.endDate, + festival.thumbnail, + festivalQueryInfo.artistInfo + ) + ) + .from(festival) + .leftJoin(festivalQueryInfo).on(festivalQueryInfo.festivalId.eq(festival.id)) + .where(festival.school.id.eq(schoolId).and(festival.endDate.lt(today))) + .stream() + .sorted(Comparator.comparing(SchoolFestivalV1Response::endDate).reversed()) + .toList(); + } +} diff --git a/backend/src/test/java/com/festago/school/application/v2/SchoolFestivalsV2QueryServiceTest.java b/backend/src/test/java/com/festago/school/application/v2/SchoolFestivalsV2QueryServiceTest.java new file mode 100644 index 000000000..0132b8c1f --- /dev/null +++ b/backend/src/test/java/com/festago/school/application/v2/SchoolFestivalsV2QueryServiceTest.java @@ -0,0 +1,185 @@ +package com.festago.school.application.v2; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.BDDMockito.given; + +import com.festago.festival.domain.Festival; +import com.festago.festival.repository.FestivalRepository; +import com.festago.school.domain.School; +import com.festago.school.dto.v1.SchoolFestivalV1Response; +import com.festago.school.repository.SchoolRepository; +import com.festago.support.ApplicationIntegrationTest; +import com.festago.support.TimeInstantProvider; +import com.festago.support.fixture.FestivalFixture; +import com.festago.support.fixture.SchoolFixture; +import java.time.Clock; +import java.time.LocalDate; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) +@SuppressWarnings("NonAsciiCharacters") +class SchoolFestivalsV2QueryServiceTest extends ApplicationIntegrationTest { + + @Autowired + SchoolFestivalsV2QueryService schoolFestivalsV2QueryService; + + @Autowired + SchoolRepository schoolRepository; + + @Autowired + FestivalRepository festivalRepository; + + @Autowired + Clock clock; + + School 테코대학교; + School 우테대학교; + Festival 테코대학교_6월_15일_6월_15일_축제; + Festival 테코대학교_6월_16일_6월_17일_축제; + Festival 테코대학교_6월_17일_6월_18일_축제; + Festival 테코대학교_6월_19일_6월_20일_축제; + LocalDate _6월_15일 = LocalDate.parse("2077-06-15"); + LocalDate _6월_16일 = LocalDate.parse("2077-06-16"); + LocalDate _6월_17일 = LocalDate.parse("2077-06-17"); + LocalDate _6월_18일 = LocalDate.parse("2077-06-18"); + LocalDate _6월_19일 = LocalDate.parse("2077-06-19"); + LocalDate _6월_20일 = LocalDate.parse("2077-06-20"); + LocalDate _6월_21일 = LocalDate.parse("2077-06-21"); + + /** + * 축제는 다음과 같이 존재한다.
테코대학교 6월 15일 ~ 6월 15일
테코대학교 6월 16일 ~ 6월 17일
테코대학교 6월 17일 ~ 6월 18일
테코대학교 + * 6월 19일 ~ 6월 20일
또한 우테대학교에는 축제가 존재하지 않는다
+ */ + @BeforeEach + void setUp() { + 테코대학교 = schoolRepository.save(SchoolFixture.builder().name("테코대학교").build()); + 우테대학교 = schoolRepository.save(SchoolFixture.builder().name("우테대학교").build()); + 테코대학교_6월_15일_6월_15일_축제 = festivalRepository.save( + FestivalFixture.builder().startDate(_6월_15일).endDate(_6월_15일).school(테코대학교).build() + ); + 테코대학교_6월_19일_6월_20일_축제 = festivalRepository.save( + FestivalFixture.builder().startDate(_6월_19일).endDate(_6월_20일).school(테코대학교).build() + ); + 테코대학교_6월_17일_6월_18일_축제 = festivalRepository.save( + FestivalFixture.builder().startDate(_6월_17일).endDate(_6월_18일).school(테코대학교).build() + ); + 테코대학교_6월_16일_6월_17일_축제 = festivalRepository.save( + FestivalFixture.builder().startDate(_6월_16일).endDate(_6월_17일).school(테코대학교).build() + ); + } + + @Nested + class findFestivalsBySchoolId { + + @Test + void 진행_중_진행_예정_축제가_없으면_빈_리스트가_반환된다() { + // given + given(clock.instant()) + .willReturn(TimeInstantProvider.from(_6월_15일)); + + // when + var actual = schoolFestivalsV2QueryService.findFestivalsBySchoolId(우테대학교.getId()); + + // then + assertThat(actual).isEmpty(); + } + + @Test + void 진행_중_진행_예정_축제_조회는_시작일_오름차순으로_정렬된다() { + // given + given(clock.instant()) + .willReturn(TimeInstantProvider.from(_6월_15일)); + + // when + var actual = schoolFestivalsV2QueryService.findFestivalsBySchoolId(테코대학교.getId()); + + // then + assertThat(actual) + .map(SchoolFestivalV1Response::id) + .containsExactly( + 테코대학교_6월_15일_6월_15일_축제.getId(), + 테코대학교_6월_16일_6월_17일_축제.getId(), + 테코대학교_6월_17일_6월_18일_축제.getId(), + 테코대학교_6월_19일_6월_20일_축제.getId() + ); + } + + @Test + void 진행_중_진행_예정_축제는_종료일을_포함한다() { + // given + given(clock.instant()) + .willReturn(TimeInstantProvider.from(_6월_18일)); + + // when + var actual = schoolFestivalsV2QueryService.findFestivalsBySchoolId(테코대학교.getId()); + + // then + assertThat(actual) + .map(SchoolFestivalV1Response::id) + .containsExactly( + 테코대학교_6월_17일_6월_18일_축제.getId(), + 테코대학교_6월_19일_6월_20일_축제.getId() + ); + } + } + + @Nested + class findPastFestivalsBySchoolId { + + @Test + void 과거_축제가_없으면_빈_리스트가_반환된다() { + // given + given(clock.instant()) + .willReturn(TimeInstantProvider.from(_6월_15일)); + + // when + var actual = schoolFestivalsV2QueryService.findPastFestivalsBySchoolId(우테대학교.getId()); + + // then + assertThat(actual).isEmpty(); + } + + @Test + void 과거_축제_조회는_종료일_내림차순으로_정렬된다() { + // given + given(clock.instant()) + .willReturn(TimeInstantProvider.from(_6월_21일)); + + // when + var actual = schoolFestivalsV2QueryService.findPastFestivalsBySchoolId(테코대학교.getId()); + + // then + assertThat(actual) + .map(SchoolFestivalV1Response::id) + .containsExactly( + 테코대학교_6월_19일_6월_20일_축제.getId(), + 테코대학교_6월_17일_6월_18일_축제.getId(), + 테코대학교_6월_16일_6월_17일_축제.getId(), + 테코대학교_6월_15일_6월_15일_축제.getId() + ); + } + + @Test + void 진행_중_진행_예정_축제는_종료일을_포함하지_않는다() { + // given + given(clock.instant()) + .willReturn(TimeInstantProvider.from(_6월_18일)); + + // when + var actual = schoolFestivalsV2QueryService.findPastFestivalsBySchoolId(테코대학교.getId()); + + // then + assertThat(actual) + .map(SchoolFestivalV1Response::id) + .containsExactly( + 테코대학교_6월_16일_6월_17일_축제.getId(), + 테코대학교_6월_15일_6월_15일_축제.getId() + ); + } + } +} From 2a2f784272c2df210338ba2f86dc66fa9b239ea5 Mon Sep 17 00:00:00 2001 From: seokjin8678 Date: Wed, 17 Apr 2024 01:14:01 +0900 Subject: [PATCH 2/7] =?UTF-8?q?build:=20Spring=20Cache,=20caffeine=20?= =?UTF-8?q?=EB=9D=BC=EC=9D=B4=EB=B8=8C=EB=9F=AC=EB=A6=AC=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/build.gradle.kts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/backend/build.gradle.kts b/backend/build.gradle.kts index 3cf8f4742..89c767b76 100644 --- a/backend/build.gradle.kts +++ b/backend/build.gradle.kts @@ -36,6 +36,7 @@ dependencies { implementation("org.springframework.boot:spring-boot-starter-web") implementation("org.springframework.boot:spring-boot-starter-thymeleaf") implementation("org.springframework.boot:spring-boot-starter-mail") + implementation("org.springframework.boot:spring-boot-starter-cache") implementation("org.springdoc:springdoc-openapi-starter-webmvc-ui:${swaggerVersion}") // Spring Security @@ -79,6 +80,9 @@ dependencies { annotationProcessor("org.projectlombok:lombok") testCompileOnly("org.projectlombok:lombok") testAnnotationProcessor("org.projectlombok:lombok") + + // Caffeine + implementation("com.github.ben-manes.caffeine:caffeine") } tasks.test { From 070cb84431a87a4c93928cd5c04eef644f5c4f57 Mon Sep 17 00:00:00 2001 From: seokjin8678 Date: Wed, 17 Apr 2024 01:16:08 +0900 Subject: [PATCH 3/7] =?UTF-8?q?feat:=20CacheConfig=20=EC=B6=94=EA=B0=80=20?= =?UTF-8?q?=EB=B0=8F=20SchoolFestivalsV2QueryService=20=EC=BA=90=EC=8B=9C?= =?UTF-8?q?=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/cache/CacheInvalidator.java | 23 +++++ .../java/com/festago/config/CacheConfig.java | 21 ++++ .../v2/SchoolFestivalsV2QueryService.java | 6 ++ .../SchoolFestivalsV2CacheConfig.java | 38 ++++++++ ...olFestivalsV2CacheInvalidateScheduler.java | 23 +++++ .../SchoolFestivalsV2CacheConfigTest.java | 96 +++++++++++++++++++ .../support/ApplicationIntegrationTest.java | 3 +- .../CacheClearTestExecutionListener.java | 22 +++++ 8 files changed, 231 insertions(+), 1 deletion(-) create mode 100644 backend/src/main/java/com/festago/common/cache/CacheInvalidator.java create mode 100644 backend/src/main/java/com/festago/config/CacheConfig.java create mode 100644 backend/src/main/java/com/festago/school/infrastructure/SchoolFestivalsV2CacheConfig.java create mode 100644 backend/src/main/java/com/festago/school/infrastructure/SchoolFestivalsV2CacheInvalidateScheduler.java create mode 100644 backend/src/test/java/com/festago/school/infrastructure/SchoolFestivalsV2CacheConfigTest.java create mode 100644 backend/src/test/java/com/festago/support/CacheClearTestExecutionListener.java diff --git a/backend/src/main/java/com/festago/common/cache/CacheInvalidator.java b/backend/src/main/java/com/festago/common/cache/CacheInvalidator.java new file mode 100644 index 000000000..424961fcb --- /dev/null +++ b/backend/src/main/java/com/festago/common/cache/CacheInvalidator.java @@ -0,0 +1,23 @@ +package com.festago.common.cache; + +import java.util.Optional; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.cache.CacheManager; +import org.springframework.stereotype.Component; + +@Component +@RequiredArgsConstructor +@Slf4j +public class CacheInvalidator { + + private final CacheManager cacheManager; + + public void invalidate(String cacheName) { + Optional.ofNullable(cacheManager.getCache(cacheName)) + .ifPresentOrElse(cache -> { + cache.invalidate(); + log.info("{} 캐시를 초기화 했습니다.", cacheName); + }, () -> log.error("{} 캐시를 찾을 수 없습니다.", cacheName)); + } +} diff --git a/backend/src/main/java/com/festago/config/CacheConfig.java b/backend/src/main/java/com/festago/config/CacheConfig.java new file mode 100644 index 000000000..390032a53 --- /dev/null +++ b/backend/src/main/java/com/festago/config/CacheConfig.java @@ -0,0 +1,21 @@ +package com.festago.config; + +import java.util.List; +import org.springframework.cache.Cache; +import org.springframework.cache.CacheManager; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.cache.support.SimpleCacheManager; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +@EnableCaching +public class CacheConfig { + + @Bean + public CacheManager cacheManager(List caches) { + SimpleCacheManager cacheManager = new SimpleCacheManager(); + cacheManager.setCaches(caches); + return cacheManager; + } +} diff --git a/backend/src/main/java/com/festago/school/application/v2/SchoolFestivalsV2QueryService.java b/backend/src/main/java/com/festago/school/application/v2/SchoolFestivalsV2QueryService.java index cca3feb59..1043ff19a 100644 --- a/backend/src/main/java/com/festago/school/application/v2/SchoolFestivalsV2QueryService.java +++ b/backend/src/main/java/com/festago/school/application/v2/SchoolFestivalsV2QueryService.java @@ -6,6 +6,7 @@ import java.time.LocalDate; import java.util.List; import lombok.RequiredArgsConstructor; +import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -14,14 +15,19 @@ @Transactional(readOnly = true) public class SchoolFestivalsV2QueryService { + public static final String SCHOOL_FESTIVALS_V2_CACHE_NAME = "schoolFestivalsV2"; + public static final String PAST_SCHOOL_FESTIVALS_V2_CACHE_NAME = "pastSchoolFestivalsV2"; + private final SchoolFestivalsV2QueryDslRepository schoolFestivalsV1QueryDslRepository; private final Clock clock; + @Cacheable(cacheNames = SCHOOL_FESTIVALS_V2_CACHE_NAME, key = "#schoolId") public List findFestivalsBySchoolId(Long schoolId) { LocalDate now = LocalDate.now(clock); return schoolFestivalsV1QueryDslRepository.findFestivalsBySchoolId(schoolId, now); } + @Cacheable(cacheNames = PAST_SCHOOL_FESTIVALS_V2_CACHE_NAME, key = "#schoolId") public List findPastFestivalsBySchoolId(Long schoolId) { LocalDate now = LocalDate.now(clock); return schoolFestivalsV1QueryDslRepository.findPastFestivalsBySchoolId(schoolId, now); diff --git a/backend/src/main/java/com/festago/school/infrastructure/SchoolFestivalsV2CacheConfig.java b/backend/src/main/java/com/festago/school/infrastructure/SchoolFestivalsV2CacheConfig.java new file mode 100644 index 000000000..621de023d --- /dev/null +++ b/backend/src/main/java/com/festago/school/infrastructure/SchoolFestivalsV2CacheConfig.java @@ -0,0 +1,38 @@ +package com.festago.school.infrastructure; + +import com.festago.school.application.v2.SchoolFestivalsV2QueryService; +import com.github.benmanes.caffeine.cache.Caffeine; +import java.util.concurrent.TimeUnit; +import org.springframework.cache.Cache; +import org.springframework.cache.caffeine.CaffeineCache; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class SchoolFestivalsV2CacheConfig { + + private static final long EXPIRED_AFTER_WRITE = 30; + private static final long MAXIMUM_SIZE = 1_000; + + @Bean + public Cache schoolFestivalsV2Cache() { + return new CaffeineCache(SchoolFestivalsV2QueryService.SCHOOL_FESTIVALS_V2_CACHE_NAME, + Caffeine.newBuilder() + .recordStats() + .expireAfterWrite(EXPIRED_AFTER_WRITE, TimeUnit.MINUTES) + .maximumSize(MAXIMUM_SIZE) + .build() + ); + } + + @Bean + public Cache pastschoolFestivalsV2Cache() { + return new CaffeineCache(SchoolFestivalsV2QueryService.PAST_SCHOOL_FESTIVALS_V2_CACHE_NAME, + Caffeine.newBuilder() + .recordStats() + .expireAfterWrite(EXPIRED_AFTER_WRITE, TimeUnit.MINUTES) + .maximumSize(MAXIMUM_SIZE) + .build() + ); + } +} diff --git a/backend/src/main/java/com/festago/school/infrastructure/SchoolFestivalsV2CacheInvalidateScheduler.java b/backend/src/main/java/com/festago/school/infrastructure/SchoolFestivalsV2CacheInvalidateScheduler.java new file mode 100644 index 000000000..557b11723 --- /dev/null +++ b/backend/src/main/java/com/festago/school/infrastructure/SchoolFestivalsV2CacheInvalidateScheduler.java @@ -0,0 +1,23 @@ +package com.festago.school.infrastructure; + +import com.festago.common.cache.CacheInvalidator; +import com.festago.school.application.v2.SchoolFestivalsV2QueryService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +@Component +@RequiredArgsConstructor +@Slf4j +public class SchoolFestivalsV2CacheInvalidateScheduler { + + private final CacheInvalidator cacheInvalidator; + + // 매일 정각마다 캐시 초기화 + @Scheduled(cron = "0 0 0 * * *") + public void invalidate() { + cacheInvalidator.invalidate(SchoolFestivalsV2QueryService.SCHOOL_FESTIVALS_V2_CACHE_NAME); + cacheInvalidator.invalidate(SchoolFestivalsV2QueryService.PAST_SCHOOL_FESTIVALS_V2_CACHE_NAME); + } +} diff --git a/backend/src/test/java/com/festago/school/infrastructure/SchoolFestivalsV2CacheConfigTest.java b/backend/src/test/java/com/festago/school/infrastructure/SchoolFestivalsV2CacheConfigTest.java new file mode 100644 index 000000000..a00064415 --- /dev/null +++ b/backend/src/test/java/com/festago/school/infrastructure/SchoolFestivalsV2CacheConfigTest.java @@ -0,0 +1,96 @@ +package com.festago.school.infrastructure; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.BDDMockito.given; + +import com.festago.festival.repository.FestivalRepository; +import com.festago.school.application.v2.SchoolFestivalsV2QueryService; +import com.festago.school.domain.School; +import com.festago.school.repository.SchoolRepository; +import com.festago.school.repository.v2.SchoolFestivalsV2QueryDslRepository; +import com.festago.support.ApplicationIntegrationTest; +import com.festago.support.TimeInstantProvider; +import com.festago.support.fixture.FestivalFixture; +import com.festago.support.fixture.SchoolFixture; +import java.time.Clock; +import java.time.LocalDate; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) +@SuppressWarnings("NonAsciiCharacters") +class SchoolFestivalsV2CacheConfigTest extends ApplicationIntegrationTest { + + @Autowired + SchoolFestivalsV2QueryService schoolFestivalsV2QueryService; + + @Autowired + SchoolFestivalsV2QueryDslRepository schoolFestivalsV2QueryDslRepository; + + @Autowired + SchoolRepository schoolRepository; + + @Autowired + FestivalRepository festivalRepository; + + @Autowired + Clock clock; + + School 테코대학교; + LocalDate _6월_15일 = LocalDate.parse("2077-06-15"); + LocalDate _6월_16일 = LocalDate.parse("2077-06-16"); + + @BeforeEach + void setUp() { + 테코대학교 = schoolRepository.save(SchoolFixture.builder().name("테코대학교").build()); + festivalRepository.save( + FestivalFixture.builder().startDate(_6월_15일).endDate(_6월_15일).school(테코대학교).build() + ); + } + + @Nested + class findFestivalsBySchoolId { + + @Test + void 캐싱이_적용되어야_한다() { + // given + given(clock.instant()) + .willReturn(TimeInstantProvider.from(_6월_15일)); + var expect = schoolFestivalsV2QueryService.findFestivalsBySchoolId(테코대학교.getId()); + + // when + festivalRepository.save( + FestivalFixture.builder().startDate(_6월_15일).endDate(_6월_15일).school(테코대학교).build() + ); + var actual = schoolFestivalsV2QueryService.findFestivalsBySchoolId(테코대학교.getId()); + + // then + assertThat(actual).isEqualTo(expect); + } + } + + @Nested + class findPastFestivalsBySchoolId { + + @Test + void 캐싱이_적용되어야_한다() { + // given + given(clock.instant()) + .willReturn(TimeInstantProvider.from(_6월_16일)); + var expect = schoolFestivalsV2QueryService.findPastFestivalsBySchoolId(테코대학교.getId()); + + // when + festivalRepository.save( + FestivalFixture.builder().startDate(_6월_15일).endDate(_6월_15일).school(테코대학교).build() + ); + var actual = schoolFestivalsV2QueryService.findPastFestivalsBySchoolId(테코대학교.getId()); + + // then + assertThat(actual).isEqualTo(expect); + } + } +} diff --git a/backend/src/test/java/com/festago/support/ApplicationIntegrationTest.java b/backend/src/test/java/com/festago/support/ApplicationIntegrationTest.java index f76220f21..1c2d5b5df 100644 --- a/backend/src/test/java/com/festago/support/ApplicationIntegrationTest.java +++ b/backend/src/test/java/com/festago/support/ApplicationIntegrationTest.java @@ -7,7 +7,8 @@ @SpringBootTest @TestExecutionListeners(value = { ResetMockTestExecutionListener.class, - DatabaseClearTestExecutionListener.class + DatabaseClearTestExecutionListener.class, + CacheClearTestExecutionListener.class }, mergeMode = TestExecutionListeners.MergeMode.MERGE_WITH_DEFAULTS) @Import({TestTimeConfig.class}) public abstract class ApplicationIntegrationTest { diff --git a/backend/src/test/java/com/festago/support/CacheClearTestExecutionListener.java b/backend/src/test/java/com/festago/support/CacheClearTestExecutionListener.java new file mode 100644 index 000000000..38fa25475 --- /dev/null +++ b/backend/src/test/java/com/festago/support/CacheClearTestExecutionListener.java @@ -0,0 +1,22 @@ +package com.festago.support; + +import org.springframework.cache.Cache; +import org.springframework.cache.CacheManager; +import org.springframework.context.ApplicationContext; +import org.springframework.test.context.TestContext; +import org.springframework.test.context.TestExecutionListener; + +public class CacheClearTestExecutionListener implements TestExecutionListener { + + @Override + public void beforeTestMethod(TestContext testContext) { + ApplicationContext applicationContext = testContext.getApplicationContext(); + CacheManager cacheManager = applicationContext.getBean(CacheManager.class); + for (String cacheName : cacheManager.getCacheNames()) { + Cache cache = cacheManager.getCache(cacheName); + if (cache != null) { + cache.invalidate(); + } + } + } +} From f52187cab839bc17b6fa19235a675b5598eb4bf6 Mon Sep 17 00:00:00 2001 From: seokjin8678 Date: Wed, 17 Apr 2024 01:25:02 +0900 Subject: [PATCH 4/7] =?UTF-8?q?chore:=20V2=20->=20V1=20=EC=9D=B4=EB=A6=84?= =?UTF-8?q?=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - V1 존재하지 않기 때문에 V1 사용 --- .../SchoolFestivalsV1QueryService.java} | 16 ++++++++-------- ...java => SchoolFestivalsV1CacheConfig.java} | 12 ++++++------ ...lFestivalsV1CacheInvalidateScheduler.java} | 8 ++++---- .../SchoolFestivalsV1QueryDslRepository.java} | 4 ++-- .../SchoolFestivalsV1QueryServiceTest.java} | 19 ++++++++++--------- ... => SchoolFestivalsV1CacheConfigTest.java} | 18 +++++++++--------- 6 files changed, 39 insertions(+), 38 deletions(-) rename backend/src/main/java/com/festago/school/application/{v2/SchoolFestivalsV2QueryService.java => v1/SchoolFestivalsV1QueryService.java} (65%) rename backend/src/main/java/com/festago/school/infrastructure/{SchoolFestivalsV2CacheConfig.java => SchoolFestivalsV1CacheConfig.java} (70%) rename backend/src/main/java/com/festago/school/infrastructure/{SchoolFestivalsV2CacheInvalidateScheduler.java => SchoolFestivalsV1CacheInvalidateScheduler.java} (60%) rename backend/src/main/java/com/festago/school/repository/{v2/SchoolFestivalsV2QueryDslRepository.java => v1/SchoolFestivalsV1QueryDslRepository.java} (95%) rename backend/src/test/java/com/festago/school/application/{v2/SchoolFestivalsV2QueryServiceTest.java => integration/SchoolFestivalsV1QueryServiceTest.java} (91%) rename backend/src/test/java/com/festago/school/infrastructure/{SchoolFestivalsV2CacheConfigTest.java => SchoolFestivalsV1CacheConfigTest.java} (83%) diff --git a/backend/src/main/java/com/festago/school/application/v2/SchoolFestivalsV2QueryService.java b/backend/src/main/java/com/festago/school/application/v1/SchoolFestivalsV1QueryService.java similarity index 65% rename from backend/src/main/java/com/festago/school/application/v2/SchoolFestivalsV2QueryService.java rename to backend/src/main/java/com/festago/school/application/v1/SchoolFestivalsV1QueryService.java index 1043ff19a..ec1136b85 100644 --- a/backend/src/main/java/com/festago/school/application/v2/SchoolFestivalsV2QueryService.java +++ b/backend/src/main/java/com/festago/school/application/v1/SchoolFestivalsV1QueryService.java @@ -1,7 +1,7 @@ -package com.festago.school.application.v2; +package com.festago.school.application.v1; import com.festago.school.dto.v1.SchoolFestivalV1Response; -import com.festago.school.repository.v2.SchoolFestivalsV2QueryDslRepository; +import com.festago.school.repository.v1.SchoolFestivalsV1QueryDslRepository; import java.time.Clock; import java.time.LocalDate; import java.util.List; @@ -13,21 +13,21 @@ @Service @RequiredArgsConstructor @Transactional(readOnly = true) -public class SchoolFestivalsV2QueryService { +public class SchoolFestivalsV1QueryService { - public static final String SCHOOL_FESTIVALS_V2_CACHE_NAME = "schoolFestivalsV2"; - public static final String PAST_SCHOOL_FESTIVALS_V2_CACHE_NAME = "pastSchoolFestivalsV2"; + public static final String SCHOOL_FESTIVALS_V1_CACHE_NAME = "schoolFestivalsV1"; + public static final String PAST_SCHOOL_FESTIVALS_V1_CACHE_NAME = "pastSchoolFestivalsV1"; - private final SchoolFestivalsV2QueryDslRepository schoolFestivalsV1QueryDslRepository; + private final SchoolFestivalsV1QueryDslRepository schoolFestivalsV1QueryDslRepository; private final Clock clock; - @Cacheable(cacheNames = SCHOOL_FESTIVALS_V2_CACHE_NAME, key = "#schoolId") + @Cacheable(cacheNames = SCHOOL_FESTIVALS_V1_CACHE_NAME, key = "#schoolId") public List findFestivalsBySchoolId(Long schoolId) { LocalDate now = LocalDate.now(clock); return schoolFestivalsV1QueryDslRepository.findFestivalsBySchoolId(schoolId, now); } - @Cacheable(cacheNames = PAST_SCHOOL_FESTIVALS_V2_CACHE_NAME, key = "#schoolId") + @Cacheable(cacheNames = PAST_SCHOOL_FESTIVALS_V1_CACHE_NAME, key = "#schoolId") public List findPastFestivalsBySchoolId(Long schoolId) { LocalDate now = LocalDate.now(clock); return schoolFestivalsV1QueryDslRepository.findPastFestivalsBySchoolId(schoolId, now); diff --git a/backend/src/main/java/com/festago/school/infrastructure/SchoolFestivalsV2CacheConfig.java b/backend/src/main/java/com/festago/school/infrastructure/SchoolFestivalsV1CacheConfig.java similarity index 70% rename from backend/src/main/java/com/festago/school/infrastructure/SchoolFestivalsV2CacheConfig.java rename to backend/src/main/java/com/festago/school/infrastructure/SchoolFestivalsV1CacheConfig.java index 621de023d..b67733694 100644 --- a/backend/src/main/java/com/festago/school/infrastructure/SchoolFestivalsV2CacheConfig.java +++ b/backend/src/main/java/com/festago/school/infrastructure/SchoolFestivalsV1CacheConfig.java @@ -1,6 +1,6 @@ package com.festago.school.infrastructure; -import com.festago.school.application.v2.SchoolFestivalsV2QueryService; +import com.festago.school.application.v1.SchoolFestivalsV1QueryService; import com.github.benmanes.caffeine.cache.Caffeine; import java.util.concurrent.TimeUnit; import org.springframework.cache.Cache; @@ -9,14 +9,14 @@ import org.springframework.context.annotation.Configuration; @Configuration -public class SchoolFestivalsV2CacheConfig { +public class SchoolFestivalsV1CacheConfig { private static final long EXPIRED_AFTER_WRITE = 30; private static final long MAXIMUM_SIZE = 1_000; @Bean - public Cache schoolFestivalsV2Cache() { - return new CaffeineCache(SchoolFestivalsV2QueryService.SCHOOL_FESTIVALS_V2_CACHE_NAME, + public Cache schoolFestivalsV1Cache() { + return new CaffeineCache(SchoolFestivalsV1QueryService.SCHOOL_FESTIVALS_V1_CACHE_NAME, Caffeine.newBuilder() .recordStats() .expireAfterWrite(EXPIRED_AFTER_WRITE, TimeUnit.MINUTES) @@ -26,8 +26,8 @@ public Cache schoolFestivalsV2Cache() { } @Bean - public Cache pastschoolFestivalsV2Cache() { - return new CaffeineCache(SchoolFestivalsV2QueryService.PAST_SCHOOL_FESTIVALS_V2_CACHE_NAME, + public Cache pastSchoolFestivalsV1Cache() { + return new CaffeineCache(SchoolFestivalsV1QueryService.PAST_SCHOOL_FESTIVALS_V1_CACHE_NAME, Caffeine.newBuilder() .recordStats() .expireAfterWrite(EXPIRED_AFTER_WRITE, TimeUnit.MINUTES) diff --git a/backend/src/main/java/com/festago/school/infrastructure/SchoolFestivalsV2CacheInvalidateScheduler.java b/backend/src/main/java/com/festago/school/infrastructure/SchoolFestivalsV1CacheInvalidateScheduler.java similarity index 60% rename from backend/src/main/java/com/festago/school/infrastructure/SchoolFestivalsV2CacheInvalidateScheduler.java rename to backend/src/main/java/com/festago/school/infrastructure/SchoolFestivalsV1CacheInvalidateScheduler.java index 557b11723..589db6aea 100644 --- a/backend/src/main/java/com/festago/school/infrastructure/SchoolFestivalsV2CacheInvalidateScheduler.java +++ b/backend/src/main/java/com/festago/school/infrastructure/SchoolFestivalsV1CacheInvalidateScheduler.java @@ -1,7 +1,7 @@ package com.festago.school.infrastructure; import com.festago.common.cache.CacheInvalidator; -import com.festago.school.application.v2.SchoolFestivalsV2QueryService; +import com.festago.school.application.v1.SchoolFestivalsV1QueryService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.scheduling.annotation.Scheduled; @@ -10,14 +10,14 @@ @Component @RequiredArgsConstructor @Slf4j -public class SchoolFestivalsV2CacheInvalidateScheduler { +public class SchoolFestivalsV1CacheInvalidateScheduler { private final CacheInvalidator cacheInvalidator; // 매일 정각마다 캐시 초기화 @Scheduled(cron = "0 0 0 * * *") public void invalidate() { - cacheInvalidator.invalidate(SchoolFestivalsV2QueryService.SCHOOL_FESTIVALS_V2_CACHE_NAME); - cacheInvalidator.invalidate(SchoolFestivalsV2QueryService.PAST_SCHOOL_FESTIVALS_V2_CACHE_NAME); + cacheInvalidator.invalidate(SchoolFestivalsV1QueryService.SCHOOL_FESTIVALS_V1_CACHE_NAME); + cacheInvalidator.invalidate(SchoolFestivalsV1QueryService.PAST_SCHOOL_FESTIVALS_V1_CACHE_NAME); } } diff --git a/backend/src/main/java/com/festago/school/repository/v2/SchoolFestivalsV2QueryDslRepository.java b/backend/src/main/java/com/festago/school/repository/v1/SchoolFestivalsV1QueryDslRepository.java similarity index 95% rename from backend/src/main/java/com/festago/school/repository/v2/SchoolFestivalsV2QueryDslRepository.java rename to backend/src/main/java/com/festago/school/repository/v1/SchoolFestivalsV1QueryDslRepository.java index 00b1775ae..bf183410b 100644 --- a/backend/src/main/java/com/festago/school/repository/v2/SchoolFestivalsV2QueryDslRepository.java +++ b/backend/src/main/java/com/festago/school/repository/v1/SchoolFestivalsV1QueryDslRepository.java @@ -1,4 +1,4 @@ -package com.festago.school.repository.v2; +package com.festago.school.repository.v1; import static com.festago.festival.domain.QFestival.festival; import static com.festago.festival.domain.QFestivalQueryInfo.festivalQueryInfo; @@ -14,7 +14,7 @@ @Repository @RequiredArgsConstructor -public class SchoolFestivalsV2QueryDslRepository { +public class SchoolFestivalsV1QueryDslRepository { private final QueryDslHelper queryDslHelper; diff --git a/backend/src/test/java/com/festago/school/application/v2/SchoolFestivalsV2QueryServiceTest.java b/backend/src/test/java/com/festago/school/application/integration/SchoolFestivalsV1QueryServiceTest.java similarity index 91% rename from backend/src/test/java/com/festago/school/application/v2/SchoolFestivalsV2QueryServiceTest.java rename to backend/src/test/java/com/festago/school/application/integration/SchoolFestivalsV1QueryServiceTest.java index 0132b8c1f..a296bec86 100644 --- a/backend/src/test/java/com/festago/school/application/v2/SchoolFestivalsV2QueryServiceTest.java +++ b/backend/src/test/java/com/festago/school/application/integration/SchoolFestivalsV1QueryServiceTest.java @@ -1,10 +1,11 @@ -package com.festago.school.application.v2; +package com.festago.school.application.integration; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.BDDMockito.given; import com.festago.festival.domain.Festival; import com.festago.festival.repository.FestivalRepository; +import com.festago.school.application.v1.SchoolFestivalsV1QueryService; import com.festago.school.domain.School; import com.festago.school.dto.v1.SchoolFestivalV1Response; import com.festago.school.repository.SchoolRepository; @@ -23,10 +24,10 @@ @DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) @SuppressWarnings("NonAsciiCharacters") -class SchoolFestivalsV2QueryServiceTest extends ApplicationIntegrationTest { +class SchoolFestivalsV1QueryServiceTest extends ApplicationIntegrationTest { @Autowired - SchoolFestivalsV2QueryService schoolFestivalsV2QueryService; + SchoolFestivalsV1QueryService schoolFestivalsV1QueryService; @Autowired SchoolRepository schoolRepository; @@ -83,7 +84,7 @@ class findFestivalsBySchoolId { .willReturn(TimeInstantProvider.from(_6월_15일)); // when - var actual = schoolFestivalsV2QueryService.findFestivalsBySchoolId(우테대학교.getId()); + var actual = schoolFestivalsV1QueryService.findFestivalsBySchoolId(우테대학교.getId()); // then assertThat(actual).isEmpty(); @@ -96,7 +97,7 @@ class findFestivalsBySchoolId { .willReturn(TimeInstantProvider.from(_6월_15일)); // when - var actual = schoolFestivalsV2QueryService.findFestivalsBySchoolId(테코대학교.getId()); + var actual = schoolFestivalsV1QueryService.findFestivalsBySchoolId(테코대학교.getId()); // then assertThat(actual) @@ -116,7 +117,7 @@ class findFestivalsBySchoolId { .willReturn(TimeInstantProvider.from(_6월_18일)); // when - var actual = schoolFestivalsV2QueryService.findFestivalsBySchoolId(테코대학교.getId()); + var actual = schoolFestivalsV1QueryService.findFestivalsBySchoolId(테코대학교.getId()); // then assertThat(actual) @@ -138,7 +139,7 @@ class findPastFestivalsBySchoolId { .willReturn(TimeInstantProvider.from(_6월_15일)); // when - var actual = schoolFestivalsV2QueryService.findPastFestivalsBySchoolId(우테대학교.getId()); + var actual = schoolFestivalsV1QueryService.findPastFestivalsBySchoolId(우테대학교.getId()); // then assertThat(actual).isEmpty(); @@ -151,7 +152,7 @@ class findPastFestivalsBySchoolId { .willReturn(TimeInstantProvider.from(_6월_21일)); // when - var actual = schoolFestivalsV2QueryService.findPastFestivalsBySchoolId(테코대학교.getId()); + var actual = schoolFestivalsV1QueryService.findPastFestivalsBySchoolId(테코대학교.getId()); // then assertThat(actual) @@ -171,7 +172,7 @@ class findPastFestivalsBySchoolId { .willReturn(TimeInstantProvider.from(_6월_18일)); // when - var actual = schoolFestivalsV2QueryService.findPastFestivalsBySchoolId(테코대학교.getId()); + var actual = schoolFestivalsV1QueryService.findPastFestivalsBySchoolId(테코대학교.getId()); // then assertThat(actual) diff --git a/backend/src/test/java/com/festago/school/infrastructure/SchoolFestivalsV2CacheConfigTest.java b/backend/src/test/java/com/festago/school/infrastructure/SchoolFestivalsV1CacheConfigTest.java similarity index 83% rename from backend/src/test/java/com/festago/school/infrastructure/SchoolFestivalsV2CacheConfigTest.java rename to backend/src/test/java/com/festago/school/infrastructure/SchoolFestivalsV1CacheConfigTest.java index a00064415..21e59421e 100644 --- a/backend/src/test/java/com/festago/school/infrastructure/SchoolFestivalsV2CacheConfigTest.java +++ b/backend/src/test/java/com/festago/school/infrastructure/SchoolFestivalsV1CacheConfigTest.java @@ -4,10 +4,10 @@ import static org.mockito.BDDMockito.given; import com.festago.festival.repository.FestivalRepository; -import com.festago.school.application.v2.SchoolFestivalsV2QueryService; +import com.festago.school.application.v1.SchoolFestivalsV1QueryService; import com.festago.school.domain.School; import com.festago.school.repository.SchoolRepository; -import com.festago.school.repository.v2.SchoolFestivalsV2QueryDslRepository; +import com.festago.school.repository.v1.SchoolFestivalsV1QueryDslRepository; import com.festago.support.ApplicationIntegrationTest; import com.festago.support.TimeInstantProvider; import com.festago.support.fixture.FestivalFixture; @@ -23,13 +23,13 @@ @DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) @SuppressWarnings("NonAsciiCharacters") -class SchoolFestivalsV2CacheConfigTest extends ApplicationIntegrationTest { +class SchoolFestivalsV1CacheConfigTest extends ApplicationIntegrationTest { @Autowired - SchoolFestivalsV2QueryService schoolFestivalsV2QueryService; + SchoolFestivalsV1QueryService schoolFestivalsV1QueryService; @Autowired - SchoolFestivalsV2QueryDslRepository schoolFestivalsV2QueryDslRepository; + SchoolFestivalsV1QueryDslRepository schoolFestivalsV1QueryDslRepository; @Autowired SchoolRepository schoolRepository; @@ -60,13 +60,13 @@ class findFestivalsBySchoolId { // given given(clock.instant()) .willReturn(TimeInstantProvider.from(_6월_15일)); - var expect = schoolFestivalsV2QueryService.findFestivalsBySchoolId(테코대학교.getId()); + var expect = schoolFestivalsV1QueryService.findFestivalsBySchoolId(테코대학교.getId()); // when festivalRepository.save( FestivalFixture.builder().startDate(_6월_15일).endDate(_6월_15일).school(테코대학교).build() ); - var actual = schoolFestivalsV2QueryService.findFestivalsBySchoolId(테코대학교.getId()); + var actual = schoolFestivalsV1QueryService.findFestivalsBySchoolId(테코대학교.getId()); // then assertThat(actual).isEqualTo(expect); @@ -81,13 +81,13 @@ class findPastFestivalsBySchoolId { // given given(clock.instant()) .willReturn(TimeInstantProvider.from(_6월_16일)); - var expect = schoolFestivalsV2QueryService.findPastFestivalsBySchoolId(테코대학교.getId()); + var expect = schoolFestivalsV1QueryService.findPastFestivalsBySchoolId(테코대학교.getId()); // when festivalRepository.save( FestivalFixture.builder().startDate(_6월_15일).endDate(_6월_15일).school(테코대학교).build() ); - var actual = schoolFestivalsV2QueryService.findPastFestivalsBySchoolId(테코대학교.getId()); + var actual = schoolFestivalsV1QueryService.findPastFestivalsBySchoolId(테코대학교.getId()); // then assertThat(actual).isEqualTo(expect); From 115c9eb2e903de129783c74ab94fb34e0d052c49 Mon Sep 17 00:00:00 2001 From: seokjin8678 Date: Wed, 17 Apr 2024 01:43:32 +0900 Subject: [PATCH 5/7] =?UTF-8?q?chore:=20SchoolFestivalsV1CacheInvalidateSc?= =?UTF-8?q?heduler=20=ED=8C=A8=ED=82=A4=EC=A7=80=20=EC=9C=84=EC=B9=98=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../v1}/SchoolFestivalsV1CacheInvalidateScheduler.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) rename backend/src/main/java/com/festago/school/{infrastructure => application/v1}/SchoolFestivalsV1CacheInvalidateScheduler.java (81%) diff --git a/backend/src/main/java/com/festago/school/infrastructure/SchoolFestivalsV1CacheInvalidateScheduler.java b/backend/src/main/java/com/festago/school/application/v1/SchoolFestivalsV1CacheInvalidateScheduler.java similarity index 81% rename from backend/src/main/java/com/festago/school/infrastructure/SchoolFestivalsV1CacheInvalidateScheduler.java rename to backend/src/main/java/com/festago/school/application/v1/SchoolFestivalsV1CacheInvalidateScheduler.java index 589db6aea..b2997b80c 100644 --- a/backend/src/main/java/com/festago/school/infrastructure/SchoolFestivalsV1CacheInvalidateScheduler.java +++ b/backend/src/main/java/com/festago/school/application/v1/SchoolFestivalsV1CacheInvalidateScheduler.java @@ -1,15 +1,12 @@ -package com.festago.school.infrastructure; +package com.festago.school.application.v1; import com.festago.common.cache.CacheInvalidator; -import com.festago.school.application.v1.SchoolFestivalsV1QueryService; import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; @Component @RequiredArgsConstructor -@Slf4j public class SchoolFestivalsV1CacheInvalidateScheduler { private final CacheInvalidator cacheInvalidator; From 218aad392373d16ef679e92f49fd51e0a8c33bb6 Mon Sep 17 00:00:00 2001 From: seokjin8678 Date: Wed, 17 Apr 2024 02:54:42 +0900 Subject: [PATCH 6/7] =?UTF-8?q?feat:=20CacheStatsLogger=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 어플리케이션 종료 시점에 캐시 스탯 로깅 --- .../common/cache/CacheStatsLogger.java | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 backend/src/main/java/com/festago/common/cache/CacheStatsLogger.java diff --git a/backend/src/main/java/com/festago/common/cache/CacheStatsLogger.java b/backend/src/main/java/com/festago/common/cache/CacheStatsLogger.java new file mode 100644 index 000000000..215bbe8b8 --- /dev/null +++ b/backend/src/main/java/com/festago/common/cache/CacheStatsLogger.java @@ -0,0 +1,28 @@ +package com.festago.common.cache; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.cache.Cache; +import org.springframework.cache.CacheManager; +import org.springframework.cache.caffeine.CaffeineCache; +import org.springframework.context.event.ContextClosedEvent; +import org.springframework.context.event.EventListener; +import org.springframework.stereotype.Component; + +@Slf4j +@Component +@RequiredArgsConstructor +public class CacheStatsLogger { + + private final CacheManager cacheManager; + + @EventListener(ContextClosedEvent.class) + public void logCacheStats() { + for (String cacheName : cacheManager.getCacheNames()) { + Cache cache = cacheManager.getCache(cacheName); + if (cache instanceof CaffeineCache caffeineCache) { + log.info("CacheName={} CacheStats={}", cacheName, caffeineCache.getNativeCache().stats()); + } + } + } +} From 81ec9480fba9e456d47a787cdb4804228c745ffd Mon Sep 17 00:00:00 2001 From: seokjin8678 Date: Wed, 17 Apr 2024 03:00:55 +0900 Subject: [PATCH 7/7] =?UTF-8?q?chore:=20CacheStatsLogger=20`@Profile({"!te?= =?UTF-8?q?st"})`=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 로그 목적이므로 테스트에서 제외 --- .../main/java/com/festago/common/cache/CacheStatsLogger.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/backend/src/main/java/com/festago/common/cache/CacheStatsLogger.java b/backend/src/main/java/com/festago/common/cache/CacheStatsLogger.java index 215bbe8b8..3fb6d9832 100644 --- a/backend/src/main/java/com/festago/common/cache/CacheStatsLogger.java +++ b/backend/src/main/java/com/festago/common/cache/CacheStatsLogger.java @@ -5,10 +5,12 @@ import org.springframework.cache.Cache; import org.springframework.cache.CacheManager; import org.springframework.cache.caffeine.CaffeineCache; +import org.springframework.context.annotation.Profile; import org.springframework.context.event.ContextClosedEvent; import org.springframework.context.event.EventListener; import org.springframework.stereotype.Component; +@Profile({"!test"}) @Slf4j @Component @RequiredArgsConstructor