Files
elink-online-common/src/main/java/com/eactive/eai/common/inflow/InflowControlDAO.java
T
curry772 a4c9a2f2bd feat: Dual 이중 버킷 유량제어 패키지 추가 (DJErp→Dual 리네임·이관)
- InflowType 열거형 추가 (ADAPTER/INTERFACE/CLIENT 타입 코드 캡슐화)
- InflowControlDAO: InflowType 기반 범용 메서드 추가, 기존 메서드 위임
- RequestProcessor: private→protected 전환, 클라이언트/어댑터/인터페이스
  유량제어 훅 메서드 5개 추가 (checkClientInflow 등)
- dual 패키지 신규 추가
  · DualCustomBucket: perSecond/threshold 이중 버킷, 차단 원인 구분
  · DualBucket: isAdapterPassDetail 등 차단 원인 반환 인터페이스
  · DualInflowControlManager: 그룹 메트릭 카운팅(TargetMetrics), 리로드 연동
  · DualRequestProcessor: 클라이언트 유량제어 + 상세 오류 메시지 훅 구현
- 단위 테스트 5종 추가 (DualCustomBucket, Manager, Metrics, RequestProcessor, Concurrency)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-27 09:40:27 +09:00

248 lines
9.8 KiB
Java

package com.eactive.eai.common.inflow;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.eactive.eai.common.dao.BaseDAO;
import com.eactive.eai.common.dao.DAOException;
import com.eactive.eai.common.exception.ExceptionUtil;
import com.eactive.eai.common.inflow.loader.InflowControlGroupLoader;
import com.eactive.eai.common.inflow.loader.InflowControlGroupMappingLoader;
import com.eactive.eai.common.inflow.loader.InflowControlLoader;
import com.eactive.eai.common.inflow.loader.InflowControlLogLogger;
import com.eactive.eai.common.util.Logger;
import com.eactive.eai.data.entity.onl.inflow.InflowControl;
import com.eactive.eai.data.entity.onl.inflow.InflowControlGroup;
import com.eactive.eai.data.entity.onl.inflow.InflowControlGroupMapping;
import com.eactive.eai.data.entity.onl.inflow.InflowControlLog;
import com.eactive.eai.data.entity.onl.inflow.InflowControlLogId;
@Service
@Transactional
public class InflowControlDAO extends BaseDAO {
private static Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT);
@Autowired
private InflowControlLoader inflowControlLoader;
@Autowired
private InflowControlLogLogger inflowControlLogLogger;
@Autowired
private InflowControlGroupLoader inflowControlGroupLoader;
@Autowired
private InflowControlGroupMappingLoader inflowControlGroupMappingLoader;
// -------------------------------------------------------------------------
// Enum 기반 범용 메서드 — type 코드를 직접 노출하지 않음
// -------------------------------------------------------------------------
public List<InflowTargetVO> getInflowList(InflowType type) throws DAOException {
return getInflowList(type.code());
}
public Map<String, InflowTargetVO> getInflowMap(InflowType type, String name) throws DAOException {
return getInflowMap(type.code(), name);
}
// -------------------------------------------------------------------------
// 기존 명명 메서드 — enum 기반 메서드로 위임
// -------------------------------------------------------------------------
public List<InflowTargetVO> getInflowAdapterList() throws DAOException {
return getInflowList(InflowType.ADAPTER);
}
public List<InflowTargetVO> getInflowInterfaceList() throws DAOException {
return getInflowList(InflowType.INTERFACE);
}
public Map<String, InflowTargetVO> getInflowTargetByAdater(String name) throws DAOException {
return getInflowMap(InflowType.ADAPTER, name);
}
public Map<String, InflowTargetVO> getInflowTargetByInterface(String name) throws DAOException {
return getInflowMap(InflowType.INTERFACE, name);
}
private List<InflowTargetVO> getInflowList(String type) throws DAOException {
try {
Iterable<InflowControl> inflowControls = inflowControlLoader.findByConditions(type, "");
List<InflowTargetVO> targetList = new ArrayList<>();
logger.info("[ @@ Load InflowControl Configuration - starting >>>>>>>>>>>>>>>>> ]");
for (InflowControl inflowControl : inflowControls) {
InflowTargetVO vo = new InflowTargetVO();
vo.setName(inflowControl.getId().getName());
vo.setThreshold(inflowControl.getThreshold());
vo.setThresholdPerSecond(inflowControl.getThresholdpersecond());
vo.setThresholdTimeUnit(inflowControl.getThresholdtimeunit());
vo.setActivate(!"0".equals(inflowControl.getUseyn()));
targetList.add(vo);
}
logger.info("[>>Load InflowControl Configuration - ended ]");
return targetList;
} catch (Exception e) {
throw new DAOException(ExceptionUtil.getErrorCode(e, "RECEAICMM101"));
}
}
private Map<String, InflowTargetVO> getInflowMap(String type, String name) throws DAOException {
try {
Iterable<InflowControl> inflowControls = inflowControlLoader.findByConditions(type, name);
Map<String, InflowTargetVO> targetList = new HashMap<>();
logger.info("[ @@ Load InflowControl getInflowMap Configuration - starting >>>>>>>>>>>>>>>>> ]");
for (InflowControl inflowControl : inflowControls) {
InflowTargetVO vo = new InflowTargetVO();
vo.setName(inflowControl.getId().getName());
vo.setThreshold(inflowControl.getThreshold());
vo.setThresholdPerSecond(inflowControl.getThresholdpersecond());
vo.setThresholdTimeUnit(inflowControl.getThresholdtimeunit());
vo.setActivate(!"0".equals(inflowControl.getUseyn()));
targetList.put(vo.getName(), vo);
}
logger.info("[>>Load InflowControl getInflowMap Configuration - ended ]");
return targetList;
} catch (Exception e) {
throw new DAOException(ExceptionUtil.getErrorCode(e, "RECEAICMM101"));
}
}
/**
* 1. 기능 : 유량제어 로그를 INSERT하는 메서드 2. 처리 개요 : 파라미터의 코드, 메시지를 테이블에 INSERT한다. - 3.
* 주의사항
*
* @param EAIBzwkDstcd EAI업무구분코드
* @param MsgDpstYMS 메시지수신일시
* @param EAISvcSerno EAI서비스일련번호
* @param EAISevrInstncName EAI서버인스턴스명
* @param EAISvcName EAI서비스명
* @param EAIOsidInstiCd EAI대외기관코드
* @exception DAOException JDBC 관련 오류(SQLException)
**/
// bzwkDstcd + msgDpstYMS + eAISvcSerno
// String bzwkDstcd, String msgDpstYMS, String eAISvcSerno,
// String eAISevrInstncName, String eAISvcName, String adapterGroupName,
// long limitPerSecond, long limit, String timeUnit
public void addInflowServicetLog(String bzwkDstcd, String msgDpstYMS, String eAISvcSerno, String eAISevrInstncName,
String eAISvcName, String adapterGroupName, long limitPerSecond, long limit, String timeUnit)
throws DAOException {
try {
InflowControlLog inflowControlLog = new InflowControlLog();
InflowControlLogId id = new InflowControlLogId();
id.setEaibzwkdstcd(bzwkDstcd);
id.setMsgdpstyms(msgDpstYMS);
id.setEaisvcserno(eAISvcSerno);
inflowControlLog.setId(id);
inflowControlLog.setEaisevrinstncname(eAISevrInstncName);
inflowControlLog.setEaisvcname(eAISvcName);
inflowControlLog.setAdptrbzwkgroupname(adapterGroupName);
inflowControlLog.setThresholdpersecond((int) limitPerSecond);
inflowControlLog.setThreshold((int) limit);
inflowControlLog.setThresholdtimeunit(timeUnit);
inflowControlLogLogger.save(inflowControlLog);
} catch (Exception e) {
throw new DAOException(ExceptionUtil.getErrorCode(e, "RECEAICMM101"));
}
}
// ==================== 그룹 관련 메서드 ====================
/**
* 활성화된 유량제어 그룹 목록 조회
*/
public List<InflowGroupVO> getInflowGroupList() throws DAOException {
try {
Iterable<InflowControlGroup> groups = inflowControlGroupLoader.findActiveGroups();
List<InflowGroupVO> groupList = new ArrayList<>();
logger.info("[ @@ Load InflowControlGroup Configuration - starting >>>>>>>>>>>>>>>>> ]");
for (InflowControlGroup group : groups) {
InflowGroupVO vo = convertToGroupVO(group);
// 그룹에 속한 인터페이스 목록 조회
Iterable<InflowControlGroupMapping> mappings = inflowControlGroupMappingLoader.findActiveByGroupId(group.getGroupId());
for (InflowControlGroupMapping mapping : mappings) {
vo.addInterface(mapping.getInterfaceId());
}
groupList.add(vo);
}
logger.info("[>>Load InflowControlGroup Configuration - ended. count=" + groupList.size() + " ]");
return groupList;
} catch (Exception e) {
throw new DAOException(ExceptionUtil.getErrorCode(e, "RECEAICMM101"));
}
}
/**
* 인터페이스ID → 그룹ID 매핑 조회
*/
public Map<String, String> getInterfaceToGroupMap() throws DAOException {
try {
Iterable<InflowControlGroupMapping> mappings = inflowControlGroupMappingLoader.findActiveMappings();
Map<String, String> interfaceToGroupMap = new HashMap<>();
logger.info("[ @@ Load InterfaceToGroupMap Configuration - starting >>>>>>>>>>>>>>>>> ]");
for (InflowControlGroupMapping mapping : mappings) {
interfaceToGroupMap.put(mapping.getInterfaceId(), mapping.getGroupId());
}
logger.info("[>>Load InterfaceToGroupMap Configuration - ended. count=" + interfaceToGroupMap.size() + " ]");
return interfaceToGroupMap;
} catch (Exception e) {
throw new DAOException(ExceptionUtil.getErrorCode(e, "RECEAICMM101"));
}
}
/**
* 특정 그룹 조회
*/
public Map<String, InflowGroupVO> getInflowTargetByGroup(String groupId) throws DAOException {
try {
Iterable<InflowControlGroup> groups = inflowControlGroupLoader.findByConditions(groupId);
Map<String, InflowGroupVO> groupMap = new HashMap<>();
logger.info("[ @@ Load InflowControlGroup getInflowTargetByGroup Configuration - starting >>>>>>>>>>>>>>>>> ]");
for (InflowControlGroup group : groups) {
InflowGroupVO vo = convertToGroupVO(group);
// 그룹에 속한 인터페이스 목록 조회
Iterable<InflowControlGroupMapping> mappings = inflowControlGroupMappingLoader.findActiveByGroupId(group.getGroupId());
for (InflowControlGroupMapping mapping : mappings) {
vo.addInterface(mapping.getInterfaceId());
}
groupMap.put(vo.getGroupId(), vo);
}
logger.info("[>>Load InflowControlGroup getInflowTargetByGroup Configuration - ended ]");
return groupMap;
} catch (Exception e) {
throw new DAOException(ExceptionUtil.getErrorCode(e, "RECEAICMM101"));
}
}
/**
* Entity → VO 변환
*/
private InflowGroupVO convertToGroupVO(InflowControlGroup group) {
InflowGroupVO vo = new InflowGroupVO();
vo.setGroupId(group.getGroupId());
vo.setGroupName(group.getGroupName());
vo.setThreshold(group.getThreshold() != null ? group.getThreshold() : 0);
vo.setThresholdPerSecond(group.getThresholdPerSecond() != null ? group.getThresholdPerSecond() : 0);
vo.setThresholdTimeUnit(group.getThresholdTimeUnit());
vo.setActivate(!"0".equals(group.getUseYn()));
return vo;
}
}