-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Feat/#215] article_view_his 테이블 추가 및 조회수 응답 추가 #216
Changes from all commits
3c02659
977de9a
1334ccf
390b898
2304654
29ca0fb
bfaebe6
362999e
9c17140
abde0c3
89a188f
a8342ba
21c0ad4
4ce6ac9
51671e4
a76ed19
dc76e36
7bac2fc
ba64abd
3348881
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
package com.few.api.repo.dao.article | ||
|
||
import com.few.api.repo.dao.article.command.ArticleViewHisCommand | ||
import com.few.api.repo.dao.article.query.ArticleViewHisCountQuery | ||
import jooq.jooq_dsl.tables.ArticleViewHis | ||
import org.jooq.DSLContext | ||
import org.springframework.stereotype.Repository | ||
|
||
@Repository | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 종준님은 DAO에 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
class ArticleViewHisDao( | ||
private val dslContext: DSLContext, | ||
) { | ||
|
||
fun insertArticleViewHis(command: ArticleViewHisCommand) { | ||
dslContext.insertInto( | ||
ArticleViewHis.ARTICLE_VIEW_HIS, | ||
ArticleViewHis.ARTICLE_VIEW_HIS.ARTICLE_MST_ID, | ||
ArticleViewHis.ARTICLE_VIEW_HIS.MEMBER_ID | ||
).values( | ||
command.articleId, | ||
command.memberId | ||
).execute() | ||
} | ||
Comment on lines
+14
to
+23
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
|
||
fun countArticleViews(query: ArticleViewHisCountQuery): Long? { | ||
return dslContext.selectCount() | ||
.from(ArticleViewHis.ARTICLE_VIEW_HIS) | ||
.where(ArticleViewHis.ARTICLE_VIEW_HIS.ARTICLE_MST_ID.eq(query.articleId)) | ||
.fetchOne(0, Long::class.java) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
package com.few.api.repo.dao.article.command | ||
|
||
data class ArticleViewHisCommand( | ||
val articleId: Long, | ||
val memberId: Long, | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
package com.few.api.repo.dao.article.query | ||
|
||
data class ArticleViewHisCountQuery( | ||
val articleId: Long, | ||
) |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
package com.few.api.config | ||
|
||
import com.few.api.config.properties.ThreadPoolProperties | ||
import io.github.oshai.kotlinlogging.KotlinLogging | ||
import org.springframework.boot.context.properties.ConfigurationProperties | ||
import org.springframework.context.annotation.Bean | ||
import org.springframework.context.annotation.Configuration | ||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor | ||
|
||
@Configuration | ||
class DatabaseAccessThreadPoolConfig { | ||
private val log = KotlinLogging.logger {} | ||
|
||
companion object { | ||
const val DATABASE_ACCESS_POOL = "database-task-" | ||
} | ||
|
||
@Bean | ||
@ConfigurationProperties(prefix = "database.thread-pool") | ||
fun databaseAccessThreadPoolProperties(): ThreadPoolProperties { | ||
return ThreadPoolProperties() | ||
} | ||
|
||
@Bean(DATABASE_ACCESS_POOL) | ||
fun databaseAccessThreadPool() = ThreadPoolTaskExecutor().apply { | ||
val properties = databaseAccessThreadPoolProperties() | ||
corePoolSize = properties.getCorePoolSize() | ||
maxPoolSize = properties.getMaxPoolSize() | ||
queueCapacity = properties.getQueueCapacity() | ||
setWaitForTasksToCompleteOnShutdown(properties.getWaitForTasksToCompleteOnShutdown()) | ||
setAwaitTerminationSeconds(properties.getAwaitTerminationSeconds()) | ||
setThreadNamePrefix("databaseAccessThreadPool-") | ||
setRejectedExecutionHandler { r, _ -> | ||
log.warn { "Database Access Task Rejected: $r" } | ||
} | ||
initialize() | ||
} | ||
Comment on lines
+10
to
+37
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 디코 훅 쓰레드 풀이랑 똑같이 디비 접근용 쓰레드 풀 생성. 추후 이걸 활용할 것들이 많아보여서 네이밍을 좀 일반적이게 했어요(조회수랑 관련없이) |
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
package com.few.api.domain.article.handler | ||
|
||
import com.few.api.config.DatabaseAccessThreadPoolConfig.Companion.DATABASE_ACCESS_POOL | ||
import com.few.api.repo.dao.article.ArticleViewHisDao | ||
import com.few.api.repo.dao.article.command.ArticleViewHisCommand | ||
import io.github.oshai.kotlinlogging.KotlinLogging | ||
import org.springframework.scheduling.annotation.Async | ||
import org.springframework.stereotype.Component | ||
import org.springframework.transaction.annotation.Transactional | ||
|
||
@Component | ||
class ArticleViewHisAsyncHandler( | ||
private val articleViewHisDao: ArticleViewHisDao, | ||
) { | ||
private val log = KotlinLogging.logger {} | ||
|
||
@Async(value = DATABASE_ACCESS_POOL) | ||
@Transactional | ||
fun addArticleViewHis(articleId: Long, memberId: Long) { | ||
try { | ||
articleViewHisDao.insertArticleViewHis(ArticleViewHisCommand(articleId, memberId)) | ||
log.debug { "Successfully inserted article view history for articleId: $articleId and memberId: $memberId" } | ||
} catch (e: Exception) { | ||
log.error { "Failed to insert article view history 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.ArticleViewHisAsyncHandler | ||
import com.few.api.domain.article.usecase.dto.ReadArticleUseCaseIn | ||
import com.few.api.domain.article.usecase.dto.ReadArticleUseCaseOut | ||
import com.few.api.domain.article.usecase.dto.WriterDetail | ||
|
@@ -9,6 +10,8 @@ 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.ArticleViewHisDao | ||
import com.few.api.repo.dao.article.query.ArticleViewHisCountQuery | ||
import com.few.api.repo.dao.article.query.SelectArticleRecordQuery | ||
import com.few.data.common.code.CategoryType | ||
import org.springframework.stereotype.Component | ||
|
@@ -19,6 +22,8 @@ class ReadArticleUseCase( | |
private val articleDao: ArticleDao, | ||
private val readArticleWriterRecordService: ReadArticleWriterRecordService, | ||
private val browseArticleProblemsService: BrowseArticleProblemsService, | ||
private val articleViewHisDao: ArticleViewHisDao, | ||
private val articleViewHisAsyncHandler: ArticleViewHisAsyncHandler, | ||
) { | ||
|
||
@Transactional(readOnly = true) | ||
|
@@ -31,9 +36,14 @@ class ReadArticleUseCase( | |
readArticleWriterRecordService.execute(query) ?: throw NotFoundException("writer.notfound.id") | ||
} | ||
|
||
val problemIds = BrowseArticleProblemIdsInDto(articleRecord.articleId).let { query: BrowseArticleProblemIdsInDto -> | ||
browseArticleProblemsService.execute(query) | ||
} | ||
val problemIds = | ||
BrowseArticleProblemIdsInDto(articleRecord.articleId).let { query: BrowseArticleProblemIdsInDto -> | ||
browseArticleProblemsService.execute(query) | ||
} | ||
|
||
val views = (articleViewHisDao.countArticleViews(ArticleViewHisCountQuery(useCaseIn.articleId)) ?: 0L) + 1L | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 조회수 가져온 뒤에 우선 + 1 하도록 변경 |
||
|
||
articleViewHisAsyncHandler.addArticleViewHis(useCaseIn.articleId, useCaseIn.memberId) | ||
|
||
return ReadArticleUseCaseOut( | ||
id = articleRecord.articleId, | ||
|
@@ -46,7 +56,8 @@ class ReadArticleUseCase( | |
content = articleRecord.content, | ||
problemIds = problemIds.problemIds, | ||
category = CategoryType.convertToDisplayName(articleRecord.category), | ||
createdAt = articleRecord.createdAt | ||
createdAt = articleRecord.createdAt, | ||
views = views | ||
) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,3 +13,11 @@ discord: | |
queue-capacity: ${DISCORD_THREAD_POOL_QUEUE_CAPACITY:30} | ||
wait-for-tasks-to-complete-on-shutdown: ${DISCORD_THREAD_POOL_WAIT_FOR_TASKS_TO_COMPLETE_ON_SHUTDOWN:true} | ||
await-termination-seconds: ${DISCORD_THREAD_POOL_AWAIT_TERMINATION_SECONDS:60} | ||
|
||
database: | ||
thread-pool: | ||
core-pool-size: 10 | ||
max-pool-size: 30 | ||
queue-capacity: 70 | ||
wait-for-tasks-to-complete-on-shutdown: true | ||
await-termination-seconds: 60 | ||
Comment on lines
+17
to
+23
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이건 VM 환경변수로 뺼까요? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이거 설정하면서 든 생각이, 만약 조회가 엄청 많이 발생하는 상황에선 max 개수인 30 + queue 대기 70 해서 100 명 까지만 Insert가 될 거 같음... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 그럼 databaseAccessThreadPool의 setRejectedExecutionHandler 부분을 수정하면 되지 않을까요? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
각 모듈별로 jooq 필드시 생성되는 .sql 파일이 gitignore되어있었는데, 최상위 위치에 통합관리하도록 변경했습니다