히스토리 마이그레이션
This commit is contained in:
@@ -10,6 +10,7 @@ import lombok.Getter;
|
|||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
import org.springframework.data.mongodb.core.mapping.Document;
|
import org.springframework.data.mongodb.core.mapping.Document;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@@ -20,7 +21,7 @@ public class DynamodbHistoryLogInfo extends HistoryLogInfoBase {
|
|||||||
private DynamoDBDocBase data;
|
private DynamoDBDocBase data;
|
||||||
|
|
||||||
public DynamodbHistoryLogInfo(EDBOperationType operationType, HISTORYTYPEDETAIL historyType, String tableName, String message, String tranId, List<FieldChange> changed, String userId, String userIP, DynamoDBDocBase data) {
|
public DynamodbHistoryLogInfo(EDBOperationType operationType, HISTORYTYPEDETAIL historyType, String tableName, String message, String tranId, List<FieldChange> changed, String userId, String userIP, DynamoDBDocBase data) {
|
||||||
super(DBType.DYNAMODB, DateUtils.nowDateTime(), operationType, historyType, tableName, message, tranId, changed, userId, userIP);
|
super(DBType.DYNAMODB, LocalDateTime.now(), operationType, historyType, tableName, message, tranId, changed, userId, userIP);
|
||||||
|
|
||||||
this.data = data;
|
this.data = data;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,16 +7,20 @@ import com.caliverse.admin.mongodb.entity.EDBOperationType;
|
|||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
|
import org.springframework.data.annotation.Id;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
public class HistoryLogInfoBase implements historyLog {
|
public class HistoryLogInfoBase implements historyLog {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
private String id;
|
||||||
private DBType dbType;
|
private DBType dbType;
|
||||||
private String timestamp;
|
private LocalDateTime timestamp;
|
||||||
private EDBOperationType operationType;
|
private EDBOperationType operationType;
|
||||||
private HISTORYTYPEDETAIL historyType;
|
private HISTORYTYPEDETAIL historyType;
|
||||||
private String tableName;
|
private String tableName;
|
||||||
@@ -27,7 +31,7 @@ public class HistoryLogInfoBase implements historyLog {
|
|||||||
private String userIP;
|
private String userIP;
|
||||||
|
|
||||||
public HistoryLogInfoBase(DBType dbType,
|
public HistoryLogInfoBase(DBType dbType,
|
||||||
String timestamp,
|
LocalDateTime timestamp,
|
||||||
EDBOperationType operationType,
|
EDBOperationType operationType,
|
||||||
HISTORYTYPEDETAIL historyType,
|
HISTORYTYPEDETAIL historyType,
|
||||||
String tableName,
|
String tableName,
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import lombok.Getter;
|
|||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
import org.springframework.data.mongodb.core.mapping.Document;
|
import org.springframework.data.mongodb.core.mapping.Document;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@@ -19,7 +20,7 @@ public class MysqlHistoryLogInfo extends HistoryLogInfoBase {
|
|||||||
private Object data;
|
private Object data;
|
||||||
|
|
||||||
public MysqlHistoryLogInfo(EDBOperationType operationType, HISTORYTYPEDETAIL historyType, String tableName, String message, String tranId, List<FieldChange> changed, String userId, String userIP, Object data) {
|
public MysqlHistoryLogInfo(EDBOperationType operationType, HISTORYTYPEDETAIL historyType, String tableName, String message, String tranId, List<FieldChange> changed, String userId, String userIP, Object data) {
|
||||||
super(DBType.MYSQL, DateUtils.nowDateTime(), operationType, historyType, tableName, message, tranId, changed, userId, userIP);
|
super(DBType.MYSQL, LocalDateTime.now(), operationType, historyType, tableName, message, tranId, changed, userId, userIP);
|
||||||
|
|
||||||
this.data = data;
|
this.data = data;
|
||||||
// this.data = deepCopy(data);
|
// this.data = deepCopy(data);
|
||||||
|
|||||||
@@ -53,6 +53,31 @@ public class BusinessLogService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Async
|
||||||
|
public CompletableFuture<String> saveLog(LogCategory category, LogStatus status, LocalDateTime logTime,
|
||||||
|
String message, Object domain, String worker, String workerIp, String processId, LogAction action) {
|
||||||
|
try {
|
||||||
|
BusinessLog businessLog = BusinessLog.builder()
|
||||||
|
.logTime(logTime)
|
||||||
|
.category(category)
|
||||||
|
.action(action)
|
||||||
|
.procId(processId)
|
||||||
|
.status(status)
|
||||||
|
.worker(worker == null || worker.isEmpty() ? CommonConstants.SYSTEM : worker)
|
||||||
|
.workerIp(workerIp == null || workerIp.isEmpty() ? "" : workerIp)
|
||||||
|
.message(message)
|
||||||
|
.domain(domain)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
BusinessLog saved = businessLogRepository.save(businessLog);
|
||||||
|
log.debug("Business log saved: {}", saved.getId());
|
||||||
|
return CompletableFuture.completedFuture(saved.getId());
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("Failed to save business log: {}", e.getMessage(), e);
|
||||||
|
return CompletableFuture.failedFuture(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// DYNAMODB 로그
|
// DYNAMODB 로그
|
||||||
public CompletableFuture<String> logDynamodb(String tableName, EDBOperationType operationType, String userId, String userIP,
|
public CompletableFuture<String> logDynamodb(String tableName, EDBOperationType operationType, String userId, String userIP,
|
||||||
DynamoDBDocBase docData, LogStatus status, List<FieldChange> changes, String message, String tranId) {
|
DynamoDBDocBase docData, LogStatus status, List<FieldChange> changes, String message, String tranId) {
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import com.caliverse.admin.global.common.constants.CommonConstants;
|
|||||||
import com.caliverse.admin.global.common.utils.CommonUtils;
|
import com.caliverse.admin.global.common.utils.CommonUtils;
|
||||||
import com.caliverse.admin.global.component.manager.TransactionIdManager;
|
import com.caliverse.admin.global.component.manager.TransactionIdManager;
|
||||||
import com.caliverse.admin.mongodb.ChangeDetector;
|
import com.caliverse.admin.mongodb.ChangeDetector;
|
||||||
import com.caliverse.admin.mongodb.domain.DynamodbHistoryLogInfo;
|
|
||||||
import com.caliverse.admin.mongodb.entity.EDBOperationType;
|
import com.caliverse.admin.mongodb.entity.EDBOperationType;
|
||||||
import com.caliverse.admin.mongodb.repository.DynamodbHistoryLogRepository;
|
import com.caliverse.admin.mongodb.repository.DynamodbHistoryLogRepository;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
@@ -28,7 +27,6 @@ public class DynamodbHistoryLogService {
|
|||||||
private String tableName;
|
private String tableName;
|
||||||
|
|
||||||
private final TransactionIdManager transactionIdManager;
|
private final TransactionIdManager transactionIdManager;
|
||||||
private final DynamodbHistoryLogRepository dynamodbHistoryLogRepository;
|
|
||||||
private final BusinessLogService businessLogService;
|
private final BusinessLogService businessLogService;
|
||||||
|
|
||||||
public void insertHistoryLog(LogStatus logStatus,
|
public void insertHistoryLog(LogStatus logStatus,
|
||||||
@@ -117,87 +115,4 @@ public class DynamodbHistoryLogService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void insertHistoryLog(HISTORYTYPEDETAIL historyType,
|
|
||||||
String message,
|
|
||||||
DynamoDBDocBase metadata
|
|
||||||
){
|
|
||||||
|
|
||||||
List<FieldChange> changes = ChangeDetector.detectInsertChanges(metadata);
|
|
||||||
|
|
||||||
if(!changes.isEmpty()) {
|
|
||||||
DynamodbHistoryLogInfo historyLog = new DynamodbHistoryLogInfo(
|
|
||||||
EDBOperationType.INSERT,
|
|
||||||
historyType,
|
|
||||||
tableName,
|
|
||||||
message,
|
|
||||||
transactionIdManager.getCurrentTransactionId(),
|
|
||||||
changes,
|
|
||||||
CommonUtils.getAdmin() == null ? CommonConstants.SYSTEM : CommonUtils.getAdmin().getEmail(),
|
|
||||||
CommonUtils.getClientIp() == null ? CommonConstants.SYSTEM : CommonUtils.getClientIp(),
|
|
||||||
metadata
|
|
||||||
);
|
|
||||||
|
|
||||||
dynamodbHistoryLogRepository.save(historyLog);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void updateHistoryLog(HISTORYTYPEDETAIL historyType,
|
|
||||||
String message,
|
|
||||||
DynamoDBDocBase beforeMetadata,
|
|
||||||
DynamoDBDocBase afterMetadata
|
|
||||||
){
|
|
||||||
List<FieldChange> changes = ChangeDetector.detectChanges(
|
|
||||||
beforeMetadata,
|
|
||||||
afterMetadata
|
|
||||||
);
|
|
||||||
|
|
||||||
if(!changes.isEmpty()) {
|
|
||||||
DynamodbHistoryLogInfo historyLog = new DynamodbHistoryLogInfo(
|
|
||||||
EDBOperationType.UPDATE,
|
|
||||||
historyType,
|
|
||||||
tableName,
|
|
||||||
message,
|
|
||||||
transactionIdManager.getCurrentTransactionId(),
|
|
||||||
changes,
|
|
||||||
CommonUtils.getAdmin() == null ? CommonConstants.SYSTEM : CommonUtils.getAdmin().getEmail(),
|
|
||||||
CommonUtils.getClientIp() == null ? CommonConstants.SYSTEM : CommonUtils.getClientIp(),
|
|
||||||
afterMetadata
|
|
||||||
);
|
|
||||||
|
|
||||||
dynamodbHistoryLogRepository.save(historyLog);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void deleteHistoryLog(HISTORYTYPEDETAIL historyType,
|
|
||||||
String message,
|
|
||||||
DynamoDBDocBase metadata
|
|
||||||
){
|
|
||||||
|
|
||||||
List<FieldChange> changes = ChangeDetector.detectDeleteChanges(metadata);
|
|
||||||
|
|
||||||
if(!changes.isEmpty()) {
|
|
||||||
DynamodbHistoryLogInfo historyLog = new DynamodbHistoryLogInfo(
|
|
||||||
EDBOperationType.DELETE,
|
|
||||||
historyType,
|
|
||||||
tableName,
|
|
||||||
message,
|
|
||||||
transactionIdManager.getCurrentTransactionId(),
|
|
||||||
changes,
|
|
||||||
CommonUtils.getAdmin() == null ? CommonConstants.SYSTEM : CommonUtils.getAdmin().getEmail(),
|
|
||||||
CommonUtils.getClientIp() == null ? CommonConstants.SYSTEM : CommonUtils.getClientIp(),
|
|
||||||
metadata
|
|
||||||
);
|
|
||||||
|
|
||||||
dynamodbHistoryLogRepository.save(historyLog);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<DynamodbHistoryLogInfo> getAllHistoryLogs() {
|
|
||||||
return dynamodbHistoryLogRepository.findAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Optional<DynamodbHistoryLogInfo> getHistoryLogById(String id) {
|
|
||||||
return dynamodbHistoryLogRepository.findById(id);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import com.caliverse.admin.global.common.exception.RestApiException;
|
|||||||
import com.caliverse.admin.global.common.utils.CommonUtils;
|
import com.caliverse.admin.global.common.utils.CommonUtils;
|
||||||
import com.caliverse.admin.global.component.manager.TransactionIdManager;
|
import com.caliverse.admin.global.component.manager.TransactionIdManager;
|
||||||
import com.caliverse.admin.mongodb.ChangeDetector;
|
import com.caliverse.admin.mongodb.ChangeDetector;
|
||||||
import com.caliverse.admin.mongodb.domain.MysqlHistoryLogInfo;
|
|
||||||
import com.caliverse.admin.mongodb.entity.EDBOperationType;
|
import com.caliverse.admin.mongodb.entity.EDBOperationType;
|
||||||
import com.caliverse.admin.mongodb.repository.MysqlHistoryLogRepository;
|
import com.caliverse.admin.mongodb.repository.MysqlHistoryLogRepository;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
@@ -151,12 +150,4 @@ public class MysqlHistoryLogService {
|
|||||||
throw new RestApiException(CommonCode.ERROR.getHttpStatus(), ErrorCode.ERROR_HISTORY_SAVE.getMessage());
|
throw new RestApiException(CommonCode.ERROR.getHttpStatus(), ErrorCode.ERROR_HISTORY_SAVE.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<MysqlHistoryLogInfo> getAllHistoryLogs() {
|
|
||||||
return mysqlHistoryLogRepository.findAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Optional<MysqlHistoryLogInfo> getHistoryLogById(String id) {
|
|
||||||
return mysqlHistoryLogRepository.findById(id);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,52 @@
|
|||||||
|
package com.caliverse.admin.mongodb.service;
|
||||||
|
|
||||||
|
import com.caliverse.admin.domain.entity.log.LogAction;
|
||||||
|
import com.caliverse.admin.domain.entity.log.LogCategory;
|
||||||
|
import com.caliverse.admin.domain.request.HistoryRequest;
|
||||||
|
import com.caliverse.admin.global.common.constants.AdminConstants;
|
||||||
|
import com.caliverse.admin.mongodb.entity.DBType;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.bson.Document;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
|
import org.springframework.data.mongodb.core.MongoTemplate;
|
||||||
|
import org.springframework.data.mongodb.core.aggregation.Aggregation;
|
||||||
|
import org.springframework.data.mongodb.core.aggregation.AggregationOperation;
|
||||||
|
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
|
||||||
|
import org.springframework.data.mongodb.core.query.Criteria;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@Service
|
||||||
|
@Slf4j
|
||||||
|
public class OldHistoryLogService {
|
||||||
|
@Autowired
|
||||||
|
@Qualifier("mongoIndicatorTemplate")
|
||||||
|
private MongoTemplate mongoTemplate;
|
||||||
|
|
||||||
|
public <T> List<T> loadHistoryData(DBType dbType, Class<T> class1) {
|
||||||
|
List<AggregationOperation> operations = new ArrayList<>();
|
||||||
|
|
||||||
|
operations.add(context ->
|
||||||
|
new Document("$match",
|
||||||
|
new Document("dbType", dbType.toString())
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
operations.add(context ->
|
||||||
|
new Document("$sort",
|
||||||
|
new Document(AdminConstants.MONGO_DB_KEY_TIMESTAMP, -1)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
Aggregation aggregation = Aggregation.newAggregation(operations);
|
||||||
|
log.info("loadHistoryData Query: {}", aggregation);
|
||||||
|
|
||||||
|
AggregationResults<T> results = mongoTemplate.aggregate(aggregation, AdminConstants.MONGO_DB_COLLECTION_HISTORY_LOG, class1);
|
||||||
|
return results.getMappedResults();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,146 @@
|
|||||||
|
package com.caliverse.admin.scheduler;
|
||||||
|
|
||||||
|
import com.caliverse.admin.domain.entity.HISTORYTYPEDETAIL;
|
||||||
|
import com.caliverse.admin.domain.entity.InGame;
|
||||||
|
import com.caliverse.admin.domain.entity.Mail;
|
||||||
|
import com.caliverse.admin.domain.entity.log.LogAction;
|
||||||
|
import com.caliverse.admin.domain.entity.log.LogCategory;
|
||||||
|
import com.caliverse.admin.domain.entity.log.LogStatus;
|
||||||
|
import com.caliverse.admin.global.common.annotation.BusinessProcess;
|
||||||
|
import com.caliverse.admin.global.common.utils.CommonUtils;
|
||||||
|
import com.caliverse.admin.global.component.manager.BusinessProcessIdManager;
|
||||||
|
import com.caliverse.admin.mongodb.domain.*;
|
||||||
|
import com.caliverse.admin.mongodb.entity.DBType;
|
||||||
|
import com.caliverse.admin.mongodb.repository.DynamodbHistoryLogRepository;
|
||||||
|
import com.caliverse.admin.mongodb.service.BusinessLogService;
|
||||||
|
import com.caliverse.admin.mongodb.service.OldHistoryLogService;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.ScheduledFuture;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@Slf4j
|
||||||
|
public class MigrationService {
|
||||||
|
private final OldHistoryLogService oldHistoryLogService;
|
||||||
|
private final BusinessLogService businessLogService;
|
||||||
|
private final BusinessProcessIdManager processIdManager;
|
||||||
|
@Autowired
|
||||||
|
private DynamodbHistoryLogRepository dynamodbHistoryLogRepository;
|
||||||
|
|
||||||
|
public MigrationService(OldHistoryLogService oldHistoryLogService, BusinessLogService businessLogService, BusinessProcessIdManager processIdManager) {
|
||||||
|
this.oldHistoryLogService = oldHistoryLogService;
|
||||||
|
this.businessLogService = businessLogService;
|
||||||
|
this.processIdManager = processIdManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
@BusinessProcess(action = LogAction.UNKNOWN)
|
||||||
|
public void migrationHistory() {
|
||||||
|
List<DynamodbHistoryLogInfo> dynamodbHistoryLogInfos = oldHistoryLogService.loadHistoryData(DBType.DYNAMODB, DynamodbHistoryLogInfo.class);
|
||||||
|
|
||||||
|
dynamodbHistoryLogInfos.forEach(history -> {
|
||||||
|
LogAction action = getLogAction(history.getHistoryType());
|
||||||
|
|
||||||
|
DynamodbDomain domain = DynamodbDomain.builder()
|
||||||
|
.tranId(history.getTranId())
|
||||||
|
.tableName(history.getTableName())
|
||||||
|
.operationType(history.getOperationType())
|
||||||
|
.changed(history.getChanged())
|
||||||
|
.data(history.getData())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
CompletableFuture<String> logFuture = businessLogService.saveLog(
|
||||||
|
LogCategory.DYNAMODB,
|
||||||
|
LogStatus.SUCCESS,
|
||||||
|
history.getTimestamp(),
|
||||||
|
"",
|
||||||
|
domain,
|
||||||
|
history.getUserId(),
|
||||||
|
history.getUserIP(),
|
||||||
|
processIdManager.getCurrentProcessId(),
|
||||||
|
action
|
||||||
|
);
|
||||||
|
|
||||||
|
logFuture.whenComplete((result, throwable) -> {
|
||||||
|
if (throwable == null) {
|
||||||
|
try {
|
||||||
|
dynamodbHistoryLogRepository.deleteById(history.getId());
|
||||||
|
log.debug("DynamoDB 히스토리 마이그레이션 및 삭제 완료: tranId={}", history.getTranId());
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("DynamoDB 히스토리 삭제 실패: tranId={}, error={}", history.getTranId(), e.getMessage());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.error("DynamoDB 히스토리 마이그레이션 실패: tranId={}", history.getTranId());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
List<MysqlHistoryLogInfo> mysqlHistoryLogInfos = oldHistoryLogService.loadHistoryData(DBType.MYSQL, MysqlHistoryLogInfo.class);
|
||||||
|
mysqlHistoryLogInfos.forEach(history -> {
|
||||||
|
LogAction action = getLogAction(history.getHistoryType());
|
||||||
|
|
||||||
|
MariadbDomain domain = MariadbDomain.builder()
|
||||||
|
.tranId(history.getTranId())
|
||||||
|
.tableName(history.getTableName())
|
||||||
|
.operationType(history.getOperationType())
|
||||||
|
.changed(history.getChanged())
|
||||||
|
.data(history.getData())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
CompletableFuture<String> logFuture = businessLogService.saveLog(
|
||||||
|
LogCategory.DYNAMODB,
|
||||||
|
LogStatus.SUCCESS,
|
||||||
|
history.getTimestamp(),
|
||||||
|
"",
|
||||||
|
domain,
|
||||||
|
history.getUserId(),
|
||||||
|
history.getUserIP(),
|
||||||
|
processIdManager.getCurrentProcessId(),
|
||||||
|
action
|
||||||
|
);
|
||||||
|
|
||||||
|
logFuture.whenComplete((result, throwable) -> {
|
||||||
|
if (throwable == null) {
|
||||||
|
try {
|
||||||
|
dynamodbHistoryLogRepository.deleteById(history.getId());
|
||||||
|
log.debug("Mysql 히스토리 마이그레이션 및 삭제 완료: tranId={}", history.getTranId());
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("Mysql 히스토리 삭제 실패: tranId={}, error={}", history.getTranId(), e.getMessage());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.error("Mysql 히스토리 마이그레이션 실패: tranId={}", history.getTranId());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private LogAction getLogAction(HISTORYTYPEDETAIL historyType) {
|
||||||
|
if(historyType.equals(HISTORYTYPEDETAIL.NOTICE_ADD)){
|
||||||
|
return LogAction.NOTICE;
|
||||||
|
}else if(historyType.equals(HISTORYTYPEDETAIL.BATTLE_EVENT_ADD) || historyType.equals(HISTORYTYPEDETAIL.BATTLE_EVENT_UPDATE)){
|
||||||
|
return LogAction.BATTLE_EVENT;
|
||||||
|
}else if(historyType.equals(HISTORYTYPEDETAIL.EVENT_ADD) || historyType.equals(HISTORYTYPEDETAIL.EVENT_UPDATE)
|
||||||
|
|| historyType.equals(HISTORYTYPEDETAIL.EVENT_DELETE) || historyType.equals(HISTORYTYPEDETAIL.SYSTEM_META_MAIL_DELETE)){
|
||||||
|
return LogAction.EVENT;
|
||||||
|
}else if(historyType.equals(HISTORYTYPEDETAIL.MAIL_ADD) || historyType.equals(HISTORYTYPEDETAIL.MAIL_DELETE) || historyType.equals(HISTORYTYPEDETAIL.MAIL_UPDATE)){
|
||||||
|
return LogAction.MAIL;
|
||||||
|
}else if(historyType.equals(HISTORYTYPEDETAIL.ITEM_DELETE) || historyType.equals(HISTORYTYPEDETAIL.ITEM_UPDATE)){
|
||||||
|
return LogAction.ITEM;
|
||||||
|
}else if(historyType.equals(HISTORYTYPEDETAIL.LAND_OWNER_CHANGE_ADD) || historyType.equals(HISTORYTYPEDETAIL.LAND_OWNER_CHANGE_MAIL)){
|
||||||
|
return LogAction.LAND_OWNER_CHANGE;
|
||||||
|
}else if(historyType.equals(HISTORYTYPEDETAIL.NICKNAME_REGISTRY_ADD) || historyType.equals(HISTORYTYPEDETAIL.NICKNAME_REGISTRY_DELETE) || historyType.equals(HISTORYTYPEDETAIL.NICKNAME_UPDATE)){
|
||||||
|
return LogAction.NICKNAME_CHANGE;
|
||||||
|
}else if(historyType.equals(HISTORYTYPEDETAIL.LAND_DESC_INITIALIZE)){
|
||||||
|
return LogAction.DATA_INIT;
|
||||||
|
}else if(historyType.equals(HISTORYTYPEDETAIL.MENU_BANNER_ADD) || historyType.equals(HISTORYTYPEDETAIL.MENU_BANNER_UPDATE)){
|
||||||
|
return LogAction.BANNER;
|
||||||
|
}
|
||||||
|
return LogAction.UNKNOWN;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,6 +8,7 @@ import com.caliverse.admin.logs.logservice.indicators.*;
|
|||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.boot.CommandLineRunner;
|
import org.springframework.boot.CommandLineRunner;
|
||||||
import org.springframework.core.annotation.Order;
|
import org.springframework.core.annotation.Order;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
@@ -33,52 +34,248 @@ public class OneTimeSchedule implements CommandLineRunner {
|
|||||||
@Autowired private IndicatorsUserLoginService userLoginService;
|
@Autowired private IndicatorsUserLoginService userLoginService;
|
||||||
@Autowired private IndicatorsCurrencyService currencyService;
|
@Autowired private IndicatorsCurrencyService currencyService;
|
||||||
@Autowired private IndicatorsItemService itemService;
|
@Autowired private IndicatorsItemService itemService;
|
||||||
|
@Autowired private IndicatorsSnapshotService snapshotService;
|
||||||
|
|
||||||
@Autowired private DynamodbService dynamodbService;
|
@Autowired private DynamodbService dynamodbService;
|
||||||
|
@Autowired private MigrationService migrationService;
|
||||||
|
|
||||||
|
@Value("${batch.delay.between.dates}") // 날짜 간 지연시간
|
||||||
|
private long delayBetweenDates;
|
||||||
|
|
||||||
|
@Value("${batch.delay.between.services}") // 서비스 간 지연시간
|
||||||
|
private long delayBetweenServices;
|
||||||
|
|
||||||
|
@Value("${batch.chunk.size}") // 한 번에 처리할 일수
|
||||||
|
private int chunkSize;
|
||||||
|
|
||||||
|
@Value("${batch.delay.between.chunks}") // 청크 간 지연시간
|
||||||
|
private long delayBetweenChunks;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run(String... args) throws Exception {
|
public void run(String... args) throws Exception {
|
||||||
log.info("=== OneTimeSchedule starting ===");
|
log.info("=== OneTimeSchedule starting ===");
|
||||||
try{
|
try{
|
||||||
log.info("Starting OneTimeSchedule");
|
|
||||||
// dynamodbService.saveUserMoney(); //유저별 재화 데이터 저장
|
|
||||||
|
|
||||||
LocalDate startDate = LocalDate.of(2024, 8, 28);
|
LocalDate startDate = LocalDate.of(2024, 8, 28);
|
||||||
// LocalDate startDate = LocalDate.of(2025, 4, 1);
|
// LocalDate startDate = LocalDate.of(2025, 7, 1);
|
||||||
// LocalDate currentDate = LocalDate.of(2025, 5, 1);
|
// LocalDate currentDate = LocalDate.of(2025, 5, 1);
|
||||||
LocalDate currentDate = LocalDate.now();
|
LocalDate currentDate = LocalDate.now();
|
||||||
//
|
//
|
||||||
log.info("Processing dates from {} to {}", startDate, currentDate);
|
log.info("Processing dates from {} to {}", startDate, currentDate);
|
||||||
|
|
||||||
for (LocalDate date = startDate; !date.isAfter(currentDate); date = date.plusDays(1)) {
|
|
||||||
log.info("Processing date: {}", date);
|
|
||||||
|
|
||||||
StartEndTime dayStartEndTime = LogServiceHelper.getCurrentLogSearchEndTime(date, AdminConstants.STAT_DAY_NUM);
|
LocalDate processDate = startDate;
|
||||||
StartEndTime weekStartEndTime = LogServiceHelper.getCurrentLogSearchEndTime(date, AdminConstants.STAT_WEEK_NUM);
|
int processedDates = 0;
|
||||||
StartEndTime monthStartEndTime = LogServiceHelper.getCurrentLogSearchEndTime(date, AdminConstants.STAT_MONTH_NUM);
|
|
||||||
|
|
||||||
log.info("Date: {}, StartTime: {}, EndTime: {}", date, dayStartEndTime.getStartTime(), dayStartEndTime.getEndTime());
|
migrationService.migrationHistory();
|
||||||
|
|
||||||
// itemService.collectItem(dayStartEndTime.getStartTime(), dayStartEndTime.getEndTime());
|
// while (!processDate.isAfter(currentDate)) {
|
||||||
// userCreateService.collectUserCreate(dayStartEndTime.getStartTime(), dayStartEndTime.getEndTime());
|
// LocalDate chunkEndDate = processDate.plusDays(chunkSize - 1);
|
||||||
// userLoginService.collectUserLogin(dayStartEndTime.getStartTime(), dayStartEndTime.getEndTime());
|
// if (chunkEndDate.isAfter(currentDate)) {
|
||||||
|
// chunkEndDate = currentDate;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// log.info("Processing chunk: {} to {}", processDate, chunkEndDate);
|
||||||
|
//
|
||||||
|
// // 청크 단위로 처리
|
||||||
|
// for (LocalDate date = processDate; !date.isAfter(chunkEndDate); date = date.plusDays(1)) {
|
||||||
|
// processDateWithLoadBalancing(date);
|
||||||
|
// processedDates++;
|
||||||
|
//
|
||||||
|
// // 날짜 간 지연
|
||||||
|
// if (!date.equals(chunkEndDate)) {
|
||||||
|
// Thread.sleep(delayBetweenDates);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// processDate = chunkEndDate.plusDays(1);
|
||||||
|
//
|
||||||
|
// // 청크 간 큰 지연 (시스템 리소스 회복 시간)
|
||||||
|
// if (!processDate.isAfter(currentDate)) {
|
||||||
|
// log.info("Chunk completed. Waiting {} ms before next chunk...", delayBetweenChunks);
|
||||||
|
// Thread.sleep(delayBetweenChunks);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
// currencyService.collectCurrency(dayStartEndTime.getStartTime(), dayStartEndTime.getEndTime());
|
// local, dev 용
|
||||||
// metaverseServerService.collectMetaverseServerCount(dayStartEndTime.getStartTime(), dayStartEndTime.getEndTime(), 13);
|
// for (LocalDate date = startDate; !date.isAfter(currentDate); date = date.plusDays(1)) {
|
||||||
// capacityService.collectDBCapacity(dayStartEndTime.getStartTime(), dayStartEndTime.getEndTime()); //체크
|
// log.info("Processing date: {}", date);
|
||||||
// dauService.collectDailyActiveUser(dayStartEndTime.getStartTime(), dayStartEndTime.getEndTime()); //체크
|
//
|
||||||
// wauService.collectWeeklyActiveUser(weekStartEndTime.getStartTime(), weekStartEndTime.getEndTime()); //체크
|
// StartEndTime dayStartEndTime = LogServiceHelper.getCurrentLogSearchEndTime(date, AdminConstants.STAT_DAY_NUM);
|
||||||
// mauService.collectMonthlyActiveUser(monthStartEndTime.getStartTime(), monthStartEndTime.getEndTime()); //체크
|
// StartEndTime weekStartEndTime = LogServiceHelper.getCurrentLogSearchEndTime(date, AdminConstants.STAT_WEEK_NUM);
|
||||||
// mcuService.collectMaxCountUser(dayStartEndTime.getStartTime(), dayStartEndTime.getEndTime()); //체크
|
// StartEndTime monthStartEndTime = LogServiceHelper.getCurrentLogSearchEndTime(date, AdminConstants.STAT_MONTH_NUM);
|
||||||
// nruService.collectCharacterCreateCount(dayStartEndTime.getStartTime(), dayStartEndTime.getEndTime()); //체크
|
//
|
||||||
// playTimeService.collectUserPlayTime(dayStartEndTime.getStartTime(), dayStartEndTime.getEndTime()); //체크
|
// log.info("Date: {}, StartTime: {}, EndTime: {}", date, dayStartEndTime.getStartTime(), dayStartEndTime.getEndTime());
|
||||||
// dglcService.collectDailyGameLoginCount(dayStartEndTime.getStartTime(), dayStartEndTime.getEndTime()); //체크
|
//
|
||||||
// ugqCreateService.collectUGQCreateCount(dayStartEndTime.getStartTime(), dayStartEndTime.getEndTime()); //체크
|
// snapshotService.collectSnapshot(dayStartEndTime.getStartTime(), dayStartEndTime.getEndTime());
|
||||||
}
|
//// itemService.collectItem(dayStartEndTime.getStartTime(), dayStartEndTime.getEndTime());
|
||||||
|
//// userCreateService.collectUserCreate(dayStartEndTime.getStartTime(), dayStartEndTime.getEndTime());
|
||||||
|
//// userLoginService.collectUserLogin(dayStartEndTime.getStartTime(), dayStartEndTime.getEndTime());
|
||||||
|
//// currencyService.collectCurrency(dayStartEndTime.getStartTime(), dayStartEndTime.getEndTime());
|
||||||
|
//
|
||||||
|
//// metaverseServerService.collectMetaverseServerCount(dayStartEndTime.getStartTime(), dayStartEndTime.getEndTime(), 13);
|
||||||
|
//// capacityService.collectDBCapacity(dayStartEndTime.getStartTime(), dayStartEndTime.getEndTime()); //체크
|
||||||
|
//// dauService.collectDailyActiveUser(dayStartEndTime.getStartTime(), dayStartEndTime.getEndTime()); //체크
|
||||||
|
//// wauService.collectWeeklyActiveUser(weekStartEndTime.getStartTime(), weekStartEndTime.getEndTime()); //체크
|
||||||
|
//// mauService.collectMonthlyActiveUser(monthStartEndTime.getStartTime(), monthStartEndTime.getEndTime()); //체크
|
||||||
|
//// mcuService.collectMaxCountUser(dayStartEndTime.getStartTime(), dayStartEndTime.getEndTime()); //체크
|
||||||
|
//// nruService.collectCharacterCreateCount(dayStartEndTime.getStartTime(), dayStartEndTime.getEndTime()); //체크
|
||||||
|
//// playTimeService.collectUserPlayTime(dayStartEndTime.getStartTime(), dayStartEndTime.getEndTime()); //체크
|
||||||
|
//// dglcService.collectDailyGameLoginCount(dayStartEndTime.getStartTime(), dayStartEndTime.getEndTime()); //체크
|
||||||
|
//// ugqCreateService.collectUGQCreateCount(dayStartEndTime.getStartTime(), dayStartEndTime.getEndTime()); //체크
|
||||||
|
// }
|
||||||
|
|
||||||
log.info("=== OneTimeSchedule completed successfully ===");
|
log.info("=== OneTimeSchedule completed successfully ===");
|
||||||
}catch (Exception e){
|
}catch (Exception e){
|
||||||
log.error("OneTimeSchedule execution failed", e);
|
log.error("OneTimeSchedule execution failed", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void processDateWithLoadBalancing(LocalDate date) throws InterruptedException {
|
||||||
|
log.info("Processing date: {}", date);
|
||||||
|
|
||||||
|
StartEndTime dayStartEndTime = LogServiceHelper.getCurrentLogSearchEndTime(date, AdminConstants.STAT_DAY_NUM);
|
||||||
|
StartEndTime weekStartEndTime = LogServiceHelper.getCurrentLogSearchEndTime(date, AdminConstants.STAT_WEEK_NUM);
|
||||||
|
StartEndTime monthStartEndTime = LogServiceHelper.getCurrentLogSearchEndTime(date, AdminConstants.STAT_MONTH_NUM);
|
||||||
|
|
||||||
|
log.info("Date: {}, StartTime: {}, EndTime: {}", date, dayStartEndTime.getStartTime(), dayStartEndTime.getEndTime());
|
||||||
|
|
||||||
|
// 1. 가장 부하가 적은 서비스부터 실행
|
||||||
|
// 아이템 DW
|
||||||
|
executeWithDelay(() -> {
|
||||||
|
try {
|
||||||
|
itemService.collectItem(dayStartEndTime.getStartTime(), dayStartEndTime.getEndTime());
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("Error in itemService for date: {}", date, e);
|
||||||
|
}
|
||||||
|
}, "itemService");
|
||||||
|
|
||||||
|
// 자산 DW
|
||||||
|
executeWithDelay(() -> {
|
||||||
|
try {
|
||||||
|
snapshotService.collectSnapshot(dayStartEndTime.getStartTime(), dayStartEndTime.getEndTime());
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("Error in snapshotService for date: {}", date, e);
|
||||||
|
}
|
||||||
|
}, "snapshotService");
|
||||||
|
|
||||||
|
// 유저 생성 DW
|
||||||
|
executeWithDelay(() -> {
|
||||||
|
try {
|
||||||
|
userCreateService.collectUserCreate(dayStartEndTime.getStartTime(), dayStartEndTime.getEndTime());
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("Error in userCreateService for date: {}", date, e);
|
||||||
|
}
|
||||||
|
}, "userCreateService");
|
||||||
|
|
||||||
|
// 유저 로그인 DW
|
||||||
|
executeWithDelay(() -> {
|
||||||
|
try {
|
||||||
|
userLoginService.collectUserLogin(dayStartEndTime.getStartTime(), dayStartEndTime.getEndTime());
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("Error in userLoginService for date: {}", date, e);
|
||||||
|
}
|
||||||
|
}, "userLoginService");
|
||||||
|
|
||||||
|
// 재화 DW
|
||||||
|
// executeWithDelay(() -> {
|
||||||
|
// try {
|
||||||
|
// currencyService.collectCurrency(dayStartEndTime.getStartTime(), dayStartEndTime.getEndTime());
|
||||||
|
// } catch (Exception e) {
|
||||||
|
// log.error("Error in currencyService for date: {}", date, e);
|
||||||
|
// }
|
||||||
|
// }, "currencyService");
|
||||||
|
|
||||||
|
// 2. 중간 부하 서비스들
|
||||||
|
// executeWithDelay(() -> {
|
||||||
|
// try {
|
||||||
|
// dauService.collectDailyActiveUser(dayStartEndTime.getStartTime(), dayStartEndTime.getEndTime());
|
||||||
|
// } catch (Exception e) {
|
||||||
|
// log.error("Error in dauService for date: {}", date, e);
|
||||||
|
// }
|
||||||
|
// }, "dauService");
|
||||||
|
|
||||||
|
// executeWithDelay(() -> {
|
||||||
|
// try {
|
||||||
|
// mcuService.collectMaxCountUser(dayStartEndTime.getStartTime(), dayStartEndTime.getEndTime());
|
||||||
|
// } catch (Exception e) {
|
||||||
|
// log.error("Error in mcuService for date: {}", date, e);
|
||||||
|
// }
|
||||||
|
// }, "mcuService");
|
||||||
|
|
||||||
|
// executeWithDelay(() -> {
|
||||||
|
// try {
|
||||||
|
// nruService.collectCharacterCreateCount(dayStartEndTime.getStartTime(), dayStartEndTime.getEndTime());
|
||||||
|
// } catch (Exception e) {
|
||||||
|
// log.error("Error in nruService for date: {}", date, e);
|
||||||
|
// }
|
||||||
|
// }, "nruService");
|
||||||
|
|
||||||
|
// 3. 높은 부하 서비스들 (더 긴 지연시간)
|
||||||
|
// executeWithDelay(() -> {
|
||||||
|
// try {
|
||||||
|
// playTimeService.collectUserPlayTime(dayStartEndTime.getStartTime(), dayStartEndTime.getEndTime());
|
||||||
|
// } catch (Exception e) {
|
||||||
|
// log.error("Error in playTimeService for date: {}", date, e);
|
||||||
|
// }
|
||||||
|
// }, "playTimeService");
|
||||||
|
|
||||||
|
// executeWithDelay(() -> {
|
||||||
|
// try {
|
||||||
|
// currencyService.collectCurrency(dayStartEndTime.getStartTime(), dayStartEndTime.getEndTime());
|
||||||
|
// } catch (Exception e) {
|
||||||
|
// log.error("Error in currencyService for date: {}", date, e);
|
||||||
|
// }
|
||||||
|
// }, "currencyService");
|
||||||
|
|
||||||
|
// 4. 주간/월간 데이터는 특정 조건에서만 실행 (부하 최소화)
|
||||||
|
// if (shouldProcessWeeklyData(date)) {
|
||||||
|
// executeWithDelay(() -> {
|
||||||
|
// try {
|
||||||
|
// wauService.collectWeeklyActiveUser(weekStartEndTime.getStartTime(), weekStartEndTime.getEndTime());
|
||||||
|
// } catch (Exception e) {
|
||||||
|
// log.error("Error in wauService for date: {}", date, e);
|
||||||
|
// }
|
||||||
|
// }, "wauService");
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if (shouldProcessMonthlyData(date)) {
|
||||||
|
// executeWithDelay(() -> {
|
||||||
|
// try {
|
||||||
|
// mauService.collectMonthlyActiveUser(monthStartEndTime.getStartTime(), monthStartEndTime.getEndTime());
|
||||||
|
// } catch (Exception e) {
|
||||||
|
// log.error("Error in mauService for date: {}", date, e);
|
||||||
|
// }
|
||||||
|
// }, "mauService");
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
private void executeWithDelay(Runnable task, String serviceName) throws InterruptedException {
|
||||||
|
executeWithDelay(task, serviceName, delayBetweenServices);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void executeWithDelay(Runnable task, String serviceName, long customDelay) throws InterruptedException {
|
||||||
|
long startTime = System.currentTimeMillis();
|
||||||
|
|
||||||
|
try {
|
||||||
|
task.run();
|
||||||
|
long endTime = System.currentTimeMillis();
|
||||||
|
log.debug("{} completed in {} ms", serviceName, (endTime - startTime));
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("Error executing {}", serviceName, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 서비스별 커스텀 지연
|
||||||
|
log.debug("Waiting {} ms after {}", customDelay, serviceName);
|
||||||
|
Thread.sleep(customDelay);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean shouldProcessWeeklyData(LocalDate date) {
|
||||||
|
// 주의 마지막 날에만 주간 데이터 처리
|
||||||
|
return date.getDayOfWeek().getValue() == 7; // 일요일
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean shouldProcessMonthlyData(LocalDate date) {
|
||||||
|
// 월의 마지막 날에만 월간 데이터 처리
|
||||||
|
return date.equals(date.withDayOfMonth(date.lengthOfMonth()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user