Skip to content

Commit

Permalink
feat: ArticleViewCountHandler 추가
Browse files Browse the repository at this point in the history
  • Loading branch information
hun-ca committed Jul 20, 2024
1 parent 5e41a3d commit 13306e6
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 12 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.few.api.domain.article.handler

import com.few.api.repo.dao.article.ArticleViewCountDao
import com.few.api.repo.dao.article.command.ArticleViewCountCommand
import org.springframework.stereotype.Component
import org.springframework.transaction.annotation.Isolation
import org.springframework.transaction.annotation.Propagation
import org.springframework.transaction.annotation.Transactional

@Component
class ArticleViewCountHandler(
private val articleViewCountDao: ArticleViewCountDao,
) {
@Transactional(isolation = Isolation.READ_UNCOMMITTED, propagation = Propagation.REQUIRES_NEW)
fun browseArticleViewCount(articleId: Long): Long {
return (articleViewCountDao.selectArticleViewCount(ArticleViewCountCommand(articleId)) ?: 0L) + 1L
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package com.few.api.domain.article.handler

import com.few.api.config.DatabaseAccessThreadPoolConfig.Companion.DATABASE_ACCESS_POOL
import com.few.api.repo.dao.article.ArticleViewCountDao
import com.few.api.repo.dao.article.ArticleViewHisDao
import com.few.api.repo.dao.article.command.ArticleViewHisCommand
import com.few.api.repo.dao.article.query.ArticleViewCountQuery
import io.github.oshai.kotlinlogging.KotlinLogging
import org.springframework.scheduling.annotation.Async
import org.springframework.stereotype.Component
Expand All @@ -11,6 +13,7 @@ import org.springframework.transaction.annotation.Transactional
@Component
class ArticleViewHisAsyncHandler(
private val articleViewHisDao: ArticleViewHisDao,
private val articleViewCountDao: ArticleViewCountDao,
) {
private val log = KotlinLogging.logger {}

Expand All @@ -20,8 +23,14 @@ class ArticleViewHisAsyncHandler(
try {
articleViewHisDao.insertArticleViewHis(ArticleViewHisCommand(articleId, memberId))
log.debug { "Successfully inserted article view history for articleId: $articleId and memberId: $memberId" }

articleViewCountDao.upsertArticleViewCount(ArticleViewCountQuery(articleId))
log.debug { "Successfully upserted article view count for articleId: $articleId and memberId: $memberId" }
} catch (e: Exception) {
log.error { "Failed to insert article view history for articleId: $articleId and memberId: $memberId" }
log.error {
"Failed insertion article view history and upsertion article view count " +
"for articleId: $articleId and memberId: $memberId"
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.few.api.domain.article.usecase

import com.few.api.domain.article.handler.ArticleViewCountHandler
import com.few.api.domain.article.handler.ArticleViewHisAsyncHandler
import com.few.api.domain.article.usecase.dto.ReadArticleUseCaseIn
import com.few.api.domain.article.usecase.dto.ReadArticleUseCaseOut
Expand All @@ -10,8 +11,6 @@ import com.few.api.domain.article.service.dto.BrowseArticleProblemIdsInDto
import com.few.api.domain.article.service.dto.ReadWriterRecordInDto
import com.few.api.exception.common.NotFoundException
import com.few.api.repo.dao.article.ArticleDao
import com.few.api.repo.dao.article.ArticleViewCountDao
import com.few.api.repo.dao.article.command.ArticleViewCountCommand
import com.few.api.repo.dao.article.query.SelectArticleRecordQuery
import com.few.data.common.code.CategoryType
import org.springframework.stereotype.Component
Expand All @@ -23,7 +22,7 @@ class ReadArticleUseCase(
private val readArticleWriterRecordService: ReadArticleWriterRecordService,
private val browseArticleProblemsService: BrowseArticleProblemsService,
private val articleViewHisAsyncHandler: ArticleViewHisAsyncHandler,
private val articleViewCountDao: ArticleViewCountDao,
private val articleViewCountHandler: ArticleViewCountHandler,
) {

@Transactional(readOnly = true)
Expand All @@ -41,8 +40,8 @@ class ReadArticleUseCase(
browseArticleProblemsService.execute(query)
}

val views = (articleViewCountDao.selectArticleViewCount(ArticleViewCountCommand(useCaseIn.articleId)) ?: 0L) + 1L

// ARTICLE VIEW HIS에 저장하기 전에 먼저 VIEW COUNT 조회하는 순서 변경 금지
val views = articleViewCountHandler.browseArticleViewCount(useCaseIn.articleId)
articleViewHisAsyncHandler.addArticleViewHis(useCaseIn.articleId, useCaseIn.memberId)

return ReadArticleUseCaseOut(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
package com.few.api.domain.article.usecase

import com.few.api.domain.article.handler.ArticleViewCountHandler
import com.few.api.domain.article.handler.ArticleViewHisAsyncHandler
import com.few.api.domain.article.service.BrowseArticleProblemsService
import com.few.api.domain.article.service.ReadArticleWriterRecordService
import com.few.api.domain.article.service.dto.BrowseArticleProblemsOutDto
import com.few.api.domain.article.service.dto.ReadWriterOutDto
import com.few.api.domain.article.usecase.dto.ReadArticleUseCaseIn
import com.few.api.repo.dao.article.ArticleDao
import com.few.api.repo.dao.article.ArticleViewCountDao
import com.few.api.repo.dao.article.record.SelectArticleRecord
import io.github.oshai.kotlinlogging.KotlinLogging
import io.kotest.assertions.throwables.shouldThrow
Expand All @@ -25,21 +25,21 @@ class ReadArticleUseCaseTest : BehaviorSpec({
lateinit var browseArticleProblemsService: BrowseArticleProblemsService
lateinit var useCase: ReadArticleUseCase
lateinit var articleViewHisAsyncHandler: ArticleViewHisAsyncHandler
lateinit var articleViewCountDao: ArticleViewCountDao
lateinit var articleViewCountHandler: ArticleViewCountHandler
val useCaseIn = ReadArticleUseCaseIn(articleId = 1L, memberId = 1L)

beforeContainer {
articleDao = mockk<ArticleDao>()
readArticleWriterRecordService = mockk<ReadArticleWriterRecordService>()
browseArticleProblemsService = mockk<BrowseArticleProblemsService>()
articleViewHisAsyncHandler = mockk<ArticleViewHisAsyncHandler>()
articleViewCountDao = mockk<ArticleViewCountDao>()
articleViewCountHandler = mockk<ArticleViewCountHandler>()
useCase = ReadArticleUseCase(
articleDao,
readArticleWriterRecordService,
browseArticleProblemsService,
articleViewHisAsyncHandler,
articleViewCountDao
articleViewCountHandler
)
}

Expand All @@ -64,7 +64,7 @@ class ReadArticleUseCaseTest : BehaviorSpec({
every { articleDao.selectArticleRecord(any()) } returns record
every { readArticleWriterRecordService.execute(any()) } returns writerSvcOutDto
every { browseArticleProblemsService.execute(any()) } returns probSvcOutDto
every { articleViewCountDao.selectArticleViewCount(any()) } returns 1L
every { articleViewCountHandler.browseArticleViewCount(any()) } returns 1L
every { articleViewHisAsyncHandler.addArticleViewHis(any(), any()) } answers {
log.debug { "Inserting article view history asynchronously" }
}
Expand All @@ -75,7 +75,7 @@ class ReadArticleUseCaseTest : BehaviorSpec({
verify(exactly = 1) { articleDao.selectArticleRecord(any()) }
verify(exactly = 1) { readArticleWriterRecordService.execute(any()) }
verify(exactly = 1) { browseArticleProblemsService.execute(any()) }
verify(exactly = 1) { articleViewCountDao.selectArticleViewCount(any()) }
verify(exactly = 1) { articleViewCountHandler.browseArticleViewCount(any()) }
verify(exactly = 1) { articleViewHisAsyncHandler.addArticleViewHis(any(), any()) }
}
}
Expand Down

0 comments on commit 13306e6

Please sign in to comment.