Compare commits
35 Commits
97fb659f15
...
feat/infer
| Author | SHA1 | Date | |
|---|---|---|---|
| 241c7222d1 | |||
| 52da4dafc3 | |||
| 24d615174d | |||
| 12b0f0867d | |||
| 283d906da6 | |||
| 360b451c38 | |||
| 80e281cb99 | |||
| b07bc38ee8 | |||
| e4c1c76b2b | |||
| 01b64eeca7 | |||
| 516f949a37 | |||
| b6ed3b57ef | |||
| 9eebf23774 | |||
| 4f742edf8b | |||
| 0aa415cf3a | |||
| 884b635585 | |||
| 6861f6b8b6 | |||
| a97af0d4dd | |||
| 9297d19e24 | |||
| 65c38b3083 | |||
| 24dca652f0 | |||
| 193cd449a8 | |||
|
|
0efde4e5bb | ||
|
|
548d82da12 | ||
| 536ff8fc65 | |||
| 1dc1ce741e | |||
| d21ed61666 | |||
| c9a1007c21 | |||
| 413afb0b7c | |||
| e69eccc82b | |||
| 828a4c5dca | |||
| 5d417d85ff | |||
| 614d6da695 | |||
| 8d45e91982 | |||
| e1febf5863 |
@@ -37,7 +37,6 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
|
||||
// JWT 토큰을 검증하고, 인증된 사용자로 SecurityContext에 등록
|
||||
if (token != null && jwtTokenProvider.isValidToken(token)) {
|
||||
String username = jwtTokenProvider.getSubject(token);
|
||||
|
||||
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
|
||||
UsernamePasswordAuthenticationToken authentication =
|
||||
new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
|
||||
|
||||
@@ -8,11 +8,13 @@ import jakarta.annotation.PostConstruct;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Date;
|
||||
import javax.crypto.SecretKey;
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/** 토큰 생성 */
|
||||
@Component
|
||||
@Log4j2
|
||||
public class JwtTokenProvider {
|
||||
|
||||
@Value("${jwt.secret}")
|
||||
@@ -34,11 +36,13 @@ public class JwtTokenProvider {
|
||||
|
||||
// Access Token 생성
|
||||
public String createAccessToken(String subject) {
|
||||
log.info("TOKEN VALIDITY = {}", accessTokenValidityInMs);
|
||||
return createToken(subject, accessTokenValidityInMs);
|
||||
}
|
||||
|
||||
// Refresh Token 생성
|
||||
public String createRefreshToken(String subject) {
|
||||
log.info("REFRESH TOKEN VALIDITY = {}", refreshTokenValidityInMs);
|
||||
return createToken(subject, refreshTokenValidityInMs);
|
||||
}
|
||||
|
||||
|
||||
@@ -58,6 +58,7 @@ public class MenuAuthorizationManager implements AuthorizationManager<RequestAut
|
||||
|
||||
for (MenuEntity menu : allowedMenus) {
|
||||
String baseUri = menu.getMenuUrl();
|
||||
|
||||
if (baseUri == null || baseUri.isBlank()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1,23 +1,45 @@
|
||||
package com.kamco.cd.kamcoback.common.service;
|
||||
|
||||
import com.kamco.cd.kamcoback.config.InferenceProperties;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Log4j2
|
||||
// 0312
|
||||
@RequiredArgsConstructor
|
||||
@Component
|
||||
public class ExternalJarRunner {
|
||||
@Value("${spring.profiles.active}")
|
||||
private String profile;
|
||||
|
||||
// 0312
|
||||
private final InferenceProperties inferenceProperties;
|
||||
|
||||
private static final long TIMEOUT_MINUTES = TimeUnit.DAYS.toMinutes(3);
|
||||
|
||||
// java -jar build/libs/shp-exporter.jar --batch --geoserver.enabled=true
|
||||
// --converter.inference-id=qq99999 --converter.batch-ids[0]=111
|
||||
// 0312 shp 파일 배치를 통해 생성
|
||||
public void run(String inferenceLearningId, List<Long> batchIds) {
|
||||
// JAR 경로 (shape파일 생성용)
|
||||
String jarPathV2 = inferenceProperties.getJarPathV2();
|
||||
List<String> args = new ArrayList<>();
|
||||
args.add(" --spring.profiles.active=" + profile);
|
||||
args.add(" --batch");
|
||||
args.add(" --geoserver.enabled=true");
|
||||
args.add(" --converter.inference-id=" + inferenceLearningId);
|
||||
batchIds.forEach(batchId -> args.add(" --converter.batch-ids[" + args.size() + "]=" + batchId));
|
||||
execJar(jarPathV2, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* shp 파일 생성
|
||||
*
|
||||
@@ -74,7 +96,8 @@ public class ExternalJarRunner {
|
||||
cmd.add("-jar");
|
||||
cmd.add(jarPath);
|
||||
cmd.addAll(args);
|
||||
|
||||
// 0312
|
||||
log.info("exec jar command: {}", cmd);
|
||||
ProcessBuilder pb = new ProcessBuilder(cmd);
|
||||
pb.redirectErrorStream(true);
|
||||
|
||||
|
||||
@@ -16,5 +16,7 @@ public class InferenceProperties {
|
||||
private String batchUrl;
|
||||
private String geojsonDir;
|
||||
private String jarPath;
|
||||
// 0312
|
||||
private String jarPathV2;
|
||||
private String inferenceServerName;
|
||||
}
|
||||
|
||||
@@ -71,6 +71,10 @@ public class SecurityConfig {
|
||||
.requestMatchers("/api/test/review")
|
||||
.hasAnyRole("ADMIN", "REVIEWER")
|
||||
|
||||
// shapefile 생성 테스트 API - 인증 없이 접근 가능
|
||||
.requestMatchers("/api/test/make-shapefile")
|
||||
.permitAll()
|
||||
|
||||
// ASYNC/ERROR 재디스패치는 막지 않기 (다운로드/스트리밍에서 필수)
|
||||
.dispatcherTypeMatchers(DispatcherType.ASYNC, DispatcherType.ERROR)
|
||||
.permitAll()
|
||||
|
||||
@@ -14,9 +14,9 @@ public class GukYuinDto {
|
||||
public enum GukYuinLinkFailCode implements EnumType {
|
||||
OK("연동 가능"),
|
||||
NOT_FOUND("대상 회차가 없습니다."),
|
||||
SCOPE_PART_NOT_ALLOWED("부분 도엽은 연동 불가능 합니다."),
|
||||
HAS_RUNNING_INFERENCE("라벨링 진행 중 회차가 있습니다."),
|
||||
OTHER_GUKYUIN_IN_PROGRESS("국유in 연동 진행 중 회차가 있습니다.");
|
||||
SCOPE_PART_NOT_ALLOWED("부분 도엽 추론 결과는 연동 할 수 없습니다."),
|
||||
HAS_RUNNING_INFERENCE("라벨링 진행중인 회차가 있습니다.\n진행중인 라벨링 작업을 종료하신 후 다시 연동해주세요."),
|
||||
OTHER_GUKYUIN_IN_PROGRESS("국유in 연동이 진행중입니다. 선행 연동 작업이 종료된 후 진행할 수 있습니다.");
|
||||
|
||||
private final String desc;
|
||||
|
||||
@@ -36,8 +36,9 @@ public class GukYuinDto {
|
||||
public static class GukYuinLinkableRes {
|
||||
|
||||
private boolean linkable;
|
||||
// private GukYuinLinkFailCode code;
|
||||
private GukYuinLinkFailCode code;
|
||||
private String message;
|
||||
private UUID inferenceUuid;
|
||||
}
|
||||
|
||||
// Repository가 반환할 Fact(조회 결과)
|
||||
@@ -45,7 +46,8 @@ public class GukYuinDto {
|
||||
boolean existsLearn,
|
||||
boolean isPartScope,
|
||||
boolean hasRunningInference,
|
||||
boolean hasOtherUnfinishedGukYuin) {}
|
||||
boolean hasOtherUnfinishedGukYuin,
|
||||
UUID inferenceUuid) {}
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
|
||||
@@ -237,9 +237,12 @@ public class GukYuinApiService {
|
||||
GukYuinLinkFailCode code = decideCode(f);
|
||||
|
||||
GukYuinLinkableRes res = new GukYuinLinkableRes();
|
||||
// res.setCode(code);
|
||||
res.setCode(code);
|
||||
res.setLinkable(code == GukYuinLinkFailCode.OK);
|
||||
res.setMessage(code.getDesc());
|
||||
if (code == GukYuinLinkFailCode.HAS_RUNNING_INFERENCE) {
|
||||
res.setInferenceUuid(f.inferenceUuid());
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto;
|
||||
import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto.InferenceServerStatusDto;
|
||||
import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto.InferenceStatusDetailDto;
|
||||
import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto.ResultList;
|
||||
import com.kamco.cd.kamcoback.inference.service.InferenceAsyncService;
|
||||
import com.kamco.cd.kamcoback.inference.service.InferenceResultService;
|
||||
import com.kamco.cd.kamcoback.log.dto.AuditLogDto;
|
||||
import com.kamco.cd.kamcoback.log.dto.AuditLogDto.DownloadReq;
|
||||
@@ -55,6 +56,7 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
public class InferenceResultApiController {
|
||||
|
||||
private final InferenceResultService inferenceResultService;
|
||||
private final InferenceAsyncService inferenceAsyncService;
|
||||
private final MapSheetMngService mapSheetMngService;
|
||||
private final ModelMngService modelMngService;
|
||||
private final RangeDownloadResponder rangeDownloadResponder;
|
||||
@@ -176,7 +178,8 @@ public class InferenceResultApiController {
|
||||
})
|
||||
@DeleteMapping("/end")
|
||||
public ApiResponseDto<UUID> getInferenceGeomList() {
|
||||
UUID uuid = inferenceResultService.deleteInferenceEnd();
|
||||
// UUID uuid = inferenceResultService.deleteInferenceEnd();
|
||||
UUID uuid = inferenceAsyncService.asyncInferenceEnd();
|
||||
return ApiResponseDto.ok(uuid);
|
||||
}
|
||||
|
||||
|
||||
@@ -87,6 +87,7 @@ public class InferenceResultDto {
|
||||
READY("대기"),
|
||||
IN_PROGRESS("진행중"),
|
||||
END("완료"),
|
||||
END_FAIL("종료실패"),
|
||||
FORCED_END("강제종료");
|
||||
private final String desc;
|
||||
|
||||
@@ -683,6 +684,7 @@ public class InferenceResultDto {
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class MapSheetFallbackYearDto {
|
||||
|
||||
private String mapSheetNum;
|
||||
private Integer mngYyyy;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
package com.kamco.cd.kamcoback.inference.service;
|
||||
|
||||
import com.kamco.cd.kamcoback.common.exception.CustomApiException;
|
||||
import com.kamco.cd.kamcoback.common.inference.service.InferenceCommonService;
|
||||
import com.kamco.cd.kamcoback.common.utils.UserUtil;
|
||||
import com.kamco.cd.kamcoback.config.resttemplate.ExternalHttpClient;
|
||||
import com.kamco.cd.kamcoback.config.resttemplate.ExternalHttpClient.ExternalCallResult;
|
||||
import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto.SaveInferenceAiDto;
|
||||
import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto.Status;
|
||||
import com.kamco.cd.kamcoback.postgres.core.AuditLogCoreService;
|
||||
import com.kamco.cd.kamcoback.postgres.core.InferenceResultCoreService;
|
||||
import com.kamco.cd.kamcoback.postgres.core.MapSheetMngCoreService;
|
||||
import com.kamco.cd.kamcoback.postgres.core.ModelMngCoreService;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/** 추론 관리 */
|
||||
@Service
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
@Transactional(readOnly = true)
|
||||
public class InferenceAsyncService {
|
||||
|
||||
private final InferenceResultCoreService inferenceResultCoreService;
|
||||
private final MapSheetMngCoreService mapSheetMngCoreService;
|
||||
private final ModelMngCoreService modelMngCoreService;
|
||||
private final AuditLogCoreService auditLogCoreService;
|
||||
private final InferenceCommonService inferenceCommonService;
|
||||
|
||||
private final ExternalHttpClient externalHttpClient;
|
||||
private final UserUtil userUtil;
|
||||
|
||||
@Value("${inference.batch-url}")
|
||||
private String batchUrl;
|
||||
|
||||
@Value("${inference.inference-server-name}")
|
||||
private String inferenceServerName;
|
||||
|
||||
@Value("${file.dataset-dir}")
|
||||
private String datasetDir;
|
||||
|
||||
@Value("${spring.profiles.active}")
|
||||
private String activeEnv;
|
||||
|
||||
@Value("${inference.geojson-dir}")
|
||||
private String inferenceDir;
|
||||
|
||||
// 0313
|
||||
@Transactional
|
||||
public UUID asyncInferenceEnd() {
|
||||
SaveInferenceAiDto dto = inferenceResultCoreService.getProcessing();
|
||||
if (dto == null) {
|
||||
throw new CustomApiException("NOT_FOUND", HttpStatus.NOT_FOUND);
|
||||
}
|
||||
|
||||
this.deleteInferenceEndAsync(dto); // 비동기 종료 호출
|
||||
|
||||
return dto.getUuid();
|
||||
}
|
||||
|
||||
// 0313
|
||||
@Async("inferenceEndExecutor")
|
||||
@Transactional
|
||||
public void deleteInferenceEndAsync(SaveInferenceAiDto dto) {
|
||||
Long batchId = dto.getBatchId();
|
||||
String url = batchUrl + "/" + batchId;
|
||||
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(MediaType.APPLICATION_JSON);
|
||||
headers.setAccept(List.of(MediaType.APPLICATION_JSON));
|
||||
|
||||
try {
|
||||
log.info("[추론 종료 비동기 시작] uuid={}, batchId={}", dto.getUuid(), batchId);
|
||||
|
||||
ExternalCallResult<String> result =
|
||||
externalHttpClient.callLong(url, HttpMethod.DELETE, dto, headers, String.class);
|
||||
|
||||
if (!result.success()) {
|
||||
log.error("[추론 종료 실패] 외부 API 호출 실패. uuid={}, batchId={}", dto.getUuid(), batchId);
|
||||
|
||||
SaveInferenceAiDto failRequest = new SaveInferenceAiDto();
|
||||
failRequest.setUuid(dto.getUuid());
|
||||
failRequest.setStatus(Status.END_FAIL.getId()); // TODO: 종료실패 상태 추가하는 게 맞는지?
|
||||
failRequest.setUpdateUid(userUtil.getId());
|
||||
failRequest.setInferEndDttm(ZonedDateTime.now());
|
||||
inferenceResultCoreService.update(failRequest);
|
||||
return;
|
||||
}
|
||||
|
||||
SaveInferenceAiDto request = new SaveInferenceAiDto();
|
||||
request.setStatus(Status.FORCED_END.getId());
|
||||
request.setUuid(dto.getUuid());
|
||||
request.setUpdateUid(userUtil.getId());
|
||||
request.setInferEndDttm(ZonedDateTime.now());
|
||||
inferenceResultCoreService.update(request);
|
||||
|
||||
Long learnId = inferenceResultCoreService.getInferenceLearnIdByUuid(dto.getUuid());
|
||||
inferenceResultCoreService.upsertGeomData(learnId);
|
||||
|
||||
log.info("[추론 종료 비동기 완료] uuid={}, batchId={}", dto.getUuid(), batchId);
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("[추론 종료 비동기 예외] uuid={}, batchId={}", dto.getUuid(), batchId, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -157,6 +157,7 @@ public class LabelAllocateService {
|
||||
return labelAllocateCoreService.findInferenceDetail(uuid);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public ApiResponseDto.ResponseObj allocateMove(
|
||||
Integer totalCnt, String uuid, List<String> targetUsers, String userId) {
|
||||
|
||||
|
||||
@@ -169,6 +169,7 @@ public class AuthController {
|
||||
if (refreshToken == null || !jwtTokenProvider.isValidToken(refreshToken)) {
|
||||
throw new AccessDeniedException("만료되었거나 유효하지 않은 리프레시 토큰 입니다.");
|
||||
}
|
||||
|
||||
String username = jwtTokenProvider.getSubject(refreshToken);
|
||||
|
||||
// Redis에 저장된 RefreshToken과 일치하는지 확인
|
||||
|
||||
@@ -519,7 +519,7 @@ public class MapSheetLearnRepositoryImpl implements MapSheetLearnRepositoryCusto
|
||||
.fetchOne();
|
||||
|
||||
if (learn == null) {
|
||||
return new GukYuinLinkFacts(false, false, false, false);
|
||||
return new GukYuinLinkFacts(false, false, false, false, null);
|
||||
}
|
||||
|
||||
// 부분 도엽 실행인지 확인
|
||||
@@ -529,19 +529,21 @@ public class MapSheetLearnRepositoryImpl implements MapSheetLearnRepositoryCusto
|
||||
QMapSheetLearnEntity learn2 = new QMapSheetLearnEntity("learn2");
|
||||
QMapSheetLearnEntity learnQ = QMapSheetLearnEntity.mapSheetLearnEntity;
|
||||
|
||||
// 실행중인 추론 있는지 확인
|
||||
boolean hasRunningInference =
|
||||
// 현재 국유인 연동하려는 추론의 비교년도,기준년도와 같은 회차 중, 할당되거나 진행중인 학습데이터 uuid 조회
|
||||
// ex. 2022-2023년도 9회차 학습데이터 제작 진행중 -> 10회차 연동하려고 할 시, 먼저 9회차를 종료해야 함
|
||||
UUID runningInferenceUuid =
|
||||
queryFactory
|
||||
.selectOne()
|
||||
.from(inf)
|
||||
.join(learn2)
|
||||
.on(inf.learnId.eq(learn2.id))
|
||||
.where(
|
||||
learn2.compareYyyy.eq(learn.getCompareYyyy()),
|
||||
learn2.targetYyyy.eq(learn.getTargetYyyy()),
|
||||
inf.analState.in("ASSIGNED", "ING"))
|
||||
.fetchFirst()
|
||||
!= null;
|
||||
.select(inf.uuid)
|
||||
.from(inf)
|
||||
.join(learn2)
|
||||
.on(inf.learnId.eq(learn2.id))
|
||||
.where(
|
||||
learn2.compareYyyy.eq(learn.getCompareYyyy()),
|
||||
learn2.targetYyyy.eq(learn.getTargetYyyy()),
|
||||
inf.analState.in("ASSIGNED", "ING"))
|
||||
.fetchFirst();
|
||||
|
||||
boolean hasRunningInference = runningInferenceUuid != null;
|
||||
|
||||
// 국유인 작업 진행중 있는지 확인
|
||||
boolean hasOtherUnfinishedGukYuin =
|
||||
@@ -556,6 +558,7 @@ public class MapSheetLearnRepositoryImpl implements MapSheetLearnRepositoryCusto
|
||||
.fetchFirst()
|
||||
!= null;
|
||||
|
||||
return new GukYuinLinkFacts(true, isPartScope, hasRunningInference, hasOtherUnfinishedGukYuin);
|
||||
return new GukYuinLinkFacts(
|
||||
true, isPartScope, hasRunningInference, hasOtherUnfinishedGukYuin, runningInferenceUuid);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,17 @@ public class AsyncConfig {
|
||||
return ex;
|
||||
}
|
||||
|
||||
@Bean(name = "makeShapeFile")
|
||||
public Executor makeShapeFileExecutor() {
|
||||
ThreadPoolTaskExecutor ex = new ThreadPoolTaskExecutor();
|
||||
ex.setCorePoolSize(2);
|
||||
ex.setMaxPoolSize(4);
|
||||
ex.setQueueCapacity(50);
|
||||
ex.setThreadNamePrefix("makeShapeFile-");
|
||||
ex.initialize();
|
||||
return ex;
|
||||
}
|
||||
|
||||
@Bean(name = "auditLogExecutor")
|
||||
public Executor auditLogExecutor() {
|
||||
ThreadPoolTaskExecutor exec = new ThreadPoolTaskExecutor();
|
||||
@@ -31,4 +42,16 @@ public class AsyncConfig {
|
||||
exec.initialize();
|
||||
return exec;
|
||||
}
|
||||
|
||||
// 0313
|
||||
@Bean(name = "inferenceEndExecutor")
|
||||
public Executor inferenceEndExecutor() {
|
||||
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
|
||||
executor.setCorePoolSize(5);
|
||||
executor.setMaxPoolSize(10);
|
||||
executor.setQueueCapacity(100);
|
||||
executor.setThreadNamePrefix("inference-async-");
|
||||
executor.initialize();
|
||||
return executor;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -255,8 +255,9 @@ public class MapSheetInferenceJobService {
|
||||
// 추론 종료일때 shp 파일 생성
|
||||
String batchIdStr = batchIds.stream().map(String::valueOf).collect(Collectors.joining(","));
|
||||
|
||||
// shp 파일 비동기 생성
|
||||
shpPipelineService.runPipeline(jarPath, datasetDir, batchIdStr, sheet.getUid());
|
||||
// 0312 shp 파일 비동기 생성 (바꿔주세요)
|
||||
shpPipelineService.makeShapeFile(sheet.getUid(), batchIds);
|
||||
// shpPipelineService.runPipeline(jarPath, datasetDir, batchIdStr, sheet.getUid());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -3,7 +3,7 @@ package com.kamco.cd.kamcoback.scheduler.service;
|
||||
import com.kamco.cd.kamcoback.common.service.ExternalJarRunner;
|
||||
import com.kamco.cd.kamcoback.postgres.core.InferenceResultCoreService;
|
||||
import com.kamco.cd.kamcoback.scheduler.config.ShpKeyLock;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.List;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
@@ -18,6 +18,30 @@ public class ShpPipelineService {
|
||||
private final ExternalJarRunner externalJarRunner;
|
||||
private final ShpKeyLock shpKeyLock;
|
||||
|
||||
// 0312 shp 파일 비동기 생성
|
||||
@Async("makeShapeFile")
|
||||
public void makeShapeFile(String inferenceId, List<Long> batchIds) {
|
||||
if (!shpKeyLock.tryLock(inferenceId)) {
|
||||
log.info("");
|
||||
log.info("============================================================");
|
||||
log.info("SHP pipeline already running. inferenceId={}", inferenceId);
|
||||
log.info("============================================================");
|
||||
try {
|
||||
log.info("SHP pipeline already start. inferenceId={}", inferenceId);
|
||||
externalJarRunner.run(inferenceId, batchIds);
|
||||
} catch (Exception e) {
|
||||
log.error("SHP pipeline failed. inferenceId={}", inferenceId, e);
|
||||
// TODO 실패 상태 업데이트 로직 추가
|
||||
} finally {
|
||||
log.info("============================================================");
|
||||
log.info("SHP pipeline DONE. inferenceId={}", inferenceId);
|
||||
log.info("============================================================");
|
||||
log.info("");
|
||||
shpKeyLock.unlock(inferenceId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* shp 파일 생성 1. merge 생성 2. 생성된 merge shp 파일로 geoserver 등록, 3.도엽별로 shp 생성
|
||||
*
|
||||
@@ -36,24 +60,33 @@ public class ShpPipelineService {
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
log.info("");
|
||||
log.info("============================================================");
|
||||
log.info("SHP pipeline started. inferenceId={}", inferenceId);
|
||||
log.info("============================================================");
|
||||
|
||||
// uid 기준 merge shp, geojson 파일 생성
|
||||
externalJarRunner.run(jarPath, batchIds, inferenceId, "", "MERGED");
|
||||
|
||||
// uid 기준 shp 파일 geoserver 등록
|
||||
String register =
|
||||
Paths.get(datasetDir, inferenceId, "merge", inferenceId + ".shp").toString();
|
||||
log.info("register={}", register);
|
||||
externalJarRunner.run(jarPath, register, inferenceId);
|
||||
|
||||
// uid 기준 도엽별 shp, geojson 파일 생성
|
||||
externalJarRunner.run(jarPath, batchIds, inferenceId, "", "RESOLVE");
|
||||
|
||||
log.info("SHP pipeline finished. inferenceId={}", inferenceId);
|
||||
// String register =
|
||||
// Paths.get(datasetDir, inferenceId, "merge", inferenceId + ".shp").toString();
|
||||
// log.info("register={}", register);
|
||||
// externalJarRunner.run(jarPath, register, inferenceId);
|
||||
//
|
||||
// // uid 기준 도엽별 shp, geojson 파일 생성
|
||||
// externalJarRunner.run(jarPath, batchIds, inferenceId, "", "RESOLVE");
|
||||
//
|
||||
// log.info("SHP pipeline finished. inferenceId={}", inferenceId);
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("SHP pipeline failed. inferenceId={}", inferenceId, e);
|
||||
// TODO 실패 상태 업데이트 로직 추가
|
||||
} finally {
|
||||
log.info("============================================================");
|
||||
log.info("SHP pipeline DONE. inferenceId={}", inferenceId);
|
||||
log.info("============================================================");
|
||||
shpKeyLock.unlock(inferenceId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
package com.kamco.cd.kamcoback.test;
|
||||
|
||||
import com.kamco.cd.kamcoback.config.api.ApiResponseDto;
|
||||
import com.kamco.cd.kamcoback.scheduler.service.ShpPipelineService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.media.Content;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponses;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import java.util.List;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.ErrorResponse;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@Tag(name = "test shape api", description = "test shape api")
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@RequestMapping("/api/test")
|
||||
public class TestShapeApiController {
|
||||
|
||||
private final ShpPipelineService shpPipelineService;
|
||||
|
||||
@Operation(
|
||||
summary = "shapefile 생성 테스트",
|
||||
description = "지정된 inference ID와 batch ID 목록으로 shapefile을 생성합니다.")
|
||||
@ApiResponses({
|
||||
@ApiResponse(
|
||||
responseCode = "200",
|
||||
description = "shapefile 생성 요청 성공",
|
||||
content = @Content(schema = @Schema(implementation = String.class))),
|
||||
@ApiResponse(
|
||||
responseCode = "400",
|
||||
description = "잘못된 요청 데이터",
|
||||
content = @Content(schema = @Schema(implementation = ErrorResponse.class))),
|
||||
@ApiResponse(
|
||||
responseCode = "500",
|
||||
description = "서버 오류",
|
||||
content = @Content(schema = @Schema(implementation = ErrorResponse.class)))
|
||||
})
|
||||
@GetMapping("/make-shapefile")
|
||||
public ApiResponseDto<String> makeShapeFile(
|
||||
@RequestParam String inferenceId, @RequestParam List<Long> batchIds) {
|
||||
shpPipelineService.makeShapeFile(inferenceId, batchIds);
|
||||
return ApiResponseDto.ok("Shapefile 생성이 시작되었습니다. inferenceId: " + inferenceId);
|
||||
}
|
||||
}
|
||||
@@ -59,8 +59,8 @@ jwt:
|
||||
secret: "kamco_token_9b71e778-19a3-4c1d-97bf-2d687de17d5b"
|
||||
access-token-validity-in-ms: 86400000 # 1일
|
||||
refresh-token-validity-in-ms: 604800000 # 7일
|
||||
#access-token-validity-in-ms: 60000 # 1분
|
||||
#refresh-token-validity-in-ms: 300000 # 5분
|
||||
#access-token-validity-in-ms: 300000 # 5분
|
||||
#refresh-token-validity-in-ms: 600000 # 10분
|
||||
|
||||
token:
|
||||
refresh-cookie-name: kamco-dev # 개발용 쿠키 이름
|
||||
@@ -100,6 +100,7 @@ inference:
|
||||
url: http://192.168.2.183:8000/jobs
|
||||
batch-url: http://192.168.2.183:8000/batches
|
||||
jar-path: ${inference.nfs}/repo/jar/shp-exporter.jar
|
||||
jar-path-v2: ${inference.nfs}/repo/jar/shp-exporter-v2.jar
|
||||
inference-server-name: server1,server2,server3,server4
|
||||
output-dir: ${inference.nfs}/model_output/export
|
||||
|
||||
|
||||
@@ -78,6 +78,7 @@ inference:
|
||||
url: http://10.100.0.11:8000/jobs
|
||||
batch-url: http://10.100.0.11:8000/batches
|
||||
jar-path: jar/shp-exporter.jar
|
||||
jar-path-v2: jar/shp-exporter-v2.jar
|
||||
inference-server-name: server1,server2,server3,server4
|
||||
output-dir: ${inference.nfs}/model_output/export
|
||||
|
||||
|
||||
@@ -95,6 +95,8 @@ inference:
|
||||
url: http://172.16.4.56:8000/jobs
|
||||
batch-url: http://172.16.4.56:8000/batches
|
||||
jar-path: ${inference.nfs}/repo/jar/shp-exporter.jar
|
||||
# //0312
|
||||
jar-path-v2: ${inference.nfs}/repo/jar/shp-exporter-v2.jar
|
||||
inference-server-name: server1,server2,server3,server4
|
||||
output-dir: ${inference.nfs}/model_output/export
|
||||
|
||||
|
||||
@@ -88,3 +88,6 @@ inference:
|
||||
nfs: /kamco-nfs
|
||||
geojson-dir: ${inference.nfs}/requests/ # 추론실행을 위한 파일생성경로
|
||||
jar-path: ${inference.nfs}/repo/jar/shp-exporter.jar
|
||||
# //0312
|
||||
jar-path-v2: ${inference.nfs}/repo/jar/shp-exporter-v2.jar
|
||||
|
||||
|
||||
Reference in New Issue
Block a user