Compare commits

..

No commits in common. "24841b9850b9e8aec8581526b721f1b6aba5c2a3" and "d35a3d1a8c5742e6722c39191bedbe1c3172f058" have entirely different histories.

1 changed files with 90 additions and 138 deletions

View File

@ -1,11 +1,8 @@
package kr.co.vividnext.sodalive.useraction package kr.co.vividnext.sodalive.useraction
import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.cancel
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import kr.co.vividnext.sodalive.content.order.OrderRepository import kr.co.vividnext.sodalive.content.order.OrderRepository
import kr.co.vividnext.sodalive.fcm.FcmService import kr.co.vividnext.sodalive.fcm.FcmService
import kr.co.vividnext.sodalive.point.MemberPoint import kr.co.vividnext.sodalive.point.MemberPoint
@ -17,8 +14,6 @@ import org.slf4j.LoggerFactory
import org.springframework.stereotype.Service import org.springframework.stereotype.Service
import org.springframework.transaction.support.TransactionTemplate import org.springframework.transaction.support.TransactionTemplate
import java.time.LocalDateTime import java.time.LocalDateTime
import javax.annotation.PreDestroy
import javax.persistence.EntityManager
@Service @Service
class UserActionService( class UserActionService(
@ -29,15 +24,10 @@ class UserActionService(
private val memberPointRepository: MemberPointRepository, private val memberPointRepository: MemberPointRepository,
private val transactionTemplate: TransactionTemplate, private val transactionTemplate: TransactionTemplate,
private val fcmService: FcmService, private val fcmService: FcmService
private val entityManager: EntityManager
) { ) {
private val coroutineScope = CoroutineScope( private val coroutineScope = CoroutineScope(Dispatchers.IO)
Dispatchers.IO + CoroutineExceptionHandler { _, e ->
logger.error("포인트 지급 또는 알림 실패: ${e.message}")
}
)
fun recordAction( fun recordAction(
memberId: Long, memberId: Long,
@ -49,151 +39,113 @@ class UserActionService(
) { ) {
coroutineScope.launch { coroutineScope.launch {
val now = LocalDateTime.now() val now = LocalDateTime.now()
val policy = policyRepository.findByActionTypeAndIsActiveTrue(actionType, now) transactionTemplate.execute {
if (policy != null) { repository.save(
val policyType = policy.policyType UserActionLog(
val todayAt15 = now.toLocalDate().atTime(15, 0)
val policyTypeDailyStartDate = if (now.toLocalTime().isBefore(todayAt15.toLocalTime())) {
now.toLocalDate().minusDays(1).atTime(15, 0)
} else {
todayAt15
}
val isValidPolicyTypeDailyAndDailyStartDateAfterPolicyStartDate =
policyType == PolicyType.DAILY && policyTypeDailyStartDate >= policy.startDate
val order = if (contentId != null) {
orderRepository.findByMemberIdAndContentId(
memberId = memberId, memberId = memberId,
contentId = contentId, actionType = actionType,
createdAt = if (isValidPolicyTypeDailyAndDailyStartDateAfterPolicyStartDate) { contentCommentId = contentCommentId
policyTypeDailyStartDate
} else {
policy.startDate
}
) )
} else { )
null repository.flush()
}
if (actionType == ActionType.ORDER_CONTENT_COMMENT && order == null) return@launch
} }
withContext(Dispatchers.IO) { if (isAuth) {
transactionTemplate.execute { try {
repository.save( transactionTemplate.execute {
UserActionLog( val policy = policyRepository.findByActionTypeAndIsActiveTrue(actionType, now)
memberId = memberId, if (policy != null) {
actionType = actionType, val policyType = policy.policyType
contentCommentId = contentCommentId val todayAt15 = now.toLocalDate().atTime(15, 0)
) val policyTypeDailyStartDate = if (now.toLocalTime().isBefore(todayAt15.toLocalTime())) {
) now.toLocalDate().minusDays(1).atTime(15, 0)
repository.flush() } else {
} todayAt15
} }
withContext(Dispatchers.IO) { val isValidPolicyTypeDailyAndDailyStartDateAfterPolicyStartDate =
if (isAuth) { policyType == PolicyType.DAILY && policyTypeDailyStartDate >= policy.startDate
try { val order = if (contentId != null) {
transactionTemplate.execute { orderRepository.findByMemberIdAndContentId(
entityManager.clear()
if (policy != null) {
val policyType = policy.policyType
val todayAt15 = now.toLocalDate().atTime(15, 0)
val policyTypeDailyStartDate =
if (now.toLocalTime().isBefore(todayAt15.toLocalTime())) {
now.toLocalDate().minusDays(1).atTime(15, 0)
} else {
todayAt15
}
val isValidPolicyTypeDailyAndDailyStartDateAfterPolicyStartDate =
policyType == PolicyType.DAILY && policyTypeDailyStartDate >= policy.startDate
val order = if (contentId != null) {
orderRepository.findByMemberIdAndContentId(
memberId = memberId,
contentId = contentId,
createdAt = if (isValidPolicyTypeDailyAndDailyStartDateAfterPolicyStartDate) {
policyTypeDailyStartDate
} else {
policy.startDate
}
)
} else {
null
}
if (actionType == ActionType.ORDER_CONTENT_COMMENT && order == null) return@execute
val actionCount = repository.countByMemberIdAndActionTypeAndCreatedAtBetween(
memberId = memberId, memberId = memberId,
actionType = actionType, contentId = contentId,
startDate = if (isValidPolicyTypeDailyAndDailyStartDateAfterPolicyStartDate) { createdAt = if (isValidPolicyTypeDailyAndDailyStartDateAfterPolicyStartDate) {
policyTypeDailyStartDate policyTypeDailyStartDate
} else { } else {
policy.startDate policy.startDate
},
endDate = policy.endDate ?: LocalDateTime.now()
)
if (actionCount < policy.threshold) return@execute
val grantedCount = grantLogRepository.countByMemberIdAndPolicyIdAndStartDate(
memberId,
policy.id!!,
startDate = if (isValidPolicyTypeDailyAndDailyStartDateAfterPolicyStartDate) {
policyTypeDailyStartDate
} else {
policy.startDate
},
orderId = order?.id
)
if (grantedCount >= policy.availableCount) return@execute
val point = if (actionType == ActionType.ORDER_CONTENT_COMMENT && order != null) {
order.can
} else {
policy.pointAmount
}
if (point > 0) {
grantLogRepository.save(
PointGrantLog(
memberId = memberId,
point = point,
actionType = actionType,
policyId = policy.id!!,
orderId = order?.id
)
)
memberPointRepository.save(
MemberPoint(
memberId = memberId,
point = point,
actionType = actionType,
expiresAt = now.plusDays(3)
)
)
if (pushTokenList.isNotEmpty()) {
fcmService.sendPointGranted(
pushTokenList,
point
)
} }
)
} else {
null
}
if (actionType == ActionType.ORDER_CONTENT_COMMENT && order == null) return@execute
val actionCount = repository.countByMemberIdAndActionTypeAndCreatedAtBetween(
memberId = memberId,
actionType = actionType,
startDate = if (isValidPolicyTypeDailyAndDailyStartDateAfterPolicyStartDate) {
policyTypeDailyStartDate
} else {
policy.startDate
},
endDate = policy.endDate ?: now
)
if (actionCount < policy.threshold) return@execute
val grantedCount = grantLogRepository.countByMemberIdAndPolicyIdAndStartDate(
memberId,
policy.id!!,
startDate = if (isValidPolicyTypeDailyAndDailyStartDateAfterPolicyStartDate) {
policyTypeDailyStartDate
} else {
policy.startDate
},
orderId = order?.id
)
if (grantedCount >= policy.availableCount) return@execute
val point = if (actionType == ActionType.ORDER_CONTENT_COMMENT && order != null) {
order.can
} else {
policy.pointAmount
}
if (point > 0) {
grantLogRepository.save(
PointGrantLog(
memberId = memberId,
point = point,
actionType = actionType,
policyId = policy.id!!,
orderId = order?.id
)
)
memberPointRepository.save(
MemberPoint(
memberId = memberId,
point = point,
actionType = actionType,
expiresAt = now.plusDays(3)
)
)
if (pushTokenList.isNotEmpty()) {
fcmService.sendPointGranted(
pushTokenList,
point
)
} }
} }
} }
} catch (e: Exception) {
logger.warn("포인트 지급 또는 알림 실패: ${e.message}")
} }
} catch (e: Exception) {
logger.warn("포인트 지급 또는 알림 실패: ${e.message}")
} }
} }
} }
} }
@PreDestroy
fun onDestroy() {
coroutineScope.cancel("UserActionService 종료")
}
companion object { companion object {
private val logger = LoggerFactory.getLogger(UserActionService::class.java) private val logger = LoggerFactory.getLogger(UserActionService::class.java)
} }