@@ -113,30 +113,6 @@ class ExplorerQueryRepository(
|
||||
.fetchOne()
|
||||
}
|
||||
|
||||
fun getMemberDonationRankingTotal(creatorId: Long): Int {
|
||||
val userMember = QMember("user")
|
||||
|
||||
val donation = useCan.rewardCan.add(useCan.can).sum()
|
||||
return queryFactory
|
||||
.select(userMember.id)
|
||||
.from(useCanCalculate)
|
||||
.innerJoin(useCanCalculate.useCan, useCan)
|
||||
.innerJoin(useCan.member, userMember)
|
||||
.where(
|
||||
useCan.isRefund.isFalse
|
||||
.and(useCanCalculate.recipientCreatorId.eq(creatorId))
|
||||
.and(
|
||||
useCan.canUsage.eq(CanUsage.DONATION)
|
||||
.or(useCan.canUsage.eq(CanUsage.SPIN_ROULETTE))
|
||||
.or(useCan.canUsage.eq(CanUsage.LIVE))
|
||||
)
|
||||
)
|
||||
.groupBy(useCan.member.id)
|
||||
.orderBy(donation.desc())
|
||||
.fetch()
|
||||
.size
|
||||
}
|
||||
|
||||
fun getMemberDonationRanking(
|
||||
creatorId: Long,
|
||||
limit: Long,
|
||||
|
||||
@@ -403,6 +403,14 @@ class ExplorerService(
|
||||
val firstDayOfLastWeek = currentDate.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY)).minusDays(7)
|
||||
val firstDayOfMonth = currentDate.with(TemporalAdjusters.firstDayOfMonth())
|
||||
|
||||
val donationMemberTotal = donationRankingService.getMemberDonationRankingTotal(creatorId)
|
||||
val donationRanking = donationRankingService.getMemberDonationRanking(
|
||||
creatorId = creatorId,
|
||||
offset = pageable.offset,
|
||||
limit = pageable.pageSize.toLong(),
|
||||
withDonationCan = creatorId == member.id!!
|
||||
)
|
||||
|
||||
return GetDonationAllResponse(
|
||||
accumulatedCansToday = if (creatorId == member.id!!) {
|
||||
queryRepository.getDonationCoinsDateRange(
|
||||
@@ -436,13 +444,8 @@ class ExplorerService(
|
||||
} else {
|
||||
false
|
||||
},
|
||||
totalCount = queryRepository.getMemberDonationRankingTotal(creatorId),
|
||||
userDonationRanking = queryRepository.getMemberDonationRanking(
|
||||
creatorId,
|
||||
offset = pageable.offset,
|
||||
limit = pageable.pageSize.toLong(),
|
||||
withDonationCan = creatorId == member.id!!
|
||||
)
|
||||
totalCount = donationMemberTotal,
|
||||
userDonationRanking = donationRanking
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -8,23 +8,14 @@ import kr.co.vividnext.sodalive.can.use.QUseCan.useCan
|
||||
import kr.co.vividnext.sodalive.can.use.QUseCanCalculate.useCanCalculate
|
||||
import kr.co.vividnext.sodalive.member.QMember.member
|
||||
import org.springframework.stereotype.Repository
|
||||
import java.time.DayOfWeek
|
||||
import java.time.LocalDateTime
|
||||
import java.time.LocalTime
|
||||
import java.time.temporal.TemporalAdjusters
|
||||
|
||||
@Repository
|
||||
class CreatorDonationRankingQueryRepository(private val queryFactory: JPAQueryFactory) {
|
||||
fun getMemberDonationRanking(
|
||||
creatorId: Long,
|
||||
offset: Long,
|
||||
limit: Long
|
||||
): List<DonationRankingProjection> {
|
||||
val now = LocalDateTime.now()
|
||||
val lastMonday = now.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY))
|
||||
.minusWeeks(1)
|
||||
.with(LocalTime.MIN)
|
||||
val lastSunday = lastMonday.plusDays(6).with(LocalTime.MAX)
|
||||
|
||||
val donationCan = useCan.rewardCan.add(useCan.can).sum()
|
||||
return queryFactory
|
||||
.select(
|
||||
@@ -47,14 +38,34 @@ class CreatorDonationRankingQueryRepository(private val queryFactory: JPAQueryFa
|
||||
.or(useCan.canUsage.eq(CanUsage.SPIN_ROULETTE))
|
||||
.or(useCan.canUsage.eq(CanUsage.LIVE))
|
||||
)
|
||||
.and(useCan.createdAt.between(lastMonday, lastSunday))
|
||||
)
|
||||
.offset(0)
|
||||
.offset(offset)
|
||||
.limit(limit)
|
||||
.groupBy(member.id)
|
||||
.orderBy(donationCan.desc(), member.id.desc())
|
||||
.fetch()
|
||||
}
|
||||
|
||||
fun getMemberDonationRankingTotal(creatorId: Long): Int {
|
||||
return queryFactory
|
||||
.select(member.id)
|
||||
.from(useCanCalculate)
|
||||
.innerJoin(useCanCalculate.useCan, useCan)
|
||||
.innerJoin(useCan.member, member)
|
||||
.where(
|
||||
useCan.member.isActive.isTrue
|
||||
.and(useCan.isRefund.isFalse)
|
||||
.and(useCanCalculate.recipientCreatorId.eq(creatorId))
|
||||
.and(
|
||||
useCan.canUsage.eq(CanUsage.DONATION)
|
||||
.or(useCan.canUsage.eq(CanUsage.SPIN_ROULETTE))
|
||||
.or(useCan.canUsage.eq(CanUsage.LIVE))
|
||||
)
|
||||
)
|
||||
.groupBy(member.id)
|
||||
.fetch()
|
||||
.size
|
||||
}
|
||||
}
|
||||
|
||||
data class DonationRankingProjection @QueryProjection constructor(
|
||||
|
||||
@@ -2,6 +2,7 @@ package kr.co.vividnext.sodalive.explorer.profile
|
||||
|
||||
import kr.co.vividnext.sodalive.explorer.MemberDonationRankingListResponse
|
||||
import kr.co.vividnext.sodalive.explorer.MemberDonationRankingResponse
|
||||
import org.springframework.beans.factory.annotation.Value
|
||||
import org.springframework.data.redis.core.RedisTemplate
|
||||
import org.springframework.stereotype.Service
|
||||
import java.time.DayOfWeek
|
||||
@@ -14,26 +15,52 @@ import java.time.temporal.TemporalAdjusters
|
||||
@Service
|
||||
class CreatorDonationRankingService(
|
||||
private val repository: CreatorDonationRankingQueryRepository,
|
||||
private val redisTemplate: RedisTemplate<String, Any>
|
||||
private val redisTemplate: RedisTemplate<String, Any>,
|
||||
|
||||
@Value("\${cloud.aws.cloud-front.host}")
|
||||
private val imageHost: String
|
||||
) {
|
||||
fun getMemberDonationRankingTotal(creatorId: Long): Int {
|
||||
val cacheKey = "creator_donation_ranking_member_total_v2:$creatorId"
|
||||
val cachedTotal = redisTemplate.opsForValue().get(cacheKey) as? Int
|
||||
if (cachedTotal != null) {
|
||||
return cachedTotal
|
||||
}
|
||||
|
||||
val total = repository.getMemberDonationRankingTotal(creatorId)
|
||||
|
||||
val now = LocalDateTime.now()
|
||||
val nextMonday = now.with(TemporalAdjusters.next(DayOfWeek.MONDAY)).with(LocalTime.MIN)
|
||||
val secondsUntilNextMonday = ChronoUnit.SECONDS.between(now, nextMonday)
|
||||
|
||||
redisTemplate.opsForValue().set(
|
||||
cacheKey,
|
||||
total,
|
||||
Duration.ofSeconds(secondsUntilNextMonday)
|
||||
)
|
||||
|
||||
return total
|
||||
}
|
||||
|
||||
fun getMemberDonationRanking(
|
||||
creatorId: Long,
|
||||
limit: Long,
|
||||
offset: Long = 0,
|
||||
limit: Long = 10,
|
||||
withDonationCan: Boolean
|
||||
): List<MemberDonationRankingResponse> {
|
||||
val cacheKey = "creator_donation_ranking:$creatorId:$limit:$withDonationCan"
|
||||
val cacheKey = "creator_donation_ranking_v2:$creatorId:$offset:$limit:$withDonationCan"
|
||||
val cachedData = redisTemplate.opsForValue().get(cacheKey) as? MemberDonationRankingListResponse
|
||||
if (cachedData != null) {
|
||||
return cachedData.rankings
|
||||
}
|
||||
|
||||
val memberDonationRanking = repository.getMemberDonationRanking(creatorId, limit)
|
||||
val memberDonationRanking = repository.getMemberDonationRanking(creatorId, offset, limit)
|
||||
|
||||
val result = memberDonationRanking.map {
|
||||
MemberDonationRankingResponse(
|
||||
it.memberId,
|
||||
it.nickname,
|
||||
it.profileImage,
|
||||
"$imageHost/${it.profileImage}",
|
||||
if (withDonationCan) it.donationCan else 0
|
||||
)
|
||||
}
|
||||
|
||||
@@ -888,9 +888,7 @@ class LiveRoomService(
|
||||
3,
|
||||
withDonationCan = false
|
||||
)
|
||||
.asSequence()
|
||||
.map { it.userId }
|
||||
.toList()
|
||||
} else {
|
||||
listOf()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user