feat: 시설 오라클 DB Merge 배치 추가(30분 마다)

main
jhseo 10 months ago
parent 6f8e3a7aec
commit 664e7f64c3

@ -56,6 +56,6 @@ public class OtherService extends AbstractService implements IOtherService {
} }
} }
return "test"; return "success";
} }
} }

@ -35,6 +35,8 @@ public class OtherController {
@PostMapping(value = "/merge", produces = MediaType.APPLICATION_JSON_VALUE) @PostMapping(value = "/merge", produces = MediaType.APPLICATION_JSON_VALUE)
public IApiResponse merge() { public IApiResponse merge() {
String msg = service.mergeData(); String msg = service.mergeData();
return ApiResponseDTO.success(msg); String errMsg = "";
if("success".equals(msg)) errMsg = service.mergeData();
return ApiResponseDTO.success(msg, errMsg);
} }
} }

@ -14,7 +14,13 @@ spring:
password: ENC(+sXCmhmSV3Q/3KgOnmpnTQ==) password: ENC(+sXCmhmSV3Q/3KgOnmpnTQ==)
read-only: false read-only: false
# multi-database # multi-database
#secondary: secondary:
database: oracle
driver-class-name: oracle.jdbc.OracleDriver
jdbc-url: jdbc:oracle:thin:@150.50.48.31:1521:ETISDDB
username: MOBELNOTI
password: wjswkrhwl12!@
read-only: false
devtools: devtools:
livereload: livereload:

@ -0,0 +1,113 @@
package kr.xit.batch.ens.job;
import kr.xit.batch.ens.task.OtherMergeTasklet;
import kr.xit.biz.ens.service.IEnsOtherMergeService;
import kr.xit.core.biz.batch.CustomRunIdIncrementer;
import kr.xit.core.biz.batch.listener.CustomJobListener;
import kr.xit.core.biz.batch.listener.CustomStepListener;
import kr.xit.core.biz.batch.listener.NoWorkFoundStepListener;
import kr.xit.core.biz.batch.service.IBatchCmmService;
import kr.xit.core.biz.batch.task.BatchEndTasklet;
import kr.xit.core.biz.batch.task.BatchFailEndTasklet;
import kr.xit.core.biz.batch.task.BatchStartTasklet;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.JobScope;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* <pre>
* description :
*
* packageName : kr.xit.batch.ens.job
* fileName : OtherMergeJobConfig
* author : jhseo
* date : 2024-01-10
* ======================================================================
*
* ----------------------------------------------------------------------
* 2024-01-10 jhseo
*
* </pre>
*/
@Slf4j
@RequiredArgsConstructor
@Configuration
public class OtherMergeJobConfig {
private static final String JOB_NAME = "OtherMergeJob";
@SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
private final JobBuilderFactory jobBuilderFactory;
private final StepBuilderFactory stepBuilderFactory;
private final IBatchCmmService lockService;
private final IEnsOtherMergeService otherService;
@Bean(name = JOB_NAME)
public Job otherMergeJob() {
return jobBuilderFactory.get(JOB_NAME)
.incrementer(new CustomRunIdIncrementer())
.listener(new CustomJobListener())
.listener(new CustomStepListener())
.listener(new NoWorkFoundStepListener())
// JOB 시작
// start() 결과가 FAILED 인경우 종료
.start(start())
.on("FAILED")
.end()
// start()의 결과로 부터 FAILED를 제외한 모든 경우 to() 실행
//.from(start())
.on("*")
.to(execution())
.on("FAILED")
.to(fail())
.from(execution())
// to() 실행 결과와 상관 없이 end() 실행
.on("*")
.to(end())
// JOB 종료
.end()
.build();
}
@Bean(name = JOB_NAME + "_step")
public Step execution() {
return stepBuilderFactory.get(JOB_NAME + "_step")
.tasklet(new OtherMergeTasklet(otherService))
.build();
}
@JobScope
@Bean(name = JOB_NAME + "_start_step")
protected Step start() {
return stepBuilderFactory.get("Job_Locking")
.tasklet(new BatchStartTasklet(lockService))
.build();
}
@JobScope
@Bean(name = JOB_NAME + "_end_step")
protected Step end() {
return stepBuilderFactory.get("Lock_Release")
.tasklet(new BatchEndTasklet(lockService))
.build();
}
@JobScope
@Bean(name = JOB_NAME + "_fail_step")
protected Step fail() {
return stepBuilderFactory.get("Lock_Release")
.tasklet(new BatchFailEndTasklet(lockService))
.build();
}
}

