콘텐츠 메인 캐싱 전략 변경 - repository 에 있던 @Cacheable 을 service 코드로 이동
This commit is contained in:
parent
3ec16b5045
commit
1c7fdfac69
|
@ -4,10 +4,13 @@ import org.springframework.beans.factory.annotation.Value
|
||||||
import org.springframework.cache.annotation.EnableCaching
|
import org.springframework.cache.annotation.EnableCaching
|
||||||
import org.springframework.context.annotation.Bean
|
import org.springframework.context.annotation.Bean
|
||||||
import org.springframework.context.annotation.Configuration
|
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.RedisConnectionFactory
|
||||||
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory
|
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory
|
||||||
import org.springframework.data.redis.core.RedisTemplate
|
import org.springframework.data.redis.core.RedisTemplate
|
||||||
import org.springframework.data.redis.repository.configuration.EnableRedisRepositories
|
import org.springframework.data.redis.repository.configuration.EnableRedisRepositories
|
||||||
|
import java.time.Duration
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@EnableCaching
|
@EnableCaching
|
||||||
|
@ -29,4 +32,21 @@ class RedisConfig(
|
||||||
redisTemplate.setConnectionFactory(redisConnectionFactory())
|
redisTemplate.setConnectionFactory(redisConnectionFactory())
|
||||||
return redisTemplate
|
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.Member
|
||||||
import kr.co.vividnext.sodalive.member.block.BlockMemberRepository
|
import kr.co.vividnext.sodalive.member.block.BlockMemberRepository
|
||||||
import org.springframework.beans.factory.annotation.Value
|
import org.springframework.beans.factory.annotation.Value
|
||||||
|
import org.springframework.cache.annotation.Cacheable
|
||||||
import org.springframework.data.domain.Pageable
|
import org.springframework.data.domain.Pageable
|
||||||
import org.springframework.stereotype.Service
|
import org.springframework.stereotype.Service
|
||||||
import java.time.DayOfWeek
|
import java.time.DayOfWeek
|
||||||
|
@ -29,21 +30,103 @@ class AudioContentMainService(
|
||||||
) {
|
) {
|
||||||
fun getMain(member: Member): GetAudioContentMainResponse {
|
fun getMain(member: Member): GetAudioContentMainResponse {
|
||||||
val isAdult = member.auth != null
|
val isAdult = member.auth != null
|
||||||
|
val memberId = member.id!!
|
||||||
|
|
||||||
// 2주일 이내에 콘텐츠를 올린 크리에이터 20명 조회
|
// 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,
|
cloudfrontHost = imageHost,
|
||||||
isAdult = isAdult
|
isAdult = isAdult
|
||||||
)
|
)
|
||||||
.asSequence()
|
.asSequence()
|
||||||
.filter { !blockMemberRepository.isBlocked(blockedMemberId = member.id!!, memberId = it.creatorId) }
|
.filter { !blockMemberRepository.isBlocked(blockedMemberId = memberId, memberId = it.creatorId) }
|
||||||
.toList()
|
.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()
|
.asSequence()
|
||||||
.filter {
|
.filter {
|
||||||
if (it.type == AudioContentBannerType.CREATOR && it.creator != null) {
|
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 {
|
} else {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
@ -86,26 +169,9 @@ class AudioContentMainService(
|
||||||
}
|
}
|
||||||
.toList()
|
.toList()
|
||||||
|
|
||||||
// 구매목록 20개
|
@Cacheable(cacheNames = ["default"], key = "'getAudioContentCurationList:' + #memberId + ':' + #isAdult")
|
||||||
val orderList = orderService.getAudioContentMainOrderList(
|
fun getAudioContentCurationList(memberId: Long, isAdult: Boolean) =
|
||||||
member = member,
|
repository.getAudioContentCurations(isAdult = isAdult)
|
||||||
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)
|
|
||||||
.asSequence()
|
.asSequence()
|
||||||
.map {
|
.map {
|
||||||
GetAudioContentCurationResponse(
|
GetAudioContentCurationResponse(
|
||||||
|
@ -119,10 +185,7 @@ class AudioContentMainService(
|
||||||
)
|
)
|
||||||
.asSequence()
|
.asSequence()
|
||||||
.filter { content ->
|
.filter { content ->
|
||||||
!blockMemberRepository.isBlocked(
|
!blockMemberRepository.isBlocked(blockedMemberId = memberId, memberId = content.creatorId)
|
||||||
blockedMemberId = member.id!!,
|
|
||||||
memberId = content.creatorId
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
.toList()
|
.toList()
|
||||||
)
|
)
|
||||||
|
@ -130,16 +193,11 @@ class AudioContentMainService(
|
||||||
.filter { it.contents.isNotEmpty() }
|
.filter { it.contents.isNotEmpty() }
|
||||||
.toList()
|
.toList()
|
||||||
|
|
||||||
val currentDateTime = LocalDateTime.now()
|
@Cacheable(
|
||||||
val startDate = currentDateTime
|
cacheNames = ["cache_ttl_3_days"],
|
||||||
.minusWeeks(1)
|
key = "'getAudioContentCurationList:' + ':' + #isAdult + ':' + #startDate + ':' + #endDate"
|
||||||
.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY))
|
)
|
||||||
.withHour(15)
|
fun getContentRanking(isAdult: Boolean, startDate: LocalDateTime, endDate: LocalDateTime): GetAudioContentRanking {
|
||||||
.withMinute(0)
|
|
||||||
.withSecond(0)
|
|
||||||
val endDate = startDate
|
|
||||||
.plusDays(7)
|
|
||||||
|
|
||||||
val startDateFormatter = DateTimeFormatter.ofPattern("yyyy년 MM월 dd일")
|
val startDateFormatter = DateTimeFormatter.ofPattern("yyyy년 MM월 dd일")
|
||||||
val endDateFormatter = DateTimeFormatter.ofPattern("MM월 dd일")
|
val endDateFormatter = DateTimeFormatter.ofPattern("MM월 dd일")
|
||||||
|
|
||||||
|
@ -151,50 +209,10 @@ class AudioContentMainService(
|
||||||
isAdult = isAdult
|
isAdult = isAdult
|
||||||
)
|
)
|
||||||
|
|
||||||
val contentRanking = GetAudioContentRanking(
|
return GetAudioContentRanking(
|
||||||
startDate = startDate.format(startDateFormatter),
|
startDate = startDate.format(startDateFormatter),
|
||||||
endDate = endDate.minusDays(1).format(endDateFormatter),
|
endDate = endDate.minusDays(1).format(endDateFormatter),
|
||||||
contentRankingItemList
|
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.QAudioContent.audioContent
|
||||||
import kr.co.vividnext.sodalive.content.theme.QAudioContentTheme.audioContentTheme
|
import kr.co.vividnext.sodalive.content.theme.QAudioContentTheme.audioContentTheme
|
||||||
import org.springframework.beans.factory.annotation.Value
|
import org.springframework.beans.factory.annotation.Value
|
||||||
|
import org.springframework.cache.annotation.Cacheable
|
||||||
import org.springframework.stereotype.Repository
|
import org.springframework.stereotype.Repository
|
||||||
|
|
||||||
@Repository
|
@Repository
|
||||||
|
@ -27,6 +28,7 @@ class AudioContentThemeQueryRepository(
|
||||||
.fetch()
|
.fetch()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Cacheable(cacheNames = ["default"], key = "'getActiveThemeOfContent:' + ':' + #isAdult")
|
||||||
fun getActiveThemeOfContent(isAdult: Boolean = false): List<String> {
|
fun getActiveThemeOfContent(isAdult: Boolean = false): List<String> {
|
||||||
var where = audioContent.isActive.isTrue
|
var where = audioContent.isActive.isTrue
|
||||||
.and(audioContentTheme.isActive.isTrue)
|
.and(audioContentTheme.isActive.isTrue)
|
||||||
|
|
Loading…
Reference in New Issue