라이브 방 정보 - ReentrantReadWriteLock 추가

This commit is contained in:
Klaus 2023-08-01 05:48:06 +09:00
parent 7671e24470
commit 5a56990d0b
2 changed files with 145 additions and 116 deletions

View File

@ -53,6 +53,8 @@ import java.time.LocalDateTime
import java.time.ZoneId import java.time.ZoneId
import java.time.format.DateTimeFormatter import java.time.format.DateTimeFormatter
import java.util.Date import java.util.Date
import java.util.concurrent.locks.ReentrantReadWriteLock
import kotlin.concurrent.write
@Service @Service
@Transactional(readOnly = true) @Transactional(readOnly = true)
@ -88,6 +90,8 @@ class LiveRoomService(
@Value("\${cloud.aws.cloud-front.host}") @Value("\${cloud.aws.cloud-front.host}")
private val cloudFrontHost: String private val cloudFrontHost: String
) { ) {
private val tokenLocks: MutableMap<Long, ReentrantReadWriteLock> = mutableMapOf()
fun getRoomList( fun getRoomList(
dateString: String?, dateString: String?,
status: LiveRoomStatus, status: LiveRoomStatus,
@ -415,6 +419,8 @@ class LiveRoomService(
throw SodaException("비밀번호가 일치하지 않습니다.\n다시 확인 후 입력해주세요.") throw SodaException("비밀번호가 일치하지 않습니다.\n다시 확인 후 입력해주세요.")
} }
val lock = getOrCreateLock(memberId = member.id!!)
lock.write {
var roomInfo = roomInfoRepository.findByIdOrNull(request.roomId) var roomInfo = roomInfoRepository.findByIdOrNull(request.roomId)
if (roomInfo == null) { if (roomInfo == null) {
roomInfo = roomInfoRepository.save(LiveRoomInfo(roomId = request.roomId)) roomInfo = roomInfoRepository.save(LiveRoomInfo(roomId = request.roomId))
@ -459,6 +465,7 @@ class LiveRoomService(
roomInfoRepository.save(roomInfo) roomInfoRepository.save(roomInfo)
roomVisitService.roomVisit(room, member) roomVisitService.roomVisit(room, member)
} }
}
fun getRecentRoomInfo(member: Member): GetRecentRoomInfoResponse { fun getRecentRoomInfo(member: Member): GetRecentRoomInfoResponse {
return repository.getRecentRoomInfo(memberId = member.id!!, cloudFrontHost = cloudFrontHost) return repository.getRecentRoomInfo(memberId = member.id!!, cloudFrontHost = cloudFrontHost)
@ -621,6 +628,8 @@ class LiveRoomService(
} }
fun deleteDonationMessage(request: DeleteLiveRoomDonationMessage, member: Member) { fun deleteDonationMessage(request: DeleteLiveRoomDonationMessage, member: Member) {
val lock = getOrCreateLock(memberId = member.id!!)
lock.write {
val room = repository.findByIdOrNull(request.roomId) val room = repository.findByIdOrNull(request.roomId)
?: throw SodaException("해당하는 라이브가 없습니다.") ?: throw SodaException("해당하는 라이브가 없습니다.")
@ -634,6 +643,7 @@ class LiveRoomService(
roomInfo.removeDonationMessage(request.messageUUID) roomInfo.removeDonationMessage(request.messageUUID)
roomInfoRepository.save(roomInfo) roomInfoRepository.save(roomInfo)
} }
}
fun getUserProfile(roomId: Long, userId: Long, member: Member): GetLiveRoomUserProfileResponse { fun getUserProfile(roomId: Long, userId: Long, member: Member): GetLiveRoomUserProfileResponse {
val room = repository.getLiveRoom(roomId) val room = repository.getLiveRoom(roomId)
@ -701,28 +711,33 @@ class LiveRoomService(
} }
fun setSpeaker(request: SetManagerOrSpeakerOrAudienceRequest) { fun setSpeaker(request: SetManagerOrSpeakerOrAudienceRequest) {
val lock = getOrCreateLock(memberId = request.memberId)
lock.write {
val roomInfo = roomInfoRepository.findByIdOrNull(request.roomId) val roomInfo = roomInfoRepository.findByIdOrNull(request.roomId)
?: throw SodaException("해당하는 라이브의 정보가 없습니다.") ?: throw SodaException("해당하는 라이브의 정보가 없습니다.")
val account = memberRepository.findByIdOrNull(request.accountId) val member = memberRepository.findByIdOrNull(request.memberId)
?: throw SodaException("로그인 정보를 확인해 주세요.") ?: throw SodaException("로그인 정보를 확인해 주세요.")
if (roomInfo.speakerCount > 9) { if (roomInfo.speakerCount > 9) {
throw SodaException("스피커 정원이 초과하였습니다.") throw SodaException("스피커 정원이 초과하였습니다.")
} }
roomInfo.removeListener(account) roomInfo.removeListener(member)
roomInfo.removeManager(account) roomInfo.removeManager(member)
roomInfo.addSpeaker(account, cloudFrontHost) roomInfo.addSpeaker(member, cloudFrontHost)
roomInfoRepository.save(roomInfo) roomInfoRepository.save(roomInfo)
} }
}
fun setListener(request: SetManagerOrSpeakerOrAudienceRequest) { fun setListener(request: SetManagerOrSpeakerOrAudienceRequest) {
val lock = getOrCreateLock(memberId = request.memberId)
lock.write {
val roomInfo = roomInfoRepository.findByIdOrNull(request.roomId) val roomInfo = roomInfoRepository.findByIdOrNull(request.roomId)
?: throw SodaException("해당하는 라이브의 정보가 없습니다.") ?: throw SodaException("해당하는 라이브의 정보가 없습니다.")
val member = memberRepository.findByIdOrNull(request.accountId) val member = memberRepository.findByIdOrNull(request.memberId)
?: throw SodaException("로그인 정보를 확인해 주세요.") ?: throw SodaException("로그인 정보를 확인해 주세요.")
roomInfo.removeSpeaker(member) roomInfo.removeSpeaker(member)
@ -731,14 +746,17 @@ class LiveRoomService(
roomInfoRepository.save(roomInfo) roomInfoRepository.save(roomInfo)
} }
}
fun setManager(request: SetManagerOrSpeakerOrAudienceRequest, member: Member) { fun setManager(request: SetManagerOrSpeakerOrAudienceRequest, member: Member) {
val lock = getOrCreateLock(memberId = member.id!!)
lock.write {
val room = repository.getLiveRoom(request.roomId) ?: throw SodaException("잘못된 요청입니다.") val room = repository.getLiveRoom(request.roomId) ?: throw SodaException("잘못된 요청입니다.")
if (room.member!!.id!! != member.id!!) { if (room.member!!.id!! != member.id!!) {
throw SodaException("권한이 없습니다.") throw SodaException("권한이 없습니다.")
} }
val user = memberRepository.findByIdOrNull(request.accountId) ?: throw SodaException("해당하는 유저가 없습니다.") val user = memberRepository.findByIdOrNull(request.memberId) ?: throw SodaException("해당하는 유저가 없습니다.")
val roomInfo = roomInfoRepository.findByIdOrNull(request.roomId) val roomInfo = roomInfoRepository.findByIdOrNull(request.roomId)
?: throw SodaException("해당하는 라이브의 정보가 없습니다.") ?: throw SodaException("해당하는 라이브의 정보가 없습니다.")
@ -760,6 +778,7 @@ class LiveRoomService(
roomInfoRepository.save(roomInfo) roomInfoRepository.save(roomInfo)
} }
}
@Transactional @Transactional
fun donation(request: LiveRoomDonationRequest, member: Member) { fun donation(request: LiveRoomDonationRequest, member: Member) {
@ -781,6 +800,8 @@ class LiveRoomService(
) )
if (request.message.isNotBlank()) { if (request.message.isNotBlank()) {
val lock = getOrCreateLock(memberId = member.id!!)
lock.write {
val roomInfo = roomInfoRepository.findByIdOrNull(room.id!!) val roomInfo = roomInfoRepository.findByIdOrNull(room.id!!)
?: throw SodaException("해당하는 라이브의 정보가 없습니다.") ?: throw SodaException("해당하는 라이브의 정보가 없습니다.")
@ -793,6 +814,7 @@ class LiveRoomService(
roomInfoRepository.save(roomInfo) roomInfoRepository.save(roomInfo)
} }
} }
}
@Transactional @Transactional
fun refundDonation(roomId: Long, member: Member) { fun refundDonation(roomId: Long, member: Member) {
@ -848,6 +870,8 @@ class LiveRoomService(
val roomId = roomVisit?.room?.id val roomId = roomVisit?.room?.id
if (roomId != null) { if (roomId != null) {
val lock = getOrCreateLock(memberId = member.id!!)
lock.write {
val roomInfo = roomInfoRepository.findByIdOrNull(roomId) val roomInfo = roomInfoRepository.findByIdOrNull(roomId)
if (roomInfo != null) { if (roomInfo != null) {
val room = repository.getLiveRoom(roomId) ?: return val room = repository.getLiveRoom(roomId) ?: return
@ -865,3 +889,8 @@ class LiveRoomService(
} }
} }
} }
private fun getOrCreateLock(memberId: Long): ReentrantReadWriteLock {
return tokenLocks.computeIfAbsent(memberId) { ReentrantReadWriteLock() }
}
}

View File

@ -2,5 +2,5 @@ package kr.co.vividnext.sodalive.live.room
data class SetManagerOrSpeakerOrAudienceRequest( data class SetManagerOrSpeakerOrAudienceRequest(
val roomId: Long, val roomId: Long,
val accountId: Long val memberId: Long
) )