배치 멀티 가능 수정 #183
@ -0,0 +1,108 @@
|
|||||||
|
package com.interplug.qcast.batch;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.batch.core.*;
|
||||||
|
import org.springframework.batch.core.explore.JobExplorer;
|
||||||
|
import org.springframework.batch.core.launch.JobOperator;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@Slf4j
|
||||||
|
public class BatchMonitorController {
|
||||||
|
private final JobExplorer jobExplorer;
|
||||||
|
private final JobOperator jobOperator;
|
||||||
|
|
||||||
|
@GetMapping("/batch/status")
|
||||||
|
public Map<String, Object> getBatchStatus() {
|
||||||
|
Map<String, Object> status = new HashMap<>();
|
||||||
|
String[] jobNames = {"storeAdditionalJob", "priceJob", "materialJob", "bomJob",
|
||||||
|
"businessChargerJob", "adminUserJob", "commonCodeJob",
|
||||||
|
"specialNoteDispItemAdditionalJob", "planConfirmJob", "estimateSyncJob"};
|
||||||
|
|
||||||
|
for (String jobName : jobNames) {
|
||||||
|
status.put(jobName, getJobStatus(jobName));
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, Object> getJobStatus(String jobName) {
|
||||||
|
Map<String, Object> jobStatus = new HashMap<>();
|
||||||
|
|
||||||
|
try {
|
||||||
|
List<JobInstance> jobInstances = jobExplorer.findJobInstancesByJobName(jobName, 0, 1);
|
||||||
|
if (jobInstances.isEmpty()) {
|
||||||
|
jobStatus.put("status", "NEVER_EXECUTED");
|
||||||
|
return jobStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
JobInstance latestJobInstance = jobInstances.get(0);
|
||||||
|
List<JobExecution> jobExecutions = jobExplorer.getJobExecutions(latestJobInstance);
|
||||||
|
|
||||||
|
if (!jobExecutions.isEmpty()) {
|
||||||
|
JobExecution latestExecution = jobExecutions.get(0);
|
||||||
|
jobStatus.put("status", latestExecution.getStatus().toString());
|
||||||
|
jobStatus.put("startTime", latestExecution.getStartTime());
|
||||||
|
jobStatus.put("endTime", latestExecution.getEndTime());
|
||||||
|
|
||||||
|
// Duration 계산 (LocalDateTime용)
|
||||||
|
if (latestExecution.getEndTime() != null && latestExecution.getStartTime() != null) {
|
||||||
|
Duration duration = Duration.between(latestExecution.getStartTime(), latestExecution.getEndTime());
|
||||||
|
jobStatus.put("durationSeconds", duration.getSeconds());
|
||||||
|
jobStatus.put("durationMinutes", duration.toMinutes());
|
||||||
|
} else if (latestExecution.getStartTime() != null) {
|
||||||
|
// 실행 중인 경우 현재까지의 경과 시간
|
||||||
|
Duration duration = Duration.between(latestExecution.getStartTime(), LocalDateTime.now());
|
||||||
|
jobStatus.put("runningDurationSeconds", duration.getSeconds());
|
||||||
|
jobStatus.put("runningDurationMinutes", duration.toMinutes());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
jobStatus.put("status", "ERROR");
|
||||||
|
jobStatus.put("error", e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
return jobStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 강제 Job 중지
|
||||||
|
*/
|
||||||
|
@PostMapping("/batch/stop/{jobName}")
|
||||||
|
public Map<String, Object> stopJob(@PathVariable String jobName) {
|
||||||
|
Map<String, Object> result = new HashMap<>();
|
||||||
|
|
||||||
|
try {
|
||||||
|
Set<Long> runningExecutions = jobOperator.getRunningExecutions(jobName);
|
||||||
|
|
||||||
|
if (runningExecutions.isEmpty()) {
|
||||||
|
result.put("code", "NO_RUNNING_JOBS");
|
||||||
|
result.put("message", "No running executions found for job: " + jobName);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> stopResults = new ArrayList<>();
|
||||||
|
for (Long executionId : runningExecutions) {
|
||||||
|
boolean stopped = jobOperator.stop(executionId);
|
||||||
|
stopResults.add("Execution " + executionId + ": " + (stopped ? "STOPPED" : "FAILED_TO_STOP"));
|
||||||
|
}
|
||||||
|
|
||||||
|
result.put("code", "SUCCESS");
|
||||||
|
result.put("message", "Stop commands sent");
|
||||||
|
result.put("results", stopResults);
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
result.put("code", "ERROR");
|
||||||
|
result.put("message", "Error stopping job: " + e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,17 +1,14 @@
|
|||||||
package com.interplug.qcast.batch;
|
package com.interplug.qcast.batch;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.time.Duration;
|
||||||
import java.util.Date;
|
import java.time.LocalDateTime;
|
||||||
import java.util.HashMap;
|
import java.util.*;
|
||||||
import java.util.Map;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.batch.core.BatchStatus;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.batch.core.ExitStatus;
|
import org.springframework.batch.core.*;
|
||||||
import org.springframework.batch.core.Job;
|
import org.springframework.batch.core.explore.JobExplorer;
|
||||||
import org.springframework.batch.core.JobExecution;
|
|
||||||
import org.springframework.batch.core.JobParameters;
|
|
||||||
import org.springframework.batch.core.JobParametersBuilder;
|
|
||||||
import org.springframework.batch.core.JobParametersInvalidException;
|
|
||||||
import org.springframework.batch.core.launch.JobLauncher;
|
import org.springframework.batch.core.launch.JobLauncher;
|
||||||
import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException;
|
import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException;
|
||||||
import org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException;
|
import org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException;
|
||||||
@ -24,370 +21,290 @@ import org.springframework.web.bind.annotation.RestController;
|
|||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
|
@Slf4j
|
||||||
public class JobLauncherController {
|
public class JobLauncherController {
|
||||||
private final Map<String, Job> jobs; // 여러 Job을 주입받도록 변경
|
private final Map<String, Job> jobs;
|
||||||
|
|
||||||
private final JobLauncher jobLauncher;
|
private final JobLauncher jobLauncher;
|
||||||
|
private final JobExplorer jobExplorer;
|
||||||
|
|
||||||
@Value("${qsp.master-admin-user-batch-url}")
|
@Value("${qsp.master-admin-user-batch-url}")
|
||||||
private String qspInterfaceUrl;
|
private String qspInterfaceUrl;
|
||||||
|
|
||||||
@Value("${spring.profiles.scheduler}")
|
@Value("${spring.profiles.scheduler}")
|
||||||
private String scheduler;
|
private String scheduler;
|
||||||
|
|
||||||
|
// 현재 실행 중인 Job 추적을 위한 Set
|
||||||
|
private final Set<String> runningJobs = ConcurrentHashMap.newKeySet();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 특정 Job을 매핑으로 실행하는 메소드
|
* 특정 Job을 매핑으로 실행하는 메소드
|
||||||
*
|
|
||||||
* @param jobName
|
|
||||||
* @return
|
|
||||||
* @throws JobInstanceAlreadyCompleteException
|
|
||||||
* @throws JobExecutionAlreadyRunningException
|
|
||||||
* @throws JobParametersInvalidException
|
|
||||||
* @throws JobRestartException
|
|
||||||
*/
|
*/
|
||||||
@GetMapping("/batch/job/{jobName}") // Path Variable로 jobName을 받음
|
@GetMapping("/batch/job/{jobName}")
|
||||||
public Map<String, Object> launchJob(@PathVariable String jobName)
|
public Map<String, Object> launchJob(@PathVariable String jobName) {
|
||||||
throws JobInstanceAlreadyCompleteException, JobExecutionAlreadyRunningException,
|
|
||||||
JobParametersInvalidException, JobRestartException {
|
|
||||||
|
|
||||||
Job job = jobs.get(jobName);
|
Job job = jobs.get(jobName);
|
||||||
Map<String, Object> resultMap = new HashMap<String, Object>();
|
Map<String, Object> resultMap = new HashMap<>();
|
||||||
|
|
||||||
if (job == null) {
|
if (job == null) {
|
||||||
// return "Job " + jobName + " not found";
|
|
||||||
resultMap.put("code", "FAILED");
|
resultMap.put("code", "FAILED");
|
||||||
resultMap.put("message", "Job " + jobName + " not found");
|
resultMap.put("message", "Job " + jobName + " not found");
|
||||||
return resultMap;
|
return resultMap;
|
||||||
}
|
}
|
||||||
// String[] arryJob = {
|
|
||||||
// "storeAdditionalJob"
|
|
||||||
// ,"BOMJob"
|
|
||||||
// ,"materialJob"
|
|
||||||
// ,"businessChargerJob"
|
|
||||||
// ,"adminUserJob"
|
|
||||||
// ,"priceJob"
|
|
||||||
//// ,"commonCodeJob"
|
|
||||||
// ,"specialNoteDispItemAdditionalJob"
|
|
||||||
// ,"planConfirmJob"
|
|
||||||
// ,"estimateSyncJob"
|
|
||||||
// };
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// if(!batchJobEnabled ){
|
|
||||||
// for(String jobName2 :arryJob){
|
|
||||||
// if(jobName2.equals(jobName)){
|
|
||||||
// resultMap.put("code", "FAILED");
|
|
||||||
// resultMap.put("message", "application.yml :: batch.job.enabled true");
|
|
||||||
// return resultMap;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
JobParameters jobParameters = new JobParametersBuilder().addString("jobName", jobName)
|
// 실행 중인 Job 확인
|
||||||
.addDate("time", new Date()).toJobParameters();
|
if (runningJobs.contains(jobName) || isJobRunning(jobName)) {
|
||||||
|
resultMap.put("code", "ALREADY_RUNNING");
|
||||||
|
resultMap.put("message", "Job " + jobName + " is already running");
|
||||||
|
return resultMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
runningJobs.add(jobName);
|
||||||
|
|
||||||
|
JobParameters jobParameters = new JobParametersBuilder()
|
||||||
|
.addString("jobName", jobName)
|
||||||
|
.addDate("time", new Date())
|
||||||
|
.toJobParameters();
|
||||||
|
|
||||||
JobExecution jobExecution = jobLauncher.run(job, jobParameters);
|
JobExecution jobExecution = jobLauncher.run(job, jobParameters);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
BatchStatus status = jobExecution.getStatus();
|
BatchStatus status = jobExecution.getStatus();
|
||||||
ExitStatus exitStatus = jobExecution.getExitStatus();
|
ExitStatus exitStatus = jobExecution.getExitStatus();
|
||||||
|
|
||||||
resultMap.put("code", status.toString());
|
resultMap.put("code", status.toString());
|
||||||
resultMap.put("message", exitStatus.getExitDescription());
|
resultMap.put("message", exitStatus.getExitDescription());
|
||||||
|
|
||||||
|
} catch (JobExecutionAlreadyRunningException e) {
|
||||||
|
resultMap.put("code", "ALREADY_RUNNING");
|
||||||
|
resultMap.put("message", "Job " + jobName + " is already running");
|
||||||
|
} catch (Exception e) {
|
||||||
|
resultMap.put("code", "FAILED");
|
||||||
|
resultMap.put("message", "Error: " + e.getMessage());
|
||||||
|
} finally {
|
||||||
|
runningJobs.remove(jobName);
|
||||||
|
}
|
||||||
|
|
||||||
// return "Job " + jobName + " started";
|
|
||||||
return resultMap;
|
return resultMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Q.CAST 판매점 / 사용자 / 즐겨찾기 / 노출 아이템 동기화 배치
|
* Q.CAST 판매점 / 사용자 / 즐겨찾기 / 노출 아이템 동기화 배치
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* @throws JobInstanceAlreadyCompleteException
|
|
||||||
* @throws JobExecutionAlreadyRunningException
|
|
||||||
* @throws JobParametersInvalidException
|
|
||||||
* @throws JobRestartException
|
|
||||||
*/
|
*/
|
||||||
// @Scheduled(cron = "*/5 * * * * *")
|
@Scheduled(cron = "0 30 23 * * *")
|
||||||
@Scheduled(cron = "0 55 23 * * *")
|
public String storeAdditionalJob() {
|
||||||
public String storeAdditionalJob() throws JobInstanceAlreadyCompleteException,
|
return executeScheduledJob("storeAdditionalJob");
|
||||||
JobExecutionAlreadyRunningException, JobParametersInvalidException, JobRestartException {
|
|
||||||
|
|
||||||
String jobName = "storeAdditionalJob";
|
|
||||||
Job job = jobs.get(jobName);
|
|
||||||
if (job == null) {
|
|
||||||
return "Job " + jobName + " not found";
|
|
||||||
}
|
|
||||||
if ("Y".equals(scheduler)) {
|
|
||||||
JobParameters jobParameters =
|
|
||||||
new JobParametersBuilder().addDate("time", new Date()).toJobParameters();
|
|
||||||
|
|
||||||
jobLauncher.run(job, jobParameters);
|
|
||||||
|
|
||||||
}
|
|
||||||
return "OK";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 아이템 동기화 배치
|
* 아이템 동기화 배치
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* @throws JobInstanceAlreadyCompleteException
|
|
||||||
* @throws JobExecutionAlreadyRunningException
|
|
||||||
* @throws JobParametersInvalidException
|
|
||||||
* @throws JobRestartException
|
|
||||||
*/
|
*/
|
||||||
@Scheduled(cron = "0 30 02 * * *")
|
@Scheduled(cron = "0 30 02 * * *")
|
||||||
public String materialJob() throws JobInstanceAlreadyCompleteException,
|
public String materialJob() {
|
||||||
JobExecutionAlreadyRunningException, JobParametersInvalidException, JobRestartException {
|
return executeScheduledJob("materialJob");
|
||||||
|
|
||||||
String jobName = "materialJob";
|
|
||||||
Job job = jobs.get(jobName);
|
|
||||||
if (job == null) {
|
|
||||||
return "Job " + jobName + " not found";
|
|
||||||
}
|
|
||||||
|
|
||||||
// if ("Y".equals(scheduler)) {
|
|
||||||
JobParameters jobParameters =
|
|
||||||
new JobParametersBuilder().addDate("time", new Date()).toJobParameters();
|
|
||||||
|
|
||||||
jobLauncher.run(job, jobParameters);
|
|
||||||
|
|
||||||
// }
|
|
||||||
return "OK";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* BOM 아이템 동기화 배치
|
* BOM 아이템 동기화 배치
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* @throws JobInstanceAlreadyCompleteException
|
|
||||||
* @throws JobExecutionAlreadyRunningException
|
|
||||||
* @throws JobParametersInvalidException
|
|
||||||
* @throws JobRestartException
|
|
||||||
*/
|
*/
|
||||||
@Scheduled(cron = "0 40 02 * * *")
|
@Scheduled(cron = "0 40 02 * * *")
|
||||||
public String bomJob() throws JobInstanceAlreadyCompleteException,
|
public String bomJob() {
|
||||||
JobExecutionAlreadyRunningException, JobParametersInvalidException, JobRestartException {
|
return executeScheduledJob("bomJob");
|
||||||
|
|
||||||
String jobName = "bomJob";
|
|
||||||
Job job = jobs.get(jobName);
|
|
||||||
if (job == null) {
|
|
||||||
return "Job " + jobName + " not found";
|
|
||||||
}
|
|
||||||
|
|
||||||
if ("Y".equals(scheduler)) {
|
|
||||||
JobParameters jobParameters =
|
|
||||||
new JobParametersBuilder().addDate("time", new Date()).toJobParameters();
|
|
||||||
|
|
||||||
jobLauncher.run(job, jobParameters);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return "OK";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 영업사원 동기화 배치
|
* 영업사원 동기화 배치
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* @throws JobInstanceAlreadyCompleteException
|
|
||||||
* @throws JobExecutionAlreadyRunningException
|
|
||||||
* @throws JobParametersInvalidException
|
|
||||||
* @throws JobRestartException
|
|
||||||
*/
|
*/
|
||||||
@Scheduled(cron = "0 40 03 * * *")
|
@Scheduled(cron = "0 40 03 * * *")
|
||||||
public String businessChargerJob() throws JobInstanceAlreadyCompleteException,
|
public String businessChargerJob() {
|
||||||
JobExecutionAlreadyRunningException, JobParametersInvalidException, JobRestartException {
|
return executeScheduledJob("businessChargerJob");
|
||||||
|
|
||||||
String jobName = "businessChargerJob";
|
|
||||||
Job job = jobs.get(jobName);
|
|
||||||
if (job == null) {
|
|
||||||
return "Job " + jobName + " not found";
|
|
||||||
}
|
|
||||||
|
|
||||||
if ("Y".equals(scheduler)) {
|
|
||||||
JobParameters jobParameters =
|
|
||||||
new JobParametersBuilder().addDate("time", new Date()).toJobParameters();
|
|
||||||
jobLauncher.run(job, jobParameters);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return "OK";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 관리자 유저 동기화 배치
|
* 관리자 유저 동기화 배치
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* @throws JobInstanceAlreadyCompleteException
|
|
||||||
* @throws JobExecutionAlreadyRunningException
|
|
||||||
* @throws JobParametersInvalidException
|
|
||||||
* @throws JobRestartException
|
|
||||||
*/
|
*/
|
||||||
@Scheduled(cron = "0 0 01 * * *")
|
@Scheduled(cron = "0 0 01 * * *")
|
||||||
public String adminUserJob() throws JobInstanceAlreadyCompleteException,
|
public String adminUserJob() {
|
||||||
JobExecutionAlreadyRunningException, JobParametersInvalidException, JobRestartException {
|
return executeScheduledJob("adminUserJob");
|
||||||
|
|
||||||
String jobName = "adminUserJob";
|
|
||||||
Job job = jobs.get(jobName);
|
|
||||||
if (job == null) {
|
|
||||||
return "Job " + jobName + " not found";
|
|
||||||
}
|
|
||||||
|
|
||||||
if ("Y".equals(scheduler)) {
|
|
||||||
JobParameters jobParameters =
|
|
||||||
new JobParametersBuilder().addDate("time", new Date()).toJobParameters();
|
|
||||||
jobLauncher.run(job, jobParameters);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return "OK";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 가격 동기화 배치
|
* 가격 동기화 배치
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* @throws JobInstanceAlreadyCompleteException
|
|
||||||
* @throws JobExecutionAlreadyRunningException
|
|
||||||
* @throws JobParametersInvalidException
|
|
||||||
* @throws JobRestartException
|
|
||||||
*/
|
*/
|
||||||
@Scheduled(cron = "0 0 0 * * *")
|
@Scheduled(cron = "0 30 0 * * *") // 시간 조정: 00:30
|
||||||
public String priceJob() throws JobInstanceAlreadyCompleteException,
|
public String priceJob() {
|
||||||
JobExecutionAlreadyRunningException, JobParametersInvalidException, JobRestartException {
|
return executeScheduledJob("priceJob");
|
||||||
|
|
||||||
String jobName = "priceJob";
|
|
||||||
Job job = jobs.get(jobName);
|
|
||||||
if (job == null) {
|
|
||||||
return "Job " + jobName + " not found";
|
|
||||||
}
|
|
||||||
|
|
||||||
if ("Y".equals(scheduler)) {
|
|
||||||
JobParameters jobParameters =
|
|
||||||
new JobParametersBuilder().addDate("time", new Date()).toJobParameters();
|
|
||||||
jobLauncher.run(job, jobParameters);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return "OK";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 공통코드 M_COMM_H, M_COMM_L 동기화 배치
|
* 공통코드 M_COMM_H, M_COMM_L 동기화 배치
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* @throws JobInstanceAlreadyCompleteException
|
|
||||||
* @throws JobExecutionAlreadyRunningException
|
|
||||||
* @throws JobParametersInvalidException
|
|
||||||
* @throws JobRestartException
|
|
||||||
*/
|
*/
|
||||||
@Scheduled(cron = "0 10 03 * * *")
|
@Scheduled(cron = "0 10 03 * * *")
|
||||||
public String commonCodeJob() throws JobInstanceAlreadyCompleteException,
|
public String commonCodeJob() {
|
||||||
JobExecutionAlreadyRunningException, JobParametersInvalidException, JobRestartException {
|
return executeScheduledJob("commonCodeJob");
|
||||||
|
|
||||||
String jobName = "commonCodeJob";
|
|
||||||
Job job = jobs.get(jobName);
|
|
||||||
if (job == null) {
|
|
||||||
return "Job " + jobName + " not found";
|
|
||||||
}
|
|
||||||
|
|
||||||
if ("Y".equals(scheduler) || "N".equals(scheduler)) {
|
|
||||||
JobParameters jobParameters =
|
|
||||||
new JobParametersBuilder().addDate("time", new Date()).toJobParameters();
|
|
||||||
|
|
||||||
jobLauncher.run(job, jobParameters);
|
|
||||||
}
|
|
||||||
return "OK";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Q.CAST 견적특이사항 / 아이템 표시, 미표시 동기화 배치
|
* Q.CAST 견적특이사항 / 아이템 표시, 미표시 동기화 배치
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* @throws JobInstanceAlreadyCompleteException
|
|
||||||
* @throws JobExecutionAlreadyRunningException
|
|
||||||
* @throws JobParametersInvalidException
|
|
||||||
* @throws JobRestartException
|
|
||||||
*/
|
*/
|
||||||
@Scheduled(cron = "0 30 23 * * *")
|
@Scheduled(cron = "0 45 23 * * *") // 시간 조정: 23:45
|
||||||
public String specialNoteDispItemAdditionalInfoJob() throws JobInstanceAlreadyCompleteException,
|
public String specialNoteDispItemAdditionalInfoJob() {
|
||||||
JobExecutionAlreadyRunningException, JobParametersInvalidException, JobRestartException {
|
return executeScheduledJob("specialNoteDispItemAdditionalJob");
|
||||||
String jobName = "specialNoteDispItemAdditionalJob";
|
|
||||||
Job job = jobs.get(jobName);
|
|
||||||
if (job == null) {
|
|
||||||
return "Job " + jobName + " not found";
|
|
||||||
}
|
|
||||||
|
|
||||||
if ("Y".equals(scheduler)) {
|
|
||||||
JobParameters jobParameters =
|
|
||||||
new JobParametersBuilder().addDate("time", new Date()).toJobParameters();
|
|
||||||
jobLauncher.run(job, jobParameters);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return "OK";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Plan Confrim 동기화 배치
|
* Plan Confrim 동기화 배치
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* @throws JobInstanceAlreadyCompleteException
|
|
||||||
* @throws JobExecutionAlreadyRunningException
|
|
||||||
* @throws JobParametersInvalidException
|
|
||||||
* @throws JobRestartException
|
|
||||||
*/
|
*/
|
||||||
@Scheduled(cron = "0 05 04 * * *")
|
@Scheduled(cron = "0 05 04 * * *")
|
||||||
public String planConfirmJob() throws JobInstanceAlreadyCompleteException,
|
public String planConfirmJob() {
|
||||||
JobExecutionAlreadyRunningException, JobParametersInvalidException, JobRestartException {
|
return executeScheduledJob("planConfirmJob");
|
||||||
|
|
||||||
String jobName = "planConfirmJob";
|
|
||||||
Job job = jobs.get(jobName);
|
|
||||||
if (job == null) {
|
|
||||||
return "Job " + jobName + " not found";
|
|
||||||
}
|
|
||||||
|
|
||||||
if ("Y".equals(scheduler)) {
|
|
||||||
JobParameters jobParameters =
|
|
||||||
new JobParametersBuilder().addDate("time", new Date()).toJobParameters();
|
|
||||||
|
|
||||||
|
|
||||||
jobLauncher.run(job, jobParameters);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return "OK";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 견적서 전송 동기화 배치
|
* 견적서 전송 동기화 배치
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* @throws JobInstanceAlreadyCompleteException
|
|
||||||
* @throws JobExecutionAlreadyRunningException
|
|
||||||
* @throws JobParametersInvalidException
|
|
||||||
* @throws JobRestartException
|
|
||||||
*/
|
*/
|
||||||
@Scheduled(cron = "0 20 04 * * *")
|
@Scheduled(cron = "0 20 04 * * *")
|
||||||
public String estimateSyncJob() throws JobInstanceAlreadyCompleteException,
|
public String estimateSyncJob() {
|
||||||
JobExecutionAlreadyRunningException, JobParametersInvalidException, JobRestartException {
|
return executeScheduledJob("estimateSyncJob");
|
||||||
|
}
|
||||||
|
|
||||||
String jobName = "estimateSyncJob";
|
/**
|
||||||
|
* 공통 스케줄러 실행 메소드
|
||||||
|
*/
|
||||||
|
private String executeScheduledJob(String jobName) {
|
||||||
Job job = jobs.get(jobName);
|
Job job = jobs.get(jobName);
|
||||||
if (job == null) {
|
if (job == null) {
|
||||||
|
log.error("Job {} not found", jobName);
|
||||||
return "Job " + jobName + " not found";
|
return "Job " + jobName + " not found";
|
||||||
}
|
}
|
||||||
|
|
||||||
if ("Y".equals(scheduler)) {
|
if (!"Y".equals(scheduler) && !"materialJob".equals(jobName) && !"commonCodeJob".equals(jobName)) {
|
||||||
JobParameters jobParameters =
|
log.info("Scheduler disabled, skipping job {}", jobName);
|
||||||
new JobParametersBuilder().addDate("time", new Date()).toJobParameters();
|
return "Scheduler disabled";
|
||||||
|
|
||||||
jobLauncher.run(job, jobParameters);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 실행 중인 Job 확인
|
||||||
|
if (runningJobs.contains(jobName) || isJobRunning(jobName)) {
|
||||||
|
log.warn("Job {} is already running, skipping execution", jobName);
|
||||||
|
return "Job already running";
|
||||||
|
}
|
||||||
|
|
||||||
|
// 다른 Job이 실행 중인지 확인
|
||||||
|
if (isAnyJobRunning()) {
|
||||||
|
log.warn("Another job is running, skipping job {}", jobName);
|
||||||
|
return "Another job is running";
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
runningJobs.add(jobName);
|
||||||
|
|
||||||
|
JobParameters jobParameters = new JobParametersBuilder()
|
||||||
|
.addDate("time", new Date())
|
||||||
|
.toJobParameters();
|
||||||
|
|
||||||
|
JobExecution jobExecution = jobLauncher.run(job, jobParameters);
|
||||||
|
log.info("Job {} started successfully", jobName);
|
||||||
return "OK";
|
return "OK";
|
||||||
|
|
||||||
|
} catch (JobExecutionAlreadyRunningException e) {
|
||||||
|
log.warn("Job {} is already running: {}", jobName, e.getMessage());
|
||||||
|
return "Job already running";
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("Error executing job {}: {}", jobName, e.getMessage());
|
||||||
|
return "Error: " + e.getMessage();
|
||||||
|
} finally {
|
||||||
|
runningJobs.remove(jobName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Job 실행 상태 확인
|
||||||
|
*/
|
||||||
|
private boolean isJobRunning(String jobName) {
|
||||||
|
try {
|
||||||
|
List<JobInstance> jobInstances = jobExplorer.findJobInstancesByJobName(jobName, 0, 1);
|
||||||
|
if (jobInstances.isEmpty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
JobInstance latestJobInstance = jobInstances.get(0);
|
||||||
|
List<JobExecution> jobExecutions = jobExplorer.getJobExecutions(latestJobInstance);
|
||||||
|
|
||||||
|
return jobExecutions.stream()
|
||||||
|
.anyMatch(execution -> execution.getStatus() == BatchStatus.STARTED
|
||||||
|
|| execution.getStatus() == BatchStatus.STARTING);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("Error checking job running status: {}", e.getMessage());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 실행 중인 Job이 있는지 확인
|
||||||
|
*/
|
||||||
|
private boolean isAnyJobRunning() {
|
||||||
|
String[] jobNames = {"storeAdditionalJob", "materialJob", "bomJob", "businessChargerJob",
|
||||||
|
"adminUserJob", "priceJob", "commonCodeJob", "specialNoteDispItemAdditionalJob",
|
||||||
|
"planConfirmJob", "estimateSyncJob"};
|
||||||
|
|
||||||
|
return Arrays.stream(jobNames)
|
||||||
|
.anyMatch(this::isJobRunning);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 현재 실행 중인 Job 목록 조회
|
||||||
|
*/
|
||||||
|
@GetMapping("/batch/running-jobs")
|
||||||
|
public Map<String, Object> getRunningJobs() {
|
||||||
|
Map<String, Object> result = new HashMap<>();
|
||||||
|
result.put("runningJobs", new ArrayList<>(runningJobs));
|
||||||
|
|
||||||
|
Map<String, Object> jobStatuses = new HashMap<>();
|
||||||
|
String[] jobNames = {"storeAdditionalJob", "materialJob", "bomJob", "businessChargerJob",
|
||||||
|
"adminUserJob", "priceJob", "commonCodeJob", "specialNoteDispItemAdditionalJob",
|
||||||
|
"planConfirmJob", "estimateSyncJob"};
|
||||||
|
|
||||||
|
for (String jobName : jobNames) {
|
||||||
|
jobStatuses.put(jobName, getJobStatus(jobName));
|
||||||
|
}
|
||||||
|
|
||||||
|
result.put("jobStatuses", jobStatuses);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 특정 Job의 상태 정보 조회
|
||||||
|
*/
|
||||||
|
private Map<String, Object> getJobStatus(String jobName) {
|
||||||
|
Map<String, Object> jobStatus = new HashMap<>();
|
||||||
|
|
||||||
|
try {
|
||||||
|
List<JobInstance> jobInstances = jobExplorer.findJobInstancesByJobName(jobName, 0, 1);
|
||||||
|
if (jobInstances.isEmpty()) {
|
||||||
|
jobStatus.put("status", "NEVER_EXECUTED");
|
||||||
|
return jobStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
JobInstance latestJobInstance = jobInstances.get(0);
|
||||||
|
List<JobExecution> jobExecutions = jobExplorer.getJobExecutions(latestJobInstance);
|
||||||
|
|
||||||
|
if (!jobExecutions.isEmpty()) {
|
||||||
|
JobExecution latestExecution = jobExecutions.get(0);
|
||||||
|
jobStatus.put("status", latestExecution.getStatus().toString());
|
||||||
|
jobStatus.put("startTime", latestExecution.getStartTime());
|
||||||
|
jobStatus.put("endTime", latestExecution.getEndTime());
|
||||||
|
|
||||||
|
// Duration 계산 (LocalDateTime용)
|
||||||
|
if (latestExecution.getEndTime() != null && latestExecution.getStartTime() != null) {
|
||||||
|
Duration duration = Duration.between(latestExecution.getStartTime(), latestExecution.getEndTime());
|
||||||
|
jobStatus.put("durationSeconds", duration.getSeconds());
|
||||||
|
jobStatus.put("durationMillis", duration.toMillis());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
jobStatus.put("status", "ERROR");
|
||||||
|
jobStatus.put("error", e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
return jobStatus;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user