히스토리 마이그레이션

This commit is contained in:
2025-08-05 18:21:53 +09:00
parent b01c355492
commit 78b10e4f3a
9 changed files with 456 additions and 124 deletions

View File

@@ -10,6 +10,7 @@ import lombok.Getter;
import lombok.Setter;
import org.springframework.data.mongodb.core.mapping.Document;
import java.time.LocalDateTime;
import java.util.List;
@Getter
@@ -20,7 +21,7 @@ public class DynamodbHistoryLogInfo extends HistoryLogInfoBase {
private 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;
}

View File

@@ -7,16 +7,20 @@ import com.caliverse.admin.mongodb.entity.EDBOperationType;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.springframework.data.annotation.Id;
import java.time.LocalDateTime;
import java.util.List;
@Getter
@Setter
@NoArgsConstructor
public class HistoryLogInfoBase implements historyLog {
@Id
private String id;
private DBType dbType;
private String timestamp;
private LocalDateTime timestamp;
private EDBOperationType operationType;
private HISTORYTYPEDETAIL historyType;
private String tableName;
@@ -27,7 +31,7 @@ public class HistoryLogInfoBase implements historyLog {
private String userIP;
public HistoryLogInfoBase(DBType dbType,
String timestamp,
LocalDateTime timestamp,
EDBOperationType operationType,
HISTORYTYPEDETAIL historyType,
String tableName,

View File

@@ -9,6 +9,7 @@ import lombok.Getter;
import lombok.Setter;
import org.springframework.data.mongodb.core.mapping.Document;
import java.time.LocalDateTime;
import java.util.List;
@Getter
@@ -19,7 +20,7 @@ public class MysqlHistoryLogInfo extends HistoryLogInfoBase {
private 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 = deepCopy(data);

View File

@@ -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 로그
public CompletableFuture<String> logDynamodb(String tableName, EDBOperationType operationType, String userId, String userIP,
DynamoDBDocBase docData, LogStatus status, List<FieldChange> changes, String message, String tranId) {

View File

@@ -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.component.manager.TransactionIdManager;
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.repository.DynamodbHistoryLogRepository;
import lombok.RequiredArgsConstructor;
@@ -28,7 +27,6 @@ public class DynamodbHistoryLogService {
private String tableName;
private final TransactionIdManager transactionIdManager;
private final DynamodbHistoryLogRepository dynamodbHistoryLogRepository;
private final BusinessLogService businessLogService;
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);
}
}

View File

@@ -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.component.manager.TransactionIdManager;
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.repository.MysqlHistoryLogRepository;
import lombok.RequiredArgsConstructor;
@@ -151,12 +150,4 @@ public class MysqlHistoryLogService {
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);
}
}

View File

@@ -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();
}
}

View File

@@ -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;
}
}

View File

@@ -8,6 +8,7 @@ import com.caliverse.admin.logs.logservice.indicators.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.CommandLineRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
@@ -33,52 +34,248 @@ public class OneTimeSchedule implements CommandLineRunner {
@Autowired private IndicatorsUserLoginService userLoginService;
@Autowired private IndicatorsCurrencyService currencyService;
@Autowired private IndicatorsItemService itemService;
@Autowired private IndicatorsSnapshotService snapshotService;
@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
public void run(String... args) throws Exception {
log.info("=== OneTimeSchedule starting ===");
try{
log.info("Starting OneTimeSchedule");
// dynamodbService.saveUserMoney(); //유저별 재화 데이터 저장
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.now();
//
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);
StartEndTime weekStartEndTime = LogServiceHelper.getCurrentLogSearchEndTime(date, AdminConstants.STAT_WEEK_NUM);
StartEndTime monthStartEndTime = LogServiceHelper.getCurrentLogSearchEndTime(date, AdminConstants.STAT_MONTH_NUM);
LocalDate processDate = startDate;
int processedDates = 0;
log.info("Date: {}, StartTime: {}, EndTime: {}", date, dayStartEndTime.getStartTime(), dayStartEndTime.getEndTime());
migrationService.migrationHistory();
// itemService.collectItem(dayStartEndTime.getStartTime(), dayStartEndTime.getEndTime());
// userCreateService.collectUserCreate(dayStartEndTime.getStartTime(), dayStartEndTime.getEndTime());
// userLoginService.collectUserLogin(dayStartEndTime.getStartTime(), dayStartEndTime.getEndTime());
// while (!processDate.isAfter(currentDate)) {
// LocalDate chunkEndDate = processDate.plusDays(chunkSize - 1);
// 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());
// 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()); //체크
}
// local, dev 용
// 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);
// 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());
//
// 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 ===");
}catch (Exception 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()));
}
}