From 66e9a715bb1f40def3a2c62824f81aaed60e9816 Mon Sep 17 00:00:00 2001 From: "semin.baek" Date: Wed, 27 Aug 2025 19:51:49 +0900 Subject: [PATCH] =?UTF-8?q?=EC=97=90=EC=9D=B4=EC=A0=84=ED=8A=B8=20?= =?UTF-8?q?=EC=A0=95=EB=B3=B4=20=EC=88=98=EC=8B=A0=20=EC=A7=84=ED=96=89?= =?UTF-8?q?=EC=A4=91=20=EC=97=90=EC=9D=B4=EC=A0=84=ED=8A=B8=EC=9D=98=20?= =?UTF-8?q?=EB=8D=B0=EC=9D=B4=ED=84=B0=20=EB=A9=94=EC=8B=9C=EC=A7=80=20?= =?UTF-8?q?=EC=88=98=EC=8B=A0=20=EA=B8=B0=EB=8A=A5=20=EA=B0=9C=EB=B0=9C=20?= =?UTF-8?q?=20-=20=ED=85=8C=EC=8A=A4=ED=8A=B8=EB=90=98=EC=A7=80=20?= =?UTF-8?q?=EC=95=8A=EC=95=98=EC=9D=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/database/create-database.sql | 29 +++++++++++ src/database/create-initial-data.sql | 29 +++++++++++ .../agent/listener/dto/ReceiveMessageDto.java | 9 ++++ .../app/agent/DfxAgentInfoController.java | 9 ++++ .../service/DfxAgentMessageHistoryDto.java | 23 +++++++++ .../service/DfxAgentMessageHistoryMapper.java | 12 +++++ .../DfxAgentMessageHistoryService.java | 19 ++++++++ .../app/communicate/ListenerController.java | 6 +++ .../communicate/service/ListenerService.java | 39 +++++++++++++++ .../mapper/app/dfx-agent-message-history.xml | 48 +++++++++++++++++++ 10 files changed, 223 insertions(+) create mode 100644 src/main/java/com/bsmlab/dfx/dfxconsole/app/agent/service/DfxAgentMessageHistoryDto.java create mode 100644 src/main/java/com/bsmlab/dfx/dfxconsole/app/agent/service/DfxAgentMessageHistoryMapper.java create mode 100644 src/main/java/com/bsmlab/dfx/dfxconsole/app/agent/service/DfxAgentMessageHistoryService.java create mode 100644 src/main/resources/mapper/app/dfx-agent-message-history.xml diff --git a/src/database/create-database.sql b/src/database/create-database.sql index dc153da..fe8aafc 100644 --- a/src/database/create-database.sql +++ b/src/database/create-database.sql @@ -71,3 +71,32 @@ COMMENT ON COLUMN TB_DFX_DROPBOX.DATA_SOURCE_ID IS 'DATA SOURCE ID'; COMMENT ON COLUMN TB_DFX_DROPBOX.SQL_ID IS 'SQL_ID'; COMMENT ON COLUMN TB_DFX_DROPBOX.DESCRIPTION IS 'DESCRIPTION'; + +CREATE TABLE TB_DFX_AGENT_MESSAGE_HISTORY ( + SENDER_AGENT_ID VARCHAR(256) NOT NULL + , SENDER_TS TIMESTAMP + , RECIPIENT_AGENT_ID VARCHAR(256) NOT NULL + , RECIPIENT_TS TIMESTAMP + , MESSAGE_UUID VARCHAR(36) NOT NULL + , MESSAGE_TYPE_CODE VARCHAR(64) + , CONSOLE_RECEIVE_TS TIMESTAMP + , PROCESS_STATUS_CODE VARCHAR(64) + , MESSAGE_DATA TEXT + , CONSTRAINT PK_DFX_AGENT_MESSAGE_HISTORY PRIMARY KEY (SENDER_AGENT_ID, MESSAGE_UUID) +); +CREATE INDEX IX_DFX_AGENT_MESSAGE_HISTORY_1 ON TB_DFX_AGENT_MESSAGE_HISTORY (RECIPIENT_AGENT_ID); +CREATE INDEX IX_DFX_AGENT_MESSAGE_HISTORY_2 ON TB_DFX_AGENT_MESSAGE_HISTORY (CONSOLE_RECEIVE_TS); +COMMENT ON TABLE TB_DFX_AGENT_MESSAGE_HISTORY IS '에이전트간 메시지 송신 이력'; +COMMENT ON COLUMN TB_DFX_AGENT_MESSAGE_HISTORY.SENDER_AGENT_ID IS '송신 에이전트ID'; +COMMENT ON COLUMN TB_DFX_AGENT_MESSAGE_HISTORY.SENDER_TS IS '송신 시간'; +COMMENT ON COLUMN TB_DFX_AGENT_MESSAGE_HISTORY.RECIPIENT_AGENT_ID IS '수신 에이전트ID'; +COMMENT ON COLUMN TB_DFX_AGENT_MESSAGE_HISTORY.RECIPIENT_TS IS '수신 시간'; +COMMENT ON COLUMN TB_DFX_AGENT_MESSAGE_HISTORY.MESSAGE_UUID IS 'MESSAGE UUID'; +COMMENT ON COLUMN TB_DFX_AGENT_MESSAGE_HISTORY.MESSAGE_TYPE_CODE IS '메시지 타입 코드 CODE_GROUP: MESSAGE_TYPE'; +COMMENT ON COLUMN TB_DFX_AGENT_MESSAGE_HISTORY.CONSOLE_RECEIVE_TS IS '콘솔 수신 시간'; +COMMENT ON COLUMN TB_DFX_AGENT_MESSAGE_HISTORY.PROCESS_STATUS_CODE IS '프로세스 상태 코드 CODE_GROUP: PROCESS_STATUS'; +COMMENT ON COLUMN TB_DFX_AGENT_MESSAGE_HISTORY.MESSAGE_DATA IS '메시지 데이터'; + + + + diff --git a/src/database/create-initial-data.sql b/src/database/create-initial-data.sql index 1d386da..bc0612d 100644 --- a/src/database/create-initial-data.sql +++ b/src/database/create-initial-data.sql @@ -24,4 +24,33 @@ VALUES ( 'DROPBOX_TASK_TYPE', 'RECEIVE_FILE', '파일 수신 후 파일 저장', '파일을 수신하여 파일로 저장한다.', 2, NULL, 'Y' ); +INSERT INTO TB_CODE ( + CODE_GROUP, CODE_NAME, CODE_VALUE, CODE_DESCRIPTION, ORDER_NO, PARENT_CODE_NAME, USE_YN +) +VALUES ( + 'MESSAGE_TYPE', 'TRANSFER_DB_TO_DB', 'DB to DB 전달', 'DB 데이터를 로드하여 DB 저장 형태로 전달한다.', 1, NULL, 'Y' +); +INSERT INTO TB_CODE ( + CODE_GROUP, CODE_NAME, CODE_VALUE, CODE_DESCRIPTION, ORDER_NO, PARENT_CODE_NAME, USE_YN +) +VALUES ( + 'MESSAGE_TYPE', 'TRANSFER_FILE', 'FILE to FILE 전달', '파일을 로드하여 파일 형태로 전달한다.', 2, NULL, 'Y' +); + +INSERT INTO TB_CODE ( + CODE_GROUP, CODE_NAME, CODE_VALUE, CODE_DESCRIPTION, ORDER_NO, PARENT_CODE_NAME, USE_YN +) +VALUES ( + 'PROCESS_STATUS', 'PROCESS_DONE', '프로세스 완료', '프로세스 완료', 1, NULL, 'Y' +); +INSERT INTO TB_CODE ( + CODE_GROUP, CODE_NAME, CODE_VALUE, CODE_DESCRIPTION, ORDER_NO, PARENT_CODE_NAME, USE_YN +) +VALUES ( + 'PROCESS_STATUS', 'PROCESS_FAIL', '프로세스 실패', '프로세스 실패', 2, NULL, 'Y' +); + + + + INSERT INTO TB_DFX_USER (USER_UUID, USER_EMAIL, USER_PASSWORD, USER_NICK) VALUES ('dad9f3b6-45bf-49f9-85c5-1a83810d921c', 'smbaek@bsm-lab.com', 'qortpals1!', '백세민'); diff --git a/src/main/java/com/bsmlab/dfx/agent/listener/dto/ReceiveMessageDto.java b/src/main/java/com/bsmlab/dfx/agent/listener/dto/ReceiveMessageDto.java index 71988f1..48551df 100644 --- a/src/main/java/com/bsmlab/dfx/agent/listener/dto/ReceiveMessageDto.java +++ b/src/main/java/com/bsmlab/dfx/agent/listener/dto/ReceiveMessageDto.java @@ -5,6 +5,7 @@ import lombok.*; import java.io.Serializable; import java.util.List; +import java.util.Map; @ToString @Getter @@ -20,6 +21,7 @@ public class ReceiveMessageDto implements Serializable { private long receivedTimestamp; private String recipientHostId; private String recipientDropBoxId; + private List routingHostList; private String data; private List attachFileList;// = new ArrayList<>(); private ProcessStatus processStatus; @@ -30,4 +32,11 @@ public class ReceiveMessageDto implements Serializable { PROCESS_NOT_POSSIBLE, PROCESS_FAIL } + + @Data + @Builder + public static class RoutingHost implements Serializable { + private String hostId; + private long receivedTimestamp; + } } diff --git a/src/main/java/com/bsmlab/dfx/dfxconsole/app/agent/DfxAgentInfoController.java b/src/main/java/com/bsmlab/dfx/dfxconsole/app/agent/DfxAgentInfoController.java index 6b0888d..d212b59 100644 --- a/src/main/java/com/bsmlab/dfx/dfxconsole/app/agent/DfxAgentInfoController.java +++ b/src/main/java/com/bsmlab/dfx/dfxconsole/app/agent/DfxAgentInfoController.java @@ -3,6 +3,8 @@ package com.bsmlab.dfx.dfxconsole.app.agent; import com.bsmlab.dfx.agent.config.AgentConfigDto; import com.bsmlab.dfx.dfxconsole.app.agent.service.DfxAgentInfoDto; import com.bsmlab.dfx.dfxconsole.app.agent.service.DfxAgentInfoService; +import com.bsmlab.dfx.dfxconsole.app.agent.service.DfxAgentMessageHistoryDto; +import com.bsmlab.dfx.dfxconsole.app.agent.service.DfxAgentMessageHistoryService; import com.bsmlab.dfx.dfxconsole.framework.support.ResponseUtils; import com.fasterxml.jackson.core.JsonProcessingException; import lombok.RequiredArgsConstructor; @@ -20,6 +22,7 @@ import java.util.Map; @Slf4j public class DfxAgentInfoController { private final DfxAgentInfoService dfxAgentInfoService; + private final DfxAgentMessageHistoryService dfxAgentMessageHistoryService; @PostMapping("/app-api/agent/getAgentInfoDtoList") public ResponseEntity> agentConfigDtoList() { @@ -45,4 +48,10 @@ public class DfxAgentInfoController { return ResponseEntity.internalServerError().body(ResponseUtils.toExceptionResponseDto(e)); } } + + @PostMapping("/app-api/agent/getAgentMessageHistoryDtoList") + public ResponseEntity> getAgentMessageHistoryDtoList() { + List dfxAgentMessageHistoryDtoList = dfxAgentMessageHistoryService.selectDfxAgentMessageHistoryDtoList(); + return ResponseEntity.ok().body(dfxAgentMessageHistoryDtoList); + } } diff --git a/src/main/java/com/bsmlab/dfx/dfxconsole/app/agent/service/DfxAgentMessageHistoryDto.java b/src/main/java/com/bsmlab/dfx/dfxconsole/app/agent/service/DfxAgentMessageHistoryDto.java new file mode 100644 index 0000000..d10a44b --- /dev/null +++ b/src/main/java/com/bsmlab/dfx/dfxconsole/app/agent/service/DfxAgentMessageHistoryDto.java @@ -0,0 +1,23 @@ +package com.bsmlab.dfx.dfxconsole.app.agent.service; + +import lombok.*; + +@NoArgsConstructor +@AllArgsConstructor +@Getter +@Setter +@Builder +@ToString +public class DfxAgentMessageHistoryDto { + private String senderAgentId; + private String senderHostName; + private long senderTs; + private String recipientAgentId; + private String recipientHostName; + private long recipientTs; + private String messageUuid; + private String messageTypeCode; + private long consoleReceiveTs; + private String processStatusCode; + private String messageData; +} diff --git a/src/main/java/com/bsmlab/dfx/dfxconsole/app/agent/service/DfxAgentMessageHistoryMapper.java b/src/main/java/com/bsmlab/dfx/dfxconsole/app/agent/service/DfxAgentMessageHistoryMapper.java new file mode 100644 index 0000000..b15528e --- /dev/null +++ b/src/main/java/com/bsmlab/dfx/dfxconsole/app/agent/service/DfxAgentMessageHistoryMapper.java @@ -0,0 +1,12 @@ +package com.bsmlab.dfx.dfxconsole.app.agent.service; + +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +@Mapper +public interface DfxAgentMessageHistoryMapper { + List selectDfxAgentMessageHistoryList(); + DfxAgentMessageHistoryDto selectDfxAgentMessageHistoryBySenderAgentIdAndMessageUuid(DfxAgentMessageHistoryDto dfxAgentMessageHistoryDto); + void insertDfxAgentMessageHistory(DfxAgentMessageHistoryDto dfxAgentMessageHistoryDto); +} diff --git a/src/main/java/com/bsmlab/dfx/dfxconsole/app/agent/service/DfxAgentMessageHistoryService.java b/src/main/java/com/bsmlab/dfx/dfxconsole/app/agent/service/DfxAgentMessageHistoryService.java new file mode 100644 index 0000000..dcb5631 --- /dev/null +++ b/src/main/java/com/bsmlab/dfx/dfxconsole/app/agent/service/DfxAgentMessageHistoryService.java @@ -0,0 +1,19 @@ +package com.bsmlab.dfx.dfxconsole.app.agent.service; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +@RequiredArgsConstructor +@Slf4j +public class DfxAgentMessageHistoryService { + private final DfxAgentMessageHistoryMapper dfxAgentMessageHistoryMapper; + + public List selectDfxAgentMessageHistoryDtoList() { + List dfxAgentMessageHistoryDtoList = dfxAgentMessageHistoryMapper.selectDfxAgentMessageHistoryList(); + return dfxAgentMessageHistoryDtoList; + } +} diff --git a/src/main/java/com/bsmlab/dfx/dfxconsole/app/communicate/ListenerController.java b/src/main/java/com/bsmlab/dfx/dfxconsole/app/communicate/ListenerController.java index c2bd0c7..dbb628a 100644 --- a/src/main/java/com/bsmlab/dfx/dfxconsole/app/communicate/ListenerController.java +++ b/src/main/java/com/bsmlab/dfx/dfxconsole/app/communicate/ListenerController.java @@ -26,6 +26,12 @@ public class ListenerController { @PostMapping(value = "/listen") public AckDto listener(HttpServletRequest request) { AckDto ackDto = AckDto.builder().build(); + try { + String bodyString = ServletUtils.getBodyString(request); + ackDto = listenerService.receiveMessage(bodyString); + } catch (IOException e) { + ackDto = AckDto.builder().result(AckDto.ResultType.RECEIVE_FAIL).resultText(e.getLocalizedMessage()).messageUuid("").build(); + } return ackDto; } diff --git a/src/main/java/com/bsmlab/dfx/dfxconsole/app/communicate/service/ListenerService.java b/src/main/java/com/bsmlab/dfx/dfxconsole/app/communicate/service/ListenerService.java index 1611391..a13104a 100644 --- a/src/main/java/com/bsmlab/dfx/dfxconsole/app/communicate/service/ListenerService.java +++ b/src/main/java/com/bsmlab/dfx/dfxconsole/app/communicate/service/ListenerService.java @@ -3,11 +3,15 @@ package com.bsmlab.dfx.dfxconsole.app.communicate.service; import com.bsmlab.dfx.agent.config.AgentConfigDto; import com.bsmlab.dfx.agent.listener.dto.AckDto; import com.bsmlab.dfx.agent.listener.dto.CommandDto; +import com.bsmlab.dfx.agent.listener.dto.ReceiveMessageDto; import com.bsmlab.dfx.agent.support.MessageUtils; import com.bsmlab.dfx.agent.support.exception.IllegalMessageException; +import com.bsmlab.dfx.agent.support.exception.InCompleteMessageException; import com.bsmlab.dfx.agent.support.exception.NullMessageException; import com.bsmlab.dfx.dfxconsole.app.agent.service.DfxAgentInfoDto; import com.bsmlab.dfx.dfxconsole.app.agent.service.DfxAgentInfoService; +import com.bsmlab.dfx.dfxconsole.app.agent.service.DfxAgentMessageHistoryDto; +import com.bsmlab.dfx.dfxconsole.app.agent.service.DfxAgentMessageHistoryMapper; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; @@ -16,11 +20,15 @@ import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; +import java.util.List; +import java.util.Map; + @Service @Slf4j @RequiredArgsConstructor public class ListenerService { private final DfxAgentInfoService dfxAgentInfoService; + private final DfxAgentMessageHistoryMapper dfxAgentMessageHistoryMapper; public AckDto receiveCommand(String messageJsonString) { AckDto ackDto; @@ -56,4 +64,35 @@ public class ListenerService { dfxAgentInfoService.saveDfxAgentInfoDto(dfxAgentInfoDto); } } + + /** + * 메시지를 파싱한다. + * 메시지의 recipientHostId가 myHostId 이거나 메시지의 라우팅 중 마지막 hostId가 myHostId 이면 수신처리 한다. + * 그렇지 않은 경우 라우팅 다음 순번으로 메시지를 전송한다. (MessageUtils.transfer) + * @param messageJsonString + * @return + */ + public AckDto receiveMessage(String messageJsonString) { + AckDto ackDto = null; + try { + ReceiveMessageDto receiveMessageDto = MessageUtils.toReceiveMessageDto(messageJsonString); + DfxAgentMessageHistoryDto dfxAgentMessageHistoryDto = DfxAgentMessageHistoryDto.builder() + .senderAgentId(receiveMessageDto.getSenderHostId()) + .senderTs(receiveMessageDto.getSenderTimestamp()) + .recipientAgentId(receiveMessageDto.getRecipientHostId()) + .recipientTs(receiveMessageDto.getReceivedTimestamp()) + .messageUuid(receiveMessageDto.getMessageUuid()) + .messageTypeCode(receiveMessageDto.getMessageType().name()) + .consoleReceiveTs(System.currentTimeMillis()) + .processStatusCode(receiveMessageDto.getProcessStatus().name()) + .messageData(receiveMessageDto.getData()) + .build(); + dfxAgentMessageHistoryMapper.insertDfxAgentMessageHistory(dfxAgentMessageHistoryDto); + ackDto = AckDto.builder().result(AckDto.ResultType.RECEIVE_SUCCESS).build(); + } catch (IllegalMessageException | NullMessageException | InCompleteMessageException e) { + log.error("{}", e, e); + ackDto = AckDto.builder().result(AckDto.ResultType.RECEIVE_FAIL).resultText(e.getLocalizedMessage()).build(); + } + return ackDto; + } } diff --git a/src/main/resources/mapper/app/dfx-agent-message-history.xml b/src/main/resources/mapper/app/dfx-agent-message-history.xml new file mode 100644 index 0000000..722dc6c --- /dev/null +++ b/src/main/resources/mapper/app/dfx-agent-message-history.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + +