-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
- Loading branch information
Showing
54 changed files
with
803 additions
and
133 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,6 +21,7 @@ spring: | |
server: | ||
servlet: | ||
context-path: /api | ||
shutdown: graceful | ||
|
||
springdoc: | ||
api-docs: | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
# 빌드 파일 옮기기 | ||
FROM public.ecr.aws/sam/build-java17:1.116.0-20240430173307 as artifact-image | ||
WORKDIR "/task" | ||
|
||
ARG JAR_FILE=./build/libs/adevspoon-batch-0.0.1-SNAPSHOT.jar | ||
COPY ${JAR_FILE} app.jar | ||
|
||
# Lambda Web Adatper 추가 및 실행 | ||
FROM public.ecr.aws/docker/library/amazoncorretto:17-al2023-headless | ||
COPY --from=public.ecr.aws/awsguru/aws-lambda-adapter:0.8.3-x86_64 /lambda-adapter /opt/extensions/lambda-adapter | ||
|
||
ARG PROFILE | ||
ENV PORT=8080 | ||
ENV ACTIVE_PROFILE=${PROFILE} | ||
|
||
RUN echo "Active Profile: ${ACTIVE_PROFILE}" | ||
|
||
WORKDIR /opt | ||
COPY --from=artifact-image /task/app.jar /opt | ||
CMD ["java", "-jar", "-Duser.timezone=Asia/Seoul", "-Dspring.profiles.active=${ACTIVE_PROFILE}", "app.jar", "--server.port=${PORT}"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
|
||
plugins { | ||
id("com.adevspoon.kotlin-common-conventions") | ||
} | ||
|
||
dependencies { | ||
implementation(project(":adevspoon-common")) | ||
implementation(project(":adevspoon-domain")) | ||
implementation(project(":adevspoon-infrastructure")) | ||
|
||
implementation("org.springframework.boot:spring-boot-starter-web") | ||
implementation("org.springframework.boot:spring-boot-starter-batch") | ||
implementation("org.springframework.boot:spring-boot-starter-data-jpa") | ||
|
||
testImplementation("org.springframework.boot:spring-boot-starter-test") | ||
testImplementation("org.springframework.batch:spring-batch-test") | ||
} | ||
|
||
tasks.getByName("bootJar") { | ||
enabled = true | ||
} | ||
|
||
tasks.getByName("jar") { | ||
enabled = false | ||
} | ||
|
||
tasks.register("copyConfig", Copy::class) { | ||
copy { | ||
from("../adevspoon-config/backend/batch") | ||
include("*.yml", "*.xml", "*.json") | ||
into("src/main/resources") | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
#!/bin/bash | ||
|
||
REGISTRY=$1 | ||
REPOSITORY=$2 | ||
TAG=$3 | ||
|
||
DOCKER_TAG="$REGISTRY/$REPOSITORY:$TAG" | ||
|
||
# 새로운 태그로 Build | ||
docker build -t $DOCKER_TAG --build-arg PROFILE=prod --platform linux/x86_64 . | ||
|
||
# ECR 로그인 - 필요하다면(--profile adevspoon) | ||
aws ecr get-login-password --region ap-northeast-2 | docker login --username AWS --password-stdin $REGISTRY | ||
|
||
# ECR에 Push | ||
docker push $DOCKER_TAG | ||
|
||
# template.yaml의 ImageUri를 변경해준다. (& sg, subnet 변경) | ||
sed -i '' -e "s/\${ImagUri}/$DOCKER_TAG|g" template.yml | ||
|
||
# SAM Build & Deploy - https://docs.aws.amazon.com/ko_kr/serverless-application-model/latest/developerguide/deploying-using-github.html | ||
sam build --use-container | ||
sam deploy --no-confirm-changeset --no-fail-on-empty-changeset |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
version = 0.1 | ||
[default.deploy.parameters] | ||
stack_name = "adevspoon-batch" | ||
resolve_s3 = true | ||
s3_prefix = "adevspoon-batch" | ||
region = "ap-northeast-2" | ||
profile = "adevspoon" | ||
confirm_changeset = true | ||
capabilities = "CAPABILITY_IAM" | ||
image_repositories = [] |
11 changes: 11 additions & 0 deletions
11
adevspoon-batch/src/main/kotlin/com/adevspoon/batch/AdevspoonBatchServerApplication.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package com.adevspoon.batch | ||
|
||
import org.springframework.boot.autoconfigure.SpringBootApplication | ||
import org.springframework.boot.runApplication | ||
|
||
@SpringBootApplication(scanBasePackages = ["com.adevspoon"]) | ||
class AdevspoonBatchServerApplication | ||
|
||
fun main(args: Array<String>) { | ||
runApplication<AdevspoonBatchServerApplication>(*args) | ||
} |
22 changes: 22 additions & 0 deletions
22
adevspoon-batch/src/main/kotlin/com/adevspoon/batch/config/BatchTaskConfig.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package com.adevspoon.batch.config | ||
|
||
import org.springframework.context.annotation.Bean | ||
import org.springframework.context.annotation.Configuration | ||
import org.springframework.context.annotation.Primary | ||
import org.springframework.core.task.TaskExecutor | ||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor | ||
|
||
|
||
@Configuration | ||
class BatchTaskConfig { | ||
@Bean | ||
@Primary | ||
fun batchTaskExecutor(): TaskExecutor = ThreadPoolTaskExecutor() | ||
.apply { | ||
corePoolSize = 5 | ||
maxPoolSize = 10 | ||
setThreadNamePrefix("batch-task-") | ||
setWaitForTasksToCompleteOnShutdown(true) | ||
initialize() | ||
} | ||
} |
23 changes: 23 additions & 0 deletions
23
adevspoon-batch/src/main/kotlin/com/adevspoon/batch/controller/EventProcessController.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package com.adevspoon.batch.controller | ||
|
||
import com.adevspoon.batch.job.JobExecutionFacade | ||
import org.slf4j.LoggerFactory | ||
import org.springframework.web.bind.annotation.PostMapping | ||
import org.springframework.web.bind.annotation.RequestBody | ||
import org.springframework.web.bind.annotation.RequestMapping | ||
import org.springframework.web.bind.annotation.RestController | ||
|
||
@RestController | ||
@RequestMapping("/events") | ||
class EventProcessController( | ||
private val jobExecutionFacade: JobExecutionFacade | ||
) { | ||
private val logger = LoggerFactory.getLogger(this.javaClass)!! | ||
@PostMapping | ||
fun processEvents(@RequestBody req: Map<String, Any>): String { | ||
logger.info("Batch Job 실행 요청") | ||
jobExecutionFacade.executeJob(req.toString()) | ||
|
||
return "Events processed" | ||
} | ||
} |
30 changes: 30 additions & 0 deletions
30
adevspoon-batch/src/main/kotlin/com/adevspoon/batch/job/JobExecutionFacade.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
package com.adevspoon.batch.job | ||
|
||
import com.adevspoon.infrastructure.alarm.dto.AlarmType | ||
import com.adevspoon.infrastructure.alarm.service.AlarmAdapter | ||
import org.springframework.batch.core.Job | ||
import org.springframework.batch.core.JobParametersBuilder | ||
import org.springframework.batch.core.launch.JobLauncher | ||
import org.springframework.context.ApplicationContext | ||
import org.springframework.stereotype.Service | ||
import java.time.LocalDateTime | ||
|
||
@Service | ||
class JobExecutionFacade( | ||
private val jobLauncher: JobLauncher, | ||
// private val batchTaskExecutor: TaskExecutor, | ||
private val applicationContext: ApplicationContext, | ||
private val alarmAdapter: AlarmAdapter, | ||
) { | ||
fun executeJob(event: String) { | ||
alarmAdapter.sendAlarm(AlarmType.CHECK, mapOf("Event" to event)) | ||
// (jobLauncher as TaskExecutorJobLauncher).setTaskExecutor(batchTaskExecutor) | ||
|
||
// TODO: 추후 Event Type에 따라 Job, JobParameter 나누기 | ||
val jobParameters = JobParametersBuilder() | ||
.addString("date", LocalDateTime.now().toString()) | ||
.toJobParameters() | ||
val job = applicationContext.getBean(QuestionPublishedNotification.JOB_NAME, Job::class.java) | ||
jobLauncher.run(job, jobParameters) | ||
} | ||
} |
146 changes: 146 additions & 0 deletions
146
adevspoon-batch/src/main/kotlin/com/adevspoon/batch/job/QuestionPublishedNotification.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
package com.adevspoon.batch.job | ||
|
||
import com.adevspoon.infrastructure.alarm.dto.AlarmType | ||
import com.adevspoon.infrastructure.alarm.service.AlarmAdapter | ||
import com.adevspoon.infrastructure.notification.dto.GroupNotificationInfo | ||
import com.adevspoon.infrastructure.notification.dto.NotificationType | ||
import com.adevspoon.infrastructure.notification.service.PushNotificationAdapter | ||
import jakarta.persistence.EntityManagerFactory | ||
import org.slf4j.LoggerFactory | ||
import org.springframework.batch.core.* | ||
import org.springframework.batch.core.configuration.annotation.JobScope | ||
import org.springframework.batch.core.configuration.annotation.StepScope | ||
import org.springframework.batch.core.job.builder.JobBuilder | ||
import org.springframework.batch.core.repository.JobRepository | ||
import org.springframework.batch.core.step.builder.StepBuilder | ||
import org.springframework.batch.item.ExecutionContext | ||
import org.springframework.batch.item.ItemWriter | ||
import org.springframework.batch.item.database.JpaPagingItemReader | ||
import org.springframework.batch.item.database.builder.JpaPagingItemReaderBuilder | ||
import org.springframework.beans.factory.annotation.Value | ||
import org.springframework.context.annotation.Bean | ||
import org.springframework.context.annotation.Configuration | ||
import org.springframework.core.task.TaskExecutor | ||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor | ||
import org.springframework.transaction.PlatformTransactionManager | ||
|
||
|
||
@Configuration | ||
class QuestionPublishedNotification( | ||
private val transactionManager: PlatformTransactionManager, | ||
private val entityManagerFactory: EntityManagerFactory, | ||
private val pushNotificationAdapter: PushNotificationAdapter, | ||
private val alarmAdapter: AlarmAdapter, | ||
){ | ||
private val logger = LoggerFactory.getLogger(this.javaClass)!! | ||
private val chunkSize = 500 | ||
private val successCountKey = "successCount" | ||
private val failCountKey = "failCount" | ||
|
||
companion object { | ||
const val JOB_NAME = "질문발급_푸시알림" | ||
} | ||
|
||
@Bean(JOB_NAME) | ||
fun job(jobRepository: JobRepository): Job { | ||
return JobBuilder(JOB_NAME, jobRepository) | ||
.preventRestart() | ||
.start(notificationStep(jobRepository)) | ||
.listener(jobListener()) | ||
.build() | ||
} | ||
|
||
@Bean(JOB_NAME + "_step") | ||
@JobScope | ||
fun notificationStep(jobRepository: JobRepository): Step { | ||
return StepBuilder(JOB_NAME + "_step", jobRepository) | ||
.chunk<String, String>(chunkSize, transactionManager) | ||
.reader(reader()) | ||
.writer(pushWriter(null)) | ||
.listener(stepListener()) | ||
.build() | ||
} | ||
|
||
@Bean(JOB_NAME + "_taskPool") | ||
fun executor(): TaskExecutor { | ||
val executor = ThreadPoolTaskExecutor() | ||
executor.corePoolSize = 5 | ||
executor.maxPoolSize = 5 | ||
executor.setThreadNamePrefix("task-step-") | ||
executor.setWaitForTasksToCompleteOnShutdown(true) | ||
executor.initialize() | ||
return executor | ||
} | ||
|
||
@Bean(JOB_NAME + "_reader") | ||
@StepScope | ||
fun reader(): JpaPagingItemReader<String> { | ||
return JpaPagingItemReaderBuilder<String>() | ||
.name(JOB_NAME + "_reader") | ||
.queryString("SELECT u.fcmToken FROM UserEntity u WHERE u.fcmToken IS NOT NULL") | ||
.pageSize(chunkSize) | ||
.entityManagerFactory(entityManagerFactory) | ||
.saveState(false) | ||
.build() | ||
} | ||
|
||
@Bean | ||
@StepScope | ||
fun pushWriter(@Value("#{stepExecution.jobExecution.executionContext}") jobExecutionContext: ExecutionContext?): ItemWriter<String> { | ||
return ItemWriter { | ||
val notificationResponse = pushNotificationAdapter.sendMessageSync( | ||
GroupNotificationInfo(NotificationType.QUESTION_OPENED, it.items) | ||
) | ||
|
||
jobExecutionContext?.let { | ||
synchronized(jobExecutionContext) { | ||
val successCount = jobExecutionContext.getInt(successCountKey, 0) | ||
val failCount = jobExecutionContext.getInt(failCountKey, 0) | ||
jobExecutionContext.put(successCountKey, successCount + notificationResponse.success) | ||
jobExecutionContext.put(failCountKey, failCount + notificationResponse.failure) | ||
} | ||
} | ||
} | ||
} | ||
|
||
@Bean(JOB_NAME + "_listener") | ||
fun jobListener(): JobExecutionListener { | ||
return object : JobExecutionListener { | ||
override fun beforeJob(jobExecution: JobExecution) { | ||
logger.info("$JOB_NAME Batch JOB Start") | ||
} | ||
|
||
override fun afterJob(jobExecution: JobExecution) { | ||
val pushSuccess = jobExecution.executionContext.getInt("successCount", -1) | ||
val pushFail = jobExecution.executionContext.getInt("failCount", -1) | ||
val jobInfo = mapOf<String, Any>( | ||
"Batch Name" to JOB_NAME, | ||
"Push Success" to pushSuccess, | ||
"Push Fail" to pushFail, | ||
) | ||
|
||
if (jobExecution.status == BatchStatus.COMPLETED) { | ||
logger.info("$JOB_NAME Batch JOB Finished - 성공: $pushSuccess, 실패: $pushFail") | ||
alarmAdapter.sendAlarm(AlarmType.BATCH_COMPLETE, jobInfo) | ||
} else { | ||
logger.error("$JOB_NAME Batch JOB Failed - 성공: $pushSuccess, 실패: $pushFail") | ||
alarmAdapter.sendAlarm(AlarmType.BATCH_ERROR, jobInfo) | ||
} | ||
} | ||
} | ||
} | ||
|
||
@Bean(JOB_NAME + "_step_execution_listener") | ||
fun stepListener(): StepExecutionListener { | ||
return object : StepExecutionListener { | ||
override fun beforeStep(stepExecution: StepExecution) { | ||
logger.info("$JOB_NAME Batch Step Start") | ||
} | ||
|
||
override fun afterStep(stepExecution: StepExecution): ExitStatus { | ||
logger.info("$JOB_NAME Batch Step Finished") | ||
return stepExecution.exitStatus | ||
} | ||
} | ||
} | ||
} |
17 changes: 17 additions & 0 deletions
17
adevspoon-batch/src/main/kotlin/com/adevspoon/batch/job/QuestionReminderNotification.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package com.adevspoon.batch.job | ||
|
||
import jakarta.persistence.EntityManagerFactory | ||
import org.springframework.context.annotation.Configuration | ||
|
||
// TODO: 추후 예정 | ||
@Configuration | ||
class QuestionReminderNotification( | ||
private val entityManagerFactory: EntityManagerFactory | ||
) { | ||
private val chunkSize = 500 | ||
|
||
companion object { | ||
const val JOB_NAME = "questionReminderNotificationJob" | ||
} | ||
|
||
} |
Oops, something went wrong.