From 205deea88ad619851276710c2b8a5579ae33ee63 Mon Sep 17 00:00:00 2001 From: Klaus Date: Tue, 9 Apr 2024 16:24:49 +0900 Subject: [PATCH 1/2] =?UTF-8?q?=EB=9D=BC=EC=9D=B4=EB=B8=8C=20=EC=A4=91=20?= =?UTF-8?q?=EB=A6=AC=EC=8A=A4=ED=8A=B8=20-=20=EB=A6=AC=EC=8A=A4=ED=8A=B8?= =?UTF-8?q?=20=EC=A0=95=EB=A0=AC=20=EC=A1=B0=EA=B1=B4=20=EC=88=98=EC=A0=95?= =?UTF-8?q?=20-=201.=2015=EB=B6=84=20=EB=8F=99=EC=95=88=20=EB=B0=9B?= =?UTF-8?q?=EC=9D=80=20=EC=BA=94=20-=202.=2015=EB=B6=84=20=EB=8F=99?= =?UTF-8?q?=EC=95=88=20=EC=B0=B8=EC=97=AC=ED=95=9C=20=EC=B0=B8=EC=97=AC?= =?UTF-8?q?=EC=9E=90=20-=203.=20=EC=B5=9C=EA=B7=BC=20=EC=8B=9C=EC=9E=91?= =?UTF-8?q?=ED=95=9C=20=EB=9D=BC=EC=9D=B4=EB=B8=8C=20-=204.=20=EC=B5=9C?= =?UTF-8?q?=EA=B7=BC=20=EA=B0=80=EC=9E=85=ED=95=9C=20=ED=81=AC=EB=A6=AC?= =?UTF-8?q?=EC=97=90=EC=9D=B4=ED=84=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sodalive/live/room/LiveRoomRepository.kt | 169 +++++++++--------- .../sodalive/live/room/LiveRoomService.kt | 63 ++++++- .../sodalive/live/room/QuarterLiveRankings.kt | 16 ++ 3 files changed, 154 insertions(+), 94 deletions(-) create mode 100644 src/main/kotlin/kr/co/vividnext/sodalive/live/room/QuarterLiveRankings.kt diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/live/room/LiveRoomRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/live/room/LiveRoomRepository.kt index 9f03a50..cffa20f 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/live/room/LiveRoomRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/live/room/LiveRoomRepository.kt @@ -1,41 +1,36 @@ package kr.co.vividnext.sodalive.live.room -import com.querydsl.core.types.OrderSpecifier -import com.querydsl.core.types.Predicate import com.querydsl.core.types.Projections import com.querydsl.core.types.dsl.CaseBuilder -import com.querydsl.core.types.dsl.Expressions import com.querydsl.jpa.impl.JPAQueryFactory import kr.co.vividnext.sodalive.can.use.CanUsage import kr.co.vividnext.sodalive.can.use.QUseCan.useCan import kr.co.vividnext.sodalive.can.use.QUseCanCalculate.useCanCalculate import kr.co.vividnext.sodalive.live.room.QLiveRoom.liveRoom +import kr.co.vividnext.sodalive.live.room.QQuarterLiveRankings.quarterLiveRankings import kr.co.vividnext.sodalive.live.room.donation.GetLiveRoomDonationItem import kr.co.vividnext.sodalive.live.room.donation.QGetLiveRoomDonationItem -import kr.co.vividnext.sodalive.member.Member -import kr.co.vividnext.sodalive.member.QMember import kr.co.vividnext.sodalive.member.QMember.member -import org.springframework.data.domain.Pageable import org.springframework.data.jpa.repository.JpaRepository import org.springframework.stereotype.Repository -import java.time.LocalDate import java.time.LocalDateTime import java.time.ZoneId -import java.time.format.DateTimeFormatter @Repository interface LiveRoomRepository : JpaRepository, LiveRoomQueryRepository interface LiveRoomQueryRepository { - fun getLiveRoomList( - dateString: String?, - status: LiveRoomStatus, - pageable: Pageable, - member: Member, - timezone: String, + fun getLiveRoomListNow(offset: Long, limit: Long, timezone: String, isAdult: Boolean): List + + fun getLiveRoomListReservationWithDate( + date: LocalDateTime, + offset: Long, + limit: Long, isAdult: Boolean ): List + fun getLiveRoomListReservationWithoutDate(timezone: String, memberId: Long, isAdult: Boolean): List + fun getLiveRoom(id: Long): LiveRoom? fun getLiveRoomAndAccountId(roomId: Long, memberId: Long): LiveRoom? fun getRecentRoomInfo(memberId: Long, cloudFrontHost: String): GetRecentRoomInfoResponse? @@ -45,67 +40,92 @@ interface LiveRoomQueryRepository { } class LiveRoomQueryRepositoryImpl(private val queryFactory: JPAQueryFactory) : LiveRoomQueryRepository { - override fun getLiveRoomList( - dateString: String?, - status: LiveRoomStatus, - pageable: Pageable, - member: Member, - timezone: String, - isAdult: Boolean - ): List { - var where: Predicate - - if (status == LiveRoomStatus.NOW) { - where = liveRoom.channelName.isNotNull - .and(liveRoom.channelName.isNotEmpty) - } else { - where = if (dateString != null) { - val dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd") - val date = LocalDate.parse(dateString, dateTimeFormatter).atStartOfDay() - .atZone(ZoneId.of(timezone)) - .withZoneSameInstant(ZoneId.of("UTC")) - .toLocalDateTime() - - liveRoom.beginDateTime.goe(date) - .and(liveRoom.beginDateTime.lt(date.plusDays(1))) - .and( - liveRoom.channelName.isNull - .or(liveRoom.channelName.isEmpty) - ) - } else { - liveRoom.beginDateTime.gt( - LocalDateTime.now() - .atZone(ZoneId.of(timezone)) - .withZoneSameInstant(ZoneId.of("UTC")) - .toLocalDateTime() - ) - .and( - liveRoom.channelName.isNull - .or(liveRoom.channelName.isEmpty) - ) - } - } + override fun getLiveRoomListNow(offset: Long, limit: Long, timezone: String, isAdult: Boolean): List { + var where = liveRoom.channelName.isNotNull + .and(liveRoom.channelName.isNotEmpty) + .and(liveRoom.isActive.isTrue) + .and(liveRoom.member.isNotNull) if (!isAdult) { where = where.and(liveRoom.isAdult.isFalse) } - where = where.and(liveRoom.isActive.isTrue) + return queryFactory + .selectFrom(liveRoom) + .innerJoin(liveRoom.member, member) + .leftJoin(quarterLiveRankings).on(liveRoom.id.eq(quarterLiveRankings.roomId)) + .where(where) + .orderBy( + quarterLiveRankings.totalCan.desc(), + quarterLiveRankings.totalParticipants.desc(), + liveRoom.beginDateTime.desc(), + liveRoom.member.createdAt.desc() + ) + .fetch() + } + + override fun getLiveRoomListReservationWithDate( + date: LocalDateTime, + offset: Long, + limit: Long, + isAdult: Boolean + ): List { + var where = liveRoom.beginDateTime.goe(date) + .and(liveRoom.beginDateTime.lt(date.plusDays(1))) + .and( + liveRoom.channelName.isNull + .or(liveRoom.channelName.isEmpty) + ) + .and(liveRoom.isActive.isTrue) .and(liveRoom.member.isNotNull) + if (!isAdult) { + where = where.and(liveRoom.isAdult.isFalse) + } + return queryFactory .selectFrom(liveRoom) - .innerJoin(liveRoom.member, QMember.member) - .offset(pageable.offset) - .limit(pageable.pageSize.toLong()) + .innerJoin(liveRoom.member, member) + .offset(offset) + .limit(limit) + .where(where) + .orderBy(liveRoom.beginDateTime.asc()) + .fetch() + } + + override fun getLiveRoomListReservationWithoutDate( + timezone: String, + memberId: Long, + isAdult: Boolean + ): List { + var where = liveRoom.beginDateTime.gt( + LocalDateTime.now() + .atZone(ZoneId.of(timezone)) + .withZoneSameInstant(ZoneId.of("UTC")) + .toLocalDateTime() + ) + .and( + liveRoom.channelName.isNull + .or(liveRoom.channelName.isEmpty) + ) + .and(liveRoom.isActive.isTrue) + .and(liveRoom.member.isNotNull) + + if (!isAdult) { + where = where.and(liveRoom.isAdult.isFalse) + } + + return queryFactory + .selectFrom(liveRoom) + .innerJoin(liveRoom.member, member) + .limit(10) .where(where) .orderBy( - *orderByFieldAccountId( - memberId = member.id!!, - status = status, - offset = pageable.offset, - dateString = dateString - ) + CaseBuilder() + .`when`(member.id.eq(memberId)).then(1) + .otherwise(2) + .asc(), + liveRoom.beginDateTime.asc() ) .fetch() } @@ -201,25 +221,4 @@ class LiveRoomQueryRepositoryImpl(private val queryFactory: JPAQueryFactory) : L ) .fetch() } - - private fun orderByFieldAccountId( - memberId: Long, - status: LiveRoomStatus, - offset: Long, - dateString: String? - ): Array> { - return if (status == LiveRoomStatus.NOW) { - arrayOf(Expressions.numberTemplate(Double::class.java, "function('rand')").asc()) - } else if (status == LiveRoomStatus.RESERVATION && offset == 0L && dateString == null) { - arrayOf( - CaseBuilder() - .`when`(member.id.eq(memberId)).then(1) - .otherwise(2) - .asc(), - liveRoom.beginDateTime.asc() - ) - } else { - arrayOf(liveRoom.beginDateTime.asc()) - } - } } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/live/room/LiveRoomService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/live/room/LiveRoomService.kt index 6cfc274..a4ac5e4 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/live/room/LiveRoomService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/live/room/LiveRoomService.kt @@ -58,6 +58,7 @@ import org.springframework.data.repository.findByIdOrNull import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional import org.springframework.web.multipart.MultipartFile +import java.time.LocalDate import java.time.LocalDateTime import java.time.ZoneId import java.time.format.DateTimeFormatter @@ -115,16 +116,24 @@ class LiveRoomService( member: Member, timezone: String ): List { - return repository - .getLiveRoomList( - dateString = dateString, - status = status, - pageable = pageable, - member = member, - timezone = timezone, + val roomList = if (status == LiveRoomStatus.NOW) { + getLiveRoomListNow(pageable, timezone, isAdult = member.auth != null) + } else if (dateString != null) { + getLiveRoomListReservationWithDate( + dateString, + pageable, + timezone, isAdult = member.auth != null ) - .asSequence() + } else { + getLiveRoomListReservationWithoutDate( + timezone, + memberId = member.id!!, + isAdult = member.auth != null + ) + } + + return roomList .filter { !blockMemberRepository.isBlocked(blockedMemberId = member.id!!, memberId = it.member!!.id!!) } .map { val roomInfo = roomInfoRepository.findByIdOrNull(it.id!!) @@ -174,7 +183,43 @@ class LiveRoomService( isPrivateRoom = it.type == LiveRoomType.PRIVATE ) } - .toList() + } + + private fun getLiveRoomListNow(pageable: Pageable, timezone: String, isAdult: Boolean): List { + return repository.getLiveRoomListNow( + offset = pageable.offset, + limit = pageable.pageSize.toLong(), + timezone = timezone, + isAdult = isAdult + ) + } + + private fun getLiveRoomListReservationWithDate( + dateString: String, + pageable: Pageable, + timezone: String, + isAdult: Boolean + ): List { + val dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd") + val date = LocalDate.parse(dateString, dateTimeFormatter).atStartOfDay() + .atZone(ZoneId.of(timezone)) + .withZoneSameInstant(ZoneId.of("UTC")) + .toLocalDateTime() + + return repository.getLiveRoomListReservationWithDate( + date = date, + offset = pageable.offset, + limit = pageable.pageSize.toLong(), + isAdult = isAdult + ) + } + + private fun getLiveRoomListReservationWithoutDate( + timezone: String, + memberId: Long, + isAdult: Boolean + ): List { + return repository.getLiveRoomListReservationWithoutDate(timezone, memberId, isAdult) } @Transactional diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/live/room/QuarterLiveRankings.kt b/src/main/kotlin/kr/co/vividnext/sodalive/live/room/QuarterLiveRankings.kt new file mode 100644 index 0000000..d484073 --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/live/room/QuarterLiveRankings.kt @@ -0,0 +1,16 @@ +package kr.co.vividnext.sodalive.live.room + +import javax.persistence.Entity +import javax.persistence.GeneratedValue +import javax.persistence.GenerationType +import javax.persistence.Id + +@Entity +data class QuarterLiveRankings( + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + var id: Long? = null, + val roomId: Long, + val totalCan: Int, + val totalParticipants: Int +) From 476e4e8eb1b07e1fefbdc36832e4a793aee3128f Mon Sep 17 00:00:00 2001 From: Klaus Date: Tue, 9 Apr 2024 16:49:43 +0900 Subject: [PATCH 2/2] =?UTF-8?q?=EB=9D=BC=EC=9D=B4=EB=B8=8C=20=EC=A4=91=20?= =?UTF-8?q?=EB=A6=AC=EC=8A=A4=ED=8A=B8=20-=20offset,=20limit=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kr/co/vividnext/sodalive/live/room/LiveRoomRepository.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/live/room/LiveRoomRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/live/room/LiveRoomRepository.kt index cffa20f..08a2904 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/live/room/LiveRoomRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/live/room/LiveRoomRepository.kt @@ -55,6 +55,8 @@ class LiveRoomQueryRepositoryImpl(private val queryFactory: JPAQueryFactory) : L .innerJoin(liveRoom.member, member) .leftJoin(quarterLiveRankings).on(liveRoom.id.eq(quarterLiveRankings.roomId)) .where(where) + .offset(offset) + .limit(limit) .orderBy( quarterLiveRankings.totalCan.desc(), quarterLiveRankings.totalParticipants.desc(), @@ -86,9 +88,9 @@ class LiveRoomQueryRepositoryImpl(private val queryFactory: JPAQueryFactory) : L return queryFactory .selectFrom(liveRoom) .innerJoin(liveRoom.member, member) + .where(where) .offset(offset) .limit(limit) - .where(where) .orderBy(liveRoom.beginDateTime.asc()) .fetch() }