Skip to content
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 #116] 알림 전송 배치 작업 #142

Merged
merged 14 commits into from
Aug 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/api-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ jobs:
echo "${{ secrets.APPLICATION_CORE }}" > ./application/src/main/resources/application-core.yml
mkdir -p ./adapters/in-web/src/main/resources
echo "${{ secrets.APPLICATION_IN_WEB_YML }}" > ./application/src/main/resources/application-in-web.yml
mkdir -p ./adapters/in-batch/src/main/resources
echo "${{ secrets.APPLICATION_IN_BATCH }}" > ./application/src/main/resources/application-in-batch.yml

- name: Build with Gradle
run: ./gradlew :entry:web:build --no-daemon
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.pokit.alert.component

import com.pokit.alert.model.AlertBatch
import com.pokit.alert.port.`in`.AlertUseCase
import org.springframework.batch.item.ItemProcessor
import org.springframework.stereotype.Component

@Component
class AlertProcessor(
private val alertUseCase: AlertUseCase,
) : ItemProcessor<AlertBatch, AlertBatch> {

override fun process(alertBatch: AlertBatch): AlertBatch {
alertUseCase.sendMessage(alertBatch)
return alertBatch
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.pokit.alert.component

import com.pokit.alert.model.AlertBatch
import com.pokit.alert.model.AlertBatchValue
import com.pokit.alert.port.`in`.AlertUseCase
import org.springframework.batch.item.ItemReader
import org.springframework.stereotype.Component

@Component
class AlertReader(
private val alertUseCase: AlertUseCase,
) : ItemReader<AlertBatch> {

private var currentPage: Int = 0
private var alertBatchList: MutableList<AlertBatch> = mutableListOf()

override fun read(): AlertBatch? {
if (alertBatchList.isEmpty()) {
val alertBatches = alertUseCase.loadAllAlertBatch(currentPage++, AlertBatchValue.CHUNK_SIZE)
alertBatchList.addAll(alertBatches)

if (alertBatchList.isEmpty()) {
return null
}
}

return alertBatchList.removeFirst()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.pokit.alert.component

import com.pokit.alert.model.AlertBatch
import com.pokit.alert.port.`in`.AlertUseCase
import org.springframework.batch.item.Chunk
import org.springframework.batch.item.ItemWriter
import org.springframework.stereotype.Component

@Component
class AlertWriter(
private val alertUseCase: AlertUseCase,
) : ItemWriter<AlertBatch> {
override fun write(alertBatches: Chunk<out AlertBatch>) {
val batchIds = alertBatches.map { it.id }
val alertContents = alertUseCase.fetchAllAlertContent(batchIds)

alertUseCase.createAlerts(alertContents)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package com.pokit.alert.job

import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl
import com.navercorp.spring.batch.plus.kotlin.configuration.step.SimpleStepBuilderDsl
import com.pokit.alert.component.AlertProcessor
import com.pokit.alert.component.AlertReader
import com.pokit.alert.component.AlertWriter
import com.pokit.alert.model.AlertBatch
import com.pokit.alert.model.AlertBatchValue
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.transaction.PlatformTransactionManager
import org.springframework.transaction.TransactionDefinition
import org.springframework.transaction.interceptor.DefaultTransactionAttribute


@Configuration
class SendAlertConfig(
private val transactionManager: PlatformTransactionManager,
private val batch: BatchDsl,
private val alertReader: AlertReader,
private val alertProcessor: AlertProcessor,
private val alertWriter: AlertWriter
) {
@Bean(name = ["sendAlertJob"])
fun sendAlertJob() = batch {
job("sendAlertJob") {
step(sendAlertStep())
}
}

@Bean
fun sendAlertStep() = batch {
step("sendAlertStep") {
chunk(AlertBatchValue.CHUNK_SIZE, transactionManager, fun SimpleStepBuilderDsl<AlertBatch, AlertBatch>.() {
reader(alertReader)
processor(alertProcessor)
writer(alertWriter)
transactionAttribute(DefaultTransactionAttribute(TransactionDefinition.PROPAGATION_NOT_SUPPORTED))
})
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.pokit.alert.scheduler

import io.github.oshai.kotlinlogging.KotlinLogging
import org.springframework.batch.core.Job
import org.springframework.batch.core.JobParametersBuilder
import org.springframework.batch.core.launch.JobLauncher
import org.springframework.beans.factory.annotation.Qualifier
import org.springframework.scheduling.annotation.Scheduled
import org.springframework.stereotype.Component

@Component
class SendAlertScheduler(
private val jobLauncher: JobLauncher,
@Qualifier("sendAlertJob") private val sendAlertJob: Job
) {
private val logger = KotlinLogging.logger { }

companion object {
private const val 매일_오전_8시 = "0 0 8 * * *"
}

@Scheduled(cron = 매일_오전_8시)
fun sendAlert() {
val jobParameters = JobParametersBuilder()
.addLong("run.id", System.currentTimeMillis())
.toJobParameters()

logger.info { "[ALERT BATCH] start daily send alert job" }
jobLauncher.run(sendAlertJob, jobParameters)
logger.info { "[ALERT BATCH] end daily send alert job" }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.pokit.config

import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.scheduling.TaskScheduler
import org.springframework.scheduling.annotation.EnableScheduling
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler

@Configuration
@EnableScheduling
class SchedulerConfig {
companion object {
private const val POOL_SIZE = 3
}

@Bean("schedulerTask")
fun taskScheduler(): TaskScheduler {
val executor = ThreadPoolTaskScheduler()
executor.poolSize = POOL_SIZE
executor.threadNamePrefix = "scheduler-thread-"
executor.initialize()
return executor
}
Comment on lines +12 to +23
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이거 pool size 왜 3으로 둔거예요 ??

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cpu 코어 1이니까 2로하려다가 3으로 했습니다! 근데 2로 수정하겠습니다

}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class DailyContentConfig(
private val batch: BatchDsl,
) {

@Bean
@Bean(name = ["updateDailyContentJob"])
fun updateDailyContentJob(): Job = batch {
job("updateDailyContentJob") {
step(deleteAllStep()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@ import io.github.oshai.kotlinlogging.KotlinLogging
import org.springframework.batch.core.Job
import org.springframework.batch.core.JobParametersBuilder
import org.springframework.batch.core.launch.JobLauncher
import org.springframework.beans.factory.annotation.Qualifier
import org.springframework.scheduling.annotation.Scheduled
import org.springframework.stereotype.Component

@Component
class DailyContentUpdateScheduler(
private val jobLauncher: JobLauncher,
private val updateDailyContent: Job,
@Qualifier("updateDailyContentJob") private val updateDailyContent: Job,
) {
private val logger = KotlinLogging.logger { }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package com.pokit.out.persistence.alert.impl

import com.pokit.alert.model.Alert
import com.pokit.alert.port.out.AlertPort
import com.pokit.out.persistence.alert.persist.AlertEntity
import com.pokit.out.persistence.alert.persist.AlertJdbcRepository
import com.pokit.out.persistence.alert.persist.AlertRepository
import com.pokit.out.persistence.alert.persist.toDomain
import org.springframework.data.domain.Pageable
Expand All @@ -11,7 +13,8 @@ import org.springframework.stereotype.Repository

@Repository
class AlertAdapter(
private val alertRepository: AlertRepository
private val alertRepository: AlertRepository,
private val alertJdbcRepository: AlertJdbcRepository
) : AlertPort {
override fun loadAllByUserId(userId: Long, pageable: Pageable): Slice<Alert> {
return alertRepository.findAllByUserIdAndDeleted(userId, false, pageable)
Expand All @@ -28,4 +31,11 @@ class AlertAdapter(
?.delete()
}

override fun persistAlerts(alerts: List<Alert>) {
val alertEntities = alerts.map {
AlertEntity.of(it)
}
alertJdbcRepository.bulkInsert(alertEntities)
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.pokit.out.persistence.alert.impl

import com.pokit.alert.model.AlertBatch
import com.pokit.alert.port.out.AlertBatchPort
import com.pokit.out.persistence.alert.persist.AlertBatchEntity
import com.pokit.out.persistence.alert.persist.AlertBatchRepository
import com.pokit.out.persistence.alert.persist.toDomain
import org.springframework.data.domain.Page
import org.springframework.data.domain.Pageable
import org.springframework.data.repository.findByIdOrNull
import org.springframework.stereotype.Repository
import java.time.LocalDate

@Repository
class AlertBatchAdapter(
private val alertBatchRepository: AlertBatchRepository
) : AlertBatchPort {
override fun loadAllByShouldBeSentAt(now: LocalDate, pageable: Pageable): Page<AlertBatch> {
return alertBatchRepository.findAllByShouldBeSentAtAfterAndSent(now, false, pageable)
.map { it.toDomain() }
}

override fun send(alertBatch: AlertBatch) {
alertBatchRepository.findByIdOrNull(alertBatch.id)
?.sent()
}
Comment on lines +18 to +26
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

알림 설정 (y) 로 하면 알림 등록하는 부분은.. 이전에 커밋했던가요 ..?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

리뷰 이상 없으면 컨텐츠 생성, 수정작업에 해당 로직 추가하려했습니다! 지금은 없슴다ㅎ


override fun loadByUserIdAndDate(userId: Long, date: LocalDate): AlertBatch? {
return alertBatchRepository.findByUserIdAndShouldBeSentAtAndSent(userId, date, false)
?.run { toDomain() }
}

override fun persist(alertBatch: AlertBatch): AlertBatch {
val alertBatchEntity = AlertBatchEntity.of(alertBatch)
return alertBatchRepository.save(alertBatchEntity).toDomain()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.pokit.out.persistence.alert.impl

import com.pokit.alert.model.AlertContent
import com.pokit.alert.port.out.AlertContentPort
import com.pokit.out.persistence.alert.persist.AlertContentEntity
import com.pokit.out.persistence.alert.persist.AlertContentRepository
import com.pokit.out.persistence.alert.persist.toDomain
import org.springframework.stereotype.Repository

@Repository
class AlertContentAdapter(
private val alertContentRepository: AlertContentRepository
) : AlertContentPort {
override fun loadAllInAlertBatchIds(ids: List<Long>): List<AlertContent> {
return alertContentRepository.findAllByAlertBatchIdIn(ids)
.map { it.toDomain() }
}

override fun deleteAll(ids: List<Long>) {
alertContentRepository.deleteAllByIdInBatch(ids)
}

override fun persist(alertContent: AlertContent): AlertContent {
val alertContentEntity = AlertContentEntity.of(alertContent)
return alertContentRepository.save(alertContentEntity).toDomain()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,9 @@ class AlertBatchEntity(
)
}
}

fun AlertBatchEntity.toDomain() = AlertBatch(
id = this.id,
userId = this.userId,
shouldBeSentAt = this.shouldBeSentAt
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.pokit.out.persistence.alert.persist

import org.springframework.data.domain.Page
import org.springframework.data.domain.Pageable
import org.springframework.data.jpa.repository.JpaRepository
import java.time.LocalDate

interface AlertBatchRepository : JpaRepository<AlertBatchEntity, Long> {
fun findAllByShouldBeSentAtAfterAndSent(now: LocalDate, send: Boolean, pageable: Pageable): Page<AlertBatchEntity>

fun findByUserIdAndShouldBeSentAtAndSent(userId: Long, date: LocalDate, sent: Boolean): AlertBatchEntity?
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,18 @@ class AlertContentEntity(

@Column(name = "content_id")
val contentId: Long,

@Column(name = "is_deleted")
var delete: Boolean = false
) : BaseEntity() {
fun delete() {
this.delete = true
}

companion object {
fun of(alertContent: AlertContent) = AlertContentEntity(
alertBatchId = alertContent.alertBatchId,
contentId = alertContent.contentId
contentId = alertContent.contentId,
)
}
}

fun AlertContentEntity.toDomain() = AlertContent(
id = this.id,
alertBatchId = this.alertBatchId,
contentId = this.contentId,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.pokit.out.persistence.alert.persist

import org.springframework.data.jpa.repository.JpaRepository

interface AlertContentRepository : JpaRepository<AlertContentEntity, Long> {
fun findAllByAlertBatchIdIn(ids: List<Long>): List<AlertContentEntity>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.pokit.out.persistence.alert.persist

interface AlertJdbcRepository {
fun bulkInsert(alertEntities: List<AlertEntity>)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.pokit.out.persistence.alert.persist

import org.springframework.jdbc.core.JdbcTemplate
import org.springframework.stereotype.Repository

@Repository
class AlertJdbcRepositoryImpl(
private val jdbcTemplate: JdbcTemplate
) : AlertJdbcRepository {
override fun bulkInsert(alertEntities: List<AlertEntity>) {
val sql = """
INSERT INTO alert (
user_id, content_id, content_thumb_nail
, title, is_deleted, created_at, updated_at
) VALUES (?, ?, ?, ?, ?, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)
""".trimIndent()


val batchArgs = alertEntities.map { alert ->
arrayOf(
alert.userId,
alert.contentId,
alert.contentThumbNail,
alert.title,
alert.deleted
)
}

jdbcTemplate.batchUpdate(sql, batchArgs)
}
}
Loading