MessageUtils ReceiveMessageDto의 정합성 체크 로직 수정

shutdown.sh 를 위한 로직 및 스크립트 추가
main
semin.baek 9 months ago
parent a67dadeb7e
commit 7b639a553d

@ -0,0 +1,27 @@
#!/bin/bash
PID_FILE="proc/dfxagent.pid"
# PID 파일 존재 여부 확인
if [ ! -f "$PID_FILE" ]; then
echo "PID 파일이 없습니다: $PID_FILE"
exit 1
fi
# PID 읽기
PID=$(cat "$PID_FILE")
# PID가 숫자인지 검증
if ! [[ "$PID" =~ ^[0-9]+$ ]]; then
echo "PID 파일에 잘못된 값이 들어있습니다: $PID"
exit 1
fi
# 프로세스 존재 여부 확인 (optional)
if ps -p "$PID" > /dev/null 2>&1; then
echo "프로세스 종료 중: PID=$PID"
kill -9 "$PID"
echo "종료 완료"
else
echo "PID=$PID 프로세스가 존재하지 않습니다."
fi

@ -0,0 +1,4 @@
#!/bin/sh
AGENT_HOME=/home/dfxagent/agent
TODAY=$(date "+%Y%m%d")
java -jar $AGENT_HOME/lib/dfxagent.jar --setting.file=$AGENT_HOME/conf/settings.json > $AGENT_HOME/logs/agent.$TODAY.log &

