init
This commit is contained in:
@@ -0,0 +1,580 @@
|
||||
package com.caliverse.admin.scheduler;
|
||||
|
||||
import com.caliverse.admin.domain.RabbitMq.MessageHandlerService;
|
||||
import com.caliverse.admin.domain.RabbitMq.message.LanguageType;
|
||||
import com.caliverse.admin.domain.RabbitMq.message.MailItem;
|
||||
import com.caliverse.admin.domain.RabbitMq.message.OperationSystemMessage;
|
||||
import com.caliverse.admin.domain.entity.*;
|
||||
import com.caliverse.admin.dynamodb.entity.ELandAuctionResult;
|
||||
import com.caliverse.admin.dynamodb.entity.ELandAuctionState;
|
||||
import com.caliverse.admin.dynamodb.domain.atrrib.LandAuctionHighestBidUserAttrib;
|
||||
import com.caliverse.admin.dynamodb.domain.atrrib.LandAuctionRegistryAttrib;
|
||||
import com.caliverse.admin.domain.entity.redis.RedisLoginInfo;
|
||||
import com.caliverse.admin.domain.service.*;
|
||||
import com.caliverse.admin.dynamodb.entity.SystemMessage;
|
||||
import com.caliverse.admin.dynamodb.service.DynamodbService;
|
||||
import com.caliverse.admin.global.common.utils.CommonUtils;
|
||||
import com.caliverse.admin.global.common.utils.ExcelUtils;
|
||||
import com.caliverse.admin.global.common.utils.JsonUtils;
|
||||
import com.caliverse.admin.redis.service.RedisUserInfoService;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.node.ArrayNode;
|
||||
import lombok.*;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.caliverse.admin.global.common.utils.DynamodbUtil.getLanguageType;
|
||||
|
||||
@Service
|
||||
@AllArgsConstructor
|
||||
@Slf4j
|
||||
public class DynamicScheduler {
|
||||
|
||||
private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
|
||||
|
||||
private final MailService mailService;
|
||||
private final NoticeService noticeService;
|
||||
private final BlackListService blackListService;
|
||||
private final EventService eventService;
|
||||
private final LandService landService;
|
||||
private final UserGameSessionService userGameSessionService;
|
||||
private final ScheduleService schedulerService;
|
||||
private final RedisUserInfoService redisUserInfoService;
|
||||
private final MessageHandlerService messageHandlerService;
|
||||
private final HistoryService historyService;
|
||||
|
||||
private final DynamodbService dynamodbService;
|
||||
|
||||
private final ExcelUtils excelUtils;
|
||||
private final ObjectMapper objectMapper;
|
||||
|
||||
public void landAuctionSchedule(){
|
||||
List<LandAuction> auctionList = landService.getScheduleLandAuctionList();
|
||||
|
||||
try{
|
||||
auctionList.forEach(auction -> {
|
||||
LocalDateTime nowDate = LocalDateTime.now();
|
||||
LocalDateTime reservationDate = auction.getResvStartDt();
|
||||
LocalDateTime auctionStartDate = auction.getAuctionStartDt();
|
||||
LocalDateTime auctionEndDate = auction.getAuctionEndDt();
|
||||
|
||||
LandAuction.AUCTION_STATUS auction_status = auction.getStatus();
|
||||
|
||||
//예약 시작시간이 되지않으면 체크하지 않는다
|
||||
if(nowDate.isBefore(reservationDate)){
|
||||
return;
|
||||
}
|
||||
|
||||
//예약일때 경매 시작시간이 되지않았다면 체크하지 않는다
|
||||
if(auction_status.equals(LandAuction.AUCTION_STATUS.RESV_START) && nowDate.isBefore(auctionStartDate)){
|
||||
return;
|
||||
}
|
||||
|
||||
// 경매중일때 경매 종료시간이 되지않았다면 체크하지 않는다
|
||||
if(auction_status.equals(LandAuction.AUCTION_STATUS.AUCTION_START) && nowDate.isBefore(auctionEndDate)){
|
||||
return;
|
||||
}
|
||||
|
||||
Map<String,Object> map = new HashMap<>();
|
||||
map.put("id", auction.getId());
|
||||
|
||||
LandAuctionRegistryAttrib attrib = landService.getLandAuctionRegistryAttrib(auction.getLandId(), auction.getAuctionSeq());
|
||||
String dynamodb_auction_state = attrib.getAuctionState();
|
||||
LandAuction.AUCTION_STATUS change_status = null;
|
||||
if(dynamodb_auction_state.equals(ELandAuctionState.SCHEDULED.getName())){
|
||||
change_status = LandAuction.AUCTION_STATUS.RESV_START;
|
||||
map.put("status", change_status);
|
||||
landService.updateLandAuctionStatus(map);
|
||||
log.info("land_auction id: {} Status Schedule Changed", auction.getId());
|
||||
}else if(dynamodb_auction_state.equals(ELandAuctionState.STARTED.getName())){
|
||||
change_status = LandAuction.AUCTION_STATUS.AUCTION_START;
|
||||
map.put("status", change_status);
|
||||
landService.updateLandAuctionStatus(map);
|
||||
log.info("land_auction id: {} Status Auction Start Changed", auction.getId());
|
||||
}else if(dynamodb_auction_state.equals(ELandAuctionState.ENDED.getName())){
|
||||
String result = attrib.getAuctionResult();
|
||||
|
||||
if(result.equals(ELandAuctionResult.SUCCESSED.getName())){
|
||||
LandAuctionHighestBidUserAttrib bidUser = landService.getLandAuctionHighestUserAttrib(auction.getLandId(), auction.getAuctionSeq());
|
||||
if(bidUser == null) return;
|
||||
log.info("land_auction id: {} Status SUCCESS Changed. bidUser: {}", auction.getId(), bidUser);
|
||||
String close_dt = CommonUtils.convertIsoByDatetime(attrib.getProcessVersionTime());
|
||||
change_status = LandAuction.AUCTION_STATUS.AUCTION_END;
|
||||
map.put("status", change_status);
|
||||
map.put("closeEndDt", close_dt);
|
||||
map.put("bidderGuid", bidUser.getHighestBidUserGuid());
|
||||
map.put("bidderNickname", bidUser.getHighestBidUserNickname());
|
||||
map.put("closePrice", bidUser.getHighestBidPrice());
|
||||
landService.updateLandAuctionStatus(map);
|
||||
}else{
|
||||
if(result.equals(ELandAuctionResult.CANCELED.getName())){
|
||||
change_status = LandAuction.AUCTION_STATUS.CANCEL;
|
||||
map.put("status", change_status);
|
||||
}else{
|
||||
change_status = LandAuction.AUCTION_STATUS.FAIL;
|
||||
map.put("status", change_status);
|
||||
}
|
||||
log.info("land_auction id: {} Status {} Changed.", auction.getId(), change_status);
|
||||
landService.updateLandAuctionStatus(map);
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (Exception e){
|
||||
log.error("landAuctionSchedule Exception: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void eventSchedule(){
|
||||
List<Event> eventList = eventService.getScheduleMailList();
|
||||
|
||||
try{
|
||||
eventList.forEach(event -> {
|
||||
LocalDateTime nowDate = LocalDateTime.now();
|
||||
LocalDateTime startTime = event.getStartDt();
|
||||
LocalDateTime endTime = event.getEndDt();
|
||||
|
||||
if(nowDate.isAfter(endTime) && event.getStatus().equals(Event.EVENTSTATUS.WAIT)){
|
||||
eventService.updateEventStatus(event.getId(), Event.EVENTSTATUS.FAIL);
|
||||
log.error("eventJob eventSchedule timeOut : {}", event);
|
||||
return;
|
||||
}
|
||||
|
||||
// 시작시간이 30분 남았을때 게임DB에 insert 해준다
|
||||
if (event.getStatus().equals(Event.EVENTSTATUS.WAIT) && Duration.between(nowDate, startTime).abs().toMinutes() <= 30 && !event.isAddFlag()) {
|
||||
// systemMailInsert(event);
|
||||
eventService.insertSystemMail(event);
|
||||
// eventService.updateEventStatus(event.getId(), Event.EVENTSTATUS.RUNNING);
|
||||
log.info("eventJob eventSchedule dynamoDB Insert & Start: {}", event);
|
||||
}
|
||||
|
||||
// if(!nowDate.isBefore(startTime) && event.getStatus().equals(Event.EVENTSTATUS.WAIT)){
|
||||
// eventService.updateEventStatus(event.getId(), Event.EVENTSTATUS.RUNNING);
|
||||
// log.info("eventJob eventSchedule block start : {}", event);
|
||||
// }
|
||||
|
||||
if(!nowDate.isBefore(endTime) && event.getStatus().equals(Event.EVENTSTATUS.RUNNING)){
|
||||
eventService.updateEventStatus(event.getId(), Event.EVENTSTATUS.FINISH);
|
||||
log.info("eventJob eventSchedule block end : {}", event);
|
||||
}
|
||||
});
|
||||
}catch (Exception e){
|
||||
log.error("eventSchedule Exception: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void blackListSchedule(){
|
||||
List<BlackList> blackList = blackListService.getScheduleBlackList();
|
||||
|
||||
try{
|
||||
blackList.forEach(blockUser -> {
|
||||
LocalDateTime nowDate = LocalDateTime.now();
|
||||
LocalDateTime startTime = blockUser.getStartDt();
|
||||
LocalDateTime endTime = blockUser.getEndDt();
|
||||
|
||||
// 이미 지난시간이면 fail 처리
|
||||
if(nowDate.isAfter(endTime) && blockUser.getStatus().equals(BlackList.STATUSTYPE.WAIT)){
|
||||
blackListService.updateBlackListStatus(blockUser.getId(), BlackList.STATUSTYPE.FAIL);
|
||||
log.error("blackListJob blackListSchedule timeOut : {}", blockUser);
|
||||
return;
|
||||
}
|
||||
|
||||
// 시작시간 지났으면 정지 처리
|
||||
if(!nowDate.isBefore(startTime) && blockUser.getStatus().equals(BlackList.STATUSTYPE.WAIT)){
|
||||
// user kick 처리
|
||||
userGameSessionService.kickUserSession(blockUser.getGuid());
|
||||
blackListService.updateScheduleBlockUser(blockUser, "start");
|
||||
blackListService.updateBlackListStatus(blockUser.getId(), BlackList.STATUSTYPE.INPROGRESS);
|
||||
log.info("blackListJob blackListSchedule block start : {}", blockUser);
|
||||
}
|
||||
|
||||
if(!nowDate.isBefore(endTime) && blockUser.getStatus().equals(BlackList.STATUSTYPE.INPROGRESS)){
|
||||
blackListService.updateScheduleBlockUser(blockUser, "end");
|
||||
blackListService.updateBlackListStatus(blockUser.getId(), BlackList.STATUSTYPE.EXPIRATION);
|
||||
log.info("blackListJob blackListSchedule block end : {}", blockUser);
|
||||
}
|
||||
});
|
||||
}catch (Exception e){
|
||||
log.error("blackListSchedule Exception: {}", e.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void mailSchedule() {
|
||||
List<Mail> mailList = mailService.getScheduleMailList();
|
||||
|
||||
try{
|
||||
mailList.forEach(mail -> {
|
||||
if(mail.getSendStatus().equals(Mail.SENDSTATUS.WAIT)){
|
||||
if(mail.getSendType() == Mail.SENDTYPE.DIRECT_SEND){
|
||||
log.info("mailJob mailSchedule direct run : {}", mail);
|
||||
mailTypeProcess(mail);
|
||||
}else {
|
||||
String key = "mail-" + mail.getId();
|
||||
if (!schedulerService.isTaskExist(key)) {
|
||||
Runnable taskRunner = () -> {
|
||||
log.info("mailJob mailSchedule schedule run : {}", mail);
|
||||
mailTypeProcess(mail);
|
||||
// 스케줄 해제
|
||||
schedulerService.closeTask(key);
|
||||
};
|
||||
|
||||
// 시작일자 - 현재일자
|
||||
LocalDateTime startDate = mail.getSendDt();
|
||||
long initialDelay = Duration.between(LocalDateTime.now(), startDate).toMillis();
|
||||
|
||||
log.info("mailJob mailSchedule schedule add : {}", mail);
|
||||
ScheduledFuture<?> schedule = scheduler.schedule(taskRunner, initialDelay, TimeUnit.MILLISECONDS);
|
||||
schedulerService.addTask(key, schedule);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}catch (Exception e){
|
||||
log.error("mailSchedule Exception: {}", e.getMessage());
|
||||
mailService.setScheduleLog(HISTORYTYPE.SCHEDULE_MAIL_FAIL, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void noticeSchedule() {
|
||||
List<InGame> noticeList = noticeService.getScheduleNoticeList();
|
||||
|
||||
try{
|
||||
noticeList.forEach(notice -> {
|
||||
String key = "notice-" + notice.getId();
|
||||
if (!schedulerService.isTaskExist(key)) {
|
||||
Runnable taskRunner = new Runnable() {
|
||||
private int count = notice.getSendCnt().intValue();
|
||||
private final int repeat_cnt = notice.getRepeatCnt().intValue();
|
||||
private final boolean isRepeat = notice.getIsRepeat();
|
||||
private final long id = notice.getId();
|
||||
private final String runKey = key;
|
||||
private final InGame.REPEATTYPE repeatType = notice.getRepeatType();
|
||||
private final LocalDateTime endDate = notice.getEndDt();
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
log.info("noticeJob noticeSchedule schedule run : {}", notice);
|
||||
|
||||
boolean is_send = noticeSend(notice);
|
||||
if(!is_send) return;
|
||||
noticeService.updateNoticeCount(id);
|
||||
|
||||
// 반복여부
|
||||
if(isRepeat){
|
||||
// 반복타입
|
||||
switch(repeatType){
|
||||
// 횟수
|
||||
case COUNT -> {
|
||||
count++;
|
||||
// 정해진 횟수만큼 돌았으면 종료
|
||||
if(count >= repeat_cnt){
|
||||
noticeService.updateNoticeStatus(id, InGame.SENDSTATUS.FINISH);
|
||||
schedulerService.closeTask(runKey);
|
||||
log.info("Notice Schedule End RepeatType: Count, id: {}", id);
|
||||
}
|
||||
}
|
||||
// 일자
|
||||
case DATE -> {
|
||||
if (LocalDateTime.now().isAfter(endDate)) {
|
||||
noticeService.updateNoticeStatus(id, InGame.SENDSTATUS.FINISH);
|
||||
schedulerService.closeTask(runKey);
|
||||
log.info("Notice Schedule End RepeatType: Date, id: {}", id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}else{
|
||||
// 스케줄 해제 및 상태 변경
|
||||
noticeService.updateNoticeStatus(id, InGame.SENDSTATUS.FINISH);
|
||||
schedulerService.closeTask(runKey);
|
||||
log.info("Notice One Time Schedule End id: {}", id);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 반복여부 체크
|
||||
if(notice.getIsRepeat()){
|
||||
// 반복타입
|
||||
switch(notice.getRepeatType()){
|
||||
// 횟수
|
||||
case COUNT ->{
|
||||
// 시작일자 - 현재일자
|
||||
LocalDateTime startDate = notice.getSendDt();
|
||||
long initialDelay = Duration.between(LocalDateTime.now(), startDate).toMillis(); // 시작시간
|
||||
long period = LocalTime.parse(notice.getRepeatDt()).toSecondOfDay(); // 반복주기
|
||||
|
||||
ScheduledFuture<?> schedule = scheduler.scheduleAtFixedRate(taskRunner, initialDelay, period, TimeUnit.MILLISECONDS);
|
||||
schedulerService.addTask(key, schedule);
|
||||
noticeService.updateNoticeStatus(notice.getId(), InGame.SENDSTATUS.RUNNING);
|
||||
}
|
||||
// 일자
|
||||
case DATE -> {
|
||||
LocalDateTime startDate = notice.getSendDt();
|
||||
long initialDelay = Duration.between(LocalDateTime.now(), startDate).toMillis(); // 시작시간
|
||||
long period = CommonUtils.intervalToMillis(notice.getRepeatDt()); // 반복주기
|
||||
|
||||
ScheduledFuture<?> schedule = scheduler.scheduleAtFixedRate(taskRunner, initialDelay, period, TimeUnit.MILLISECONDS);
|
||||
schedulerService.addTask(key, schedule);
|
||||
noticeService.updateNoticeStatus(notice.getId(), InGame.SENDSTATUS.RUNNING);
|
||||
}
|
||||
// 특정시간
|
||||
case TIME -> {
|
||||
LocalDateTime now_date = LocalDateTime.now();
|
||||
LocalDateTime start_date = notice.getSendDt();
|
||||
|
||||
if(now_date.isAfter(start_date)) {
|
||||
LocalTime now_time = LocalTime.now();
|
||||
LocalTime repeat_time = CommonUtils.stringToTime(notice.getRepeatDt());
|
||||
LocalDateTime end_date = notice.getEndDt();
|
||||
InGame.SENDSTATUS status = notice.getSendStatus();
|
||||
Long id = notice.getId();
|
||||
|
||||
if(status.equals(InGame.SENDSTATUS.WAIT)) noticeService.updateNoticeStatus(id, InGame.SENDSTATUS.RUNNING);
|
||||
|
||||
if (now_time.equals(repeat_time)) {
|
||||
log.info("noticeJob noticeSchedule RepeatType: Time run : {}", notice);
|
||||
boolean is_send = noticeSend(notice);
|
||||
if (!is_send) {
|
||||
log.error("Notice Schedule Fail RepeatType: Time, id: {}", id);
|
||||
}
|
||||
}
|
||||
|
||||
if(status.equals(InGame.SENDSTATUS.RUNNING) && (now_date.isBefore(end_date) || now_date.isEqual(end_date))){
|
||||
noticeService.updateNoticeStatus(id, InGame.SENDSTATUS.FINISH);
|
||||
log.info("Notice Schedule End RepeatType: Time, id: {}", id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}else{
|
||||
// 시작일자 - 현재일자
|
||||
LocalDateTime startDate = notice.getSendDt();
|
||||
long initialDelay = Duration.between(LocalDateTime.now(), startDate).toMillis();
|
||||
|
||||
if(initialDelay < 0) {
|
||||
log.error("noticeJob noticeSchedule schedule add fail time over");
|
||||
noticeService.updateNoticeStatus(notice.getId(), InGame.SENDSTATUS.FAIL);
|
||||
mailService.setScheduleLog(HISTORYTYPE.SCHEDULE_NOTICE_FAIL, "시작일자가 현재일자보다 이전으로 송출 중단.");
|
||||
return;
|
||||
}
|
||||
|
||||
log.info("noticeJob noticeSchedule schedule add : {}", notice);
|
||||
ScheduledFuture<?> schedule = scheduler.schedule(taskRunner, initialDelay, TimeUnit.MILLISECONDS);
|
||||
schedulerService.addTask(key, schedule);
|
||||
}
|
||||
}
|
||||
});
|
||||
}catch (Exception e){
|
||||
log.error("noticeSchedule Exception: {}", e.getMessage());
|
||||
noticeService.setScheduleLog(HISTORYTYPE.SCHEDULE_NOTICE_FAIL, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void mailTypeProcess(Mail mail){
|
||||
if(mail.getReceiveType().equals(Mail.RECEIVETYPE.SINGLE)){
|
||||
boolean is_send = mainSend(mail);
|
||||
if(is_send) mailService.updateMailStatus(mail.getId(), Mail.SENDSTATUS.FINISH);
|
||||
}
|
||||
else{
|
||||
List<Excel> excelList = excelUtils.getExcelListData(mail.getTarget());
|
||||
log.info("mailJob mailSchedule schedule run ExcelList : {}", excelList);
|
||||
boolean is_send;
|
||||
mailService.updateMailStatus(mail.getId(), Mail.SENDSTATUS.RUNNING);
|
||||
for(Excel excel : excelList){
|
||||
String guid = mailService.getGuid(excel.getUser(), excel.getType());
|
||||
mail.setTarget(guid);
|
||||
is_send = mainSend(mail);
|
||||
if(!is_send){
|
||||
log.error("mailJob mailSchedule Excel fail user : {}", excel.getUser());
|
||||
mailService.setScheduleLog(HISTORYTYPE.SCHEDULE_MAIL_FAIL, "mail schedule id: " + mail.getId() + " Excel Send Fail User: " + excel.getUser());
|
||||
}
|
||||
else log.info("mailJob mailSchedule Excel send user : {}", excel.getUser());
|
||||
}
|
||||
mailService.updateMailStatus(mail.getId(), Mail.SENDSTATUS.FINISH);
|
||||
}
|
||||
}
|
||||
|
||||
// 우편 전송
|
||||
private boolean mainSend(Mail mail){
|
||||
// 서버정보 가져오기
|
||||
try{
|
||||
RedisLoginInfo info = redisUserInfoService.getUserLoginSessionInfo(mail.getTarget());
|
||||
String server_name = null;
|
||||
if(info == null){
|
||||
server_name = redisUserInfoService.getFirstChannel();
|
||||
if(server_name == null){
|
||||
log.error("mailJob mainSend serverName is empty");
|
||||
mailService.updateMailStatus(mail.getId(), Mail.SENDSTATUS.FAIL);
|
||||
mailService.setScheduleLog(HISTORYTYPE.MAIL_SEND_FAIL, "is null server name");
|
||||
return false;
|
||||
}
|
||||
}else{
|
||||
server_name = info.getCurrentServer();
|
||||
}
|
||||
|
||||
// 메시지 처리
|
||||
List<Message> msgList = mailService.getMailMessageList(mail.getId());
|
||||
List<OperationSystemMessage> titleList = new ArrayList<>();
|
||||
List<OperationSystemMessage> contentList = new ArrayList<>();
|
||||
List<OperationSystemMessage> senderList = new ArrayList<>();
|
||||
for(Message msg : msgList){
|
||||
LanguageType lang = null;
|
||||
String langText = msg.getLanguage();
|
||||
String sender = null;
|
||||
|
||||
if(langText.equals(LANGUAGETYPE.EN.toString())){
|
||||
lang = LanguageType.LanguageType_en;
|
||||
sender = "Administrator";
|
||||
}else if(langText.equals(LANGUAGETYPE.JA.toString())){
|
||||
lang = LanguageType.LanguageType_ja;
|
||||
sender = "アドミニストレーター";
|
||||
}else{
|
||||
lang = LanguageType.LanguageType_ko;
|
||||
sender = "시스템 관리자";
|
||||
}
|
||||
titleList.add(OperationSystemMessage.newBuilder()
|
||||
.setLanguageType(lang)
|
||||
.setText(CommonUtils.stringToByte(msg.getTitle())).build());
|
||||
contentList.add(OperationSystemMessage.newBuilder()
|
||||
.setLanguageType(lang)
|
||||
.setText(CommonUtils.stringToByte(msg.getContent())).build());
|
||||
senderList.add(OperationSystemMessage.newBuilder()
|
||||
.setLanguageType(lang)
|
||||
.setText(CommonUtils.stringToByte(sender)).build());
|
||||
}
|
||||
|
||||
// 아이템 처리
|
||||
List<Item> itemList = mailService.getMailItemList(mail.getId());
|
||||
List<MailItem> mailItemList = new ArrayList<>();
|
||||
for(Item item : itemList){
|
||||
mailItemList.add(MailItem.newBuilder()
|
||||
.setItemId(CommonUtils.stringToInt(item.getItem()))
|
||||
.setCount(item.getItemCnt()).build());
|
||||
}
|
||||
|
||||
log.info("Send Mail Message : {}, target : {}, type :{}", contentList, mail.getTarget(), mail.getMailType());
|
||||
messageHandlerService.sendMailMessage(server_name, mail.getTarget(), mail.getMailType().toString(), titleList, contentList, mailItemList, senderList);
|
||||
log.info("mailJob mailSend completed");
|
||||
return true;
|
||||
}catch(Exception e){
|
||||
log.error("mailSend Exception: {}", e.getMessage());
|
||||
mailService.updateMailStatus(mail.getId(), Mail.SENDSTATUS.FAIL);
|
||||
mailService.setScheduleLog(HISTORYTYPE.MAIL_SEND_FAIL, e.getMessage());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// 공지사항 전송
|
||||
private boolean noticeSend(InGame notice){
|
||||
try{
|
||||
//redis 채널 및 인던 정보 가져오기
|
||||
List<String> serverList = redisUserInfoService.getAllServerList();
|
||||
if(serverList.isEmpty()){
|
||||
log.error("noticeJob noticeSend serverList is empty");
|
||||
noticeService.updateNoticeStatus(notice.getId(), InGame.SENDSTATUS.FAIL);
|
||||
noticeService.setScheduleLog(HISTORYTYPE.NOTICE_SEND_FAIL, "is null server name");
|
||||
return false;
|
||||
}
|
||||
|
||||
//메시지 처리
|
||||
List<Message> msgList = noticeService.getNoticeMessageList(notice.getId());
|
||||
List<OperationSystemMessage> contentList = new ArrayList<>();
|
||||
List<OperationSystemMessage> senderList = new ArrayList<>();
|
||||
for(Message msg : Collections.unmodifiableList(msgList)){
|
||||
LanguageType lang = null;
|
||||
String langText = msg.getLanguage();
|
||||
String sender = null;
|
||||
|
||||
if(langText.equals(LANGUAGETYPE.EN.toString())){
|
||||
lang = LanguageType.LanguageType_en;
|
||||
sender = "Administrator";
|
||||
}else if(langText.equals(LANGUAGETYPE.JA.toString())){
|
||||
lang = LanguageType.LanguageType_ja;
|
||||
sender = "アドミニストレーター";
|
||||
}else{
|
||||
lang = LanguageType.LanguageType_ko;
|
||||
sender = "시스템 관리자";
|
||||
}
|
||||
contentList.add(OperationSystemMessage.newBuilder()
|
||||
.setLanguageType(lang)
|
||||
.setText(CommonUtils.stringToByte(msg.getContent())).build());
|
||||
senderList.add(OperationSystemMessage.newBuilder()
|
||||
.setLanguageType(lang)
|
||||
.setText(CommonUtils.stringToByte(sender)).build());
|
||||
}
|
||||
|
||||
log.info("Send Notice Message: {}, type: {}", contentList, notice.getMessageType());
|
||||
messageHandlerService.sendNoticeMessage(serverList, notice.getMessageType().toString(), contentList, senderList);
|
||||
log.info("noticeJob noticeSend completed");
|
||||
return true;
|
||||
}catch (Exception e){
|
||||
log.error("noticeSend Exception: {}", e.getMessage());
|
||||
noticeService.updateNoticeStatus(notice.getId(), InGame.SENDSTATUS.FAIL);
|
||||
noticeService.setScheduleLog(HISTORYTYPE.NOTICE_SEND_FAIL, e.getMessage());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// 시스템 우편 등록
|
||||
// private void systemMailInsert(Event event){
|
||||
// try {
|
||||
// log.info("systemMailInsert Info: {}", event);
|
||||
// ObjectMapper objectMapper = new ObjectMapper();
|
||||
// ArrayNode mailTitleArray = objectMapper.createArrayNode();
|
||||
// ArrayNode mailTextArray = objectMapper.createArrayNode();
|
||||
// ArrayNode mailSenderArray = objectMapper.createArrayNode();
|
||||
// ArrayNode mailItemArray = objectMapper.createArrayNode();
|
||||
//
|
||||
// List<Message> msgList = eventService.getMessageList(event.getId());
|
||||
// List<Item> itemList = eventService.getItemList(event.getId());
|
||||
// for (Message msg : msgList) {
|
||||
// String langText = msg.getLanguage();
|
||||
// int lang;
|
||||
// String sender;
|
||||
//
|
||||
// if (langText.equals(LANGUAGETYPE.EN.toString())) {
|
||||
// lang = LanguageType.LanguageType_en.getNumber();
|
||||
// sender = "CALIVERSE";
|
||||
// } else if (langText.equals(LANGUAGETYPE.JA.toString())) {
|
||||
// lang = LanguageType.LanguageType_ja.getNumber();
|
||||
// sender = "カリバース";
|
||||
// } else {
|
||||
// lang = LanguageType.LanguageType_ko.getNumber();
|
||||
// sender = "칼리버스";
|
||||
// }
|
||||
// SystemMessage titleMessage = SystemMessage.builder().LanguageType(lang).Text(msg.getTitle()).build();
|
||||
// SystemMessage textMessage = SystemMessage.builder().LanguageType(lang).Text(msg.getContent()).build();
|
||||
// SystemMessage senderMessage = SystemMessage.builder().LanguageType(lang).Text(sender).build();
|
||||
//
|
||||
// mailTitleArray.add(JsonUtils.createSystemMessage(titleMessage));
|
||||
// mailTextArray.add(JsonUtils.createSystemMessage(textMessage));
|
||||
// mailSenderArray.add(JsonUtils.createSystemMessage(senderMessage));
|
||||
// }
|
||||
// for (Item item : itemList) {
|
||||
// MailItem mailItem = MailItem.newBuilder().setItemId(CommonUtils.stringToInt(item.getItem())).setCount(item.getItemCnt()).build();
|
||||
// mailItemArray.add(JsonUtils.createMAilItem(mailItem));
|
||||
// }
|
||||
//
|
||||
// eventService.insertSystemMail(event, mailTitleArray, mailTextArray, mailSenderArray, mailItemArray);
|
||||
//
|
||||
// }catch (Exception e){
|
||||
// log.error("systemMailInsert Exception: {}", e.getMessage());
|
||||
// eventService.updateEventStatus(event.getId(), Event.EVENTSTATUS.FAIL);
|
||||
// historyService.setScheduleLog(HISTORYTYPE.SCHEDULE_EVENT_FAIL, e.getMessage());
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package com.caliverse.admin.scheduler;
|
||||
|
||||
import com.caliverse.admin.dynamodb.service.DynamodbService;
|
||||
import com.caliverse.admin.global.common.constants.AdminConstants;
|
||||
import com.caliverse.admin.logs.Indicatordomain.StartEndTime;
|
||||
import com.caliverse.admin.logs.logservice.LogServiceHelper;
|
||||
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.boot.CommandLineRunner;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.LocalDate;
|
||||
|
||||
@Component
|
||||
@Order(1)
|
||||
@RequiredArgsConstructor
|
||||
@Slf4j
|
||||
public class OneTimeSchedule implements CommandLineRunner {
|
||||
@Autowired private IndicatorsDauService dauService;
|
||||
@Autowired private IndicatorsWauService wauService;
|
||||
@Autowired private IndicatorsMauService mauService;
|
||||
@Autowired private IndicatorsMcuService mcuService;
|
||||
@Autowired private IndicatorsNruService nruService;
|
||||
@Autowired private IndicatorsPlayTimeService playTimeService;
|
||||
@Autowired private IndicatorsDglcService dglcService;
|
||||
@Autowired private IndicatorsDBCapacityService capacityService;
|
||||
@Autowired private IndicatorsUgqCreateService ugqCreateService;
|
||||
@Autowired private IndicatorsMetaverseServerService metaverseServerService;
|
||||
@Autowired private DynamodbService dynamodbService;
|
||||
|
||||
@Override
|
||||
public void run(String... args) throws Exception {
|
||||
try{
|
||||
log.info("Starting OneTimeSchedule");
|
||||
// dynamodbService.saveUserMoney(); //유저별 재화 데이터 저장
|
||||
|
||||
// LocalDate startDate = LocalDate.of(2024, 11, 8);
|
||||
//// LocalDate currentDate = LocalDate.of(2024, 9, 10);
|
||||
// LocalDate currentDate = LocalDate.now();
|
||||
//
|
||||
// for (LocalDate date = startDate; !date.isAfter(currentDate); date = date.plusDays(1)) {
|
||||
// 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);
|
||||
//
|
||||
// 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()); //체크
|
||||
// }
|
||||
|
||||
|
||||
}catch (Exception e){
|
||||
log.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
185
src/main/java/com/caliverse/admin/scheduler/ScheduleRunner.java
Normal file
185
src/main/java/com/caliverse/admin/scheduler/ScheduleRunner.java
Normal file
@@ -0,0 +1,185 @@
|
||||
package com.caliverse.admin.scheduler;
|
||||
|
||||
import com.caliverse.admin.domain.RabbitMq.MessageHandlerService;
|
||||
import com.caliverse.admin.domain.entity.BlackList;
|
||||
import com.caliverse.admin.domain.entity.Event;
|
||||
import com.caliverse.admin.domain.entity.InGame;
|
||||
import com.caliverse.admin.domain.entity.Mail;
|
||||
import com.caliverse.admin.domain.service.*;
|
||||
import com.caliverse.admin.global.common.utils.ExcelUtils;
|
||||
import com.caliverse.admin.logs.logservice.indicators.*;
|
||||
import com.caliverse.admin.redis.service.RedisUserInfoService;
|
||||
import com.caliverse.admin.scheduler.service.BlackListScheduler;
|
||||
import com.caliverse.admin.scheduler.service.EventScheduler;
|
||||
import com.caliverse.admin.scheduler.service.MailScheduler;
|
||||
import com.caliverse.admin.scheduler.service.NoticeScheduler;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
// import org.springframework.batch.core.JobParameters;
|
||||
// import org.springframework.batch.core.JobParametersBuilder;
|
||||
// import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
|
||||
import com.caliverse.admin.global.common.constants.AdminConstants;
|
||||
import com.caliverse.admin.logs.Indicatordomain.StartEndTime;
|
||||
import com.caliverse.admin.logs.logservice.LogServiceHelper;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
@EnableScheduling
|
||||
public class ScheduleRunner {
|
||||
@Autowired private IndicatorsAuService auService;
|
||||
@Autowired private IndicatorsDauService dauService;
|
||||
@Autowired private IndicatorsWauService wauService;
|
||||
@Autowired private IndicatorsMauService mauService;
|
||||
@Autowired private IndicatorsMcuService mcuService;
|
||||
@Autowired private IndicatorsNruService statNruService;
|
||||
|
||||
@Autowired private RedisUserInfoService userInfoService;
|
||||
@Autowired private SchedulerManager schedulerManager;
|
||||
@Autowired private DynamicScheduler dynamicScheduler;
|
||||
@Autowired private MailService mailService;
|
||||
@Autowired private NoticeService noticeService;
|
||||
@Autowired private BlackListService blackListService;
|
||||
@Autowired private EventService eventService;
|
||||
@Autowired
|
||||
private RedisUserInfoService redisUserInfoService;
|
||||
@Autowired
|
||||
private MessageHandlerService messageHandlerService;
|
||||
@Autowired
|
||||
private ExcelUtils excelUtils;
|
||||
|
||||
/*
|
||||
매일 UTC 기준 00시 50분 00초에 실행, (한국 시간 9시 50분) 30분에 돌릴경우 데이터가 다 넘어 오지 않는 경우 있어서 수정처리
|
||||
이게 가장 먼저 실행 되어야 한다.
|
||||
로그가 많을 경우 성능 이슈 있을 수 있음
|
||||
*/
|
||||
@Scheduled(cron = "0 50 0 * * *")
|
||||
public void auScheduler() {
|
||||
//이걸 나중에 어떻게 활용할지 생각해보자.
|
||||
log.info("run auScheduler");
|
||||
StartEndTime startEndTime = LogServiceHelper.getCurrentLogSearchEndTime(AdminConstants.STAT_DAY_NUM);
|
||||
auService.collectActiveUser(startEndTime.getStartTime(), startEndTime.getEndTime());
|
||||
log.info("end auScheduler");
|
||||
}
|
||||
|
||||
// @Scheduled(cron = "00 55 0 * * *") // 매일 UTC 기준 00시 56분 00초에 실행
|
||||
@Scheduled(cron = "1 * * * * *") // 매일 UTC 기준 00시 56분 00초에 실행
|
||||
public void dauScheduler() {
|
||||
log.info("run dauScheduler");
|
||||
StartEndTime startEndTime = LogServiceHelper.getCurrentLogSearchEndTime(AdminConstants.STAT_DAY_NUM);
|
||||
dauService.collectDailyActiveUser(startEndTime.getStartTime(), startEndTime.getEndTime());
|
||||
log.info("end dauScheduler");
|
||||
}
|
||||
|
||||
@Scheduled(cron = "00 56 0 * * *") // 매일 UTC 기준 00시 56분 00초에 실행
|
||||
public void wauScheduler() {
|
||||
log.info("run wauScheduler");
|
||||
StartEndTime startEndTime = LogServiceHelper.getCurrentLogSearchEndTime(AdminConstants.STAT_WEEK_NUM);
|
||||
wauService.collectWeeklyActiveUser(startEndTime.getStartTime(), startEndTime.getEndTime());
|
||||
log.info("end wauScheduler");
|
||||
}
|
||||
|
||||
@Scheduled(cron = "00 57 0 * * *") // 매일 UTC 기준 00시 57분 00초에 실행
|
||||
public void mauScheduler() {
|
||||
log.info("run mauScheduler");
|
||||
StartEndTime startEndTime = LogServiceHelper.getCurrentLogSearchEndTime(AdminConstants.STAT_MONTH_NUM);
|
||||
mauService.collectMonthlyActiveUser(startEndTime.getStartTime(), startEndTime.getEndTime());
|
||||
log.info("end mauScheduler");
|
||||
}
|
||||
|
||||
@Scheduled(cron = "00 58 0 * * *") // 매일 UTC 기준 00시 58분 00초에 실행
|
||||
public void mcuScheduler() {
|
||||
log.info("run mcuScheduler");
|
||||
StartEndTime startEndTime = LogServiceHelper.getCurrentLogSearchEndTime(AdminConstants.STAT_DAY_NUM);
|
||||
mcuService.collectMaxCountUser(startEndTime.getStartTime(), startEndTime.getEndTime());
|
||||
log.info("end mcuScheduler");
|
||||
}
|
||||
|
||||
@Scheduled(cron = "00 59 0 * * *") // 매일 UTC 기준 00시 59분 00초에 실행
|
||||
public void nruScheduler() {
|
||||
log.info("run mcuScheduler");
|
||||
//StartEndTime startEndTime = LogServiceHelper.getCurrentLogSearchEndTime(AdminConstants.STAT_DAY_NUM);
|
||||
//statNruService.collectStatLogs(startEndTime.getStartTime(), startEndTime.getEndTime());
|
||||
log.info("end mcuScheduler");
|
||||
}
|
||||
|
||||
@Scheduled(cron = "1 * * * * *")
|
||||
public void noticeJob(){
|
||||
log.info("run noticeJob");
|
||||
List<InGame> noticeList = noticeService.getScheduleNoticeList();
|
||||
noticeList.forEach(notice -> {
|
||||
if (notice.getIsRepeat() &&
|
||||
notice.getRepeatType() == InGame.REPEATTYPE.COUNT &&
|
||||
notice.getSendCnt() >= notice.getRepeatCnt()) {
|
||||
log.info("Skipping notice - already reached max count. NoticeId: {}", notice.getId());
|
||||
noticeService.updateNoticeStatus(notice.getId(), InGame.SENDSTATUS.FINISH);
|
||||
return;
|
||||
}
|
||||
|
||||
NoticeScheduler task = NoticeScheduler.builder()
|
||||
.notice(notice)
|
||||
.noticeService(noticeService)
|
||||
.redisUserInfoService(redisUserInfoService)
|
||||
.messageHandlerService(messageHandlerService)
|
||||
.build();
|
||||
schedulerManager.scheduleTask(task);
|
||||
});
|
||||
log.info("end noticeJob");
|
||||
}
|
||||
|
||||
@Scheduled(cron = "2 * * * * *")
|
||||
public void mailJob(){
|
||||
log.info("run mailJob");
|
||||
List<Mail> mailList = mailService.getScheduleMailList();
|
||||
mailList.stream()
|
||||
.filter(mail -> mail.getSendStatus().equals(Mail.SENDSTATUS.WAIT))
|
||||
.forEach(mail -> {
|
||||
MailScheduler task = MailScheduler.builder()
|
||||
.mail(mail)
|
||||
.mailService(mailService)
|
||||
.redisUserInfoService(redisUserInfoService)
|
||||
.messageHandlerService(messageHandlerService)
|
||||
.excelUtils(excelUtils)
|
||||
.build();
|
||||
schedulerManager.scheduleTask(task);
|
||||
});
|
||||
log.info("end mailJob");
|
||||
}
|
||||
|
||||
@Scheduled(cron = "3 * * * * *")
|
||||
public void blackListJob(){
|
||||
log.info("run blackListJob");
|
||||
List<BlackList> blackList = blackListService.getScheduleBlackList();
|
||||
blackList.forEach(blockUser -> {
|
||||
BlackListScheduler task = BlackListScheduler.builder()
|
||||
.blackList(blockUser)
|
||||
.blackListService(blackListService)
|
||||
.build();
|
||||
schedulerManager.scheduleTask(task);
|
||||
});
|
||||
log.info("end blackListJob");
|
||||
}
|
||||
|
||||
@Scheduled(cron = "4 * * * * *")
|
||||
public void eventJob(){
|
||||
log.info("run eventJob");
|
||||
List<Event> eventList = eventService.getScheduleMailList();
|
||||
eventList.forEach(event -> {
|
||||
EventScheduler task = EventScheduler.builder()
|
||||
.event(event)
|
||||
.eventService(eventService)
|
||||
.redisUserInfoService(redisUserInfoService)
|
||||
.messageHandlerService(messageHandlerService)
|
||||
.build();
|
||||
schedulerManager.scheduleTask(task);
|
||||
});
|
||||
log.info("end eventJob");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package com.caliverse.admin.scheduler;
|
||||
|
||||
import com.caliverse.admin.domain.entity.InGame;
|
||||
import com.caliverse.admin.domain.entity.Mail;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.scheduling.config.ScheduledTask;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
|
||||
@Service
|
||||
public class ScheduleService {
|
||||
|
||||
private final Map<String, ScheduledFuture<?>> scheduledTasks = new ConcurrentHashMap<>();
|
||||
|
||||
private final Map<Long, Mail> mailTask = new ConcurrentHashMap<>();
|
||||
private final Map<Long, InGame> noticeTask = new ConcurrentHashMap<>();
|
||||
|
||||
public boolean isTaskExist(String key){
|
||||
return scheduledTasks.containsKey(key);
|
||||
}
|
||||
|
||||
public void addTask(String key, ScheduledFuture<?> schdule){
|
||||
scheduledTasks.put(key, schdule);
|
||||
}
|
||||
|
||||
public void closeTask(String key) {
|
||||
ScheduledFuture<?> scheduledFuture = scheduledTasks.get(key);
|
||||
if (scheduledFuture != null) {
|
||||
scheduledFuture.cancel(true);
|
||||
scheduledTasks.remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
// public boolean isTaskExist(String type, Long id) {
|
||||
// switch (type) {
|
||||
// case "mail" -> {
|
||||
// return mailTask.containsKey(id);
|
||||
// }
|
||||
// case "notice" -> {
|
||||
// return noticeTask.containsKey(id);
|
||||
// }
|
||||
// default -> {
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// public void createTask(Mail mail) {
|
||||
// mailTask.put(mail.getId(), mail);
|
||||
// }
|
||||
|
||||
}
|
||||
197
src/main/java/com/caliverse/admin/scheduler/ScheduleSetter.java
Normal file
197
src/main/java/com/caliverse/admin/scheduler/ScheduleSetter.java
Normal file
@@ -0,0 +1,197 @@
|
||||
package com.caliverse.admin.scheduler;
|
||||
|
||||
import com.caliverse.admin.domain.service.CaliumService;
|
||||
import com.caliverse.admin.global.common.utils.CommonUtils;
|
||||
import com.caliverse.admin.logs.logservice.indicators.*;
|
||||
import com.caliverse.admin.scheduler.service.LogCompressService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
|
||||
import com.caliverse.admin.global.common.constants.AdminConstants;
|
||||
import com.caliverse.admin.logs.Indicatordomain.StartEndTime;
|
||||
import com.caliverse.admin.logs.logservice.LogServiceHelper;
|
||||
import com.caliverse.admin.redis.service.RedisUserInfoService;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.time.LocalDate;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
@EnableScheduling
|
||||
public class ScheduleSetter {
|
||||
|
||||
@Autowired private IndicatorsAuService auService;
|
||||
@Autowired private IndicatorsDauService dauService;
|
||||
@Autowired private IndicatorsWauService wauService;
|
||||
@Autowired private IndicatorsMauService mauService;
|
||||
@Autowired private IndicatorsMcuService mcuService;
|
||||
@Autowired private IndicatorsNruService nruService;
|
||||
@Autowired private IndicatorsPlayTimeService playTimeService;
|
||||
@Autowired private IndicatorsDglcService dglcService;
|
||||
@Autowired private IndicatorsDBCapacityService capacityService;
|
||||
@Autowired private IndicatorsUgqCreateService ugqCreateService;
|
||||
@Autowired private IndicatorsMetaverseServerService metaverseServerService;
|
||||
|
||||
@Autowired private IndicatorsNruService statNruService;
|
||||
@Autowired private RedisUserInfoService userInfoService;
|
||||
@Autowired private DynamicScheduler dynamicScheduler;
|
||||
|
||||
@Autowired private CaliumService caliumService;
|
||||
@Autowired private LogCompressService logService;
|
||||
|
||||
@Scheduled(cron = "0 01 0 * * *") // 매일 UTC 기준 00시 01분 00초에 실행
|
||||
public void capacityScheduler() {
|
||||
// log.info("run capacityScheduler");
|
||||
StartEndTime startEndTime = LogServiceHelper.getCurrentLogSearchEndTime(AdminConstants.STAT_DAY_NUM);
|
||||
capacityService.collectDBCapacity(startEndTime.getStartTime(), startEndTime.getEndTime());
|
||||
// log.info("end capacityScheduler");
|
||||
}
|
||||
|
||||
@Scheduled(cron = "0 02 0 * * *") // 매일 UTC 기준 00시 02분 00초에 실행
|
||||
public void metaverServerScheduler() {
|
||||
// log.info("run metaverServerScheduler");
|
||||
StartEndTime startEndTime = LogServiceHelper.getCurrentLogSearchEndTime(AdminConstants.STAT_DAY_NUM);
|
||||
int serverCount = 13;
|
||||
metaverseServerService.collectMetaverseServerCount(startEndTime.getStartTime(), startEndTime.getEndTime(), serverCount);
|
||||
// log.info("end metaverServerScheduler");
|
||||
}
|
||||
|
||||
/*
|
||||
매일 UTC 기준 00시 50분 00초에 실행, (한국 시간 9시 50분) 30분에 돌릴경우 데이터가 다 넘어 오지 않는 경우 있어서 수정처리
|
||||
이게 가장 먼저 실행 되어야 한다.
|
||||
로그가 많을 경우 성능 이슈 있을 수 있음
|
||||
*/
|
||||
@Scheduled(cron = "0 50 0 * * *")
|
||||
public void auScheduler() {
|
||||
//이걸 나중에 어떻게 활용할지 생각해보자.
|
||||
// log.info("run auScheduler");
|
||||
StartEndTime startEndTime = LogServiceHelper.getCurrentLogSearchEndTime(AdminConstants.STAT_DAY_NUM);
|
||||
auService.collectActiveUser(startEndTime.getStartTime(), startEndTime.getEndTime());
|
||||
// log.info("end auScheduler");
|
||||
}
|
||||
|
||||
@Scheduled(cron = "00 55 0 * * *") // 매일 UTC 기준 00시 55분 00초에 실행
|
||||
public void dauScheduler() {
|
||||
// log.info("run dauScheduler");
|
||||
StartEndTime startEndTime = LogServiceHelper.getCurrentLogSearchEndTime(AdminConstants.STAT_DAY_NUM);
|
||||
dauService.collectDailyActiveUser(startEndTime.getStartTime(), startEndTime.getEndTime());
|
||||
// log.info("end dauScheduler");
|
||||
}
|
||||
|
||||
@Scheduled(cron = "00 56 0 * * *") // 매일 UTC 기준 00시 56분 00초에 실행
|
||||
public void wauScheduler() {
|
||||
// log.info("run wauScheduler");
|
||||
StartEndTime startEndTime = LogServiceHelper.getCurrentLogSearchEndTime(AdminConstants.STAT_WEEK_NUM);
|
||||
wauService.collectWeeklyActiveUser(startEndTime.getStartTime(), startEndTime.getEndTime());
|
||||
// log.info("end wauScheduler");
|
||||
}
|
||||
|
||||
// @Scheduled(cron = "00 57 0 * * *") // 매일 UTC 기준 00시 57분 00초에 실행
|
||||
@Scheduled(cron = "00 57 0 1 * ?") // 매월 1일 UTC 기준 00시 57분 00초에 실행
|
||||
public void mauScheduler() {
|
||||
// log.info("run mauScheduler");
|
||||
int monthLength = CommonUtils.getLengthOfLastMonth(LocalDate.now()); // 지난달 총일수 가져오기
|
||||
StartEndTime startEndTime = LogServiceHelper.getCurrentLogSearchEndTime(monthLength);
|
||||
mauService.collectMonthlyActiveUser(startEndTime.getStartTime(), startEndTime.getEndTime());
|
||||
// log.info("end mauScheduler");
|
||||
}
|
||||
|
||||
@Scheduled(cron = "00 58 0 * * *") // 매일 UTC 기준 00시 58분 00초에 실행
|
||||
public void mcuScheduler() {
|
||||
// log.info("run mcuScheduler");
|
||||
StartEndTime startEndTime = LogServiceHelper.getCurrentLogSearchEndTime(AdminConstants.STAT_DAY_NUM);
|
||||
mcuService.collectMaxCountUser(startEndTime.getStartTime(), startEndTime.getEndTime());
|
||||
// log.info("end mcuScheduler");
|
||||
}
|
||||
|
||||
@Scheduled(cron = "00 59 0 * * *") // 매일 UTC 기준 00시 59분 00초에 실행
|
||||
public void nruScheduler() {
|
||||
// log.info("run nruScheduler");
|
||||
StartEndTime startEndTime = LogServiceHelper.getCurrentLogSearchEndTime(AdminConstants.STAT_DAY_NUM);
|
||||
nruService.collectCharacterCreateCount(startEndTime.getStartTime(), startEndTime.getEndTime());
|
||||
// log.info("end nruScheduler");
|
||||
}
|
||||
|
||||
@Scheduled(cron = "00 00 1 * * *") // 매일 UTC 기준 1시 00분 00초에 실행
|
||||
public void playTimeScheduler() {
|
||||
// log.info("run playTimeScheduler");
|
||||
StartEndTime startEndTime = LogServiceHelper.getCurrentLogSearchEndTime(AdminConstants.STAT_DAY_NUM);
|
||||
playTimeService.collectUserPlayTime(startEndTime.getStartTime(), startEndTime.getEndTime());
|
||||
// log.info("end playTimeScheduler");
|
||||
}
|
||||
|
||||
@Scheduled(cron = "00 01 1 * * *") // 매일 UTC 기준 01시 01분 00초에 실행
|
||||
public void dglcScheduler() {
|
||||
// log.info("run dglcScheduler");
|
||||
StartEndTime startEndTime = LogServiceHelper.getCurrentLogSearchEndTime(AdminConstants.STAT_DAY_NUM);
|
||||
dglcService.collectDailyGameLoginCount(startEndTime.getStartTime(), startEndTime.getEndTime());
|
||||
// log.info("end dglcScheduler");
|
||||
}
|
||||
|
||||
@Scheduled(cron = "00 00 2 * * *") // 매일 UTC 기준 02시 00분 00초에 실행 (Log 데이터가 늦게 넘어올때가 있기때문에 나중에 실행)
|
||||
public void ugqCreateScheduler() {
|
||||
// log.info("run ugqCreateScheduler");
|
||||
StartEndTime startEndTime = LogServiceHelper.getCurrentLogSearchEndTime(AdminConstants.STAT_DAY_NUM);
|
||||
ugqCreateService.collectUGQCreateCount(startEndTime.getStartTime(), startEndTime.getEndTime());
|
||||
// log.info("end ugqCreateScheduler");
|
||||
}
|
||||
|
||||
|
||||
@Scheduled(cron = "0 * * * * *") // 매 분 00초에 실행
|
||||
public void runJob() {
|
||||
//log.info("run runJob");
|
||||
}
|
||||
|
||||
@Scheduled(cron = "1 * * * * *")
|
||||
public void noticeJob(){
|
||||
// log.info("run noticeJob");
|
||||
dynamicScheduler.noticeSchedule();
|
||||
// log.info("end noticeJob");
|
||||
}
|
||||
|
||||
@Scheduled(cron = "2 * * * * *")
|
||||
public void mailJob(){
|
||||
// log.info("run mailJob");
|
||||
dynamicScheduler.mailSchedule();
|
||||
// log.info("end mailJob");
|
||||
}
|
||||
|
||||
@Scheduled(cron = "3 * * * * *")
|
||||
public void blackListJob(){
|
||||
// log.info("run blackListJob");
|
||||
dynamicScheduler.blackListSchedule();
|
||||
// log.info("end blackListJob");
|
||||
}
|
||||
|
||||
@Scheduled(cron = "4 * * * * *")
|
||||
public void eventJob(){
|
||||
// log.info("run eventJob");
|
||||
dynamicScheduler.eventSchedule();
|
||||
// log.info("end eventJob");
|
||||
}
|
||||
|
||||
@Scheduled(cron = "5 * * * * *")
|
||||
public void landAuctionJob(){
|
||||
// log.info("run landAuctionJob");
|
||||
dynamicScheduler.landAuctionSchedule();
|
||||
// log.info("end landAuctionJob");
|
||||
}
|
||||
|
||||
//web3
|
||||
@Scheduled(cron = "1 * * * * *")
|
||||
public void web3Job(){
|
||||
// log.info("run web3Job");
|
||||
caliumService.getScheduleCaliumRequestList();
|
||||
// log.info("end web3Job");
|
||||
}
|
||||
|
||||
//log
|
||||
@Scheduled(cron = "00 00 00 1 * ?") // 매월 1일에 실행
|
||||
public void logJob(){
|
||||
logService.compressLastMonthLogs();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,178 @@
|
||||
package com.caliverse.admin.scheduler;
|
||||
|
||||
import com.caliverse.admin.domain.service.CaliumService;
|
||||
import com.caliverse.admin.logs.logservice.indicators.*;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
|
||||
import com.caliverse.admin.global.common.constants.AdminConstants;
|
||||
import com.caliverse.admin.logs.Indicatordomain.StartEndTime;
|
||||
import com.caliverse.admin.logs.logservice.LogServiceHelper;
|
||||
import com.caliverse.admin.redis.service.RedisUserInfoService;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
@EnableScheduling
|
||||
public class ScheduleSetter {
|
||||
|
||||
@Autowired private IndicatorsAuService auService;
|
||||
@Autowired private IndicatorsDauService dauService;
|
||||
@Autowired private IndicatorsWauService wauService;
|
||||
@Autowired private IndicatorsMauService mauService;
|
||||
@Autowired private IndicatorsMcuService mcuService;
|
||||
@Autowired private IndicatorsNruService nruService;
|
||||
@Autowired private IndicatorsPlayTimeService playTimeService;
|
||||
@Autowired private IndicatorsDglcService dglcService;
|
||||
@Autowired private IndicatorsDBCapacityService capacityService;
|
||||
@Autowired private IndicatorsUgqCreateService ugqCreateService;
|
||||
@Autowired private IndicatorsMetaverseServerService metaverseServerService;
|
||||
|
||||
@Autowired private IndicatorsNruService statNruService;
|
||||
@Autowired private RedisUserInfoService userInfoService;
|
||||
@Autowired private DynamicScheduler dynamicScheduler;
|
||||
|
||||
@Autowired private CaliumService caliumService;
|
||||
|
||||
@Scheduled(cron = "0 01 0 * * *") // 매일 UTC 기준 00시 01분 00초에 실행
|
||||
public void capacityScheduler() {
|
||||
log.info("run capacityScheduler");
|
||||
StartEndTime startEndTime = LogServiceHelper.getCurrentLogSearchEndTime(AdminConstants.STAT_DAY_NUM);
|
||||
capacityService.collectDBCapacity(startEndTime.getStartTime(), startEndTime.getEndTime());
|
||||
log.info("end capacityScheduler");
|
||||
}
|
||||
|
||||
@Scheduled(cron = "0 02 0 * * *") // 매일 UTC 기준 00시 01분 00초에 실행
|
||||
public void metaverServerScheduler() {
|
||||
log.info("run metaverServerScheduler");
|
||||
StartEndTime startEndTime = LogServiceHelper.getCurrentLogSearchEndTime(AdminConstants.STAT_DAY_NUM);
|
||||
int serverCount = 13;
|
||||
metaverseServerService.collectMetaverseServerCount(startEndTime.getStartTime(), startEndTime.getEndTime(), serverCount);
|
||||
log.info("end metaverServerScheduler");
|
||||
}
|
||||
|
||||
/*
|
||||
매일 UTC 기준 00시 50분 00초에 실행, (한국 시간 9시 50분) 30분에 돌릴경우 데이터가 다 넘어 오지 않는 경우 있어서 수정처리
|
||||
이게 가장 먼저 실행 되어야 한다.
|
||||
로그가 많을 경우 성능 이슈 있을 수 있음
|
||||
*/
|
||||
@Scheduled(cron = "0 50 0 * * *")
|
||||
public void auScheduler() {
|
||||
//이걸 나중에 어떻게 활용할지 생각해보자.
|
||||
log.info("run auScheduler");
|
||||
StartEndTime startEndTime = LogServiceHelper.getCurrentLogSearchEndTime(AdminConstants.STAT_DAY_NUM);
|
||||
auService.collectActiveUser(startEndTime.getStartTime(), startEndTime.getEndTime());
|
||||
log.info("end auScheduler");
|
||||
}
|
||||
|
||||
@Scheduled(cron = "00 55 0 * * *") // 매일 UTC 기준 00시 55분 00초에 실행
|
||||
public void dauScheduler() {
|
||||
log.info("run dauScheduler");
|
||||
StartEndTime startEndTime = LogServiceHelper.getCurrentLogSearchEndTime(AdminConstants.STAT_DAY_NUM);
|
||||
dauService.collectDailyActiveUser(startEndTime.getStartTime(), startEndTime.getEndTime());
|
||||
log.info("end dauScheduler");
|
||||
}
|
||||
|
||||
@Scheduled(cron = "00 56 0 * * *") // 매일 UTC 기준 00시 56분 00초에 실행
|
||||
public void wauScheduler() {
|
||||
log.info("run wauScheduler");
|
||||
StartEndTime startEndTime = LogServiceHelper.getCurrentLogSearchEndTime(AdminConstants.STAT_WEEK_NUM);
|
||||
wauService.collectWeeklyActiveUser(startEndTime.getStartTime(), startEndTime.getEndTime());
|
||||
log.info("end wauScheduler");
|
||||
}
|
||||
|
||||
@Scheduled(cron = "00 57 0 * * *") // 매일 UTC 기준 00시 57분 00초에 실행
|
||||
public void mauScheduler() {
|
||||
log.info("run mauScheduler");
|
||||
// int monthLength = CommonUtils.getLengthOfLastMonth(LocalDate.now()); // 지난달 총일수 가져오기
|
||||
StartEndTime startEndTime = LogServiceHelper.getCurrentLogSearchEndTime(AdminConstants.STAT_MONTH_NUM);
|
||||
mauService.collectMonthlyActiveUser(startEndTime.getStartTime(), startEndTime.getEndTime());
|
||||
log.info("end mauScheduler");
|
||||
}
|
||||
|
||||
@Scheduled(cron = "00 58 0 * * *") // 매일 UTC 기준 00시 58분 00초에 실행
|
||||
public void mcuScheduler() {
|
||||
log.info("run mcuScheduler");
|
||||
StartEndTime startEndTime = LogServiceHelper.getCurrentLogSearchEndTime(AdminConstants.STAT_DAY_NUM);
|
||||
mcuService.collectMaxCountUser(startEndTime.getStartTime(), startEndTime.getEndTime());
|
||||
log.info("end mcuScheduler");
|
||||
}
|
||||
|
||||
@Scheduled(cron = "00 59 0 * * *") // 매일 UTC 기준 00시 59분 00초에 실행
|
||||
public void nruScheduler() {
|
||||
log.info("run nruScheduler");
|
||||
StartEndTime startEndTime = LogServiceHelper.getCurrentLogSearchEndTime(AdminConstants.STAT_DAY_NUM);
|
||||
nruService.collectCharacterCreateCount(startEndTime.getStartTime(), startEndTime.getEndTime());
|
||||
log.info("end nruScheduler");
|
||||
}
|
||||
|
||||
@Scheduled(cron = "00 00 1 * * *") // 매일 UTC 기준 1시 00분 00초에 실행
|
||||
public void playTimeScheduler() {
|
||||
log.info("run playTimeScheduler");
|
||||
StartEndTime startEndTime = LogServiceHelper.getCurrentLogSearchEndTime(AdminConstants.STAT_DAY_NUM);
|
||||
playTimeService.collectUserPlayTime(startEndTime.getStartTime(), startEndTime.getEndTime());
|
||||
log.info("end playTimeScheduler");
|
||||
}
|
||||
|
||||
@Scheduled(cron = "00 01 1 * * *") // 매일 UTC 기준 01시 01분 00초에 실행
|
||||
public void dglcScheduler() {
|
||||
log.info("run dglcScheduler");
|
||||
StartEndTime startEndTime = LogServiceHelper.getCurrentLogSearchEndTime(AdminConstants.STAT_DAY_NUM);
|
||||
dglcService.collectDailyGameLoginCount(startEndTime.getStartTime(), startEndTime.getEndTime());
|
||||
log.info("end dglcScheduler");
|
||||
}
|
||||
|
||||
@Scheduled(cron = "00 00 2 * * *") // 매일 UTC 기준 02시 00분 00초에 실행 (Log 데이터가 늦게 넘어올때가 있기때문에 나중에 실행)
|
||||
public void ugqCreateScheduler() {
|
||||
log.info("run ugqCreateScheduler");
|
||||
StartEndTime startEndTime = LogServiceHelper.getCurrentLogSearchEndTime(AdminConstants.STAT_DAY_NUM);
|
||||
ugqCreateService.collectUGQCreateCount(startEndTime.getStartTime(), startEndTime.getEndTime());
|
||||
log.info("end ugqCreateScheduler");
|
||||
}
|
||||
|
||||
|
||||
@Scheduled(cron = "0 * * * * *") // 매 분 00초에 실행
|
||||
public void runJob() {
|
||||
//log.info("run runJob");
|
||||
}
|
||||
|
||||
@Scheduled(cron = "1 * * * * *")
|
||||
public void noticeJob(){
|
||||
log.info("run noticeJob");
|
||||
dynamicScheduler.noticeSchedule();
|
||||
log.info("end noticeJob");
|
||||
}
|
||||
|
||||
@Scheduled(cron = "2 * * * * *")
|
||||
public void mailJob(){
|
||||
log.info("run mailJob");
|
||||
dynamicScheduler.mailSchedule();
|
||||
log.info("end mailJob");
|
||||
}
|
||||
|
||||
@Scheduled(cron = "3 * * * * *")
|
||||
public void blackListJob(){
|
||||
log.info("run blackListJob");
|
||||
dynamicScheduler.blackListSchedule();
|
||||
log.info("end blackListJob");
|
||||
}
|
||||
|
||||
@Scheduled(cron = "4 * * * * *")
|
||||
public void eventJob(){
|
||||
log.info("run eventJob");
|
||||
dynamicScheduler.eventSchedule();
|
||||
log.info("end eventJob");
|
||||
}
|
||||
|
||||
//web3
|
||||
@Scheduled(cron = "1 * * * * *")
|
||||
public void web3Job(){
|
||||
log.info("run web3Job");
|
||||
caliumService.getScheduleCaliumRequestList();
|
||||
log.info("end web3Job");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.caliverse.admin.scheduler;
|
||||
|
||||
public enum ScheduleType {
|
||||
IMMEDIATE, //즉시 실행
|
||||
DELAYED, //지연 실행
|
||||
RECURRING, //반복 실행
|
||||
PERIODIC //특정 시간
|
||||
}
|
||||
10
src/main/java/com/caliverse/admin/scheduler/Scheduler.java
Normal file
10
src/main/java/com/caliverse/admin/scheduler/Scheduler.java
Normal file
@@ -0,0 +1,10 @@
|
||||
package com.caliverse.admin.scheduler;
|
||||
|
||||
import com.caliverse.admin.scheduler.config.ScheduleExecutionConfig;
|
||||
|
||||
public interface Scheduler {
|
||||
void execute();
|
||||
boolean isRepeatable();
|
||||
ScheduleType getScheduleType();
|
||||
ScheduleExecutionConfig getSchedulerConfig();
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.caliverse.admin.scheduler;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
|
||||
|
||||
@Configuration
|
||||
public class SchedulerConfig {
|
||||
|
||||
@Bean
|
||||
public ThreadPoolTaskScheduler taskScheduler() {
|
||||
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
|
||||
scheduler.setPoolSize(5); // 스레드 풀 크기 설정
|
||||
scheduler.setThreadNamePrefix("ScheduledTask-");
|
||||
return scheduler;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,433 @@
|
||||
package com.caliverse.admin.scheduler;
|
||||
|
||||
import com.caliverse.admin.scheduler.config.MissedExecutionConfig;
|
||||
import com.caliverse.admin.scheduler.config.ScheduleExecutionConfig;
|
||||
import com.caliverse.admin.scheduler.service.NoticeScheduler;
|
||||
import jakarta.annotation.PreDestroy;
|
||||
import lombok.*;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.*;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
public class SchedulerManager {
|
||||
private final ScheduledExecutorService scheduler;
|
||||
|
||||
// 실행 중인 작업 추적을 위한 Map
|
||||
private final Map<String, ScheduledTaskInfo> scheduledTasks = new ConcurrentHashMap<>();
|
||||
|
||||
// 재시도 설정
|
||||
private static final int MAX_RETRY_COUNT = 3;
|
||||
private static final long RETRY_DELAY_MS = 1000;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
//스케줄 프로세스 관리
|
||||
private static class ScheduledTaskInfo {
|
||||
private final Scheduler task;
|
||||
private final ScheduledFuture<?> future;
|
||||
private final LocalDateTime startTime;
|
||||
private int retryCount;
|
||||
private ScheduleStatus status;
|
||||
|
||||
public static ScheduledTaskInfo of(Scheduler task, ScheduledFuture<?> future) {
|
||||
return ScheduledTaskInfo.builder()
|
||||
.task(task)
|
||||
.future(future)
|
||||
.startTime(LocalDateTime.now())
|
||||
.retryCount(0)
|
||||
.status(ScheduleStatus.SCHEDULED)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum ScheduleStatus {
|
||||
SCHEDULED("예약됨"),
|
||||
RUNNING("실행 중"),
|
||||
COMPLETED("완료됨"),
|
||||
FAILED("실패"),
|
||||
CANCELLED("취소됨");
|
||||
|
||||
private final String description;
|
||||
}
|
||||
|
||||
//스케줄 실행
|
||||
public void scheduleTask(Scheduler task) {
|
||||
String taskId = task.getSchedulerConfig().getTaskId();
|
||||
|
||||
// 이미 존재하는 작업 체크
|
||||
if (scheduledTasks.containsKey(taskId)) {
|
||||
ScheduledTaskInfo existingTask = scheduledTasks.get(taskId);
|
||||
if (shouldReplaceExisting(existingTask)) {
|
||||
log.info("Replacing existing task: {}", taskId);
|
||||
cancelTask(taskId);
|
||||
} else {
|
||||
log.warn("Task {} is already scheduled and running", taskId);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
//타입별 스케줄러 등록
|
||||
ScheduledFuture<?> future = scheduleTaskByType(task);
|
||||
if (future != null) {
|
||||
ScheduledTaskInfo taskInfo = ScheduledTaskInfo.of(task, future);
|
||||
scheduledTasks.put(taskId, taskInfo);
|
||||
log.info("Successfully scheduled task: {}", taskId);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("Failed to schedule task: {}", taskId, e);
|
||||
throw new SchedulerException("Failed to schedule task: " + taskId, e);
|
||||
}
|
||||
}
|
||||
|
||||
//스케줄 상태 체크
|
||||
private boolean shouldReplaceExisting(ScheduledTaskInfo taskInfo) {
|
||||
return taskInfo.getStatus() == ScheduleStatus.FAILED ||
|
||||
taskInfo.getStatus() == ScheduleStatus.COMPLETED ||
|
||||
taskInfo.getFuture().isDone();
|
||||
}
|
||||
|
||||
//스케줄 타입 별 처리
|
||||
private ScheduledFuture<?> scheduleTaskByType(Scheduler task) {
|
||||
return switch (task.getScheduleType()) {
|
||||
case IMMEDIATE -> scheduleImmediate(task);
|
||||
case DELAYED -> scheduleDelayed(task);
|
||||
case RECURRING -> scheduleRecurring(task);
|
||||
case PERIODIC -> schedulePeriodic(task);
|
||||
};
|
||||
}
|
||||
|
||||
//즉시 실행
|
||||
private ScheduledFuture<?> scheduleImmediate(Scheduler task) {
|
||||
return (ScheduledFuture<?>) scheduler.submit(() -> executeTaskWithRetry(task));
|
||||
}
|
||||
|
||||
//지연 실행
|
||||
private ScheduledFuture<?> scheduleDelayed(Scheduler task) {
|
||||
ScheduleExecutionConfig config = task.getSchedulerConfig();
|
||||
long delay = calculateDelay(config.getStartTime());
|
||||
|
||||
if (delay < 0) {
|
||||
log.error("Task {} scheduled for past time", config.getTaskId());
|
||||
return null;
|
||||
}
|
||||
|
||||
return scheduler.schedule(
|
||||
() -> executeTaskWithRetry(task),
|
||||
delay,
|
||||
TimeUnit.MILLISECONDS
|
||||
);
|
||||
}
|
||||
|
||||
//반복 실행
|
||||
private ScheduledFuture<?> scheduleRecurring(Scheduler task) {
|
||||
ScheduleExecutionConfig config = task.getSchedulerConfig();
|
||||
long initialDelay = calculateDelay(config.getStartTime());
|
||||
|
||||
if (initialDelay < 0) {
|
||||
Duration timeSinceStart = Duration.between(config.getStartTime(), LocalDateTime.now());
|
||||
|
||||
// 종료 시간 체크
|
||||
if (config.getEndTime() != null && LocalDateTime.now().isAfter(config.getEndTime())) {
|
||||
log.warn("Task {} scheduled end time has passed", config.getTaskId());
|
||||
return null;
|
||||
}
|
||||
|
||||
// 다음 실행 시간 계산
|
||||
long interval = config.getInterval().toMillis();
|
||||
long missedExecutions = timeSinceStart.toMillis() / interval;
|
||||
initialDelay = interval - (timeSinceStart.toMillis() % interval);
|
||||
|
||||
log.info("Task {} was scheduled to start {} ago. Missed {} executions. " +
|
||||
"Next execution in {} ms",
|
||||
config.getTaskId(),
|
||||
timeSinceStart,
|
||||
missedExecutions,
|
||||
initialDelay);
|
||||
|
||||
if (shouldProcessMissedExecutions(task)) {
|
||||
processMissedExecutions(task, (int) missedExecutions);
|
||||
}
|
||||
}
|
||||
|
||||
return scheduler.scheduleAtFixedRate(
|
||||
() -> {
|
||||
String taskId = config.getTaskId();
|
||||
ScheduledTaskInfo taskInfo = scheduledTasks.get(taskId);
|
||||
|
||||
try {
|
||||
// NoticeSchedule 경우 추가 검증
|
||||
if (task instanceof NoticeScheduler noticeTask) {
|
||||
if (noticeTask.hasReachedMaxExecutions()) {
|
||||
cancelTask(taskId);
|
||||
log.info("Cancelling notice task - reached max executions. TaskId: {}", taskId);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!noticeTask.isValidExecutionCount()) {
|
||||
log.error("Invalid execution count detected. TaskId: {}", taskId);
|
||||
cancelTask(taskId);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldStopRecurring(task)) {
|
||||
cancelTask(taskId);
|
||||
return;
|
||||
}
|
||||
|
||||
taskInfo.setStatus(ScheduleStatus.RUNNING);
|
||||
task.execute();
|
||||
taskInfo.setStatus(ScheduleStatus.SCHEDULED);
|
||||
|
||||
} catch (Exception e) {
|
||||
handleTaskExecutionFailure(task, taskInfo, e);
|
||||
}
|
||||
},
|
||||
initialDelay,
|
||||
config.getInterval().toMillis(),
|
||||
TimeUnit.MILLISECONDS
|
||||
);
|
||||
}
|
||||
|
||||
//주기적 실행
|
||||
private ScheduledFuture<?> schedulePeriodic(Scheduler task){
|
||||
ScheduleExecutionConfig config = task.getSchedulerConfig();
|
||||
LocalTime executionTime = config.getDailyExecutionTime();
|
||||
|
||||
if (executionTime == null) {
|
||||
log.error("Daily execution time is not set for task: {}", config.getTaskId());
|
||||
return null;
|
||||
}
|
||||
|
||||
// 현재 시간
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
|
||||
// 시작일이 미래인 경우, 시작일의 지정 시간을 첫 실행 시간으로 설정
|
||||
// 시작일이 과거인 경우, 오늘 또는 다음 날의 지정 시간을 첫 실행 시간으로 설정
|
||||
LocalDateTime firstExecution = calculateFirstExecution(now, config.getStartTime(), executionTime);
|
||||
|
||||
// 종료 시간 확인
|
||||
if (config.getEndTime() != null && firstExecution.isAfter(config.getEndTime())) {
|
||||
log.warn("Task {} end time has already passed", config.getTaskId());
|
||||
return null;
|
||||
}
|
||||
|
||||
// 첫 실행까지의 지연 시간 계산
|
||||
long initialDelay = Duration.between(now, firstExecution).toMillis();
|
||||
|
||||
// 24시간을 밀리초로 변환
|
||||
long dailyInterval = Duration.ofDays(1).toMillis();
|
||||
|
||||
return scheduler.scheduleAtFixedRate(
|
||||
() -> executeDaily(task),
|
||||
initialDelay,
|
||||
dailyInterval,
|
||||
TimeUnit.MILLISECONDS
|
||||
);
|
||||
}
|
||||
|
||||
private LocalDateTime calculateFirstExecution(
|
||||
LocalDateTime now,
|
||||
LocalDateTime startTime,
|
||||
LocalTime executionTime
|
||||
) {
|
||||
LocalDateTime candidateTime = now.with(executionTime);
|
||||
|
||||
// 시작 시간이 미래인 경우
|
||||
if (startTime.isAfter(now)) {
|
||||
candidateTime = startTime.with(executionTime);
|
||||
}
|
||||
|
||||
// 만약 오늘의 실행 시간이 이미 지났다면 다음 날로 설정
|
||||
if (candidateTime.isBefore(now)) {
|
||||
candidateTime = candidateTime.plusDays(1);
|
||||
}
|
||||
|
||||
return candidateTime;
|
||||
}
|
||||
|
||||
private void executeDaily(Scheduler task) {
|
||||
String taskId = task.getSchedulerConfig().getTaskId();
|
||||
ScheduledTaskInfo taskInfo = scheduledTasks.get(taskId);
|
||||
|
||||
try {
|
||||
// 현재 시간이 종료 시간을 지났는지 확인
|
||||
if (shouldStopDaily(task)) {
|
||||
cancelTask(taskId);
|
||||
return;
|
||||
}
|
||||
|
||||
// 지정된 시간에만 실행
|
||||
LocalTime currentTime = LocalTime.now();
|
||||
LocalTime executionTime = task.getSchedulerConfig().getDailyExecutionTime();
|
||||
|
||||
if (currentTime.getHour() == executionTime.getHour() &&
|
||||
currentTime.getMinute() == executionTime.getMinute()) {
|
||||
|
||||
taskInfo.setStatus(ScheduleStatus.RUNNING);
|
||||
task.execute();
|
||||
taskInfo.setStatus(ScheduleStatus.SCHEDULED);
|
||||
|
||||
log.info("Daily task {} executed at scheduled time: {}",
|
||||
taskId, executionTime);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
handleTaskExecutionFailure(task, taskInfo, e);
|
||||
}
|
||||
}
|
||||
|
||||
//종료일자 체크
|
||||
private boolean shouldStopDaily(Scheduler task) {
|
||||
ScheduleExecutionConfig config = task.getSchedulerConfig();
|
||||
if (config.getEndTime() == null) {
|
||||
return false;
|
||||
}
|
||||
return LocalDateTime.now().isAfter(config.getEndTime());
|
||||
}
|
||||
|
||||
private boolean shouldProcessMissedExecutions(Scheduler task) {
|
||||
// 작업 유형에 따라 누락된 실행 처리 여부 결정
|
||||
return task.getSchedulerConfig().isProcessMissedExecutions();
|
||||
}
|
||||
|
||||
private void processMissedExecutions(Scheduler task, int missedCount) {
|
||||
// 누락된 실행 처리를 위한 설정 가져오기
|
||||
MissedExecutionConfig missedConfig = task.getSchedulerConfig().getMissedExecutionConfig();
|
||||
if (missedConfig == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
int executionsToProcess = Math.min(
|
||||
missedCount,
|
||||
missedConfig.getMaxMissedExecutionsToProcess()
|
||||
);
|
||||
|
||||
if (executionsToProcess <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
CompletableFuture.runAsync(() -> {
|
||||
try {
|
||||
log.info("Processing {} missed executions for task {}", executionsToProcess, task.getSchedulerConfig().getTaskId());
|
||||
|
||||
for (int i = 0; i < executionsToProcess; i++) {
|
||||
if (missedConfig.isSequentialProcessing()) {
|
||||
task.execute();
|
||||
} else {
|
||||
// 마지막 실행만 처리
|
||||
if (i == executionsToProcess - 1) {
|
||||
task.execute();
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("Error processing missed executions for task {}",
|
||||
task.getSchedulerConfig().getTaskId(), e);
|
||||
}
|
||||
}, scheduler);
|
||||
}
|
||||
|
||||
private void executeTaskWithRetry(Scheduler task) {
|
||||
String taskId = task.getSchedulerConfig().getTaskId();
|
||||
ScheduledTaskInfo taskInfo = scheduledTasks.get(taskId);
|
||||
|
||||
try {
|
||||
taskInfo.setStatus(ScheduleStatus.RUNNING);
|
||||
task.execute();
|
||||
taskInfo.setStatus(ScheduleStatus.COMPLETED);
|
||||
log.info("Task {} completed successfully", taskId);
|
||||
|
||||
} catch (Exception e) {
|
||||
handleTaskExecutionFailure(task, taskInfo, e);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleTaskExecutionFailure(Scheduler task, ScheduledTaskInfo taskInfo, Exception e) {
|
||||
String taskId = task.getSchedulerConfig().getTaskId();
|
||||
taskInfo.setRetryCount(taskInfo.getRetryCount() + 1);
|
||||
|
||||
if (taskInfo.getRetryCount() < MAX_RETRY_COUNT) {
|
||||
log.warn("Task {} failed, attempting retry {}/{}",
|
||||
taskId, taskInfo.getRetryCount(), MAX_RETRY_COUNT, e);
|
||||
|
||||
scheduler.schedule(
|
||||
() -> executeTaskWithRetry(task),
|
||||
RETRY_DELAY_MS,
|
||||
TimeUnit.MILLISECONDS
|
||||
);
|
||||
} else {
|
||||
log.error("Task {} failed after {} retries", taskId, MAX_RETRY_COUNT, e);
|
||||
taskInfo.setStatus(ScheduleStatus.FAILED);
|
||||
cancelTask(taskId);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean shouldStopRecurring(Scheduler task) {
|
||||
ScheduleExecutionConfig config = task.getSchedulerConfig();
|
||||
|
||||
// 종료 시간 체크
|
||||
if (config.getEndTime() != null && LocalDateTime.now().isAfter(config.getEndTime())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 반복 횟수 체크
|
||||
if (config.getRepeatCount() != null) {
|
||||
String taskId = config.getTaskId();
|
||||
ScheduledTaskInfo taskInfo = scheduledTasks.get(taskId);
|
||||
return taskInfo.getRetryCount() >= config.getRepeatCount();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void cancelTask(String taskId) {
|
||||
ScheduledTaskInfo taskInfo = scheduledTasks.get(taskId);
|
||||
if (taskInfo != null) {
|
||||
taskInfo.getFuture().cancel(false);
|
||||
taskInfo.setStatus(ScheduleStatus.CANCELLED);
|
||||
scheduledTasks.remove(taskId);
|
||||
log.info("Task {} cancelled and removed from scheduler", taskId);
|
||||
}
|
||||
}
|
||||
|
||||
public void cancelAllTasks() {
|
||||
scheduledTasks.keySet().forEach(this::cancelTask);
|
||||
}
|
||||
|
||||
private long calculateDelay(LocalDateTime startTime) {
|
||||
return Duration.between(LocalDateTime.now(), startTime).toMillis();
|
||||
}
|
||||
|
||||
@PreDestroy
|
||||
public void shutdown() {
|
||||
cancelAllTasks();
|
||||
scheduler.shutdown();
|
||||
try {
|
||||
if (!scheduler.awaitTermination(60, TimeUnit.SECONDS)) {
|
||||
scheduler.shutdownNow();
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
scheduler.shutdownNow();
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
// 스케줄러 관련 예외 클래스
|
||||
public static class SchedulerException extends RuntimeException {
|
||||
public SchedulerException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.caliverse.admin.scheduler;
|
||||
|
||||
import com.caliverse.admin.domain.entity.InGame;
|
||||
import com.caliverse.admin.domain.entity.Mail;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
|
||||
@Service
|
||||
public class SchedulerService {
|
||||
|
||||
private final Map<String, ScheduledFuture<?>> scheduledTasks = new ConcurrentHashMap<>();
|
||||
|
||||
private final Map<Long, Mail> mailTask = new ConcurrentHashMap<>();
|
||||
private final Map<Long, InGame> noticeTask = new ConcurrentHashMap<>();
|
||||
|
||||
public boolean isTaskExist(String key){
|
||||
return scheduledTasks.containsKey(key);
|
||||
}
|
||||
|
||||
public void addTask(String key, ScheduledFuture<?> schdule){
|
||||
scheduledTasks.put(key, schdule);
|
||||
}
|
||||
|
||||
public void closeTask(String key) {
|
||||
ScheduledFuture<?> scheduledFuture = scheduledTasks.get(key);
|
||||
if (scheduledFuture != null) {
|
||||
scheduledFuture.cancel(true);
|
||||
scheduledTasks.remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
// public boolean isTaskExist(String type, Long id) {
|
||||
// switch (type) {
|
||||
// case "mail" -> {
|
||||
// return mailTask.containsKey(id);
|
||||
// }
|
||||
// case "notice" -> {
|
||||
// return noticeTask.containsKey(id);
|
||||
// }
|
||||
// default -> {
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// public void createTask(Mail mail) {
|
||||
// mailTask.put(mail.getId(), mail);
|
||||
// }
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.caliverse.admin.scheduler.config;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class MissedExecutionConfig {
|
||||
@Builder.Default
|
||||
private int maxMissedExecutionsToProcess = 1; // 기본값으로 최근 1회만 처리
|
||||
|
||||
@Builder.Default
|
||||
private boolean sequentialProcessing = false; // 기본값으로 순차 처리하지 않음
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.caliverse.admin.scheduler.config;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class ScheduleExecutionConfig {
|
||||
private String taskId;
|
||||
private LocalDateTime startTime;
|
||||
private LocalDateTime endTime;
|
||||
private Duration interval;
|
||||
private Integer repeatCount;
|
||||
private String cronExpression;
|
||||
private LocalTime dailyExecutionTime;
|
||||
|
||||
@Builder.Default
|
||||
private boolean processMissedExecutions = false;
|
||||
|
||||
private MissedExecutionConfig missedExecutionConfig;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.caliverse.admin.scheduler.config;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
||||
@Configuration
|
||||
@Slf4j
|
||||
public class ScheduleSystemConfig {
|
||||
@Bean
|
||||
public ScheduledExecutorService scheduledExecutorService() {
|
||||
return Executors.newScheduledThreadPool(
|
||||
Runtime.getRuntime().availableProcessors(),
|
||||
r -> {
|
||||
Thread thread = new Thread(r, "scheduler-");
|
||||
thread.setDaemon(true);
|
||||
return thread;
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
package com.caliverse.admin.scheduler.service;
|
||||
|
||||
import com.caliverse.admin.domain.entity.BlackList;
|
||||
import com.caliverse.admin.domain.service.BlackListService;
|
||||
import com.caliverse.admin.domain.service.UserGameSessionService;
|
||||
import com.caliverse.admin.scheduler.ScheduleType;
|
||||
import com.caliverse.admin.scheduler.Scheduler;
|
||||
import com.caliverse.admin.scheduler.config.ScheduleExecutionConfig;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Slf4j
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class BlackListScheduler implements Scheduler {
|
||||
private BlackList blackList;
|
||||
private BlackListService blackListService;
|
||||
private UserGameSessionService userGameSessionService;
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
try {
|
||||
processBlackList();
|
||||
} catch (Exception e) {
|
||||
log.error("BlackList execution failed for ID: {}", blackList.getId(), e);
|
||||
blackListService.updateBlackListStatus(blackList.getId(), BlackList.STATUSTYPE.FAIL);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRepeatable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScheduleType getScheduleType() {
|
||||
return ScheduleType.DELAYED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScheduleExecutionConfig getSchedulerConfig() {
|
||||
return ScheduleExecutionConfig.builder()
|
||||
.taskId("blacklist-" + blackList.getId())
|
||||
.startTime(blackList.getStartDt())
|
||||
.endTime(blackList.getEndDt())
|
||||
.build();
|
||||
}
|
||||
|
||||
private void processBlackList() {
|
||||
LocalDateTime nowDate = LocalDateTime.now();
|
||||
LocalDateTime startTime = blackList.getStartDt();
|
||||
LocalDateTime endTime = blackList.getEndDt();
|
||||
|
||||
// 이미 지난시간이면 fail 처리
|
||||
if(nowDate.isAfter(endTime) && blackList.getStatus().equals(BlackList.STATUSTYPE.WAIT)) {
|
||||
blackListService.updateBlackListStatus(blackList.getId(), BlackList.STATUSTYPE.FAIL);
|
||||
log.error("blackListJob blackListSchedule timeOut : {}", blackList);
|
||||
return;
|
||||
}
|
||||
|
||||
// 시작시간 지났으면 정지 처리
|
||||
if(!nowDate.isBefore(startTime) && blackList.getStatus().equals(BlackList.STATUSTYPE.WAIT)) {
|
||||
// user kick 처리
|
||||
userGameSessionService.kickUserSession(blackList.getGuid());
|
||||
blackListService.updateScheduleBlockUser(blackList, "start");
|
||||
blackListService.updateBlackListStatus(blackList.getId(), BlackList.STATUSTYPE.INPROGRESS);
|
||||
log.info("blackListJob blackListSchedule block start : {}", blackList);
|
||||
}
|
||||
|
||||
// 종료시간 지났으면 만료 처리
|
||||
if(!nowDate.isBefore(endTime) && blackList.getStatus().equals(BlackList.STATUSTYPE.INPROGRESS)) {
|
||||
blackListService.updateScheduleBlockUser(blackList, "end");
|
||||
blackListService.updateBlackListStatus(blackList.getId(), BlackList.STATUSTYPE.EXPIRATION);
|
||||
log.info("blackListJob blackListSchedule block end : {}", blackList);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,216 @@
|
||||
package com.caliverse.admin.scheduler.service;
|
||||
|
||||
import com.caliverse.admin.domain.RabbitMq.MessageHandlerService;
|
||||
import com.caliverse.admin.domain.RabbitMq.message.LanguageType;
|
||||
import com.caliverse.admin.domain.RabbitMq.message.MailItem;
|
||||
import com.caliverse.admin.domain.entity.*;
|
||||
import com.caliverse.admin.domain.service.EventService;
|
||||
import com.caliverse.admin.domain.service.HistoryService;
|
||||
import com.caliverse.admin.dynamodb.entity.SystemMessage;
|
||||
import com.caliverse.admin.redis.service.RedisUserInfoService;
|
||||
import com.caliverse.admin.global.common.utils.CommonUtils;
|
||||
import com.caliverse.admin.global.common.utils.JsonUtils;
|
||||
import com.caliverse.admin.scheduler.config.ScheduleExecutionConfig;
|
||||
import com.caliverse.admin.scheduler.ScheduleType;
|
||||
import com.caliverse.admin.scheduler.Scheduler;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.node.ArrayNode;
|
||||
import lombok.*;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Slf4j
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class EventScheduler implements Scheduler {
|
||||
private Event event;
|
||||
private EventService eventService;
|
||||
private RedisUserInfoService redisUserInfoService;
|
||||
private MessageHandlerService messageHandlerService;
|
||||
private HistoryService historyService;
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
try {
|
||||
processEvent();
|
||||
} catch (Exception e) {
|
||||
log.error("Event execution failed for event ID: {}", event.getId(), e);
|
||||
eventService.updateEventStatus(event.getId(), Event.EVENTSTATUS.FAIL);
|
||||
historyService.setScheduleLog(HISTORYTYPE.SCHEDULE_EVENT_FAIL, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRepeatable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScheduleType getScheduleType() {
|
||||
return ScheduleType.DELAYED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScheduleExecutionConfig getSchedulerConfig() {
|
||||
return ScheduleExecutionConfig.builder()
|
||||
.taskId("event-" + event.getId())
|
||||
.startTime(event.getStartDt())
|
||||
.endTime(event.getEndDt())
|
||||
.build();
|
||||
}
|
||||
|
||||
private void processEvent() {
|
||||
LocalDateTime nowDate = LocalDateTime.now();
|
||||
LocalDateTime startTime = event.getStartDt();
|
||||
LocalDateTime endTime = event.getEndDt();
|
||||
|
||||
// 이벤트가 이미 종료되었는지 체크
|
||||
if (nowDate.isAfter(endTime) && event.getStatus().equals(Event.EVENTSTATUS.WAIT)) {
|
||||
eventService.updateEventStatus(event.getId(), Event.EVENTSTATUS.FAIL);
|
||||
log.error("eventJob eventSchedule timeOut : {}", event);
|
||||
return;
|
||||
}
|
||||
|
||||
// 시작 30분 전에 게임 DB에 insert
|
||||
if (event.getStatus().equals(Event.EVENTSTATUS.WAIT)
|
||||
&& Duration.between(nowDate, startTime).abs().toMinutes() <= 30
|
||||
&& !event.isAddFlag()) {
|
||||
|
||||
systemMailInsert();
|
||||
eventService.updateEventStatus(event.getId(), Event.EVENTSTATUS.RUNNING);
|
||||
log.info("eventJob eventSchedule dynamoDB Insert & Start: {}", event);
|
||||
}
|
||||
|
||||
// 종료 시간이 되면 이벤트 종료
|
||||
if (!nowDate.isBefore(endTime) && event.getStatus().equals(Event.EVENTSTATUS.RUNNING)) {
|
||||
eventService.updateEventStatus(event.getId(), Event.EVENTSTATUS.FINISH);
|
||||
log.info("eventJob eventSchedule block end : {}", event);
|
||||
}
|
||||
}
|
||||
|
||||
private void systemMailInsert() {
|
||||
try {
|
||||
log.info("systemMailInsert Info: {}", event);
|
||||
|
||||
// 메시지 처리
|
||||
List<SystemMessage> mailTitleMessages = new ArrayList<>();
|
||||
List<SystemMessage> mailTextMessages = new ArrayList<>();
|
||||
List<SystemMessage> mailSenderMessages = new ArrayList<>();
|
||||
List<MailItem> mailItems = new ArrayList<>();
|
||||
|
||||
processMessages(mailTitleMessages, mailTextMessages, mailSenderMessages);
|
||||
processItems(mailItems);
|
||||
|
||||
// JSON 변환
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
ArrayNode mailTitleArray = convertToJsonArray(objectMapper, mailTitleMessages);
|
||||
ArrayNode mailTextArray = convertToJsonArray(objectMapper, mailTextMessages);
|
||||
ArrayNode mailSenderArray = convertToJsonArray(objectMapper, mailSenderMessages);
|
||||
ArrayNode mailItemArray = convertToJsonArray(objectMapper, mailItems);
|
||||
|
||||
// 시스템 메일 등록
|
||||
eventService.insertSystemMail(
|
||||
event,
|
||||
mailTitleArray,
|
||||
mailTextArray,
|
||||
mailSenderArray,
|
||||
mailItemArray
|
||||
);
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("systemMailInsert Exception: {}", e.getMessage());
|
||||
eventService.updateEventStatus(event.getId(), Event.EVENTSTATUS.FAIL);
|
||||
historyService.setScheduleLog(HISTORYTYPE.SCHEDULE_EVENT_FAIL, e.getMessage());
|
||||
throw new RuntimeException("Failed to insert system mail", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void processMessages(
|
||||
List<SystemMessage> titleMessages,
|
||||
List<SystemMessage> textMessages,
|
||||
List<SystemMessage> senderMessages
|
||||
) {
|
||||
List<Message> msgList = eventService.getMessageList(event.getId());
|
||||
|
||||
for (Message msg : msgList) {
|
||||
LanguageConfig langConfig = getLanguageConfig(msg.getLanguage());
|
||||
|
||||
// Title message
|
||||
titleMessages.add(SystemMessage.builder()
|
||||
.languageType(langConfig.getLangType())
|
||||
.text(msg.getTitle())
|
||||
.build());
|
||||
|
||||
// Content message
|
||||
textMessages.add(SystemMessage.builder()
|
||||
.languageType(langConfig.getLangType())
|
||||
.text(msg.getContent())
|
||||
.build());
|
||||
|
||||
// Sender message
|
||||
senderMessages.add(SystemMessage.builder()
|
||||
.languageType(langConfig.getLangType())
|
||||
.text(langConfig.getSender())
|
||||
.build());
|
||||
}
|
||||
}
|
||||
|
||||
private void processItems(List<MailItem> mailItems) {
|
||||
List<Item> itemList = eventService.getItemList(event.getId());
|
||||
|
||||
for (Item item : itemList) {
|
||||
mailItems.add(MailItem.newBuilder()
|
||||
.setItemId(CommonUtils.stringToInt(item.getItem()))
|
||||
.setCount(item.getItemCnt())
|
||||
.build());
|
||||
}
|
||||
}
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
private static class LanguageConfig {
|
||||
int langType;
|
||||
String sender;
|
||||
|
||||
static LanguageConfig from(String language) {
|
||||
return switch (language) {
|
||||
case "EN" -> new LanguageConfig(
|
||||
LanguageType.LanguageType_en.getNumber(),
|
||||
"CALIVERSE"
|
||||
);
|
||||
case "JA" -> new LanguageConfig(
|
||||
LanguageType.LanguageType_ja.getNumber(),
|
||||
"カリバース"
|
||||
);
|
||||
default -> new LanguageConfig(
|
||||
LanguageType.LanguageType_ko.getNumber(),
|
||||
"칼리버스"
|
||||
);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private LanguageConfig getLanguageConfig(String language) {
|
||||
return LanguageConfig.from(language);
|
||||
}
|
||||
|
||||
private <T> ArrayNode convertToJsonArray(ObjectMapper objectMapper, List<T> items) {
|
||||
ArrayNode arrayNode = objectMapper.createArrayNode();
|
||||
|
||||
items.forEach(item -> {
|
||||
if (item instanceof SystemMessage) {
|
||||
arrayNode.add(JsonUtils.createSystemMessage((SystemMessage) item));
|
||||
} else if (item instanceof MailItem) {
|
||||
arrayNode.add(JsonUtils.createMAilItem((MailItem) item));
|
||||
}
|
||||
});
|
||||
|
||||
return arrayNode;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.caliverse.admin.scheduler.service;
|
||||
|
||||
public interface LogCompressService {
|
||||
void compressLastMonthLogs();
|
||||
}
|
||||
@@ -0,0 +1,194 @@
|
||||
package com.caliverse.admin.scheduler.service;
|
||||
|
||||
import com.caliverse.admin.domain.RabbitMq.MessageHandlerService;
|
||||
import com.caliverse.admin.domain.RabbitMq.message.LanguageType;
|
||||
import com.caliverse.admin.domain.RabbitMq.message.MailItem;
|
||||
import com.caliverse.admin.domain.RabbitMq.message.OperationSystemMessage;
|
||||
import com.caliverse.admin.domain.entity.*;
|
||||
import com.caliverse.admin.domain.service.MailService;
|
||||
import com.caliverse.admin.redis.service.RedisUserInfoService;
|
||||
import com.caliverse.admin.domain.entity.redis.RedisLoginInfo;
|
||||
import com.caliverse.admin.global.common.utils.CommonUtils;
|
||||
import com.caliverse.admin.global.common.utils.ExcelUtils;
|
||||
import com.caliverse.admin.scheduler.config.ScheduleExecutionConfig;
|
||||
import com.caliverse.admin.scheduler.ScheduleType;
|
||||
import com.caliverse.admin.scheduler.Scheduler;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Slf4j
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class MailScheduler implements Scheduler {
|
||||
private Mail mail;
|
||||
private MailService mailService;
|
||||
private RedisUserInfoService redisUserInfoService;
|
||||
private MessageHandlerService messageHandlerService;
|
||||
private ExcelUtils excelUtils;
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
try {
|
||||
processMail();
|
||||
} catch (Exception e) {
|
||||
log.error("Mail execution failed for mail ID: {}", mail.getId(), e);
|
||||
mailService.updateMailStatus(mail.getId(), Mail.SENDSTATUS.FAIL);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRepeatable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScheduleType getScheduleType() {
|
||||
return mail.getSendType() == Mail.SENDTYPE.DIRECT_SEND
|
||||
? ScheduleType.IMMEDIATE
|
||||
: ScheduleType.DELAYED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScheduleExecutionConfig getSchedulerConfig() {
|
||||
return ScheduleExecutionConfig.builder()
|
||||
.taskId("mail-" + mail.getId())
|
||||
.startTime(mail.getSendDt())
|
||||
.build();
|
||||
}
|
||||
|
||||
private void processMail() {
|
||||
if (mail.getReceiveType().equals(Mail.RECEIVETYPE.SINGLE)) {
|
||||
boolean isSend = mailSend(mail);
|
||||
if (isSend) {
|
||||
mailService.updateMailStatus(mail.getId(), Mail.SENDSTATUS.FINISH);
|
||||
}
|
||||
} else {
|
||||
List<Excel> excelList = excelUtils.getExcelListData(mail.getTarget());
|
||||
log.info("mailJob mailSchedule schedule run ExcelList : {}", excelList);
|
||||
boolean isSend;
|
||||
mailService.updateMailStatus(mail.getId(), Mail.SENDSTATUS.RUNNING);
|
||||
|
||||
for (Excel excel : excelList) {
|
||||
String guid = mailService.getGuid(excel.getUser(), excel.getType());
|
||||
Mail tempMail = copyMailWithNewTarget(mail, guid);
|
||||
isSend = mailSend(tempMail);
|
||||
|
||||
if (!isSend) {
|
||||
log.error("mailJob mailSchedule Excel fail user : {}", excel.getUser());
|
||||
mailService.setScheduleLog(HISTORYTYPE.SCHEDULE_MAIL_FAIL,
|
||||
"mail schedule id: " + mail.getId() + " Excel Send Fail User: " + excel.getUser());
|
||||
} else {
|
||||
log.info("mailJob mailSchedule Excel send user : {}", excel.getUser());
|
||||
}
|
||||
}
|
||||
mailService.updateMailStatus(mail.getId(), Mail.SENDSTATUS.FINISH);
|
||||
}
|
||||
}
|
||||
|
||||
private Mail copyMailWithNewTarget(Mail originalMail, String newTarget) {
|
||||
Mail newMail = new Mail();
|
||||
BeanUtils.copyProperties(originalMail, newMail);
|
||||
newMail.setTarget(newTarget);
|
||||
return newMail;
|
||||
}
|
||||
|
||||
// 메일 전송
|
||||
private boolean mailSend(Mail mail) {
|
||||
try {
|
||||
RedisLoginInfo info = redisUserInfoService.getUserLoginSessionInfo(mail.getTarget());
|
||||
String serverName = Optional.ofNullable(info)
|
||||
.map(RedisLoginInfo::getCurrentServer)
|
||||
.orElseGet(() -> {
|
||||
String firstChannel = redisUserInfoService.getFirstChannel();
|
||||
if (firstChannel == null) {
|
||||
log.error("mailJob mailSend serverName is empty");
|
||||
mailService.updateMailStatus(mail.getId(), Mail.SENDSTATUS.FAIL);
|
||||
mailService.setScheduleLog(HISTORYTYPE.MAIL_SEND_FAIL, "is null server name");
|
||||
return null;
|
||||
}
|
||||
return firstChannel;
|
||||
});
|
||||
|
||||
if (serverName == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
List<Message> msgList = mailService.getMailMessageList(mail.getId());
|
||||
List<OperationSystemMessage> titleList = new ArrayList<>();
|
||||
List<OperationSystemMessage> contentList = new ArrayList<>();
|
||||
List<OperationSystemMessage> senderList = new ArrayList<>();
|
||||
|
||||
for (Message msg : msgList) {
|
||||
LanguageType lang;
|
||||
String sender;
|
||||
|
||||
switch (msg.getLanguage()) {
|
||||
case "EN" -> {
|
||||
lang = LanguageType.LanguageType_en;
|
||||
sender = "Administrator";
|
||||
}
|
||||
case "JA" -> {
|
||||
lang = LanguageType.LanguageType_ja;
|
||||
sender = "アドミニストレーター";
|
||||
}
|
||||
default -> {
|
||||
lang = LanguageType.LanguageType_ko;
|
||||
sender = "시스템 관리자";
|
||||
}
|
||||
}
|
||||
|
||||
titleList.add(createOperationSystemMessage(lang, msg.getTitle()));
|
||||
contentList.add(createOperationSystemMessage(lang, msg.getContent()));
|
||||
senderList.add(createOperationSystemMessage(lang, sender));
|
||||
}
|
||||
|
||||
List<Item> itemList = mailService.getMailItemList(mail.getId());
|
||||
List<MailItem> mailItemList = itemList.stream()
|
||||
.map(item -> MailItem.newBuilder()
|
||||
.setItemId(CommonUtils.stringToInt(item.getItem()))
|
||||
.setCount(item.getItemCnt())
|
||||
.build())
|
||||
.collect(Collectors.toList());
|
||||
|
||||
log.info("Send Mail Message : {}, target : {}, type :{}",
|
||||
contentList, mail.getTarget(), mail.getMailType());
|
||||
|
||||
messageHandlerService.sendMailMessage(
|
||||
serverName,
|
||||
mail.getTarget(),
|
||||
mail.getMailType().toString(),
|
||||
titleList,
|
||||
contentList,
|
||||
mailItemList,
|
||||
senderList
|
||||
);
|
||||
|
||||
log.info("mailJob mailSend completed");
|
||||
return true;
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("mailSend Exception: {}", e.getMessage());
|
||||
mailService.updateMailStatus(mail.getId(), Mail.SENDSTATUS.FAIL);
|
||||
mailService.setScheduleLog(HISTORYTYPE.MAIL_SEND_FAIL, e.getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private OperationSystemMessage createOperationSystemMessage(LanguageType lang, String text) {
|
||||
return OperationSystemMessage.newBuilder()
|
||||
.setLanguageType(lang)
|
||||
.setText(CommonUtils.stringToByte(text))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,228 @@
|
||||
package com.caliverse.admin.scheduler.service;
|
||||
|
||||
import com.caliverse.admin.domain.RabbitMq.MessageHandlerService;
|
||||
import com.caliverse.admin.domain.RabbitMq.message.LanguageType;
|
||||
import com.caliverse.admin.domain.RabbitMq.message.OperationSystemMessage;
|
||||
import com.caliverse.admin.domain.entity.HISTORYTYPE;
|
||||
import com.caliverse.admin.domain.entity.InGame;
|
||||
import com.caliverse.admin.domain.entity.Message;
|
||||
import com.caliverse.admin.domain.service.NoticeService;
|
||||
import com.caliverse.admin.redis.service.RedisUserInfoService;
|
||||
import com.caliverse.admin.global.common.utils.CommonUtils;
|
||||
import com.caliverse.admin.scheduler.config.ScheduleExecutionConfig;
|
||||
import com.caliverse.admin.scheduler.ScheduleType;
|
||||
import com.caliverse.admin.scheduler.Scheduler;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import java.time.Duration;
|
||||
import java.time.LocalTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
@Slf4j
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class NoticeScheduler implements Scheduler {
|
||||
private InGame notice;
|
||||
private NoticeService noticeService;
|
||||
private RedisUserInfoService redisUserInfoService;
|
||||
private MessageHandlerService messageHandlerService;
|
||||
|
||||
private final AtomicInteger currentExecutionCount = new AtomicInteger(0); // 현재 실행 횟수를 추적
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
try {
|
||||
// 실행 전 횟수 체크
|
||||
if (shouldStopExecution()) {
|
||||
log.info("Notice execution stopped - Reached maximum count. NoticeId: {}, Current count: {}, Max count: {}",
|
||||
notice.getId(), getCurrentCount(), getMaxCount());
|
||||
noticeService.updateNoticeStatus(notice.getId(), InGame.SENDSTATUS.FINISH);
|
||||
return;
|
||||
}
|
||||
|
||||
// 실행 횟수 증가 및 검증
|
||||
int newCount = currentExecutionCount.incrementAndGet();
|
||||
if (newCount > getMaxCount()) {
|
||||
log.warn("Notice execution exceeded max count. NoticeId: {}, Current count: {}, Max count: {}",
|
||||
notice.getId(), newCount, getMaxCount());
|
||||
noticeService.updateNoticeStatus(notice.getId(), InGame.SENDSTATUS.FINISH);
|
||||
return;
|
||||
}
|
||||
|
||||
boolean isSend = noticeSend();
|
||||
if (!isSend) {
|
||||
// 전송 실패 시 카운트 롤백
|
||||
currentExecutionCount.decrementAndGet();
|
||||
return;
|
||||
}
|
||||
|
||||
if(notice.getSendStatus().equals(InGame.SENDSTATUS.WAIT)) {
|
||||
noticeService.updateNoticeStatus(notice.getId(), InGame.SENDSTATUS.RUNNING);
|
||||
}
|
||||
|
||||
// DB 업데이트 전 한번 더 체크
|
||||
if (newCount <= getMaxCount()) {
|
||||
noticeService.updateNoticeCount(notice.getId());
|
||||
log.info("Notice execution successful. NoticeId: {}, Current count: {}, Max count: {}",
|
||||
notice.getId(), newCount, getMaxCount());
|
||||
|
||||
// 최대 횟수 도달 시 상태 업데이트
|
||||
if (newCount >= getMaxCount()) {
|
||||
noticeService.updateNoticeStatus(notice.getId(), InGame.SENDSTATUS.FINISH);
|
||||
log.info("Notice completed all executions. NoticeId: {}", notice.getId());
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
currentExecutionCount.decrementAndGet();
|
||||
log.error("Notice execution failed for notice ID: {}", notice.getId(), e);
|
||||
noticeService.updateNoticeStatus(notice.getId(), InGame.SENDSTATUS.FAIL);
|
||||
noticeService.setScheduleLog(HISTORYTYPE.SCHEDULE_NOTICE_FAIL, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private boolean shouldStopExecution() {
|
||||
if (!notice.getIsRepeat() || notice.getRepeatType() != InGame.REPEATTYPE.COUNT) {
|
||||
return false;
|
||||
}
|
||||
return getCurrentCount() >= getMaxCount();
|
||||
}
|
||||
|
||||
private int getCurrentCount() {
|
||||
return currentExecutionCount.get();
|
||||
}
|
||||
|
||||
private int getMaxCount() {
|
||||
return notice.getRepeatCnt().intValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRepeatable() {
|
||||
return notice.getIsRepeat();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScheduleType getScheduleType() {
|
||||
if (!notice.getIsRepeat()) {
|
||||
return ScheduleType.DELAYED;
|
||||
}
|
||||
|
||||
return switch (notice.getRepeatType()) {
|
||||
case COUNT, DATE -> ScheduleType.RECURRING;
|
||||
case TIME -> ScheduleType.PERIODIC;
|
||||
default -> ScheduleType.DELAYED;
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScheduleExecutionConfig getSchedulerConfig() {
|
||||
return ScheduleExecutionConfig.builder()
|
||||
.taskId("notice-" + notice.getId())
|
||||
.startTime(notice.getSendDt())
|
||||
.endTime(notice.getEndDt())
|
||||
.interval(getRepeatInterval())
|
||||
.repeatCount(notice.getRepeatCnt().intValue())
|
||||
.build();
|
||||
}
|
||||
|
||||
private Duration getRepeatInterval() {
|
||||
if (!notice.getIsRepeat()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return switch (notice.getRepeatType()) {
|
||||
case COUNT -> Duration.ofSeconds(LocalTime.parse(notice.getRepeatDt()).toSecondOfDay());
|
||||
case DATE -> Duration.ofMillis(CommonUtils.intervalToMillis(notice.getRepeatDt()));
|
||||
case TIME -> null;
|
||||
};
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
private void initialize() {
|
||||
// 기존 실행 횟수로 초기화
|
||||
currentExecutionCount.set(notice.getSendCnt().intValue());
|
||||
}
|
||||
|
||||
// SchedulerManager에서 사용할 수 있도록 현재 실행 상태 제공
|
||||
public boolean hasReachedMaxExecutions() {
|
||||
return getCurrentCount() >= getMaxCount();
|
||||
}
|
||||
|
||||
// 실행 횟수 검증을 위한 메서드
|
||||
public boolean isValidExecutionCount() {
|
||||
return getCurrentCount() <= getMaxCount();
|
||||
}
|
||||
|
||||
private boolean noticeSend() {
|
||||
try {
|
||||
List<String> serverList = redisUserInfoService.getAllServerList();
|
||||
if (serverList.isEmpty()) {
|
||||
log.error("noticeJob noticeSend serverList is empty");
|
||||
noticeService.updateNoticeStatus(notice.getId(), InGame.SENDSTATUS.FAIL);
|
||||
noticeService.setScheduleLog(HISTORYTYPE.NOTICE_SEND_FAIL, "is null server name");
|
||||
return false;
|
||||
}
|
||||
|
||||
List<Message> msgList = noticeService.getNoticeMessageList(notice.getId());
|
||||
List<OperationSystemMessage> contentList = new ArrayList<>();
|
||||
List<OperationSystemMessage> senderList = new ArrayList<>();
|
||||
|
||||
for (Message msg : Collections.unmodifiableList(msgList)) {
|
||||
LanguageType lang;
|
||||
String sender;
|
||||
|
||||
switch (msg.getLanguage()) {
|
||||
case "EN" -> {
|
||||
lang = LanguageType.LanguageType_en;
|
||||
sender = "Administrator";
|
||||
}
|
||||
case "JA" -> {
|
||||
lang = LanguageType.LanguageType_ja;
|
||||
sender = "アドミニストレーター";
|
||||
}
|
||||
default -> {
|
||||
lang = LanguageType.LanguageType_ko;
|
||||
sender = "시스템 관리자";
|
||||
}
|
||||
}
|
||||
|
||||
contentList.add(createOperationSystemMessage(lang, msg.getContent()));
|
||||
senderList.add(createOperationSystemMessage(lang, sender));
|
||||
}
|
||||
|
||||
log.info("Send Notice Message: {}, type: {}", contentList, notice.getMessageType());
|
||||
|
||||
messageHandlerService.sendNoticeMessage(
|
||||
serverList,
|
||||
notice.getMessageType().toString(),
|
||||
contentList,
|
||||
senderList
|
||||
);
|
||||
|
||||
log.info("noticeJob noticeSend completed");
|
||||
return true;
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("noticeSend Exception: {}", e.getMessage());
|
||||
noticeService.updateNoticeStatus(notice.getId(), InGame.SENDSTATUS.FAIL);
|
||||
noticeService.setScheduleLog(HISTORYTYPE.NOTICE_SEND_FAIL, e.getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private OperationSystemMessage createOperationSystemMessage(LanguageType lang, String text) {
|
||||
return OperationSystemMessage.newBuilder()
|
||||
.setLanguageType(lang)
|
||||
.setText(CommonUtils.stringToByte(text))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package com.caliverse.admin.scheduler.service.impl;
|
||||
|
||||
import com.caliverse.admin.scheduler.service.LogCompressService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.time.LocalDate;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class LogCompressServiceImpl implements LogCompressService {
|
||||
|
||||
private static final String LOG_DIR = "..\\logs";
|
||||
private static final String LOG_FILE_PREFIX = "caliverse";
|
||||
|
||||
@Override
|
||||
public void compressLastMonthLogs() {
|
||||
log.info("Start compressing last month's logs");
|
||||
try {
|
||||
LocalDate lastMonth = LocalDate.now().minusMonths(1);
|
||||
String yearMonth = lastMonth.format(DateTimeFormatter.ofPattern("yyyy-MM"));
|
||||
|
||||
String zipFileName = LOG_DIR + File.separator +
|
||||
LOG_FILE_PREFIX + "_" + yearMonth + ".zip";
|
||||
|
||||
String logFilePattern = LOG_FILE_PREFIX + "." + yearMonth + "*";
|
||||
|
||||
try (FileOutputStream fos = new FileOutputStream(zipFileName);
|
||||
ZipOutputStream zos = new ZipOutputStream(fos)) {
|
||||
|
||||
Files.newDirectoryStream(Paths.get(LOG_DIR), logFilePattern)
|
||||
.forEach(path -> {
|
||||
try {
|
||||
addToZipFile(path.toFile(), zos);
|
||||
Files.delete(path);
|
||||
log.info("Compressed and deleted file: {}", path.getFileName());
|
||||
} catch (IOException e) {
|
||||
log.error("Error while compressing file: {}", path.getFileName(), e);
|
||||
}
|
||||
});
|
||||
}
|
||||
log.info("Finished compressing last month's logs");
|
||||
} catch (IOException e) {
|
||||
log.error("Error in log compression service", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void addToZipFile(File file, ZipOutputStream zos) throws IOException {
|
||||
try (FileInputStream fis = new FileInputStream(file)) {
|
||||
ZipEntry zipEntry = new ZipEntry(file.getName());
|
||||
zos.putNextEntry(zipEntry);
|
||||
|
||||
byte[] bytes = new byte[1024];
|
||||
int length;
|
||||
while ((length = fis.read(bytes)) >= 0) {
|
||||
zos.write(bytes, 0, length);
|
||||
}
|
||||
zos.closeEntry();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user