feat(home-following): 최근 소식 발행 service를 추가한다

This commit is contained in:
2026-06-26 02:48:29 +09:00
parent 8b5c872b45
commit e598d2058d
2 changed files with 285 additions and 0 deletions

View File

@@ -0,0 +1,146 @@
package kr.co.vividnext.sodalive.v2.home.following.application
import kr.co.vividnext.sodalive.v2.home.following.domain.FollowingNewsType
import kr.co.vividnext.sodalive.v2.home.following.domain.HomeFollowingNewsSourceKey
import kr.co.vividnext.sodalive.v2.home.following.port.out.HomeFollowingNewsInboxPort
import kr.co.vividnext.sodalive.v2.home.following.port.out.HomeFollowingNewsInboxRecord
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Propagation
import org.springframework.transaction.annotation.Transactional
import java.time.LocalDateTime
@Service
class HomeFollowingNewsPublishService(
private val inboxPort: HomeFollowingNewsInboxPort
) {
@Transactional(propagation = Propagation.REQUIRES_NEW)
fun publishCommunityPostCreated(
postId: Long,
creatorId: Long,
creatorNickname: String,
creatorProfileImagePath: String?,
title: String,
body: String,
thumbnailImagePath: String?,
occurredAtUtc: LocalDateTime,
isAdult: Boolean
): Int {
return publishToFollowers(
creatorId = creatorId,
newsType = FollowingNewsType.COMMUNITY_POST,
sourceKey = HomeFollowingNewsSourceKey.communityPost(postId),
targetId = postId,
occurredAtUtc = occurredAtUtc,
visibleFromAtUtc = occurredAtUtc,
creatorNickname = creatorNickname,
creatorProfileImagePath = creatorProfileImagePath,
title = title,
body = body,
thumbnailImagePath = thumbnailImagePath,
rank = null,
isAdult = isAdult
)
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
fun publishContentUploaded(
contentId: Long,
creatorId: Long,
creatorNickname: String,
creatorProfileImagePath: String?,
title: String,
body: String,
thumbnailImagePath: String?,
occurredAtUtc: LocalDateTime,
visibleFromAtUtc: LocalDateTime,
isAdult: Boolean
): Int {
return publishToFollowers(
creatorId = creatorId,
newsType = FollowingNewsType.AUDIO_CONTENT,
sourceKey = HomeFollowingNewsSourceKey.audioContent(contentId),
targetId = contentId,
occurredAtUtc = occurredAtUtc,
visibleFromAtUtc = visibleFromAtUtc,
creatorNickname = creatorNickname,
creatorProfileImagePath = creatorProfileImagePath,
title = title,
body = body,
thumbnailImagePath = thumbnailImagePath,
rank = null,
isAdult = isAdult
)
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
fun publishCreatorRankingVisible(
creatorId: Long,
creatorNickname: String,
creatorProfileImagePath: String?,
aggregationStartAtUtc: LocalDateTime,
visibleFromAtUtc: LocalDateTime,
rank: Int
): Int {
return publishToFollowers(
creatorId = creatorId,
newsType = FollowingNewsType.CREATOR_RANKING,
sourceKey = HomeFollowingNewsSourceKey.creatorRanking(creatorId, aggregationStartAtUtc),
targetId = creatorId,
occurredAtUtc = visibleFromAtUtc,
visibleFromAtUtc = visibleFromAtUtc,
creatorNickname = creatorNickname,
creatorProfileImagePath = creatorProfileImagePath,
title = creatorNickname,
body = "$rank",
thumbnailImagePath = creatorProfileImagePath,
rank = rank,
isAdult = false
)
}
private fun publishToFollowers(
creatorId: Long,
newsType: FollowingNewsType,
sourceKey: String,
targetId: Long,
occurredAtUtc: LocalDateTime,
visibleFromAtUtc: LocalDateTime,
creatorNickname: String,
creatorProfileImagePath: String?,
title: String,
body: String,
thumbnailImagePath: String?,
rank: Int?,
isAdult: Boolean
): Int {
val followerIds = inboxPort.findActiveFollowerIds(creatorId)
if (followerIds.isEmpty()) {
return 0
}
val records = followerIds.map { memberId ->
HomeFollowingNewsInboxRecord(
memberId = memberId,
creatorId = creatorId,
newsType = newsType.name,
sourceKey = sourceKey,
targetId = targetId,
occurredAtUtc = occurredAtUtc,
visibleFromAtUtc = visibleFromAtUtc,
creatorNickname = creatorNickname,
creatorProfileImagePath = creatorProfileImagePath,
title = title.take(TITLE_MAX_LENGTH),
body = body.take(BODY_MAX_LENGTH),
thumbnailImagePath = thumbnailImagePath,
rank = rank,
isAdult = isAdult
)
}
return inboxPort.insertIgnoreAll(records)
}
companion object {
private const val TITLE_MAX_LENGTH = 255
private const val BODY_MAX_LENGTH = 1_000
}
}