Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

캐싱이 필요한 API 캐싱 구현 #170

Merged
merged 12 commits into from
Jan 23, 2024
Merged
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
2 changes: 2 additions & 0 deletions src/main/java/com/coolpeace/CoolPeaceApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@

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 CoolPeaceApplication {

public static void main(String[] args) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import com.coolpeace.global.jwt.security.JwtPrincipal;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

@Service
Expand All @@ -22,6 +23,7 @@ public class AccomodationService {
private final AccommodationRepository accommodationRepository;
private final RoomRepository roomRepository;

@Cacheable(value = "accommodation", key = "#jwtPrincipal.toString()",cacheManager = "contentCacheManager")
public List<AccommodationResponse> getAccommodations(JwtPrincipal jwtPrincipal) {

Long memberId = Long.parseLong(jwtPrincipal.getMemberId());
Expand All @@ -34,6 +36,7 @@ public List<AccommodationResponse> getAccommodations(JwtPrincipal jwtPrincipal)
.toList();
}

@Cacheable(value = "rooms", key = "#accommodationId",cacheManager = "contentCacheManager")
public List<RoomResponse> getRooms(JwtPrincipal jwtPrincipal, Long accommodationId) {

Long memberId = Long.parseLong(jwtPrincipal.getMemberId());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import com.coolpeace.domain.coupon.repository.CouponRepository;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

Expand All @@ -16,17 +17,21 @@ public class CouponQueryService {

private final CouponRepository couponRepository;

@Cacheable(value = "dailyReport", key = "#accommodationId",cacheManager = "contentCacheManager")
public CouponDailyResponse dailyReport(String jwtPrincipal, Long accommodationId) {
Long memberId = Long.valueOf(jwtPrincipal);

if (Boolean.TRUE.equals(couponRepository.noRegister(memberId, accommodationId))) {
return CouponDailyResponse.from(1,CouponDailyCondition.NO_REGISTER);
}

List<Coupon> expiration3daysCoupons = couponRepository.expiration3days(memberId,
accommodationId);
if (!expiration3daysCoupons.isEmpty()) {
return CouponDailyResponse.from(3, CouponDailyCondition.EXPIRATION_3DAYS,
expiration3daysCoupons.stream().map(Coupon::getCouponTitle).toList());
}

if (Boolean.TRUE.equals(couponRepository.noExposure(memberId, accommodationId))) {
return CouponDailyResponse.from(2, CouponDailyCondition.NO_EXPOSURE);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,12 @@
import com.coolpeace.domain.coupon.dto.response.CouponCategoryResponse;
import com.coolpeace.domain.coupon.dto.response.CouponResponse;
import com.coolpeace.domain.coupon.entity.Coupon;
import com.coolpeace.domain.coupon.entity.type.*;
import com.coolpeace.domain.coupon.entity.type.CouponIssuerType;
import com.coolpeace.domain.coupon.entity.type.CouponRoomType;
import com.coolpeace.domain.coupon.entity.type.CouponStatusType;
import com.coolpeace.domain.coupon.entity.type.CouponUseDaysType;
import com.coolpeace.domain.coupon.entity.type.CustomerType;
import com.coolpeace.domain.coupon.entity.type.DiscountType;
import com.coolpeace.domain.coupon.exception.CouponAccessDeniedException;
import com.coolpeace.domain.coupon.exception.CouponNotFoundException;
import com.coolpeace.domain.coupon.exception.CouponUpdateLimitExposureStateException;
Expand All @@ -24,7 +29,13 @@
import com.coolpeace.domain.room.exception.RoomNotFoundException;
import com.coolpeace.domain.room.repository.RoomRepository;
import com.coolpeace.global.common.ValuedEnum;
import java.time.LocalDate;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import lombok.RequiredArgsConstructor;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
Expand All @@ -33,12 +44,6 @@
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.time.LocalDate;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;

@RequiredArgsConstructor
@Service
public class CouponService {
Expand Down Expand Up @@ -84,6 +89,7 @@ public List<CouponResponse> getRecentHistory(Long memberId) {
}

@Transactional
@CacheEvict(value = "dailyReport", key = "#couponRegisterRequest.accommodationId()",cacheManager = "contentCacheManager")
public void register(Long memberId, CouponRegisterRequest couponRegisterRequest) {
Member storedMember = memberRepository.findById(memberId).orElseThrow(MemberNotFoundException::new);
Accommodation accommodation = accommodationRepository.findById(couponRegisterRequest.accommodationId())
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.coolpeace.domain.dashboard.dto.response;

import java.util.List;

public record WrapMonthlyDataResponse (
List<MonthlyDataResponse> monthlyDataResponses
){

public static WrapMonthlyDataResponse from(List<MonthlyDataResponse> monthlyDataResponses) {
return new WrapMonthlyDataResponse(monthlyDataResponses);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import com.coolpeace.domain.dashboard.dto.response.MonthlyDataLightResponse;
import com.coolpeace.domain.dashboard.dto.response.MonthlyDataResponse;
import com.coolpeace.domain.dashboard.dto.response.WeeklyCouponResponse;
import com.coolpeace.domain.dashboard.dto.response.WrapMonthlyDataResponse;
import com.coolpeace.domain.member.entity.Member;
import com.coolpeace.domain.member.exception.MemberNotFoundException;
import com.coolpeace.domain.member.repository.MemberRepository;
Expand All @@ -28,6 +29,7 @@
import java.util.Comparator;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

Expand All @@ -42,7 +44,8 @@ public class DashboardService {
private final AccommodationRepository accommodationRepository;
private final LocalCouponDownloadRepository localCouponDownloadRepository;

public List<MonthlyDataResponse> monthlyData(String memberId, Long accommodationId) {
@Cacheable(value = "monthlyData", key = "#accommodationId", cacheManager = "contentCacheManager")
public WrapMonthlyDataResponse monthlyData(String memberId, Long accommodationId) {
Accommodation accommodation = checkAccommodationMatchMember(memberId, accommodationId);
MonthlySearchDate monthlySearchDate = MonthlySearchDate.getMonthlySearchDate(0,0);

Expand All @@ -51,11 +54,11 @@ public List<MonthlyDataResponse> monthlyData(String memberId, Long accommodation
monthlyStatisticsRepository.findLast6monthsMonthlyStatistics
(accommodation, last6Months[0], last6Months[1], last6Months[2], last6Months[3]);

return last6monthsMonthlyStatistics.stream()
.map(MonthlyDataResponse::from).toList();

return WrapMonthlyDataResponse.from(last6monthsMonthlyStatistics.stream()
.map(MonthlyDataResponse::from).toList());
}

@Cacheable(value = "weeklyCoupon", key = "#accommodationId", cacheManager = "contentCacheManager")
public WeeklyCouponResponse weeklyCoupon(String memberId, Long accommodationId) {
Accommodation accommodation = checkAccommodationMatchMember(memberId, accommodationId);

Expand All @@ -65,6 +68,7 @@ public WeeklyCouponResponse weeklyCoupon(String memberId, Long accommodationId)
return WeeklyCouponResponse.from(dailyStatisticsList);
}

@Cacheable(value = "downloadCouponTop3", key = "#accommodationId", cacheManager = "contentCacheManager")
public MonthlyCouponDownloadResponse downloadCouponTop3(String memberId, Long accommodationId) {
Accommodation accommodation = checkAccommodationMatchMember(memberId, accommodationId);
MonthlySearchDate monthlySearchDate = MonthlySearchDate.getMonthlySearchDate(0,0);
Expand All @@ -78,6 +82,7 @@ public MonthlyCouponDownloadResponse downloadCouponTop3(String memberId, Long ac

}

@Cacheable(value = "couponCountAvg", key = "#accommodationId", cacheManager = "contentCacheManager")
public CouponCountAvgResponse couponCountAvg(String memberId,Long accommodationId) {
Accommodation accommodation = checkAccommodationMatchMember(memberId, accommodationId);
MonthlySearchDate monthlySearchDate = MonthlySearchDate.getMonthlySearchDate(0,0);
Expand All @@ -91,7 +96,7 @@ public CouponCountAvgResponse couponCountAvg(String memberId,Long accommodationI
return getCouponCountAvgResponse(type, localCouponDownload, address);
}


@Cacheable(value = "byYearCumulativeData", key = "#accommodationId", cacheManager = "contentCacheManager")
public ByYearCumulativeDataResponse byYearCumulativeData(int year, String memberId, Long accommodationId) {
Accommodation accommodation = checkAccommodationMatchMember(memberId, accommodationId);
List<MonthlyStatistics> monthlyStatisticsList = monthlyStatisticsRepository
Expand All @@ -113,7 +118,7 @@ public ByYearCumulativeDataResponse byYearCumulativeData(int year, String member
.map(MonthlyDataLightResponse::from).toList());
}


@Cacheable(value = "cumulativeData", key = "#accommodationId", cacheManager = "contentCacheManager")
public CumulativeDataResponse cumulativeData(String memberId, Long accommodationId) {
Accommodation accommodation = checkAccommodationMatchMember(memberId, accommodationId);
List<MonthlyStatistics> monthlyStatisticsList = monthlyStatisticsRepository
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import java.time.LocalDate;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;
Expand All @@ -37,6 +38,7 @@ public class SettlementService {
private final AccommodationRepository accommodationRepository;
private final MemberRepository memberRepository;

@Cacheable(value = "sumSettlement", key = "#accommodationId", cacheManager = "contentCacheManager")
public SumSettlementResponse sumSettlement(String memberId, Long accommodationId) {
Accommodation accommodation = checkAccommodationMatchMember(memberId, accommodationId);
MonthlySearchDate monthlySearchDate = MonthlySearchDate.getMonthlySearchDate(0,0);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,12 @@
import com.coolpeace.domain.statistics.entity.DailyStatistics;
import com.coolpeace.domain.statistics.exception.DailyStatisticsNotFoundException;
import com.coolpeace.domain.statistics.repository.DailyStatisticsRepository;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDate;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@RequiredArgsConstructor
Expand All @@ -33,6 +34,7 @@ public class DailyStatisticsService {

private final SettlementRepository settlementRepository;

@CacheEvict(value = "weeklyCoupon", cacheManager = "contentCacheManager")
public void updateSales(int statisticsYear, int statisticsMonth, int statisticsDay){
DailySearchDate dailySearchDate = DailySearchDate.
getDailySearchDate(statisticsYear,statisticsMonth,statisticsDay);
Expand Down Expand Up @@ -90,6 +92,7 @@ public void updateCoupon(int statisticsYear, int statisticsMonth, int statistics
});
}

@CacheEvict(value = "sumSettlement", cacheManager = "contentCacheManager")
public void updateSettlement(int statisticsYear, int statisticsMonth, int statisticsDay){
DailySearchDate dailySearchDate = DailySearchDate.
getDailySearchDate(statisticsYear,statisticsMonth,statisticsDay);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import java.time.LocalDate;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

Expand All @@ -31,6 +32,7 @@ public class MonthlyStatisticsService {
private final LocalCouponDownloadRepository localCouponDownloadRepository;
private final AccommodationRepository accommodationRepository;

@CacheEvict(value = {"monthlyData","byYearCumulativeData","cumulativeData "}, cacheManager = "contentCacheManager")
public void updateMonthlySum(int statisticsYear, int statisticsMonth) {
MonthlySearchDate monthlySearchDate = MonthlySearchDate.
getMonthlySearchDate(statisticsYear,statisticsMonth);
Expand Down Expand Up @@ -64,7 +66,7 @@ public void updateMonthlySum(int statisticsYear, int statisticsMonth) {
});
}


@CacheEvict(value = {"downloadCouponTop3","couponCountAvg"}, cacheManager = "contentCacheManager")
public void updateCouponDownloadTop3(int statisticsYear, int statisticsMonth) {
MonthlySearchDate monthlySearchDate = MonthlySearchDate.
getMonthlySearchDate(statisticsYear,statisticsMonth);
Expand Down
31 changes: 31 additions & 0 deletions src/main/java/com/coolpeace/global/config/RedisCacheConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.coolpeace.global.config;

import java.time.Duration;
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.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext.SerializationPair;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@Configuration
@EnableCaching
public class RedisCacheConfig {

@Bean
public CacheManager contentCacheManager(RedisConnectionFactory cf) {
RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
.serializeKeysWith(SerializationPair.fromSerializer(
new StringRedisSerializer()))
.serializeValuesWith(SerializationPair.fromSerializer(
new GenericJackson2JsonRedisSerializer()))
.entryTtl(Duration.ofHours(12));

return RedisCacheManager.RedisCacheManagerBuilder.fromConnectionFactory(cf)
.cacheDefaults(redisCacheConfiguration).build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import com.coolpeace.domain.dashboard.dto.response.MonthlyDataLightResponse;
import com.coolpeace.domain.dashboard.dto.response.MonthlyDataResponse;
import com.coolpeace.domain.dashboard.dto.response.WeeklyCouponResponse;
import com.coolpeace.domain.dashboard.dto.response.WrapMonthlyDataResponse;
import com.coolpeace.domain.dashboard.service.DashboardService;
import com.coolpeace.domain.member.entity.Member;
import com.coolpeace.domain.room.entity.Room;
Expand Down Expand Up @@ -68,7 +69,9 @@ void monthlyData_success() throws Exception {
List<MonthlyDataResponse> monthlyDataResponses = monthlyStatistics.stream()
.map(MonthlyDataResponse::from).toList();

given(dashboardService.monthlyData(any(), anyLong())).willReturn(monthlyDataResponses);
WrapMonthlyDataResponse wrapMonthlyDataResponse =
WrapMonthlyDataResponse.from(monthlyDataResponses);
given(dashboardService.monthlyData(any(), anyLong())).willReturn(wrapMonthlyDataResponse);
//when,then
mockMvc.perform(RestDocumentationRequestBuilders
.get("/v1/dashboards/{accommodation_id}/reports/month", 1L)
Expand All @@ -80,21 +83,21 @@ void monthlyData_success() throws Exception {
.description("월간 비교 그래프 조회 API")
.responseSchema(Schema.schema(MonthlyDataResponse.class.getSimpleName()))
.responseFields(
fieldWithPath("[].statistics_year").type(JsonFieldType.NUMBER)
fieldWithPath(".monthly_data_responses[].statistics_year").type(JsonFieldType.NUMBER)
.description("통계 집계한 연도"),
fieldWithPath("[].statistics_month").type(JsonFieldType.NUMBER)
fieldWithPath(".monthly_data_responses[].statistics_month").type(JsonFieldType.NUMBER)
.description("통계 집계한 월"),
fieldWithPath("[].total_sales").type(JsonFieldType.NUMBER)
fieldWithPath(".monthly_data_responses[].total_sales").type(JsonFieldType.NUMBER)
.description("해당 월 총 매출 "),
fieldWithPath("[].coupon_total_sales").type(JsonFieldType.NUMBER)
fieldWithPath(".monthly_data_responses[].coupon_total_sales").type(JsonFieldType.NUMBER)
.description("쿠폰 적용 매출"),
fieldWithPath("[].download_count").type(JsonFieldType.NUMBER)
fieldWithPath(".monthly_data_responses[].download_count").type(JsonFieldType.NUMBER)
.description("쿠폰 다운로드 수"),
fieldWithPath("[].used_count").type(JsonFieldType.NUMBER)
fieldWithPath(".monthly_data_responses[].used_count").type(JsonFieldType.NUMBER)
.description("쿠폰 사용 완료 수 "),
fieldWithPath("[].settlement_amount").type(JsonFieldType.NUMBER)
fieldWithPath(".monthly_data_responses[].settlement_amount").type(JsonFieldType.NUMBER)
.description("이번달 쿠폰 정산 금액"),
fieldWithPath("[].conversion_rate").type(JsonFieldType.NUMBER)
fieldWithPath(".monthly_data_responses[].conversion_rate").type(JsonFieldType.NUMBER)
.description("전환율")
)
.build()
Expand Down
Loading