콘텐츠 메인 캐싱 전략 변경 - repository 에 있던 @Cacheable 을 service 코드로 이동
This commit is contained in:
		| @@ -4,10 +4,13 @@ import org.springframework.beans.factory.annotation.Value | ||||
| 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.connection.lettuce.LettuceConnectionFactory | ||||
| import org.springframework.data.redis.core.RedisTemplate | ||||
| import org.springframework.data.redis.repository.configuration.EnableRedisRepositories | ||||
| import java.time.Duration | ||||
|  | ||||
| @Configuration | ||||
| @EnableCaching | ||||
| @@ -29,4 +32,21 @@ class RedisConfig( | ||||
|         redisTemplate.setConnectionFactory(redisConnectionFactory()) | ||||
|         return redisTemplate | ||||
|     } | ||||
|  | ||||
|     @Bean | ||||
|     fun cacheManager(redisConnectionFactory: RedisConnectionFactory): RedisCacheManager { | ||||
|         val defaultCacheConfig = RedisCacheConfiguration.defaultCacheConfig() | ||||
|             .entryTtl(Duration.ofMinutes(30)) | ||||
|  | ||||
|         val cacheConfigMap = mutableMapOf<String, RedisCacheConfiguration>() | ||||
|         cacheConfigMap["default"] = RedisCacheConfiguration.defaultCacheConfig() | ||||
|             .entryTtl(Duration.ofMinutes(30)) | ||||
|         cacheConfigMap["cache_ttl_3_days"] = RedisCacheConfiguration.defaultCacheConfig() | ||||
|             .entryTtl(Duration.ofDays(3)) | ||||
|  | ||||
|         return RedisCacheManager.builder(redisConnectionFactory) | ||||
|             .cacheDefaults(defaultCacheConfig) | ||||
|             .withInitialCacheConfigurations(cacheConfigMap) | ||||
|             .build() | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -10,6 +10,7 @@ import kr.co.vividnext.sodalive.event.EventItem | ||||
| import kr.co.vividnext.sodalive.member.Member | ||||
| import kr.co.vividnext.sodalive.member.block.BlockMemberRepository | ||||
| import org.springframework.beans.factory.annotation.Value | ||||
| import org.springframework.cache.annotation.Cacheable | ||||
| import org.springframework.data.domain.Pageable | ||||
| import org.springframework.stereotype.Service | ||||
| import java.time.DayOfWeek | ||||
| @@ -29,21 +30,103 @@ class AudioContentMainService( | ||||
| ) { | ||||
|     fun getMain(member: Member): GetAudioContentMainResponse { | ||||
|         val isAdult = member.auth != null | ||||
|         val memberId = member.id!! | ||||
|  | ||||
|         // 2주일 이내에 콘텐츠를 올린 크리에이터 20명 조회 | ||||
|         val newContentUploadCreatorList = repository.getNewContentUploadCreatorList( | ||||
|         val newContentUploadCreatorList = getNewContentUploadCreatorList(memberId = memberId, isAdult = isAdult) | ||||
|  | ||||
|         val bannerList = getAudioContentMainBannerList(memberId = memberId, isAdult = isAdult) | ||||
|  | ||||
|         // 구매목록 20개 | ||||
|         val orderList = orderService.getAudioContentMainOrderList( | ||||
|             member = member, | ||||
|             limit = 20 | ||||
|         ) | ||||
|  | ||||
|         // 콘텐츠 테마 | ||||
|         val themeList = audioContentThemeRepository.getActiveThemeOfContent(isAdult = isAdult) | ||||
|  | ||||
|         // 새 콘텐츠 20개 - 시간 내림차순 정렬 | ||||
|         val newContentList = repository.findByTheme( | ||||
|             cloudfrontHost = imageHost, | ||||
|             isAdult = isAdult | ||||
|         ) | ||||
|             .asSequence() | ||||
|             .filter { !blockMemberRepository.isBlocked(blockedMemberId = member.id!!, memberId = it.creatorId) } | ||||
|             .filter { !blockMemberRepository.isBlocked(blockedMemberId = memberId, memberId = it.creatorId) } | ||||
|             .toList() | ||||
|  | ||||
|         val bannerList = repository.getAudioContentMainBannerList(isAdult = isAdult) | ||||
|         val curationList = getAudioContentCurationList(memberId = memberId, isAdult = isAdult) | ||||
|  | ||||
|         val currentDateTime = LocalDateTime.now() | ||||
|         val startDate = currentDateTime | ||||
|             .minusWeeks(1) | ||||
|             .with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY)) | ||||
|             .withHour(15) | ||||
|             .withMinute(0) | ||||
|             .withSecond(0) | ||||
|         val endDate = startDate.plusDays(7) | ||||
|  | ||||
|         val contentRanking = getContentRanking(isAdult = isAdult, startDate = startDate, endDate = endDate) | ||||
|  | ||||
|         return GetAudioContentMainResponse( | ||||
|             newContentUploadCreatorList = newContentUploadCreatorList, | ||||
|             bannerList = bannerList, | ||||
|             orderList = orderList, | ||||
|             themeList = themeList, | ||||
|             newContentList = newContentList, | ||||
|             curationList = curationList, | ||||
|             contentRanking = contentRanking | ||||
|         ) | ||||
|     } | ||||
|  | ||||
|     fun getThemeList(member: Member): List<String> { | ||||
|         return audioContentThemeRepository.getActiveThemeOfContent(isAdult = member.auth != null) | ||||
|     } | ||||
|  | ||||
|     fun getNewContentByTheme(theme: String, member: Member, pageable: Pageable): List<GetAudioContentMainItem> { | ||||
|         return repository.findByTheme( | ||||
|             cloudfrontHost = imageHost, | ||||
|             theme = theme, | ||||
|             isAdult = member.auth != null, | ||||
|             offset = pageable.offset, | ||||
|             limit = pageable.pageSize.toLong() | ||||
|         ) | ||||
|             .asSequence() | ||||
|             .filter { !blockMemberRepository.isBlocked(blockedMemberId = member.id!!, memberId = it.creatorId) } | ||||
|             .toList() | ||||
|     } | ||||
|  | ||||
|     fun getNewContentFor2WeeksByTheme(theme: String, member: Member, pageable: Pageable): GetNewContentAllResponse { | ||||
|         val totalCount = repository.totalCountNewContentFor2Weeks(theme, isAdult = member.auth != null) | ||||
|         val items = repository.findByThemeFor2Weeks( | ||||
|             cloudfrontHost = imageHost, | ||||
|             theme = theme, | ||||
|             isAdult = member.auth != null, | ||||
|             offset = pageable.offset, | ||||
|             limit = pageable.pageSize.toLong() | ||||
|         ) | ||||
|  | ||||
|         return GetNewContentAllResponse(totalCount, items) | ||||
|     } | ||||
|  | ||||
|     @Cacheable(cacheNames = ["default"], key = "'getNewContentUploadCreatorList:' + #memberId + ':' + #isAdult") | ||||
|     fun getNewContentUploadCreatorList(memberId: Long, isAdult: Boolean): List<GetNewContentUploadCreator> { | ||||
|         return repository.getNewContentUploadCreatorList( | ||||
|             cloudfrontHost = imageHost, | ||||
|             isAdult = isAdult | ||||
|         ) | ||||
|             .asSequence() | ||||
|             .filter { !blockMemberRepository.isBlocked(blockedMemberId = memberId, memberId = it.creatorId) } | ||||
|             .toList() | ||||
|     } | ||||
|  | ||||
|     @Cacheable(cacheNames = ["default"], key = "'getAudioContentMainBannerList:' + #memberId + ':' + #isAdult") | ||||
|     fun getAudioContentMainBannerList(memberId: Long, isAdult: Boolean) = | ||||
|         repository.getAudioContentMainBannerList(isAdult = isAdult) | ||||
|             .asSequence() | ||||
|             .filter { | ||||
|                 if (it.type == AudioContentBannerType.CREATOR && it.creator != null) { | ||||
|                     !blockMemberRepository.isBlocked(blockedMemberId = member.id!!, memberId = it.creator!!.id!!) | ||||
|                     !blockMemberRepository.isBlocked(blockedMemberId = memberId, memberId = it.creator!!.id!!) | ||||
|                 } else { | ||||
|                     true | ||||
|                 } | ||||
| @@ -86,26 +169,9 @@ class AudioContentMainService( | ||||
|             } | ||||
|             .toList() | ||||
|  | ||||
|         // 구매목록 20개 | ||||
|         val orderList = orderService.getAudioContentMainOrderList( | ||||
|             member = member, | ||||
|             limit = 20 | ||||
|         ) | ||||
|  | ||||
|         // 콘텐츠 테마 | ||||
|         val themeList = audioContentThemeRepository.getActiveThemeOfContent(isAdult = isAdult) | ||||
|  | ||||
|         // 새 콘텐츠 20개 - 시간 내림차순 정렬 | ||||
|         val newContentList = repository.findByTheme( | ||||
|             cloudfrontHost = imageHost, | ||||
|             isAdult = isAdult | ||||
|         ) | ||||
|             .asSequence() | ||||
|             .filter { !blockMemberRepository.isBlocked(blockedMemberId = member.id!!, memberId = it.creatorId) } | ||||
|             .toList() | ||||
|  | ||||
|         val curationList = repository | ||||
|             .getAudioContentCurations(isAdult = isAdult) | ||||
|     @Cacheable(cacheNames = ["default"], key = "'getAudioContentCurationList:' + #memberId + ':' + #isAdult") | ||||
|     fun getAudioContentCurationList(memberId: Long, isAdult: Boolean) = | ||||
|         repository.getAudioContentCurations(isAdult = isAdult) | ||||
|             .asSequence() | ||||
|             .map { | ||||
|                 GetAudioContentCurationResponse( | ||||
| @@ -119,10 +185,7 @@ class AudioContentMainService( | ||||
|                     ) | ||||
|                         .asSequence() | ||||
|                         .filter { content -> | ||||
|                             !blockMemberRepository.isBlocked( | ||||
|                                 blockedMemberId = member.id!!, | ||||
|                                 memberId = content.creatorId | ||||
|                             ) | ||||
|                             !blockMemberRepository.isBlocked(blockedMemberId = memberId, memberId = content.creatorId) | ||||
|                         } | ||||
|                         .toList() | ||||
|                 ) | ||||
| @@ -130,16 +193,11 @@ class AudioContentMainService( | ||||
|             .filter { it.contents.isNotEmpty() } | ||||
|             .toList() | ||||
|  | ||||
|         val currentDateTime = LocalDateTime.now() | ||||
|         val startDate = currentDateTime | ||||
|             .minusWeeks(1) | ||||
|             .with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY)) | ||||
|             .withHour(15) | ||||
|             .withMinute(0) | ||||
|             .withSecond(0) | ||||
|         val endDate = startDate | ||||
|             .plusDays(7) | ||||
|  | ||||
|     @Cacheable( | ||||
|         cacheNames = ["cache_ttl_3_days"], | ||||
|         key = "'getAudioContentCurationList:' + ':' + #isAdult + ':' + #startDate + ':' + #endDate" | ||||
|     ) | ||||
|     fun getContentRanking(isAdult: Boolean, startDate: LocalDateTime, endDate: LocalDateTime): GetAudioContentRanking { | ||||
|         val startDateFormatter = DateTimeFormatter.ofPattern("yyyy년 MM월 dd일") | ||||
|         val endDateFormatter = DateTimeFormatter.ofPattern("MM월 dd일") | ||||
|  | ||||
| @@ -151,50 +209,10 @@ class AudioContentMainService( | ||||
|                 isAdult = isAdult | ||||
|             ) | ||||
|  | ||||
|         val contentRanking = GetAudioContentRanking( | ||||
|         return GetAudioContentRanking( | ||||
|             startDate = startDate.format(startDateFormatter), | ||||
|             endDate = endDate.minusDays(1).format(endDateFormatter), | ||||
|             contentRankingItemList | ||||
|         ) | ||||
|  | ||||
|         return GetAudioContentMainResponse( | ||||
|             newContentUploadCreatorList = newContentUploadCreatorList, | ||||
|             bannerList = bannerList, | ||||
|             orderList = orderList, | ||||
|             themeList = themeList, | ||||
|             newContentList = newContentList, | ||||
|             curationList = curationList, | ||||
|             contentRanking = contentRanking | ||||
|         ) | ||||
|     } | ||||
|  | ||||
|     fun getThemeList(member: Member): List<String> { | ||||
|         return audioContentThemeRepository.getActiveThemeOfContent(isAdult = member.auth != null) | ||||
|     } | ||||
|  | ||||
|     fun getNewContentByTheme(theme: String, member: Member, pageable: Pageable): List<GetAudioContentMainItem> { | ||||
|         return repository.findByTheme( | ||||
|             cloudfrontHost = imageHost, | ||||
|             theme = theme, | ||||
|             isAdult = member.auth != null, | ||||
|             offset = pageable.offset, | ||||
|             limit = pageable.pageSize.toLong() | ||||
|         ) | ||||
|             .asSequence() | ||||
|             .filter { !blockMemberRepository.isBlocked(blockedMemberId = member.id!!, memberId = it.creatorId) } | ||||
|             .toList() | ||||
|     } | ||||
|  | ||||
|     fun getNewContentFor2WeeksByTheme(theme: String, member: Member, pageable: Pageable): GetNewContentAllResponse { | ||||
|         val totalCount = repository.totalCountNewContentFor2Weeks(theme, isAdult = member.auth != null) | ||||
|         val items = repository.findByThemeFor2Weeks( | ||||
|             cloudfrontHost = imageHost, | ||||
|             theme = theme, | ||||
|             isAdult = member.auth != null, | ||||
|             offset = pageable.offset, | ||||
|             limit = pageable.pageSize.toLong() | ||||
|         ) | ||||
|  | ||||
|         return GetNewContentAllResponse(totalCount, items) | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -4,6 +4,7 @@ import com.querydsl.jpa.impl.JPAQueryFactory | ||||
| import kr.co.vividnext.sodalive.content.QAudioContent.audioContent | ||||
| import kr.co.vividnext.sodalive.content.theme.QAudioContentTheme.audioContentTheme | ||||
| import org.springframework.beans.factory.annotation.Value | ||||
| import org.springframework.cache.annotation.Cacheable | ||||
| import org.springframework.stereotype.Repository | ||||
|  | ||||
| @Repository | ||||
| @@ -27,6 +28,7 @@ class AudioContentThemeQueryRepository( | ||||
|             .fetch() | ||||
|     } | ||||
|  | ||||
|     @Cacheable(cacheNames = ["default"], key = "'getActiveThemeOfContent:' + ':' + #isAdult") | ||||
|     fun getActiveThemeOfContent(isAdult: Boolean = false): List<String> { | ||||
|         var where = audioContent.isActive.isTrue | ||||
|             .and(audioContentTheme.isActive.isTrue) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user