feat: 클라이언트 유량제어/RequestProcessor custom 패키지로 분리

- DJBRequestProcessor: inbound.processor → custom.inbound.processor 이동
- ClientInflowTargetMetricService/Controller: custom.inflow 패키지 신규 생성
  클라이언트 메트릭 API(/manage/inflow/client/**)를 InflowTargetMetric*에서 분리
- InflowTargetMetricService/Controller: 클라이언트 관련 메서드/엔드포인트 제거
- InflowTargetBucketService: getClientDualManager() 분리 반영
- standard-message-config.properties: requestProcessor.class 경로 업데이트
- 단위 테스트: ClientInflowTargetMetric{Service,Controller}Test 추가,
  기존 테스트에서 클라이언트 케이스 분리

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
curry772
2026-05-07 18:02:51 +09:00
parent 8bcbee7e52
commit 31171d0187
14 changed files with 860 additions and 243 deletions
@@ -9,6 +9,7 @@ import org.springframework.stereotype.Service;
import com.eactive.eai.common.inflow.AbstractInflowControlManager;
import com.eactive.eai.common.inflow.InflowControlUtil;
import com.eactive.eai.common.inflow.InflowTargetVO;
import com.eactive.eai.common.inflow.dual.ClientDualInflowControlManager;
import com.eactive.eai.common.inflow.dual.DualCustomBucket;
import com.eactive.eai.common.inflow.dual.DualInflowControlManager;
@@ -62,7 +63,7 @@ public class InflowTargetBucketService {
// -------------------------------------------------------------------------
public TargetBucketStatusDTO getClientBucketStatus(String clientId) {
DualInflowControlManager manager = getDualManager();
ClientDualInflowControlManager manager = getClientDualManager();
if (manager == null) return null;
DualCustomBucket bucket = manager.getClientBucket(clientId);
if (bucket == null) return null;
@@ -70,7 +71,7 @@ public class InflowTargetBucketService {
}
public List<TargetBucketStatusDTO> getAllClientBucketStatus() {
DualInflowControlManager manager = getDualManager();
ClientDualInflowControlManager manager = getClientDualManager();
if (manager == null) return new ArrayList<>();
return toDtoList("CLIENT", manager.getClientBucketMap());
}
@@ -84,6 +85,11 @@ public class InflowTargetBucketService {
return (base instanceof DualInflowControlManager) ? (DualInflowControlManager) base : null;
}
protected ClientDualInflowControlManager getClientDualManager() {
AbstractInflowControlManager base = InflowControlUtil.getInflowControlManager();
return (base instanceof ClientDualInflowControlManager) ? (ClientDualInflowControlManager) base : null;
}
private TargetBucketStatusDTO toDto(String targetId, String targetType, DualCustomBucket bucket) {
InflowTargetVO vo = bucket.getInflowTargetVo();
List<GroupBucketStatusDTO.BucketInfo> buckets = new ArrayList<>();
@@ -13,7 +13,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 어댑터/인터페이스/클라이언트 유량제어 메트릭 API.
* 어댑터/인터페이스 유량제어 메트릭 API.
*
* DualInflowControlManager 가 활성화된 환경에서만 정상 응답한다.
*
@@ -26,11 +26,6 @@ import org.springframework.web.bind.annotation.RestController;
* GET /manage/inflow/interface/{interfaceId}/metric → 특정 인터페이스 메트릭
* POST /manage/inflow/interface/metric/reset → 전체 인터페이스 메트릭 초기화
* POST /manage/inflow/interface/{interfaceId}/metric/reset → 특정 인터페이스 메트릭 초기화
*
* GET /manage/inflow/client/metric → 전체 클라이언트 메트릭
* GET /manage/inflow/client/{clientId}/metric → 특정 클라이언트 메트릭
* POST /manage/inflow/client/metric/reset → 전체 클라이언트 메트릭 초기화
* POST /manage/inflow/client/{clientId}/metric/reset → 특정 클라이언트 메트릭 초기화
*/
@RestController
@RequestMapping("/manage/inflow")
@@ -95,34 +90,6 @@ public class InflowTargetMetricController {
return okResetSingle(ok, interfaceId, "인터페이스");
}
// =========================================================================
// 클라이언트
// =========================================================================
@GetMapping("/client/metric")
public ResponseEntity<?> getAllClientMetrics() {
List<TargetMetricDTO> list = metricService.getAllClientMetrics();
return okList(list);
}
@GetMapping("/client/{clientId}/metric")
public ResponseEntity<?> getClientMetric(@PathVariable String clientId) {
TargetMetricDTO dto = metricService.getClientMetric(clientId);
return okSingle(dto, "클라이언트를 찾을 수 없습니다: " + clientId);
}
@PostMapping("/client/metric/reset")
public ResponseEntity<?> resetAllClientMetrics() {
metricService.resetAllClientMetrics();
return okReset("전체 클라이언트 메트릭 초기화 완료");
}
@PostMapping("/client/{clientId}/metric/reset")
public ResponseEntity<?> resetClientMetric(@PathVariable String clientId) {
boolean ok = metricService.resetClientMetric(clientId);
return okResetSingle(ok, clientId, "클라이언트");
}
// =========================================================================
// Helpers
// =========================================================================
@@ -85,42 +85,6 @@ public class InflowTargetMetricService {
if (manager != null) manager.resetAllInterfaceMetrics();
}
// -------------------------------------------------------------------------
// 클라이언트
// -------------------------------------------------------------------------
public TargetMetricDTO getClientMetric(String clientId) {
DualInflowControlManager manager = getDualManager();
if (manager == null) return null;
InflowTargetVO vo = manager.getClientInflowThreshold(clientId);
if (vo == null) return null;
return buildDTO(clientId, "CLIENT", vo, manager.getClientMetrics(clientId));
}
public List<TargetMetricDTO> getAllClientMetrics() {
DualInflowControlManager manager = getDualManager();
if (manager == null) return new ArrayList<>();
List<TargetMetricDTO> result = new ArrayList<>();
for (String id : manager.getClientBucketMap().keySet()) {
TargetMetricDTO dto = getClientMetric(id);
if (dto != null) result.add(dto);
}
return result;
}
public boolean resetClientMetric(String clientId) {
DualInflowControlManager manager = getDualManager();
if (manager == null) return false;
if (manager.getClientInflowThreshold(clientId) == null) return false;
manager.resetClientMetrics(clientId);
return true;
}
public void resetAllClientMetrics() {
DualInflowControlManager manager = getDualManager();
if (manager != null) manager.resetAllClientMetrics();
}
// -------------------------------------------------------------------------
// Private helpers
// -------------------------------------------------------------------------