diff --git a/src/main/java/com/interplug/qcast/batch/JobLauncherController.java b/src/main/java/com/interplug/qcast/batch/JobLauncherController.java index d0f79ccd..80aa39a2 100644 --- a/src/main/java/com/interplug/qcast/batch/JobLauncherController.java +++ b/src/main/java/com/interplug/qcast/batch/JobLauncherController.java @@ -98,8 +98,8 @@ public class JobLauncherController { * @throws JobParametersInvalidException * @throws JobRestartException */ - // @Scheduled(cron = "*/30 * * * * *") - @Scheduled(cron = "0 0 0 * * *") + // @Scheduled(cron = "*/5 * * * * *") + @Scheduled(cron = "0 55 23 * * *") public String storeAdditionalInfoJob() throws JobInstanceAlreadyCompleteException, JobExecutionAlreadyRunningException, @@ -111,7 +111,6 @@ public class JobLauncherController { if (job == null) { return "Job " + jobName + " not found"; } - JobParameters jobParameters = new JobParametersBuilder().addDate("time", new Date()).toJobParameters(); diff --git a/src/main/java/com/interplug/qcast/batch/master/StoreJobConfiguration.java b/src/main/java/com/interplug/qcast/batch/master/StoreJobConfiguration.java index 659b1fb6..472ea902 100644 --- a/src/main/java/com/interplug/qcast/batch/master/StoreJobConfiguration.java +++ b/src/main/java/com/interplug/qcast/batch/master/StoreJobConfiguration.java @@ -1,24 +1,19 @@ package com.interplug.qcast.batch.master; -import com.fasterxml.jackson.databind.DeserializationFeature; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.interplug.qcast.biz.displayItem.DisplayItemMapper; -import com.interplug.qcast.biz.storeFavorite.StoreFavoriteMapper; +import com.interplug.qcast.biz.storeFavorite.StoreFavoriteService; import com.interplug.qcast.biz.storeFavorite.dto.StoreFavoriteRequest; -import com.interplug.qcast.biz.user.UserMapper; +import com.interplug.qcast.biz.user.UserService; import com.interplug.qcast.biz.user.dto.StoreRequest; import com.interplug.qcast.biz.user.dto.StoreSyncResponse; -import com.interplug.qcast.biz.user.dto.SyncResponse; import com.interplug.qcast.biz.user.dto.UserRequest; import com.interplug.qcast.util.InterfaceQsp; -import jakarta.annotation.PostConstruct; import java.util.Collections; -import org.springframework.batch.core.Job; -import org.springframework.batch.core.Step; +import java.util.List; +import org.springframework.batch.core.*; +import org.springframework.batch.core.configuration.annotation.StepScope; import org.springframework.batch.core.job.builder.JobBuilder; import org.springframework.batch.core.repository.JobRepository; import org.springframework.batch.core.step.builder.StepBuilder; -import org.springframework.batch.item.ItemProcessor; import org.springframework.batch.item.ItemReader; import org.springframework.batch.item.ItemWriter; import org.springframework.batch.item.support.ListItemReader; @@ -28,38 +23,38 @@ import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpMethod; import org.springframework.transaction.PlatformTransactionManager; -/** chunk 방식의 Job을 생성하는 Configuration */ @Configuration -public class StoreJobConfiguration { +public class StoreJobConfiguration implements JobExecutionListener { private final InterfaceQsp interfaceQsp; - private final UserMapper userMapper; - private final StoreFavoriteMapper storeFavoriteMapper; - private final DisplayItemMapper displayItemMapper; - - @Value("${qsp.url}") - private String qspUrl; + private final UserService userService; + private final StoreFavoriteService storeFavService; @Value("${qsp.master-store-batch-url}") private String qspMasterStoreBatchUrl; + private StoreSyncResponse storeSyncResponse; + public StoreJobConfiguration( - InterfaceQsp interfaceQsp, - UserMapper userMapper, - StoreFavoriteMapper storeFavoriteMapper, - DisplayItemMapper displayItemMapper) { + InterfaceQsp interfaceQsp, UserService userService, StoreFavoriteService storeFavService) { this.interfaceQsp = interfaceQsp; - this.userMapper = userMapper; - this.storeFavoriteMapper = storeFavoriteMapper; - this.displayItemMapper = displayItemMapper; + this.userService = userService; + this.storeFavService = storeFavService; } - private StoreSyncResponse storeSyncResponse; // 데이터를 저장할 필드 - - @PostConstruct - public void init() throws Exception { - // 애플리케이션 시작 시 fetchData를 한 번만 호출하여 데이터 로드 - this.storeSyncResponse = fetchData(); + @Override + public void beforeJob(JobExecution jobExecution) { + System.out.println("Job 시작: 초기화 메서드 호출 중..."); + try { + this.storeSyncResponse = + interfaceQsp.callApiData( + HttpMethod.GET, qspMasterStoreBatchUrl, null, StoreSyncResponse.class); + System.out.println( + "API 호출을 통해 storeSyncResponse 갱신 완료, 항목 수: " + + this.storeSyncResponse.getStoreList().size()); + } catch (Exception e) { + System.err.println("storeSyncResponse를 갱신하는 중 오류 발생: " + e.getMessage()); + } } @Bean @@ -69,132 +64,104 @@ public class StoreJobConfiguration { .start(storeStep) .next(userStep) .next(favoriteStep) + .listener(this) .build(); } @Bean - public Step storeStep(JobRepository jobRepository, PlatformTransactionManager transactionManager) - throws Exception { + public Step storeStep( + JobRepository jobRepository, PlatformTransactionManager transactionManager) { return new StepBuilder("storeStep", jobRepository) .chunk(10, transactionManager) .reader(storeListReader()) - .processor(storeProcessor()) .writer(storeWriter()) .build(); } @Bean - public Step userStep(JobRepository jobRepository, PlatformTransactionManager transactionManager) - throws Exception { + public Step userStep(JobRepository jobRepository, PlatformTransactionManager transactionManager) { return new StepBuilder("userStep", jobRepository) .chunk(10, transactionManager) .reader(userListReader()) - .processor(userProcessor()) .writer(userWriter()) .build(); } @Bean public Step favoriteStep( - JobRepository jobRepository, PlatformTransactionManager transactionManager) throws Exception { + JobRepository jobRepository, PlatformTransactionManager transactionManager) { return new StepBuilder("favoriteStep", jobRepository) .chunk(10, transactionManager) .reader(storeFavListReader()) - .processor(favoriteProcessor()) .writer(favoriteWriter()) .build(); } - private StoreSyncResponse fetchData() throws Exception { - - // 데이터 읽기 - SyncResponse syncResponse = new SyncResponse(); - StoreSyncResponse storeSyncResponse = new StoreSyncResponse(); - - String strResponse = - interfaceQsp.callApi(HttpMethod.GET, qspUrl + qspMasterStoreBatchUrl, null); - - if (!"".equals(strResponse)) { - ObjectMapper om = - new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); - syncResponse = om.readValue(strResponse, SyncResponse.class); - - // 'data' 필드를 직접 사용하여 BatchResponse로 변환 - if (syncResponse.getData() != null) { - String dataJson = om.writeValueAsString(syncResponse.getData()); - // data를 JSON 문자열로 변환 - storeSyncResponse = om.readValue(dataJson, StoreSyncResponse.class); - } - } - - return storeSyncResponse; + @Bean + @StepScope + public ItemReader storeListReader() { + System.out.println("storeListReader 호출됨..."); + return (storeSyncResponse != null && storeSyncResponse.getStoreList() != null) + ? new ListItemReader<>(storeSyncResponse.getStoreList()) + : new ListItemReader<>(Collections.emptyList()); } @Bean - public ItemReader storeListReader() throws Exception { - if (storeSyncResponse.getStoreList() == null) { - storeSyncResponse.setStoreList(Collections.emptyList()); - } - return new ListItemReader<>(storeSyncResponse.getStoreList()); + @StepScope + public ItemReader userListReader() { + System.out.println("userListReader 호출됨..."); + return (storeSyncResponse != null && storeSyncResponse.getUserList() != null) + ? new ListItemReader<>(storeSyncResponse.getUserList()) + : new ListItemReader<>(Collections.emptyList()); } @Bean - public ItemReader userListReader() throws Exception { - if (storeSyncResponse.getUserList() == null) { - storeSyncResponse.setUserList(Collections.emptyList()); - } - return new ListItemReader<>(storeSyncResponse.getUserList()); - } - - @Bean - public ItemReader storeFavListReader() throws Exception { - if (storeSyncResponse.getStoreFavList() == null) { - storeSyncResponse.setStoreFavList(Collections.emptyList()); - } - return new ListItemReader<>(storeSyncResponse.getStoreFavList()); - } - - @Bean - public ItemProcessor storeProcessor() { - return item -> { - userMapper.setStoreSave(item); // 판매정 정보 동기화 - userMapper.setStoreSapCdSave(item); // 판매점 custCd 동기화 - userMapper.setStoreNorthModuleSave(item); - System.out.println("Processing store: " + item); - return item; - }; - } - - @Bean - public ItemProcessor userProcessor() { - return item -> { - userMapper.setUserSave(item); - System.out.println("Processing user: " + item); - return item; - }; - } - - @Bean - public ItemProcessor favoriteProcessor() { - return item -> { - storeFavoriteMapper.setStoreFavoriteSave(item); - System.out.println("Processing favorite: " + item); - return item; - }; + @StepScope + public ItemReader storeFavListReader() { + System.out.println("storeFavListReader 호출됨..."); + return (storeSyncResponse != null && storeSyncResponse.getStoreFavList() != null) + ? new ListItemReader<>(storeSyncResponse.getStoreFavList()) + : new ListItemReader<>(Collections.emptyList()); } @Bean public ItemWriter storeWriter() { - return items -> items.forEach(item -> System.out.println("Writing store: " + item)); + return items -> { + try { + List storeRequestList = + (List) items.getItems(); // Chunk에서 List로 추출 + userService.setStoreBatch(storeRequestList); // 서비스에 List를 한 번에 전달 + System.out.println("storeWriter: " + items.size() + " items 처리 완료"); + } catch (Exception e) { + System.err.println("storeWriter 오류: " + e.getMessage()); + } + }; } @Bean public ItemWriter userWriter() { - return items -> items.forEach(item -> System.out.println("Writing user: " + item)); + return items -> { + try { + List userRequestList = (List) items.getItems(); + userService.setUserBatch(userRequestList); + System.out.println("userWriter: " + items.size() + " items 처리 완료"); + } catch (Exception e) { + System.err.println("userWriter 오류: " + e.getMessage()); + } + }; } @Bean public ItemWriter favoriteWriter() { - return items -> items.forEach(item -> System.out.println("Writing favorite: " + item)); + return items -> { + try { + List storeFavoriteList = + (List) items.getItems(); + storeFavService.setStoreFavoriteBatch(storeFavoriteList); + System.out.println("favoriteWriter: " + items.size() + " items 처리 완료"); + } catch (Exception e) { + System.err.println("favoriteWriter 오류: " + e.getMessage()); + } + }; } } diff --git a/src/main/java/com/interplug/qcast/biz/storeFavorite/StoreFavoriteService.java b/src/main/java/com/interplug/qcast/biz/storeFavorite/StoreFavoriteService.java index bbb3b70b..9546d7e3 100644 --- a/src/main/java/com/interplug/qcast/biz/storeFavorite/StoreFavoriteService.java +++ b/src/main/java/com/interplug/qcast/biz/storeFavorite/StoreFavoriteService.java @@ -8,13 +8,16 @@ import com.interplug.qcast.config.Exception.ErrorCode; import com.interplug.qcast.config.Exception.QcastException; import com.interplug.qcast.config.message.Messages; import com.interplug.qcast.util.InterfaceQsp; +import java.util.List; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpMethod; import org.springframework.stereotype.Service; import org.springframework.web.util.UriComponentsBuilder; +@Slf4j @Service @RequiredArgsConstructor public class StoreFavoriteService { @@ -77,4 +80,15 @@ public class StoreFavoriteService { } return response; } + + public void setStoreFavoriteBatch(List storeFavList) throws Exception { + // 즐겨찾기 동기화 + for (StoreFavoriteRequest storeFavoriteRequest : storeFavList) { + try { + storeFavoriteMapper.setStoreFavoriteSave(storeFavoriteRequest); + } catch (Exception e) { + log.error(e.getMessage()); + } + } + } } diff --git a/src/main/java/com/interplug/qcast/biz/user/UserService.java b/src/main/java/com/interplug/qcast/biz/user/UserService.java index 400c9a42..76dcfe36 100644 --- a/src/main/java/com/interplug/qcast/biz/user/UserService.java +++ b/src/main/java/com/interplug/qcast/biz/user/UserService.java @@ -4,8 +4,10 @@ import com.interplug.qcast.biz.user.dto.StoreRequest; import com.interplug.qcast.biz.user.dto.UserRequest; import java.util.List; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; +@Slf4j @Service @RequiredArgsConstructor public class UserService { @@ -52,4 +54,32 @@ public class UserService { public int setStoreSapCdSave(StoreRequest storeReq) throws Exception { return userMapper.setStoreSapCdSave(storeReq); } + + /** + * @param storeList + * @throws Exception + */ + public void setStoreBatch(List storeList) throws Exception { + // 판매점 동기화 + for (StoreRequest storeRequest : storeList) { + try { + userMapper.setStoreSave(storeRequest); + userMapper.setStoreSapCdSave(storeRequest); + userMapper.setStoreNorthModuleSave(storeRequest); + } catch (Exception e) { + log.error(e.getMessage()); + } + } + } + + public void setUserBatch(List userList) throws Exception { + // 사용자 동기화 + for (UserRequest userRequest : userList) { + try { + userMapper.setUserSave(userRequest); + } catch (Exception e) { + log.error(e.getMessage()); + } + } + } }