Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
import com.example.solidconnection.admin.university.dto.AdminHostUniversityResponse;
import com.example.solidconnection.admin.university.dto.AdminHostUniversitySearchCondition;
import com.example.solidconnection.admin.university.dto.AdminHostUniversityUpdateRequest;
import com.example.solidconnection.cache.annotation.DefaultCacheOut;
import com.example.solidconnection.cache.manager.CustomCacheManager;
import com.example.solidconnection.common.exception.CustomException;
import com.example.solidconnection.location.country.domain.Country;
import com.example.solidconnection.location.country.repository.CountryRepository;
Expand All @@ -19,6 +21,7 @@
import com.example.solidconnection.university.domain.HostUniversity;
import com.example.solidconnection.university.repository.HostUniversityRepository;
import com.example.solidconnection.university.repository.UnivApplyInfoRepository;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
Expand All @@ -33,6 +36,7 @@ public class AdminHostUniversityService {
private final CountryRepository countryRepository;
private final RegionRepository regionRepository;
private final UnivApplyInfoRepository univApplyInfoRepository;
private final CustomCacheManager cacheManager;

@Transactional(readOnly = true)
public Page<AdminHostUniversityResponse> getHostUniversities(
Expand All @@ -56,6 +60,11 @@ public AdminHostUniversityDetailResponse getHostUniversity(Long id) {
}

@Transactional
@DefaultCacheOut(
key = {"univApplyInfoTextSearch", "university:recommend:general"},
cacheManager = "customCacheManager",
prefix = true
)
public AdminHostUniversityDetailResponse createHostUniversity(AdminHostUniversityCreateRequest request) {
validateKoreanNameNotExists(request.koreanName());

Expand Down Expand Up @@ -89,6 +98,11 @@ private void validateKoreanNameNotExists(String koreanName) {
}

@Transactional
@DefaultCacheOut(
key = {"univApplyInfoTextSearch", "university:recommend:general"},
cacheManager = "customCacheManager",
prefix = true
)
public AdminHostUniversityDetailResponse updateHostUniversity(Long id, AdminHostUniversityUpdateRequest request) {
HostUniversity hostUniversity = hostUniversityRepository.findById(id)
.orElseThrow(() -> new CustomException(UNIVERSITY_NOT_FOUND));
Expand All @@ -112,6 +126,8 @@ public AdminHostUniversityDetailResponse updateHostUniversity(Long id, AdminHost
region
);

evictUnivApplyInfoDetailCaches(id);

return AdminHostUniversityDetailResponse.from(hostUniversity);
}

Expand All @@ -135,6 +151,11 @@ private Region findRegionByCode(String regionCode) {
}

@Transactional
@DefaultCacheOut(
key = {"univApplyInfoTextSearch", "university:recommend:general"},
cacheManager = "customCacheManager",
prefix = true
)
public void deleteHostUniversity(Long id) {
HostUniversity hostUniversity = hostUniversityRepository.findById(id)
.orElseThrow(() -> new CustomException(UNIVERSITY_NOT_FOUND));
Expand All @@ -149,4 +170,14 @@ private void validateNoReferences(Long hostUniversityId) {
throw new CustomException(HOST_UNIVERSITY_HAS_REFERENCES);
}
}

private void evictUnivApplyInfoDetailCaches(Long hostUniversityId) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

마지막으로 해당 메서드를 호출하는 곳이 updateHostUniversity이기에 해당 메서드 밑에 선언부를 위치시켜주세요 !

List<Long> affectedUnivApplyInfoIds = univApplyInfoRepository.findIdsByUniversityId(hostUniversityId);

List<String> cacheKeys = affectedUnivApplyInfoIds.stream()
.map(univApplyInfoId -> "univApplyInfo:" + univApplyInfoId)
.toList();

cacheManager.evictMultiple(cacheKeys);
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.example.solidconnection.cache.manager;

import java.time.Duration;
import java.util.List;
import java.util.Set;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
Expand Down Expand Up @@ -38,4 +39,10 @@ public void evictUsingPrefix(String key) {
redisTemplate.delete(keys);
}
}

public void evictMultiple(List<String> keys) {
if (keys != null && !keys.isEmpty()) {
redisTemplate.delete(keys);
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CacheManager 인터페이스에 해당 추상 메서드 작성해주세요 !!

}
Original file line number Diff line number Diff line change
Expand Up @@ -68,4 +68,11 @@ default UnivApplyInfo getUnivApplyInfoById(Long id) {
List<UnivApplyInfo> findAllByIds(@Param("ids") List<Long> ids);

boolean existsByUniversityId(Long universityId);

@Query("""
SELECT uai.id
FROM UnivApplyInfo uai
WHERE uai.university.id = :universityId
""")
List<Long> findIdsByUniversityId(@Param("universityId") Long universityId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatCode;
import static org.mockito.BDDMockito.then;
import static org.mockito.Mockito.times;

import com.example.solidconnection.admin.university.dto.AdminHostUniversityCreateRequest;
import com.example.solidconnection.admin.university.dto.AdminHostUniversityDetailResponse;
import com.example.solidconnection.admin.university.dto.AdminHostUniversityResponse;
import com.example.solidconnection.admin.university.dto.AdminHostUniversitySearchCondition;
import com.example.solidconnection.admin.university.dto.AdminHostUniversityUpdateRequest;
import com.example.solidconnection.admin.university.service.AdminHostUniversityService;
import com.example.solidconnection.cache.manager.CustomCacheManager;
import com.example.solidconnection.common.exception.CustomException;
import com.example.solidconnection.common.exception.ErrorCode;
import com.example.solidconnection.location.country.domain.Country;
Expand All @@ -17,13 +20,16 @@
import com.example.solidconnection.location.region.fixture.RegionFixture;
import com.example.solidconnection.support.TestContainerSpringBootTest;
import com.example.solidconnection.university.domain.HostUniversity;
import com.example.solidconnection.university.domain.UnivApplyInfo;
import com.example.solidconnection.university.fixture.UnivApplyInfoFixtureBuilder;
import com.example.solidconnection.university.fixture.UniversityFixture;
import com.example.solidconnection.university.repository.HostUniversityRepository;
import java.util.List;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.mock.mockito.SpyBean;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;

Expand All @@ -49,6 +55,9 @@ class AdminHostUniversityServiceTest {
@Autowired
private UnivApplyInfoFixtureBuilder univApplyInfoFixtureBuilder;

@SpyBean
private CustomCacheManager cacheManager;

@Nested
class 목록_조회 {

Expand Down Expand Up @@ -398,4 +407,82 @@ class 삭제 {
.hasMessage(ErrorCode.HOST_UNIVERSITY_HAS_REFERENCES.getMessage());
}
}

@Nested
class 캐시_무효화 {

@Test
void 대학_생성_시_캐시가_무효화된다() {
// given
Country country = countryFixture.미국();
Region region = regionFixture.영미권();

AdminHostUniversityCreateRequest request = new AdminHostUniversityCreateRequest(
"캐시 테스트 대학",
"Cache Test University",
"캐시 테스트 대학",
"https://homepage.com",
null, null,
"https://logo.com/image.png",
"https://background.com/image.png",
null,
country.getCode(),
region.getCode()
);

// when
adminHostUniversityService.createHostUniversity(request);

// then
then(cacheManager).should(times(1)).evictUsingPrefix("univApplyInfoTextSearch");
then(cacheManager).should(times(1)).evictUsingPrefix("university:recommend:general");
}

@Test
void 대학_수정_시_캐시가_무효화된다() {
// given
HostUniversity university = universityFixture.괌_대학();
UnivApplyInfo univApplyInfo = univApplyInfoFixtureBuilder.univApplyInfo()
.termId(1L)
.koreanName("괌 대학 지원 정보")
.university(university)
.create();

Country country = countryFixture.일본();
Region region = regionFixture.아시아();

AdminHostUniversityUpdateRequest request = new AdminHostUniversityUpdateRequest(
"수정된 대학명",
"Updated University",
"수정된 표시명",
null, null, null,
"https://logo.com/image.png",
"https://background.com/image.png",
null,
country.getCode(),
region.getCode()
);

// when
adminHostUniversityService.updateHostUniversity(university.getId(), request);

// then
then(cacheManager).should(times(1)).evictUsingPrefix("univApplyInfoTextSearch");
then(cacheManager).should(times(1)).evictUsingPrefix("university:recommend:general");
then(cacheManager).should(times(1)).evictMultiple(List.of("univApplyInfo:" + univApplyInfo.getId()));
}

@Test
void 대학_삭제_시_캐시가_무효화된다() {
// given
HostUniversity university = universityFixture.괌_대학();

// when
adminHostUniversityService.deleteHostUniversity(university.getId());

// then
then(cacheManager).should(times(1)).evictUsingPrefix("univApplyInfoTextSearch");
then(cacheManager).should(times(1)).evictUsingPrefix("university:recommend:general");
}
}
}
Loading