diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/configs/RedisConfig.kt b/src/main/kotlin/kr/co/vividnext/sodalive/configs/RedisConfig.kt index f309011..015324c 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/configs/RedisConfig.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/configs/RedisConfig.kt @@ -10,9 +10,6 @@ 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 org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer -import org.springframework.data.redis.serializer.RedisSerializationContext -import org.springframework.data.redis.serializer.StringRedisSerializer import java.time.Duration @Configuration @@ -37,29 +34,19 @@ class RedisConfig( } @Bean - fun cacheManager(connectionFactory: RedisConnectionFactory): RedisCacheManager { - val defaultConfig = RedisCacheConfiguration.defaultCacheConfig() - .entryTtl(Duration.ofHours(1)) // Default TTL - .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(StringRedisSerializer())) - .serializeValuesWith( - RedisSerializationContext.SerializationPair.fromSerializer( - GenericJackson2JsonRedisSerializer() - ) - ) + fun cacheManager(redisConnectionFactory: RedisConnectionFactory): RedisCacheManager { + val defaultCacheConfig = RedisCacheConfiguration.defaultCacheConfig() + .entryTtl(Duration.ofMinutes(30)) - val weekLivedCacheConfig = RedisCacheConfiguration.defaultCacheConfig() + val cacheConfigMap = mutableMapOf() + cacheConfigMap["default"] = RedisCacheConfiguration.defaultCacheConfig() + .entryTtl(Duration.ofMinutes(30)) + cacheConfigMap["cache_ttl_3_days"] = RedisCacheConfiguration.defaultCacheConfig() .entryTtl(Duration.ofDays(3)) - .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(StringRedisSerializer())) - .serializeValuesWith( - RedisSerializationContext.SerializationPair.fromSerializer( - GenericJackson2JsonRedisSerializer() - ) - ) - return RedisCacheManager.RedisCacheManagerBuilder - .fromConnectionFactory(connectionFactory) - .cacheDefaults(defaultConfig) - .withCacheConfiguration("weekLivedCache", weekLivedCacheConfig) + return RedisCacheManager.builder(redisConnectionFactory) + .cacheDefaults(defaultCacheConfig) + .withInitialCacheConfigurations(cacheConfigMap) .build() } } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContentRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContentRepository.kt index 0c195ea..e7bfebe 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContentRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContentRepository.kt @@ -17,7 +17,6 @@ import kr.co.vividnext.sodalive.content.order.QOrder.order import kr.co.vividnext.sodalive.content.theme.QAudioContentTheme.audioContentTheme import kr.co.vividnext.sodalive.event.QEvent.event import kr.co.vividnext.sodalive.member.QMember.member -import org.springframework.cache.annotation.Cacheable import org.springframework.data.jpa.repository.JpaRepository import org.springframework.stereotype.Repository import java.time.LocalDateTime @@ -77,9 +76,6 @@ interface AudioContentQueryRepository { fun getAudioContentMainBannerList(isAdult: Boolean): List fun getAudioContentCurations(isAdult: Boolean): List - - fun getAudioContentCurationList(isAdult: Boolean, offset: Long = 0, limit: Long = 10): List - fun findAudioContentByCurationId( curationId: Long, cloudfrontHost: String, @@ -390,10 +386,6 @@ class AudioContentQueryRepositoryImpl(private val queryFactory: JPAQueryFactory) .fetch() } - @Cacheable( - value = ["getAudioContentCurations"], - cacheManager = "cacheManager" - ) override fun getAudioContentCurations(isAdult: Boolean): List { var where = audioContentCuration.isActive.isTrue @@ -408,26 +400,6 @@ class AudioContentQueryRepositoryImpl(private val queryFactory: JPAQueryFactory) .fetch() } - override fun getAudioContentCurationList( - isAdult: Boolean, - offset: Long, - limit: Long - ): List { - var where = audioContentCuration.isActive.isTrue - - if (!isAdult) { - where = where.and(audioContentCuration.isAdult.isFalse) - } - - return queryFactory - .selectFrom(audioContentCuration) - .where(where) - .orderBy(audioContentCuration.orders.asc()) - .offset(offset) - .limit(limit) - .fetch() - } - override fun findAudioContentByCurationId( curationId: Long, cloudfrontHost: String, @@ -465,10 +437,6 @@ class AudioContentQueryRepositoryImpl(private val queryFactory: JPAQueryFactory) .fetch() } - @Cacheable( - value = ["weekLivedCache"], - cacheManager = "cacheManager" - ) override fun getAudioContentRanking( cloudfrontHost: String, isAdult: Boolean, diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/AudioContentMainController.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/AudioContentMainController.kt index df51a73..41cee69 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/AudioContentMainController.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/AudioContentMainController.kt @@ -23,33 +23,6 @@ class AudioContentMainController(private val service: AudioContentMainService) { ApiResponse.ok(service.getMain(member = member)) } - @GetMapping("/new-content-upload-creator") - fun getNewContentUploadCreatorList( - @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? - ) = run { - if (member == null) throw SodaException("로그인 정보를 확인해주세요.") - - ApiResponse.ok(service.getNewContentUploadCreatorList(member = member)) - } - - @GetMapping("/banner-list") - fun getAudioContentMainBannerList( - @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? - ) = run { - if (member == null) throw SodaException("로그인 정보를 확인해주세요.") - - ApiResponse.ok(service.getAudioContentMainBannerList(member = member)) - } - - @GetMapping("/order-list") - fun getAudioContentMainOrderList( - @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? - ) = run { - if (member == null) throw SodaException("로그인 정보를 확인해주세요.") - - ApiResponse.ok(service.getAudioContentMainOrderList(member = member)) - } - @GetMapping("/new") fun getNewContentByTheme( @RequestParam("theme") theme: String, @@ -80,29 +53,4 @@ class AudioContentMainController(private val service: AudioContentMainService) { ApiResponse.ok(service.getNewContentFor2WeeksByTheme(theme, member, pageable)) } - - @GetMapping("/curation-list") - fun getAudioContentMainCurationList( - @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?, - pageable: Pageable - ) = run { - if (member == null) throw SodaException("로그인 정보를 확인해주세요.") - - ApiResponse.ok( - service.getAudioContentMainCurationList( - member, - offset = pageable.offset, - limit = pageable.pageSize.toLong() - ) - ) - } - - @GetMapping("/content-ranking") - fun getAudioContentMainContentRanking( - @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? - ) = run { - if (member == null) throw SodaException("로그인 정보를 확인해주세요.") - - ApiResponse.ok(service.getAudioContentMainContentRanking(member)) - } } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/AudioContentMainService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/AudioContentMainService.kt index 159b661..c2d80d0 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/main/AudioContentMainService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/main/AudioContentMainService.kt @@ -30,62 +30,12 @@ class AudioContentMainService( ) { fun getMain(member: Member): GetAudioContentMainResponse { val isAdult = member.auth != null + val memberId = member.id!! // 2주일 이내에 콘텐츠를 올린 크리에이터 20명 조회 - val newContentUploadCreatorList = repository.getNewContentUploadCreatorList( - cloudfrontHost = imageHost, - isAdult = isAdult - ) - .asSequence() - .filter { !blockMemberRepository.isBlocked(blockedMemberId = member.id!!, memberId = it.creatorId) } - .toList() + val newContentUploadCreatorList = getNewContentUploadCreatorList(memberId = memberId, isAdult = isAdult) - val bannerList = repository.getAudioContentMainBannerList(isAdult = isAdult) - .asSequence() - .filter { - if (it.type == AudioContentBannerType.CREATOR && it.creator != null) { - !blockMemberRepository.isBlocked(blockedMemberId = member.id!!, memberId = it.creator!!.id!!) - } else { - true - } - } - .map { - GetAudioContentBannerResponse( - type = it.type, - thumbnailImageUrl = "$imageHost/${it.thumbnailImage}", - eventItem = if (it.type == AudioContentBannerType.EVENT && it.event != null) { - EventItem( - id = it.event!!.id!!, - thumbnailImageUrl = if (!it.event!!.thumbnailImage.startsWith("https://")) { - "$imageHost/${it.event!!.thumbnailImage}" - } else { - it.event!!.thumbnailImage - }, - detailImageUrl = if ( - it.event!!.detailImage != null && - !it.event!!.detailImage!!.startsWith("https://") - ) { - "$imageHost/${it.event!!.detailImage}" - } else { - it.event!!.detailImage - }, - popupImageUrl = null, - link = it.event!!.link, - title = it.event!!.title, - isPopup = false - ) - } else { - null - }, - creatorId = if (it.type == AudioContentBannerType.CREATOR && it.creator != null) { - it.creator!!.id - } else { - null - }, - link = it.link - ) - } - .toList() + val bannerList = getAudioContentMainBannerList(memberId = memberId, isAdult = isAdult) // 구매목록 20개 val orderList = orderService.getAudioContentMainOrderList( @@ -102,34 +52,10 @@ class AudioContentMainService( isAdult = isAdult ) .asSequence() - .filter { !blockMemberRepository.isBlocked(blockedMemberId = member.id!!, memberId = it.creatorId) } + .filter { !blockMemberRepository.isBlocked(blockedMemberId = memberId, memberId = it.creatorId) } .toList() - val curationList = repository - .getAudioContentCurations(isAdult = isAdult) - .asSequence() - .map { - GetAudioContentCurationResponse( - curationId = it.id!!, - title = it.title, - description = it.description, - contents = repository.findAudioContentByCurationId( - curationId = it.id!!, - cloudfrontHost = imageHost, - isAdult = isAdult - ) - .asSequence() - .filter { content -> - !blockMemberRepository.isBlocked( - blockedMemberId = member.id!!, - memberId = content.creatorId - ) - } - .toList() - ) - } - .filter { it.contents.isNotEmpty() } - .toList() + val curationList = getAudioContentCurationList(memberId = memberId, isAdult = isAdult) val currentDateTime = LocalDateTime.now() val startDate = currentDateTime @@ -138,25 +64,9 @@ class AudioContentMainService( .withHour(15) .withMinute(0) .withSecond(0) - val endDate = startDate - .plusDays(7) + val endDate = startDate.plusDays(7) - val startDateFormatter = DateTimeFormatter.ofPattern("yyyy년 MM월 dd일") - val endDateFormatter = DateTimeFormatter.ofPattern("MM월 dd일") - - val contentRankingItemList = repository - .getAudioContentRanking( - cloudfrontHost = imageHost, - startDate = startDate.minusDays(1), - endDate = endDate.minusDays(1), - isAdult = isAdult - ) - - val contentRanking = GetAudioContentRanking( - startDate = startDate.format(startDateFormatter), - endDate = endDate.minusDays(1).format(endDateFormatter), - contentRankingItemList - ) + val contentRanking = getContentRanking(isAdult = isAdult, startDate = startDate, endDate = endDate) return GetAudioContentMainResponse( newContentUploadCreatorList = newContentUploadCreatorList, @@ -169,87 +79,6 @@ class AudioContentMainService( ) } - @Cacheable( - value = ["getNewContentUploadCreatorList"], - cacheManager = "cacheManager" - ) - fun getNewContentUploadCreatorList(member: Member): List { - val isAdult = member.auth != null - - // 2주일 이내에 콘텐츠를 올린 크리에이터 20명 조회 - return repository.getNewContentUploadCreatorList( - cloudfrontHost = imageHost, - isAdult = isAdult - ) - .asSequence() - .filter { !blockMemberRepository.isBlocked(blockedMemberId = member.id!!, memberId = it.creatorId) } - .toList() - } - - @Cacheable( - value = ["getAudioContentMainBannerList"], - cacheManager = "cacheManager" - ) - fun getAudioContentMainBannerList(member: Member): List { - val isAdult = member.auth != null - - return repository - .getAudioContentMainBannerList(isAdult = isAdult) - .asSequence() - .filter { - if (it.type == AudioContentBannerType.CREATOR && it.creator != null) { - !blockMemberRepository.isBlocked(blockedMemberId = member.id!!, memberId = it.creator!!.id!!) - } else { - true - } - } - .map { - GetAudioContentBannerResponse( - type = it.type, - thumbnailImageUrl = "$imageHost/${it.thumbnailImage}", - eventItem = if (it.type == AudioContentBannerType.EVENT && it.event != null) { - EventItem( - id = it.event!!.id!!, - thumbnailImageUrl = if (!it.event!!.thumbnailImage.startsWith("https://")) { - "$imageHost/${it.event!!.thumbnailImage}" - } else { - it.event!!.thumbnailImage - }, - detailImageUrl = if ( - it.event!!.detailImage != null && - !it.event!!.detailImage!!.startsWith("https://") - ) { - "$imageHost/${it.event!!.detailImage}" - } else { - it.event!!.detailImage - }, - popupImageUrl = null, - link = it.event!!.link, - title = it.event!!.title, - isPopup = false - ) - } else { - null - }, - creatorId = if (it.type == AudioContentBannerType.CREATOR && it.creator != null) { - it.creator!!.id - } else { - null - }, - link = it.link - ) - } - .toList() - } - - fun getAudioContentMainOrderList(member: Member): List { - return orderService - .getAudioContentMainOrderList( - member = member, - limit = 20 - ) - } - fun getThemeList(member: Member): List { return audioContentThemeRepository.getActiveThemeOfContent(isAdult = member.auth != null) } @@ -280,23 +109,69 @@ class AudioContentMainService( return GetNewContentAllResponse(totalCount, items) } - @Cacheable( - value = ["getAudioContentMainCurationList"], - cacheManager = "cacheManager" - ) - fun getAudioContentMainCurationList( - member: Member, - offset: Long, - limit: Long - ): List { - val isAdult = member.auth != null + @Cacheable(cacheNames = ["default"], key = "'getNewContentUploadCreatorList:' + #memberId + ':' + #isAdult") + fun getNewContentUploadCreatorList(memberId: Long, isAdult: Boolean): List { + return repository.getNewContentUploadCreatorList( + cloudfrontHost = imageHost, + isAdult = isAdult + ) + .asSequence() + .filter { !blockMemberRepository.isBlocked(blockedMemberId = memberId, memberId = it.creatorId) } + .toList() + } - return repository - .getAudioContentCurationList( - isAdult = isAdult, - offset = offset, - limit = limit - ) + @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 = memberId, memberId = it.creator!!.id!!) + } else { + true + } + } + .map { + GetAudioContentBannerResponse( + type = it.type, + thumbnailImageUrl = "$imageHost/${it.thumbnailImage}", + eventItem = if (it.type == AudioContentBannerType.EVENT && it.event != null) { + EventItem( + id = it.event!!.id!!, + thumbnailImageUrl = if (!it.event!!.thumbnailImage.startsWith("https://")) { + "$imageHost/${it.event!!.thumbnailImage}" + } else { + it.event!!.thumbnailImage + }, + detailImageUrl = if ( + it.event!!.detailImage != null && + !it.event!!.detailImage!!.startsWith("https://") + ) { + "$imageHost/${it.event!!.detailImage}" + } else { + it.event!!.detailImage + }, + popupImageUrl = null, + link = it.event!!.link, + title = it.event!!.title, + isPopup = false + ) + } else { + null + }, + creatorId = if (it.type == AudioContentBannerType.CREATOR && it.creator != null) { + it.creator!!.id + } else { + null + }, + link = it.link + ) + } + .toList() + + @Cacheable(cacheNames = ["default"], key = "'getAudioContentCurationList:' + #memberId + ':' + #isAdult") + fun getAudioContentCurationList(memberId: Long, isAdult: Boolean) = + repository.getAudioContentCurations(isAdult = isAdult) .asSequence() .map { GetAudioContentCurationResponse( @@ -310,31 +185,19 @@ class AudioContentMainService( ) .asSequence() .filter { content -> - !blockMemberRepository.isBlocked( - blockedMemberId = member.id!!, - memberId = content.creatorId - ) + !blockMemberRepository.isBlocked(blockedMemberId = memberId, memberId = content.creatorId) } .toList() ) } .filter { it.contents.isNotEmpty() } .toList() - } - - fun getAudioContentMainContentRanking(member: Member): GetAudioContentRanking { - val isAdult = member.auth != null - - 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일") diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/theme/AudioContentThemeQueryRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/theme/AudioContentThemeQueryRepository.kt index e5cba07..bf7bfc1 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/theme/AudioContentThemeQueryRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/theme/AudioContentThemeQueryRepository.kt @@ -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 { var where = audioContent.isActive.isTrue .and(audioContentTheme.isActive.isTrue) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/event/EventService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/event/EventService.kt index 2237d7b..e6ddd74 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/event/EventService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/event/EventService.kt @@ -5,7 +5,6 @@ import kr.co.vividnext.sodalive.aws.s3.S3Uploader import kr.co.vividnext.sodalive.common.SodaException import kr.co.vividnext.sodalive.utils.generateFileName import org.springframework.beans.factory.annotation.Value -import org.springframework.cache.annotation.Cacheable import org.springframework.data.repository.findByIdOrNull import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional @@ -21,10 +20,6 @@ class EventService( @Value("\${cloud.aws.cloud-front.host}") private val cloudFrontHost: String ) { - @Cacheable( - value = ["getEventList"], - cacheManager = "cacheManager" - ) fun getEventList(): GetEventResponse { val eventList = repository.getEventList() .asSequence() diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/live/recommend/LiveRecommendRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/live/recommend/LiveRecommendRepository.kt index b65eecb..e6ece32 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/live/recommend/LiveRecommendRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/live/recommend/LiveRecommendRepository.kt @@ -9,7 +9,6 @@ import kr.co.vividnext.sodalive.member.MemberRole import kr.co.vividnext.sodalive.member.QMember.member import kr.co.vividnext.sodalive.member.following.QCreatorFollowing.creatorFollowing import org.springframework.beans.factory.annotation.Value -import org.springframework.cache.annotation.Cacheable import org.springframework.stereotype.Repository import java.time.LocalDateTime @@ -20,10 +19,6 @@ class LiveRecommendRepository( @Value("\${cloud.aws.cloud-front.host}") private val cloudFrontHost: String ) { - @Cacheable( - value = ["getRecommendLive"], - cacheManager = "cacheManager" - ) fun getRecommendLive( memberId: Long, isBlocked: (Long) -> Boolean,