jenkinsfile
This commit is contained in:
@@ -38,70 +38,115 @@ public class ExportGeoJsonTasklet implements Tasklet {
|
||||
|
||||
@Override
|
||||
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) {
|
||||
log.info("========================================");
|
||||
log.info("배치 작업 시작");
|
||||
log.info("========================================");
|
||||
|
||||
// 1. StepContext를 통해 바로 가져오기 (가장 추천)
|
||||
String jobName = chunkContext.getStepContext().getJobName();
|
||||
log.info("Job Name: {}", jobName);
|
||||
|
||||
// 진행중인 회차 중, complete_cnt 가 존재하는 회차 목록 가져오기
|
||||
log.info("진행중인 회차 목록 조회 중...");
|
||||
List<AnalCntInfo> analList = repository.findAnalCntInfoList();
|
||||
log.info("진행중인 회차 수: {}", analList.size());
|
||||
|
||||
int processedAnalCount = 0;
|
||||
for (AnalCntInfo info : analList) {
|
||||
log.info("----------------------------------------");
|
||||
log.info("회차 처리 중: AnalUid={}, ResultUid={}", info.getAnalUid(), info.getResultUid());
|
||||
log.info("전체 건수: {}, 파일 건수: {}", info.getAllCnt(), info.getFileCnt());
|
||||
|
||||
if (Objects.equals(info.getAllCnt(), info.getFileCnt())) {
|
||||
log.info("모든 파일이 이미 처리됨. 건너뜀.");
|
||||
continue;
|
||||
}
|
||||
|
||||
//추론 ID
|
||||
String resultUid = info.getResultUid();
|
||||
log.info("ResultUid: {}", resultUid);
|
||||
|
||||
//insert 하기 jobname, resultUid , 시작시간
|
||||
// 어제까지 검수 완료된 총 데이터의 도엽별 목록 가져오기
|
||||
log.info("검수 완료된 도엽 목록 조회 중... (AnalUid={})", info.getAnalUid());
|
||||
List<AnalMapSheetList> analMapList = repository.findCompletedAnalMapSheetList(info.getAnalUid());
|
||||
log.info("검수 완료된 도엽 수: {}", analMapList.size());
|
||||
|
||||
//TODO 도엽이 4개이상 존재할때 만 RUN 하기
|
||||
if (analMapList.isEmpty()) {
|
||||
log.warn("검수 완료된 도엽이 없음. 건너뜀.");
|
||||
continue;
|
||||
}
|
||||
|
||||
//insert 하기 jobname, resultUid , 시작시간
|
||||
boolean anyProcessed = false;
|
||||
int processedMapSheetCount = 0;
|
||||
int totalGeoJsonFiles = 0;
|
||||
|
||||
for (AnalMapSheetList mapSheet : analMapList) {
|
||||
log.info(" 도엽 처리 중: MapSheetNum={}", mapSheet.getMapSheetNum());
|
||||
|
||||
//도엽별 geom 데이터 가지고 와서 geojson 만들기
|
||||
List<CompleteLabelData> completeList =
|
||||
repository.findCompletedYesterdayLabelingList(
|
||||
info.getAnalUid(), mapSheet.getMapSheetNum());
|
||||
log.info(" 완료된 라벨링 데이터 수: {}", completeList.size());
|
||||
|
||||
if (!completeList.isEmpty()) {
|
||||
List<Long> geoUids = completeList.stream().map(CompleteLabelData::getGeoUid).toList();
|
||||
log.info(" GeoUID 목록 생성 완료: {} 건", geoUids.size());
|
||||
|
||||
List<GeoJsonFeature> features = completeList.stream().map(GeoJsonFeature::from).toList();
|
||||
log.info(" GeoJSON Feature 변환 완료: {} 개", features.size());
|
||||
|
||||
FeatureCollection collection = new FeatureCollection(features);
|
||||
String filename = mapSheet.buildFilename(resultUid);
|
||||
log.info(" GeoJSON 파일명: {}", filename);
|
||||
|
||||
// 형식 /kamco-nfs/dataset/request/uuid/filename
|
||||
Path outputPath = Paths.get(trainingDataDir + File.separator + "request" + File.separator + resultUid, filename);
|
||||
log.info(" 출력 경로: {}", outputPath);
|
||||
|
||||
try {
|
||||
Files.createDirectories(outputPath.getParent());
|
||||
log.info(" 디렉토리 생성 완료: {}", outputPath.getParent());
|
||||
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
objectMapper.enable(SerializationFeature.INDENT_OUTPUT);
|
||||
objectMapper.writeValue(outputPath.toFile(), collection);
|
||||
log.info(" GeoJSON 파일 저장 완료: {}", outputPath);
|
||||
|
||||
repository.updateLearnDataGeomFileCreateYn(geoUids);
|
||||
log.info(" DB 업데이트 완료: {} 건", geoUids.size());
|
||||
|
||||
anyProcessed = true;
|
||||
processedMapSheetCount++;
|
||||
totalGeoJsonFiles++;
|
||||
} catch (IOException e) {
|
||||
log.error(e.getMessage());
|
||||
log.error(" GeoJSON 파일 생성 실패: {}", e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
log.info("회차 처리 완료: ResultUid={}", resultUid);
|
||||
log.info(" 처리된 도엽 수: {}", processedMapSheetCount);
|
||||
log.info(" 생성된 GeoJSON 파일 수: {}", totalGeoJsonFiles);
|
||||
|
||||
if (anyProcessed) {
|
||||
log.info("Docker 컨테이너 실행 중... (ResultUid={})", resultUid);
|
||||
dockerRunnerService.run(resultUid);
|
||||
log.info("Docker 컨테이너 실행 완료 (ResultUid={})", resultUid);
|
||||
processedAnalCount++;
|
||||
} else {
|
||||
log.warn("처리된 도엽이 없어 Docker 실행 건너뜀 (ResultUid={})", resultUid);
|
||||
}
|
||||
}
|
||||
|
||||
log.info("========================================");
|
||||
log.info("배치 작업 완료");
|
||||
log.info("처리된 회차 수: {}", processedAnalCount);
|
||||
log.info("========================================");
|
||||
|
||||
return RepeatStatus.FINISHED;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
package com.kamco.cd.geojsonscheduler.listener;
|
||||
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
import org.springframework.batch.core.JobExecution;
|
||||
import org.springframework.batch.core.JobExecutionListener;
|
||||
import org.springframework.batch.core.BatchStatus;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.UUID;
|
||||
|
||||
@Log4j2
|
||||
@Component
|
||||
public class BatchHistoryListener implements JobExecutionListener {
|
||||
|
||||
@@ -18,8 +21,13 @@ public class BatchHistoryListener implements JobExecutionListener {
|
||||
|
||||
@Override
|
||||
public void beforeJob(JobExecution jobExecution) {
|
||||
log.info("=========================================================");
|
||||
log.info("배치 Job 시작 - BatchHistoryListener");
|
||||
log.info("=========================================================");
|
||||
|
||||
// 1. UUID 생성 (또는 파라미터에서 가져오기)
|
||||
UUID uuid = UUID.randomUUID();
|
||||
log.info("배치 UUID 생성: {}", uuid);
|
||||
|
||||
// 2. JobExecutionContext에 UUID 저장 (afterJob에서 쓰기 위해)
|
||||
jobExecution.getExecutionContext().put("batch_uuid", uuid);
|
||||
@@ -27,22 +35,56 @@ public class BatchHistoryListener implements JobExecutionListener {
|
||||
// 3. Job 이름과 비즈니스 ID(파라미터 등) 가져오기
|
||||
String jobName = jobExecution.getJobInstance().getJobName();
|
||||
String businessId = jobExecution.getJobParameters().getString("id", "UNKNOWN"); // 파라미터 'id'가 있다고 가정
|
||||
log.info("Job Name: {}", jobName);
|
||||
log.info("Business ID: {}", businessId);
|
||||
log.info("Job Instance ID: {}", jobExecution.getJobInstance().getInstanceId());
|
||||
log.info("Job Execution ID: {}", jobExecution.getId());
|
||||
|
||||
// 4. 시작 기록
|
||||
log.info("batch_history 테이블에 시작 기록 저장 중...");
|
||||
batchHistoryService.startBatch(uuid, jobName, businessId);
|
||||
log.info("배치 시작 기록 저장 완료");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterJob(JobExecution jobExecution) {
|
||||
log.info("=========================================================");
|
||||
log.info("배치 Job 종료 - BatchHistoryListener");
|
||||
log.info("=========================================================");
|
||||
|
||||
// 1. 저장해둔 UUID 꺼내기
|
||||
UUID uuid = (UUID) jobExecution.getExecutionContext().get("batch_uuid");
|
||||
log.info("배치 UUID: {}", uuid);
|
||||
|
||||
// 2. 성공 여부 판단 (COMPLETED면 성공, 그 외 실패)
|
||||
boolean isSuccess = jobExecution.getStatus() == BatchStatus.COMPLETED;
|
||||
log.info("배치 상태: {}", jobExecution.getStatus());
|
||||
log.info("배치 성공 여부: {}", isSuccess ? "성공" : "실패");
|
||||
|
||||
if (jobExecution.getStatus() == BatchStatus.FAILED) {
|
||||
log.error("배치 실행 실패!");
|
||||
jobExecution.getAllFailureExceptions().forEach(t ->
|
||||
log.error("실패 원인: {}", t.getMessage(), t)
|
||||
);
|
||||
}
|
||||
|
||||
// 실행 시간 계산
|
||||
if (jobExecution.getStartTime() != null && jobExecution.getEndTime() != null) {
|
||||
Duration duration = Duration.between(jobExecution.getStartTime(), jobExecution.getEndTime());
|
||||
long seconds = duration.getSeconds();
|
||||
long millis = duration.toMillis();
|
||||
log.info("배치 실행 시간: {} ms ({} 초)", millis, seconds);
|
||||
}
|
||||
|
||||
// 3. 종료 기록
|
||||
if (uuid != null) {
|
||||
log.info("batch_history 테이블에 종료 기록 저장 중...");
|
||||
batchHistoryService.finishBatch(uuid, isSuccess);
|
||||
log.info("배치 종료 기록 저장 완료");
|
||||
} else {
|
||||
log.warn("배치 UUID가 없어 종료 기록을 저장할 수 없습니다.");
|
||||
}
|
||||
|
||||
log.info("=========================================================");
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.kamco.cd.geojsonscheduler.listener;
|
||||
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
@@ -8,6 +9,7 @@ import java.sql.Timestamp;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.UUID;
|
||||
|
||||
@Log4j2
|
||||
@Service
|
||||
public class BatchHistoryService {
|
||||
|
||||
@@ -22,16 +24,22 @@ public class BatchHistoryService {
|
||||
*/
|
||||
@Transactional
|
||||
public void startBatch(UUID uuid, String jobName, String businessId) {
|
||||
log.info("[BatchHistoryService] 배치 시작 기록 저장");
|
||||
log.info(" UUID: {}", uuid);
|
||||
log.info(" Job Name: {}", jobName);
|
||||
log.info(" Business ID: {}", businessId);
|
||||
|
||||
String sql = """
|
||||
INSERT INTO public.batch_history
|
||||
(uuid, job, id, created_dttm, updated_dttm, status)
|
||||
INSERT INTO public.batch_history
|
||||
(uuid, job, id, created_dttm, updated_dttm, status)
|
||||
VALUES (?, ?, ?, ?, ?, ?)
|
||||
""";
|
||||
|
||||
Timestamp now = Timestamp.valueOf(LocalDateTime.now());
|
||||
log.info(" 시작 시간: {}", now);
|
||||
|
||||
// 초기 상태는 'STARTED'로 저장
|
||||
jdbcTemplate.update(sql,
|
||||
int rowsAffected = jdbcTemplate.update(sql,
|
||||
uuid,
|
||||
jobName,
|
||||
businessId,
|
||||
@@ -39,6 +47,8 @@ public class BatchHistoryService {
|
||||
now, // updated_dttm
|
||||
"STARTED"
|
||||
);
|
||||
|
||||
log.info("[BatchHistoryService] 배치 시작 기록 저장 완료 ({} rows affected)", rowsAffected);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -46,22 +56,34 @@ public class BatchHistoryService {
|
||||
*/
|
||||
@Transactional
|
||||
public void finishBatch(UUID uuid, boolean isSuccess) {
|
||||
log.info("[BatchHistoryService] 배치 종료 기록 업데이트");
|
||||
log.info(" UUID: {}", uuid);
|
||||
log.info(" 성공 여부: {}", isSuccess);
|
||||
|
||||
String sql = """
|
||||
UPDATE public.batch_history
|
||||
SET status = ?,
|
||||
updated_dttm = ?,
|
||||
completed_dttm = ?
|
||||
UPDATE public.batch_history
|
||||
SET status = ?,
|
||||
updated_dttm = ?,
|
||||
completed_dttm = ?
|
||||
WHERE uuid = ?
|
||||
""";
|
||||
|
||||
Timestamp now = Timestamp.valueOf(LocalDateTime.now());
|
||||
String status = isSuccess ? "COMPLETED" : "FAILED";
|
||||
log.info(" 완료 시간: {}", now);
|
||||
log.info(" 최종 상태: {}", status);
|
||||
|
||||
jdbcTemplate.update(sql,
|
||||
int rowsAffected = jdbcTemplate.update(sql,
|
||||
status,
|
||||
now, // updated_dttm (마지막 변경 시간)
|
||||
now, // completed_dttm (완료 시간)
|
||||
uuid
|
||||
);
|
||||
|
||||
if (rowsAffected > 0) {
|
||||
log.info("[BatchHistoryService] 배치 종료 기록 업데이트 완료 ({} rows affected)", rowsAffected);
|
||||
} else {
|
||||
log.warn("[BatchHistoryService] 업데이트된 row가 없습니다. UUID가 존재하지 않을 수 있습니다: {}", uuid);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,8 +13,11 @@ spring:
|
||||
max-lifetime: 1800000
|
||||
sql:
|
||||
init:
|
||||
mode: always
|
||||
schema-locations: classpath:sql/schema.sql
|
||||
mode: never
|
||||
# schema-locations: classpath:sql/schema.sql
|
||||
# Note: batch_history 테이블이 이미 존재하므로 SQL 초기화 비활성화
|
||||
# 새 환경에서 테이블 생성이 필요한 경우, 아래 SQL을 수동으로 실행:
|
||||
# src/main/resources/sql/schema.sql
|
||||
batch:
|
||||
job:
|
||||
enabled: true
|
||||
|
||||
Reference in New Issue
Block a user