@ -0,0 +1,66 @@
package kr.xit.batch.ens.scheduler;
import kr.xit.batch.ens.job.OtherMergeJobConfig;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.batch.core.JobParameter;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.JobParametersInvalidException;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException;
import org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
* <pre>
* description : Oracle Merge
* : Maria DB (tb_cntc_sndng_mastr, tb_cntc_sndng_detail, tb_cntc_sndng_result)
* -> (elecnoticemst)
* (elecnoticedtl)
* packageName : kr.xit.batch.ens.scheduler
* fileName : OtherMergeJobScheduler
* author : jhseo
* date : 2024-01-10
* ======================================================================
*
* ----------------------------------------------------------------------
* 2024-01-10 jhseo
*
* </pre>
*/
@Slf4j
@RequiredArgsConstructor
@Component
public class OtherMergeJobScheduler {
@SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
private final JobLauncher jobLauncher;
private final OtherMergeJobConfig jobConfiguration;
@Value("${app.slack-webhook.enabled:false}")
private String isSlackEnabled;
@Scheduled(cron = "${app.batch.cron.other.merge}")
public void runJob() {
Map<String, JobParameter> confMap = new HashMap<>();
confMap.put("startDate", new JobParameter(new Date()));
confMap.put("isSlackEnabled", new JobParameter(isSlackEnabled));
try {
JobParameters jobParameters = new JobParameters(confMap);
jobLauncher.run(jobConfiguration.otherMergeJob(), jobParameters);
} catch (JobExecutionAlreadyRunningException | JobInstanceAlreadyCompleteException
| JobParametersInvalidException | org.springframework.batch.core.repository.JobRestartException e) {
log.error(e.getMessage());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}

@ -0,0 +1,60 @@
package kr.xit.batch.ens.task;
import kr.xit.batch.ens.task.cmm.TaskCmmUtils;
import kr.xit.biz.ens.service.IEnsOtherMergeService;
import kr.xit.core.exception.ErrorParse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.configuration.annotation.JobScope;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
/**
* <pre>
* description :
*
* packageName : kr.xit.batch.ens.task
* fileName : OtherMergeTasklet
* author : jhseo
* date : 2024-01-10
* ======================================================================
*
* ----------------------------------------------------------------------
* 2024-01-10 jhseo
*
* </pre>
*/
@Slf4j
@RequiredArgsConstructor
public class OtherMergeTasklet implements Tasklet {
private final IEnsOtherMergeService service;
@Override
@JobScope
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) {
final String isSlackEnabled = contribution.getStepExecution().getJobParameters().getString("isSlackEnabled");
try {
MDC.put("service_error_msg", "");
service.mergeData();
}catch(Exception e){
String errMsg = ErrorParse.extractError(e).getMessage();
log.error("OtherMergeTasklet error :: {}", e.getMessage());
MDC.put("service_error_msg", errMsg);
TaskCmmUtils.taskBatchErrorLog(
contribution.getStepExecution().getJobExecution().getJobInstance().getJobName(),
errMsg,
isSlackEnabled
);
contribution.setExitStatus(ExitStatus.FAILED);
return RepeatStatus.FINISHED;
}
contribution.setExitStatus(ExitStatus.COMPLETED);
return RepeatStatus.FINISHED;
}
}

@ -0,0 +1,68 @@
package kr.xit.biz.ens.service;
import kr.xit.biz.ens.cmm.CmmEnsBizUtils;
import kr.xit.core.exception.BizRuntimeException;
import kr.xit.core.model.ApiResponseDTO;
import kr.xit.core.service.AbstractService;
import kr.xit.core.spring.util.ApiWebClientUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
/**
* <pre>
* description : Oracle DB Merge
* - Transaction
* - Transactional(propagation = Propagation.REQUIRES_NEW)
* packageName : kr.xit.biz.ens.service
* fileName : EnsOtherMergeService
* author : jhseo
* date : 2023-08-31
* ======================================================================
*
* ----------------------------------------------------------------------
* 2023-08-31 jhseo
*
* </pre>
*/
@Slf4j
@RequiredArgsConstructor
@Service
public class EnsOtherMergeService extends AbstractService implements IEnsOtherMergeService {
@Value("${app.contract.host}")
private String apiHost;
@Value("${app.contract.other.api.merge}")
private String apiOtherMerge;
private final ApiWebClientUtil apiWebClient;
/**
* <pre>
* () send bulks - send
* </pre>
*/
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void mergeData() {
final String url = apiHost + apiOtherMerge;
final ApiResponseDTO apiResult = apiWebClient.exchange(
url,
HttpMethod.POST,
"",
ApiResponseDTO.class,
CmmEnsBizUtils.getHeadeMap());
String errMsg = "";
if(apiResult.getData() != null) {
if(!"success".equals(apiResult.getData())){
errMsg = apiResult.getMessage();
throw BizRuntimeException.create(errMsg);
}
}
}
}

@ -0,0 +1,20 @@
package kr.xit.biz.ens.service;
/**
* <pre>
* description : Oracle DB Merge
*
* packageName : kr.xit.biz.ens.service
* fileName : IEnsOtherMergeService
* author : jhseo
* date : 2024-01-10
* ======================================================================
*
* ----------------------------------------------------------------------
* 2024-01-10 jhseo
*
* </pre>
*/
public interface IEnsOtherMergeService {
void mergeData();
}

@ -57,3 +57,5 @@ app:
close: '0 59 21 * * *' close: '0 59 21 * * *'
pni: pni:
accept: '0 0/1 23 * * *' accept: '0 0/1 23 * * *'
other:
merge: '0 30 8-21 * * *'

@ -30,6 +30,9 @@ app:
epost: epost:
api: api:
trace: /api/ens/epost/v1/trace trace: /api/ens/epost/v1/trace
other:
api:
merge: /api/other/v1/merge
# 배치 설정 # 배치 설정
batch: batch:

Loading…
Cancel
Save