일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- 리눅스
- 파이썬 소스
- gradle
- 자바
- 문법 정리
- 티스토리
- 오라클 디비
- 유사코드
- 프로젝트
- 학점
- 자바 프로젝트
- smart cast
- 오라클
- auto configure
- 초대장
- c#
- SQL
- JVM
- 알고리즘
- spring
- hyperledger
- 파이썬
- 백준 알고리즘
- K6
- dynamic query
- jsp
- oracle
- 운영체제
- MongoDB
- resilience4j
- Today
- Total
모종닷컴
Quartz Job Scheduling 2편 - API로 활용 본문
안녕하세요. 오늘은 지난 Quartz Job Schedule 1편 - 소개 및 간단한 예제에 이어서 Quartz를 좀 더 다양하게 활용하기 위한 포스팅을 하려고 합니다. Quartz를 많이 다뤄보지는 못해서 활용도가 조금 떨어질 수 있지만 이런식으로 활용할 수 있겠구나 정도의 가벼운 마음으로 읽어주시면 감사하겠습니다 :)
이번 예제에서는 Controller를 활용할 예정이라 혹시라도 의존성이 없다면 web 관련 dependencies를 구성해주시기 바랍니다. 제대로 확인은 안했지만 spring-boot-starter-web 정도만 추가하면 되지 않을까 싶습니다.
QuartzApiController 만들기
이번 포스팅에서 예제는 모두 api 형식으로 제공할 예정이라 컨트롤러를 먼저 작성하도록 하겠습니다.
private val log = KotlinLogging.logger { }
@RestController
@RequestMapping("/api/quartz")
class QuartzController(
private val scheduler: Scheduler
) {
}
KotlinLogging 라이브러리 없다면 LoggingFactory.getLogger(..)를 이용하셔도 좋습니다. KotlinLogging 사용하길 원한다면 의존성에 io.github.microutils:kotlin-logging 를 추가해주시면 됩니다. KotlinLogging이 뭔지 궁금하다면 https://github.com/MicroUtils/kotlin-logging 페이지를 보시면 될 겁니다. 일반 slf4j 라이브러리의 기능을 모두 지원할 뿐더러 보일러플레이트 코드 제거 및 lazy-evaluate 를 지원합니다.
스프링에서 지원해주는 spring-boot-starter-quartz 를 이용하면 scheduler가 자동으로 등록된다고 지난 글에 설명하였습니다. 주입이 잘 될 겁니다.
현재 애플리케이션에서 등록된 JobDetail 출력하기
모든 JobDetail 출력
scheduler는 job과 trigger 세부정보들이 등록되어 있습니다. 그렇다면 이 scheduler에 등록된 jobDetail에 대한 내용들을 출력해주는 API를 하나 만들어 보겠습니다. 아래의 코드를 위에서 만든 컨트롤러 안에 넣어주면 됩니다.
@GetMapping("/jobDetails")
fun getAllJobDetails(): ResponseEntity<List<JobDetailInfo>> {
val jobInfos = scheduler.jobGroupNames.map { groupName ->
scheduler.getJobKeys(GroupMatcher.jobGroupEquals(groupName)).map {
JobDetailInfo(scheduler.getJobDetail(it))
}
}.flatten()
return ResponseEntity.ok(jobInfos)
}
class JobDetailInfo (
val groupName: String,
val jobName: String,
val desc: String
) {
constructor(jobDetail: JobDetail): this(
groupName = jobDetail.key.group,
jobName = jobDetail.key.name,
desc = jobDetail.description
)
}
애플리케이션을 띄우고 해당 api를 요청해보면 됩니다. 저는 아래와 같은 데이터를 받았습니다.
이걸 보니 job 마다 그룹을 지정해 줄 수 있나 보네요. 일단 DEFAULT 그룹은 맘에 들지 않으니 위의 job에 그룹이름을 다른걸로 지정해보겠습니다. 그룹 이름은 상수로 사용될 수 있으니 먼저 eum으로 관리하도록 하겠습니다.
enum class QuartzGroup {
DEFAULT,
MONITORING
}
이제 Job에다가 그룹을 설정하도록 하겠습니다. 지난글 중 QuartzConfig 클래스의 testJobDetail 메서드를 아래와 같이 수정하겠습니다.
@Bean
fun testJobDetail(): JobDetailFactoryBean {
val jobDataMap = JobDataMap()
jobDataMap["name"] = "mojong"
return JobDetailFactoryBean().apply {
setJobClass(TestJob::class.java) // 어떤 Job에 대한 JobDetail 인지 명시
setDescription("Invoke Test Job") // 설명
setDurability(true) // 필수인 듯
setJobDataMap(jobDataMap)
setGroup(QuartzGroup.MONITORING.name)
}
}
이 상태에서 다시 API를 요청해보겠습니다. 아래 사진과 같이 그룹이름이 변경되었네요.
그룹명으로 JobDetail 정보를 가져오도록 수정
위의 API의 기능을 확장해보겠습니다. 만약 요청할 때 group 파라미터를 추가해주면 해당 그룹에 대한 jobDetail만 가져오도록 하고, group 파라미터가 없는 경우 이전 기능그대로 전체 jobDetail 정보를 가져오도록 하겠습니다.
@GetMapping("/jobDetails")
fun getAllJobDetails(group: QuartzGroup?): ResponseEntity<List<JobDetailInfo>> {
val groupNames = if(group == null) scheduler.jobGroupNames else listOf(group.name)
val jobInfos = groupNames.map { groupName ->
scheduler.getJobKeys(GroupMatcher.jobGroupEquals(groupName)).map {
JobDetailInfo(scheduler.getJobDetail(it))
}
}.flatten()
return ResponseEntity.ok(jobInfos)
}
위와 같이 코드를 수정하고 먼저 group=DEFAULT를 붙여서 요청해보면 빈리스트가 group=MONITORING를 붙여 요청하면 MONITORING 그룹에 해당하는 jobDetail을 받을 수 있게 되었습니다. 그리고 query param을 지우면 모든 jobDetail을 볼 수 있습니다.
원타임 실행
scheduler를 보다보니 triggerJob이라는 메서드가 있는 것을 봤는데요. 느낌이 강제로 실행을 하는듯합니다. 이걸 이용해서 원타임 실행 api를 만들어보도록 할게요.
@PostMapping("/trigger")
fun triggerOnetime(@RequestBody request: OnetimeTriggerRequest): ResponseEntity<String> {
val jobKeys = scheduler.getJobKeys(GroupMatcher.jobGroupEquals(request.group.name))
val jobKey = jobKeys.find { it.name == request.jobKeyName } ?: return ResponseEntity.ok("NOT_FOUND")
scheduler.triggerJob(jobKey)
return ResponseEntity.ok("OK")
}
class OnetimeTriggerRequest(
val group: QuartzGroup,
val jobKeyName: String
)
triggerJob을 호출하기 위해서는 jobKey가 필요합니다. 그래서 그룹과 jobKey 이름을 받아야 합니다. 요청시에 이 내용들을 받도록 스펙을 만들었습니다. validation 까지 넣으면 좋을 것 같지만 시간상 붙이지는 않겠습니다. 위의 코드를 Controller에 추가하고 api를 호출해보면 예상대로 원타임 실행이었네요
마치며
Quartz로 할 수 있는게 상당히 많네요.
이 포스팅에 다 쓰려니 글이 너무 길어져서 3편에 이어서 작성해보도록 하겠습니다. 계획으로는 3편에서는 태스크 정보들을 다이나믹하게 조정하는 방법에 대해서 쓰려고 합니다.
여기까지 읽어주셔서 감사합니다. 다음편에 만나요
'Programming' 카테고리의 다른 글
MySQL vs MongoDB Atomic Counter 비교 (0) | 2022.09.09 |
---|---|
TCP 연결과 종료를 이해하고 코드와 패킷을 분석해보자 (0) | 2022.09.03 |
멀티 모듈 설계 고민 (0) | 2022.08.24 |
Postman 꿀팁 방출 (0) | 2022.08.07 |
Github에 파일 크기 및 리포지토리 크기 제한 (0) | 2022.08.05 |