diff --git a/src/main/java/com/caliverse/admin/mongodb/domain/DynamodbHistoryLogInfo.java b/src/main/java/com/caliverse/admin/mongodb/domain/DynamodbHistoryLogInfo.java index 3087398..e64217d 100644 --- a/src/main/java/com/caliverse/admin/mongodb/domain/DynamodbHistoryLogInfo.java +++ b/src/main/java/com/caliverse/admin/mongodb/domain/DynamodbHistoryLogInfo.java @@ -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 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; } diff --git a/src/main/java/com/caliverse/admin/mongodb/domain/HistoryLogInfoBase.java b/src/main/java/com/caliverse/admin/mongodb/domain/HistoryLogInfoBase.java index b88a78d..6df4182 100644 --- a/src/main/java/com/caliverse/admin/mongodb/domain/HistoryLogInfoBase.java +++ b/src/main/java/com/caliverse/admin/mongodb/domain/HistoryLogInfoBase.java @@ -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, diff --git a/src/main/java/com/caliverse/admin/mongodb/domain/MysqlHistoryLogInfo.java b/src/main/java/com/caliverse/admin/mongodb/domain/MysqlHistoryLogInfo.java index 86a1bfe..7edc5b3 100644 --- a/src/main/java/com/caliverse/admin/mongodb/domain/MysqlHistoryLogInfo.java +++ b/src/main/java/com/caliverse/admin/mongodb/domain/MysqlHistoryLogInfo.java @@ -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 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); diff --git a/src/main/java/com/caliverse/admin/mongodb/service/BusinessLogService.java b/src/main/java/com/caliverse/admin/mongodb/service/BusinessLogService.java index a032240..c3022e8 100644 --- a/src/main/java/com/caliverse/admin/mongodb/service/BusinessLogService.java +++ b/src/main/java/com/caliverse/admin/mongodb/service/BusinessLogService.java @@ -53,6 +53,31 @@ public class BusinessLogService { } } + @Async + public CompletableFuture 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 logDynamodb(String tableName, EDBOperationType operationType, String userId, String userIP, DynamoDBDocBase docData, LogStatus status, List changes, String message, String tranId) { diff --git a/src/main/java/com/caliverse/admin/mongodb/service/DynamodbHistoryLogService.java b/src/main/java/com/caliverse/admin/mongodb/service/DynamodbHistoryLogService.java index 2d5cd55..5f1365e 100644 --- a/src/main/java/com/caliverse/admin/mongodb/service/DynamodbHistoryLogService.java +++ b/src/main/java/com/caliverse/admin/mongodb/service/DynamodbHistoryLogService.java @@ -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 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 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 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 getAllHistoryLogs() { - return dynamodbHistoryLogRepository.findAll(); - } - - public Optional getHistoryLogById(String id) { - return dynamodbHistoryLogRepository.findById(id); - } } diff --git a/src/main/java/com/caliverse/admin/mongodb/service/MysqlHistoryLogService.java b/src/main/java/com/caliverse/admin/mongodb/service/MysqlHistoryLogService.java index 60de828..ecd6f9b 100644 --- a/src/main/java/com/caliverse/admin/mongodb/service/MysqlHistoryLogService.java +++ b/src/main/java/com/caliverse/admin/mongodb/service/MysqlHistoryLogService.java @@ -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 getAllHistoryLogs() { - return mysqlHistoryLogRepository.findAll(); - } - - public Optional getHistoryLogById(String id) { - return mysqlHistoryLogRepository.findById(id); - } } diff --git a/src/main/java/com/caliverse/admin/mongodb/service/OldHistoryLogService.java b/src/main/java/com/caliverse/admin/mongodb/service/OldHistoryLogService.java new file mode 100644 index 0000000..b7aa4dc --- /dev/null +++ b/src/main/java/com/caliverse/admin/mongodb/service/OldHistoryLogService.java @@ -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 List loadHistoryData(DBType dbType, Class class1) { + List 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 results = mongoTemplate.aggregate(aggregation, AdminConstants.MONGO_DB_COLLECTION_HISTORY_LOG, class1); + return results.getMappedResults(); + } +} diff --git a/src/main/java/com/caliverse/admin/scheduler/MigrationService.java b/src/main/java/com/caliverse/admin/scheduler/MigrationService.java new file mode 100644 index 0000000..650695c --- /dev/null +++ b/src/main/java/com/caliverse/admin/scheduler/MigrationService.java @@ -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 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 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 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 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; + } +} diff --git a/src/main/java/com/caliverse/admin/scheduler/OneTimeSchedule.java b/src/main/java/com/caliverse/admin/scheduler/OneTimeSchedule.java index 30cc1b3..659905d 100644 --- a/src/main/java/com/caliverse/admin/scheduler/OneTimeSchedule.java +++ b/src/main/java/com/caliverse/admin/scheduler/OneTimeSchedule.java @@ -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())); + } }