feat(recommend): 추천 팔로우 성공 로그를 커밋 후 기록한다

This commit is contained in:
2026-06-01 17:56:50 +09:00
parent da387f43a0
commit bb96f07872
2 changed files with 113 additions and 28 deletions

View File

@@ -5,47 +5,103 @@ import kr.co.vividnext.sodalive.member.Member
import kr.co.vividnext.sodalive.member.MemberRepository
import kr.co.vividnext.sodalive.member.following.CreatorFollowing
import kr.co.vividnext.sodalive.member.following.CreatorFollowingRepository
import org.slf4j.LoggerFactory
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional
import org.springframework.transaction.support.TransactionSynchronization
import org.springframework.transaction.support.TransactionSynchronizationManager
@Service
class RecommendedCreatorFollowService(
private val memberRepository: MemberRepository,
private val creatorFollowingRepository: CreatorFollowingRepository
) {
private val log = LoggerFactory.getLogger(javaClass)
@Transactional
fun followCreators(member: Member, creatorIds: List<Long>) {
val distinctCreatorIds = creatorIds.distinct()
val creatorById = distinctCreatorIds
.filter { it != member.id }
.associateWith { creatorId ->
memberRepository.findCreatorByIdOrNull(creatorId)
?: throw SodaException(messageKey = "member.validation.creator_not_found")
}
val startedAt = System.currentTimeMillis()
var savedCount = 0
var reactivatedCount = 0
var skippedCount = 0
distinctCreatorIds.forEach { creatorId ->
if (creatorId == member.id) {
return@forEach
}
val existingFollowing = creatorFollowingRepository.findByCreatorIdAndMemberId(
creatorId = creatorId,
memberId = member.id!!
)
if (existingFollowing != null) {
if (!existingFollowing.isActive) {
existingFollowing.isNotify = true
existingFollowing.isActive = true
runCatching {
val distinctCreatorIds = creatorIds.distinct()
val creatorById = distinctCreatorIds
.filter { it != member.id }
.associateWith { creatorId ->
memberRepository.findCreatorByIdOrNull(creatorId)
?: throw SodaException(messageKey = "member.validation.creator_not_found")
}
return@forEach
}
creatorFollowingRepository.save(
CreatorFollowing().apply {
this.member = member
creator = creatorById.getValue(creatorId)
distinctCreatorIds.forEach { creatorId ->
if (creatorId == member.id) {
skippedCount += 1
return@forEach
}
val existingFollowing = creatorFollowingRepository.findByCreatorIdAndMemberId(
creatorId = creatorId,
memberId = member.id!!
)
if (existingFollowing != null) {
if (!existingFollowing.isActive) {
existingFollowing.isNotify = true
existingFollowing.isActive = true
reactivatedCount += 1
} else {
skippedCount += 1
}
return@forEach
}
creatorFollowingRepository.save(
CreatorFollowing().apply {
this.member = member
creator = creatorById.getValue(creatorId)
}
)
savedCount += 1
}
distinctCreatorIds.size
}.onSuccess { distinctCount ->
afterCommit {
log.info(
"event=recommended_creator_follow_success " +
"memberId={} requestedCount={} distinctCount={} savedCount={} " +
"reactivatedCount={} skippedCount={} elapsedMs={}",
member.id,
creatorIds.size,
distinctCount,
savedCount,
reactivatedCount,
skippedCount,
System.currentTimeMillis() - startedAt
)
}
}.onFailure { ex ->
log.warn(
"event=recommended_creator_follow_failure memberId={} requestedCount={} distinctCount={} elapsedMs={} error={}",
member.id,
creatorIds.size,
creatorIds.distinct().size,
System.currentTimeMillis() - startedAt,
ex.message,
ex
)
throw ex
}
}
private fun afterCommit(action: () -> Unit) {
if (!TransactionSynchronizationManager.isSynchronizationActive()) {
action()
return
}
TransactionSynchronizationManager.registerSynchronization(
object : TransactionSynchronization {
override fun afterCommit() = action()
}
)
}
}