콘텐츠 메인 캐싱 전략 변경 - repository 에 있던 @Cacheable 을 service 코드로 이동

This commit is contained in:
Klaus 2023-10-27 01:08:40 +09:00
parent 3ec16b5045
commit 1c7fdfac69
3 changed files with 119 additions and 79 deletions

View File

@ -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()
}
}

View File

@ -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)
}
}

View File

@ -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)