@ -37,7 +37,7 @@
"taskType": "DB_READ_THEN_SEND", "taskType": "DB_READ_THEN_SEND",
"action": { "action": {
"type": "SCHEDULED", "type": "SCHEDULED",
"cron": "0 */1 * * * *" "cron": "0 0/1 * * * *"
}, },
"message": { "message": {
"messageType": "TRANSFER_DB_TO_DB", "messageType": "TRANSFER_DB_TO_DB",

@ -1,5 +1,6 @@
package com.bsmlab.dfx.agent.config; package com.bsmlab.dfx.agent.config;
import com.bsmlab.dfx.agent.DfxAgentApplication;
import com.bsmlab.dfx.agent.config.datasource.DynamicDataSourceService; import com.bsmlab.dfx.agent.config.datasource.DynamicDataSourceService;
import com.bsmlab.dfx.agent.config.datasource.DynamicRoutingDataSource; import com.bsmlab.dfx.agent.config.datasource.DynamicRoutingDataSource;
import com.bsmlab.dfx.agent.config.datasource.RefreshableSqlSessionFactoryBean; import com.bsmlab.dfx.agent.config.datasource.RefreshableSqlSessionFactoryBean;
@ -21,7 +22,15 @@ import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException; import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.*; import java.util.*;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
@ -41,13 +50,14 @@ public class DfxAgentConfiguration {
//example: setting.file=D:\projects\bsm-lab\dfx\dfxagent\src\docs\settings-examples\dfxagent.json //example: setting.file=D:\projects\bsm-lab\dfx\dfxagent\src\docs\settings-examples\dfxagent.json
@Value("${setting.file}") @Value("${setting.file}")
private String settingFile; private String settingFile;
private String pid;
private Map<String, SqlSessionFactory> temporarySqlSessionFactoryMap = new HashMap<>(); private Map<String, SqlSessionFactory> temporarySqlSessionFactoryMap = new HashMap<>();
Map<String, DataSourceTransactionManager> temporaryTransactionManagerMap = new HashMap<>(); Map<String, DataSourceTransactionManager> temporaryTransactionManagerMap = new HashMap<>();
// agent 설정 관리자. 대부분의 기능에 필요함 // agent 설정 관리자. 대부분의 기능에 필요함
@Bean(name = "agentConfigReader") @Bean(name = "agentConfigReader")
public AgentConfigReader agentConfigReader() { // 실행확인됨 public AgentConfigReader agentConfigReader() throws URISyntaxException, IOException { // 실행확인됨
if(StringUtils.isBlank(this.settingFile)) { if(StringUtils.isBlank(this.settingFile)) {
log.error("cannot found a setting file. {}", this.settingFile); log.error("cannot found a setting file. {}", this.settingFile);
log.error("exit application"); log.error("exit application");
@ -55,6 +65,37 @@ public class DfxAgentConfiguration {
} }
AgentConfigReader agentConfigReader = new AgentConfigReader(); AgentConfigReader agentConfigReader = new AgentConfigReader();
agentConfigReader.loadConfigFile(this.settingFile); agentConfigReader.loadConfigFile(this.settingFile);
// Process ID를 찾아 app_home/proc/pid 파일에 기록한다. 이후 shutdown.sh에서 해당 pid를 사용하여 kill -9 pid 를 실행한다.
this.pid = String.valueOf(ProcessHandle.current().pid());
URL location = DfxAgentApplication.class.getProtectionDomain().getCodeSource().getLocation();
URI uri = location.toURI();
File file;
if ("file".equalsIgnoreCase(uri.getScheme())) {
// 파일 시스템 상의 경로
file = new File(uri);
}
else if ("jar".equalsIgnoreCase(uri.getScheme()) || location.toString().startsWith("jar:")) {
// JAR 내부 경로일 경우
String path = location.toString();
log.debug("path: {}", path);
if (path.startsWith("jar:")) {
path = path.substring(4, path.indexOf("!") - 1);
path = path.substring(path.indexOf(":") + 1, path.lastIndexOf("/"));
}
log.debug("path: {}", path);
file = new File(path);
}
else {
// 파일 시스템 상의 경로
file = new File(uri);
}
String procDirectoryPath = file.getParent() + File.separator + "proc";
File procFile = new File(procDirectoryPath);
if(!procFile.exists()) {
procFile.mkdirs();
}
Path pidFilePath = Path.of(procDirectoryPath + File.separator, "dfxagent.pid");
Files.writeString(pidFilePath, pid, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
return agentConfigReader; return agentConfigReader;
} }

@ -32,6 +32,7 @@ public class ListenerController {
String contentType = request.getContentType(); String contentType = request.getContentType();
if(contentType != null && contentType.contains("application/json")) { if(contentType != null && contentType.contains("application/json")) {
String bodyString = ServletUtils.getBodyString(request); String bodyString = ServletUtils.getBodyString(request);
log.debug("from: {} receive a message: {}", request.getRemoteAddr(), bodyString);
ackDto = listenerService.receiveMessage(bodyString); ackDto = listenerService.receiveMessage(bodyString);
} }
else if(contentType != null && contentType.contains("multipart/form-data")) { else if(contentType != null && contentType.contains("multipart/form-data")) {

@ -7,6 +7,7 @@ import java.io.Serializable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ToString
@Getter @Getter
@Setter @Setter
@Builder @Builder

@ -16,6 +16,7 @@ import java.util.*;
public class MessageUtils { public class MessageUtils {
private MessageUtils() {}; private MessageUtils() {};
@SuppressWarnings("unchecked")
public static ReceiveMessageDto toReceiveMessageDto(String messageJsonString) throws IllegalMessageException, NullMessageException, InCompleteMessageException { public static ReceiveMessageDto toReceiveMessageDto(String messageJsonString) throws IllegalMessageException, NullMessageException, InCompleteMessageException {
ReceiveMessageDto receiveMessageDto = null; ReceiveMessageDto receiveMessageDto = null;
ObjectMapper objectMapper = new ObjectMapper(); ObjectMapper objectMapper = new ObjectMapper();
@ -25,36 +26,29 @@ public class MessageUtils {
if(map == null) { if(map == null) {
throw new NullMessageException(""); throw new NullMessageException("");
} }
if(map.get("sender") == null) {
throw new InCompleteMessageException("sender 엘리먼트를 찾을 수 없습니다.");
}
else if(!(map.get("sender") instanceof Map)) {
throw new InCompleteMessageException("sender 엘리먼트의 데이터가 객체타입이 아닙니다.");
}
Map<String, Object> senderMap = (Map<String, Object>)map.get("sender");
String senderHostId; String senderHostId;
if(senderMap.get("hostId") == null) { if(map.get("senderHostId") == null) {
throw new InCompleteMessageException("sender.hostId 엘리먼트를 찾을 수 없습니다."); throw new InCompleteMessageException("senderHostId 엘리먼트를 찾을 수 없습니다.");
} }
else if(StringUtils.isBlank(String.valueOf(senderMap.get("hostId")))) { else if(StringUtils.isBlank(String.valueOf(map.get("senderHostId")))) {
throw new InCompleteMessageException("sender.hostId 값을 찾을 수 없습니다."); throw new InCompleteMessageException("senderHostId 값을 찾을 수 없습니다.");
} }
else { else {
senderHostId = String.valueOf(senderMap.get("hostId")); senderHostId = String.valueOf(map.get("senderHostId"));
} }
long senderTimestamp = 0; long senderTimestamp = 0;
if(senderMap.get("timestamp") == null) { if(map.get("senderTimestamp") == null) {
throw new InCompleteMessageException("sender.timestamp 엘리먼트를 찾을 수 없습니다."); throw new InCompleteMessageException("senderTimestamp 엘리먼트를 찾을 수 없습니다.");
} }
else if(StringUtils.isBlank(String.valueOf(senderMap.get("timestamp")))) { else if(StringUtils.isBlank(String.valueOf(map.get("senderTimestamp")))) {
throw new InCompleteMessageException("sender.timestamp 값을 찾을 수 없습니다."); throw new InCompleteMessageException("senderTimestamp 값을 찾을 수 없습니다.");
} }
else { else {
String senderTimeStampString = String.valueOf(senderMap.get("timestamp")); String senderTimeStampString = String.valueOf(map.get("senderTimestamp"));
try { try {
senderTimestamp = Long.parseLong(senderTimeStampString); senderTimestamp = Long.parseLong(senderTimeStampString);
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
throw new InCompleteMessageException("sender.timestamp 값의 형식이 숫자형식이 아닙니다. " + senderTimeStampString); throw new InCompleteMessageException("senderTimestamp 값의 형식이 숫자형식이 아닙니다. " + senderTimeStampString);
} }
} }
String messageUuid; String messageUuid;
@ -73,35 +67,6 @@ public class MessageUtils {
throw new InCompleteMessageException("messageUuid 값의 형식이 숫자형식이 아닙니다. " + messageUuid); throw new InCompleteMessageException("messageUuid 값의 형식이 숫자형식이 아닙니다. " + messageUuid);
} }
} }
long receivedTimestamp = System.currentTimeMillis();
if(map.get("recipient") == null) {
throw new InCompleteMessageException("recipient 엘리먼트를 찾을 수 없습니다.");
}
else if(!(map.get("recipient") instanceof Map)) {
throw new InCompleteMessageException("recipient 엘리먼트의 데이터가 객체타입이 아닙니다.");
}
Map<String, Object> recipientMap = (Map<String, Object>)map.get("recipient");
//TODO recipient
String recipientHostId;
if(recipientMap.get("hostId") == null) {
throw new InCompleteMessageException("recipient.hostId 엘리먼트를 찾을 수 없습니다.");
}
else if(StringUtils.isBlank(String.valueOf(recipientMap.get("hostId")))) {
throw new InCompleteMessageException("recipient.hostId 값을 찾을 수 없습니다.");
}
else {
recipientHostId = String.valueOf(recipientMap.get("hostId"));
}
String recipientDropBoxId;
if(recipientMap.get("dropBoxId") == null) {
throw new InCompleteMessageException("recipient.dropBoxId 엘리먼트를 찾을 수 없습니다.");
}
else if(StringUtils.isBlank(String.valueOf(recipientMap.get("dropBoxId")))) {
throw new InCompleteMessageException("recipient.dropBoxId 값을 찾을 수 없습니다.");
}
else {
recipientDropBoxId = String.valueOf(recipientMap.get("dropBoxId"));
}
AgentConfigDto.MessageType messageType; AgentConfigDto.MessageType messageType;
if(map.get("messageType") == null) { if(map.get("messageType") == null) {
throw new InCompleteMessageException("messageType 엘리먼트를 찾을 수 없습니다."); throw new InCompleteMessageException("messageType 엘리먼트를 찾을 수 없습니다.");
@ -116,6 +81,41 @@ public class MessageUtils {
} }
messageType = EnumUtils.getEnum(AgentConfigDto.MessageType.class, messageTypeString); messageType = EnumUtils.getEnum(AgentConfigDto.MessageType.class, messageTypeString);
} }
long receivedTimestamp = 0;
if(map.get("receivedTimestamp") == null) {
throw new InCompleteMessageException("receivedTimestamp 엘리먼트를 찾을 수 없습니다.");
}
else if(StringUtils.isBlank(String.valueOf(map.get("receivedTimestamp")))) {
throw new InCompleteMessageException("receivedTimestamp 값을 찾을 수 없습니다.");
}
else {
String receivedTimestampString = String.valueOf(map.get("receivedTimestamp"));
try {
receivedTimestamp = Long.parseLong(receivedTimestampString);
} catch (NumberFormatException e) {
throw new InCompleteMessageException("receivedTimestamp 값의 형식이 숫자형식이 아닙니다. " + receivedTimestampString);
}
}
String recipientHostId;
if(map.get("recipientHostId") == null) {
throw new InCompleteMessageException("recipientHostId 엘리먼트를 찾을 수 없습니다.");
}
else if(StringUtils.isBlank(String.valueOf(map.get("recipientHostId")))) {
throw new InCompleteMessageException("recipientHostId 값을 찾을 수 없습니다.");
}
else {
recipientHostId = String.valueOf(map.get("recipientHostId"));
}
String recipientDropBoxId;
if(map.get("recipientDropBoxId") == null) {
throw new InCompleteMessageException("recipientDropBoxId 엘리먼트를 찾을 수 없습니다.");
}
else if(StringUtils.isBlank(String.valueOf(map.get("recipientDropBoxId")))) {
throw new InCompleteMessageException("recipientDropBoxId 값을 찾을 수 없습니다.");
}
else {
recipientDropBoxId = String.valueOf(map.get("recipientDropBoxId"));
}
String dataString; String dataString;
if(map.get("data") == null) { if(map.get("data") == null) {
throw new InCompleteMessageException("data 엘리먼트를 찾을 수 없습니다."); throw new InCompleteMessageException("data 엘리먼트를 찾을 수 없습니다.");

@ -89,7 +89,8 @@ public class PostmanSchedulerService {
HttpEntity<ReceiveMessageDto> bodyEntity = new HttpEntity<>(receiveMessageDto, httpHeaders); HttpEntity<ReceiveMessageDto> bodyEntity = new HttpEntity<>(receiveMessageDto, httpHeaders);
RestTemplate restTemplate = new RestTemplate(); RestTemplate restTemplate = new RestTemplate();
AgentConfigDto.KnownAgent knownAgent = agentConfigReader.getKnownAgent(postman.getRecipientHostId()); AgentConfigDto.KnownAgent knownAgent = agentConfigReader.getKnownAgent(postman.getRecipientHostId());
String url = "https://" + knownAgent.getHostName() + ":" + knownAgent.getListenPort() + "/listen"; String url = "http://" + knownAgent.getHostName() + ":" + knownAgent.getListenPort() + "/listen";
log.debug("postman to {} send a message {}", receiveMessageDto.getRecipientHostId(), receiveMessageDto.toString());
String response = restTemplate.postForObject(url, bodyEntity, String.class); String response = restTemplate.postForObject(url, bodyEntity, String.class);
AckDto ackDto = objectMapper.readValue(response, new TypeReference<AckDto>() {}); AckDto ackDto = objectMapper.readValue(response, new TypeReference<AckDto>() {});
if(AckDto.ResultType.RECEIVE_SUCCESS != ackDto.getResult()) { if(AckDto.ResultType.RECEIVE_SUCCESS != ackDto.getResult()) {

Loading…
Cancel
Save