ObpGwMetric UK 문제 수정

This commit is contained in:
Rinjae
2026-01-13 21:54:21 +09:00
parent 7ae5958b7c
commit 792aea1246
2 changed files with 68 additions and 26 deletions
@@ -12,6 +12,7 @@ import com.eactive.eai.rms.data.entity.onl.apim.obp.ObpGwMetricService;
import com.eactive.eai.rms.data.entity.onl.apim.obp.ObpGwMetricVO; import com.eactive.eai.rms.data.entity.onl.apim.obp.ObpGwMetricVO;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@@ -185,40 +186,59 @@ public class ObpGwMetricManService extends BaseService {
int insertCount = 0; int insertCount = 0;
int updateCount = 0; int updateCount = 0;
int conflictRetryCount = 0;
for (ObpGwMetricVO vo : aggregatedList) { for (ObpGwMetricVO vo : aggregatedList) {
LocalDateTime timesliceDateTime = vo.getTimesliceAsLocalDateTime(); LocalDateTime timesliceDateTime = vo.getTimesliceAsLocalDateTime();
Optional<ObpGwMetric> existing = obpGwMetricService.findByUniqueKey( try {
timesliceDateTime, Optional<ObpGwMetric> existing = obpGwMetricService.findByUniqueKey(
vo.getApiId(), timesliceDateTime,
vo.getClientId(), vo.getApiId(),
vo.getHostname(), vo.getClientId(),
vo.getOrgId() vo.getHostname(),
); vo.getOrgId()
);
if (existing.isPresent()) { if (existing.isPresent()) {
// UPDATE: 기존 데이터 갱신 // UPDATE: 기존 데이터 갱신
ObpGwMetric entity = existing.get(); updateExistingMetric(existing.get(), vo, apiNameMap, uriMap, methodMap, appIdMap);
entity.setAttemptedCount(vo.getAttemptedCount()); updateCount++;
entity.setCompletedCount(vo.getCompletedCount()); } else {
entity.setApiName(apiNameMap.get(vo.getApiId())); // INSERT: 신규 데이터 생성
entity.setUri(uriMap.get(vo.getEaiSvcSerno())); // eaiSvcSerno로 URI 조회 ObpGwMetric entity = convertToEntity(vo, apiNameMap, uriMap, methodMap, appIdMap);
entity.setMethod(methodMap.get(vo.getEaiSvcSerno())); // eaiSvcSerno로 HTTP Method 조회 obpGwMetricService.save(entity);
entity.setAppId(appIdMap.get(vo.getOrgId())); insertCount++;
entity.setUpdateCount(entity.getUpdateCount() + 1); // 보정 횟수 증가 }
entity.setUpdatedAt(LocalDateTime.now()); } catch (DataIntegrityViolationException e) {
entity.setUpdatedBy("GwMetricHourJob"); // Unique constraint violation 발생 시 UPDATE로 재시도
obpGwMetricService.save(entity); log.debug("UK 충돌 발생, UPDATE로 재시도: timeslice={}, apiId={}, clientId={}",
updateCount++; timesliceDateTime, vo.getApiId(), vo.getClientId());
} else {
// INSERT: 신규 데이터 생성 Optional<ObpGwMetric> existing = obpGwMetricService.findByUniqueKey(
ObpGwMetric entity = convertToEntity(vo, apiNameMap, uriMap, methodMap, appIdMap); timesliceDateTime,
obpGwMetricService.save(entity); vo.getApiId(),
insertCount++; vo.getClientId(),
vo.getHostname(),
vo.getOrgId()
);
if (existing.isPresent()) {
updateExistingMetric(existing.get(), vo, apiNameMap, uriMap, methodMap, appIdMap);
updateCount++;
conflictRetryCount++;
} else {
// 재조회에서도 없으면 예외 재발생 (비정상 상황)
log.error("UK 충돌 후 재조회 실패: timeslice={}, apiId={}", timesliceDateTime, vo.getApiId());
throw e;
}
} }
} }
if (conflictRetryCount > 0) {
log.info("[4단계] UK 충돌 재시도 건수: {}", conflictRetryCount);
}
log.info("[4단계] UPSERT 완료: INSERT={}, UPDATE={}, elapsed={}ms", log.info("[4단계] UPSERT 완료: INSERT={}, UPDATE={}, elapsed={}ms",
insertCount, updateCount, System.currentTimeMillis() - step4Start); insertCount, updateCount, System.currentTimeMillis() - step4Start);
@@ -247,6 +267,26 @@ public class ObpGwMetricManService extends BaseService {
return existing; return existing;
} }
/**
* 기존 엔티티 업데이트
*/
private void updateExistingMetric(ObpGwMetric entity, ObpGwMetricVO vo,
Map<String, String> apiNameMap,
Map<String, String> uriMap,
Map<String, String> methodMap,
Map<String, String> appIdMap) {
entity.setAttemptedCount(vo.getAttemptedCount());
entity.setCompletedCount(vo.getCompletedCount());
entity.setApiName(apiNameMap.get(vo.getApiId()));
entity.setUri(uriMap.get(vo.getEaiSvcSerno()));
entity.setMethod(methodMap.get(vo.getEaiSvcSerno()));
entity.setAppId(appIdMap.get(vo.getOrgId()));
entity.setUpdateCount(entity.getUpdateCount() + 1);
entity.setUpdatedAt(LocalDateTime.now());
entity.setUpdatedBy("GwMetricHourJob");
obpGwMetricService.save(entity);
}
/** /**
* VO → Entity 변환 * VO → Entity 변환
*/ */
@@ -4,6 +4,7 @@ import com.eactive.eai.rms.common.context.MonitoringContext;
import com.eactive.eai.rms.common.util.CommonUtil; import com.eactive.eai.rms.common.util.CommonUtil;
import com.eactive.eai.rms.onl.apim.obp.ObpGwMetricManService; import com.eactive.eai.rms.onl.apim.obp.ObpGwMetricManService;
import com.eactive.eai.rms.onl.common.util.DateUtil; import com.eactive.eai.rms.onl.common.util.DateUtil;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.Job; import org.quartz.Job;
import org.quartz.JobDataMap; import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext; import org.quartz.JobExecutionContext;
@@ -41,6 +42,7 @@ import org.springframework.context.ApplicationContext;
* jobDataMap.put("aggregation.hour.range", "3"); * jobDataMap.put("aggregation.hour.range", "3");
* </pre> * </pre>
*/ */
@DisallowConcurrentExecution
public class ObpGwMetricHourJob implements Job { public class ObpGwMetricHourJob implements Job {
private static final Logger log = LoggerFactory.getLogger(ObpGwMetricHourJob.class); private static final Logger log = LoggerFactory.getLogger(ObpGwMetricHourJob.class);