store 배치 수정

This commit is contained in:
DESKTOP-6ARNG1Q\dlsgk 2024-11-08 14:45:29 +09:00
parent e3b78204c2
commit d3bd562d80
4 changed files with 125 additions and 115 deletions

View File

@ -98,8 +98,8 @@ public class JobLauncherController {
* @throws JobParametersInvalidException * @throws JobParametersInvalidException
* @throws JobRestartException * @throws JobRestartException
*/ */
// @Scheduled(cron = "*/30 * * * * *") // @Scheduled(cron = "*/5 * * * * *")
@Scheduled(cron = "0 0 0 * * *") @Scheduled(cron = "0 55 23 * * *")
public String storeAdditionalInfoJob() public String storeAdditionalInfoJob()
throws JobInstanceAlreadyCompleteException, throws JobInstanceAlreadyCompleteException,
JobExecutionAlreadyRunningException, JobExecutionAlreadyRunningException,
@ -111,7 +111,6 @@ public class JobLauncherController {
if (job == null) { if (job == null) {
return "Job " + jobName + " not found"; return "Job " + jobName + " not found";
} }
JobParameters jobParameters = JobParameters jobParameters =
new JobParametersBuilder().addDate("time", new Date()).toJobParameters(); new JobParametersBuilder().addDate("time", new Date()).toJobParameters();

View File

@ -1,24 +1,19 @@
package com.interplug.qcast.batch.master; package com.interplug.qcast.batch.master;
import com.fasterxml.jackson.databind.DeserializationFeature; import com.interplug.qcast.biz.storeFavorite.StoreFavoriteService;
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.dto.StoreFavoriteRequest; 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.StoreRequest;
import com.interplug.qcast.biz.user.dto.StoreSyncResponse; 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.biz.user.dto.UserRequest;
import com.interplug.qcast.util.InterfaceQsp; import com.interplug.qcast.util.InterfaceQsp;
import jakarta.annotation.PostConstruct;
import java.util.Collections; import java.util.Collections;
import org.springframework.batch.core.Job; import java.util.List;
import org.springframework.batch.core.Step; 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.job.builder.JobBuilder;
import org.springframework.batch.core.repository.JobRepository; import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.step.builder.StepBuilder; 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.ItemReader;
import org.springframework.batch.item.ItemWriter; import org.springframework.batch.item.ItemWriter;
import org.springframework.batch.item.support.ListItemReader; 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.http.HttpMethod;
import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.PlatformTransactionManager;
/** chunk 방식의 Job을 생성하는 Configuration */
@Configuration @Configuration
public class StoreJobConfiguration { public class StoreJobConfiguration implements JobExecutionListener {
private final InterfaceQsp interfaceQsp; private final InterfaceQsp interfaceQsp;
private final UserMapper userMapper; private final UserService userService;
private final StoreFavoriteMapper storeFavoriteMapper; private final StoreFavoriteService storeFavService;
private final DisplayItemMapper displayItemMapper;
@Value("${qsp.url}")
private String qspUrl;
@Value("${qsp.master-store-batch-url}") @Value("${qsp.master-store-batch-url}")
private String qspMasterStoreBatchUrl; private String qspMasterStoreBatchUrl;
private StoreSyncResponse storeSyncResponse;
public StoreJobConfiguration( public StoreJobConfiguration(
InterfaceQsp interfaceQsp, InterfaceQsp interfaceQsp, UserService userService, StoreFavoriteService storeFavService) {
UserMapper userMapper,
StoreFavoriteMapper storeFavoriteMapper,
DisplayItemMapper displayItemMapper) {
this.interfaceQsp = interfaceQsp; this.interfaceQsp = interfaceQsp;
this.userMapper = userMapper; this.userService = userService;
this.storeFavoriteMapper = storeFavoriteMapper; this.storeFavService = storeFavService;
this.displayItemMapper = displayItemMapper;
} }
private StoreSyncResponse storeSyncResponse; // 데이터를 저장할 필드 @Override
public void beforeJob(JobExecution jobExecution) {
@PostConstruct System.out.println("Job 시작: 초기화 메서드 호출 중...");
public void init() throws Exception { try {
// 애플리케이션 시작 fetchData를 번만 호출하여 데이터 로드 this.storeSyncResponse =
this.storeSyncResponse = fetchData(); 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 @Bean
@ -69,132 +64,104 @@ public class StoreJobConfiguration {
.start(storeStep) .start(storeStep)
.next(userStep) .next(userStep)
.next(favoriteStep) .next(favoriteStep)
.listener(this)
.build(); .build();
} }
@Bean @Bean
public Step storeStep(JobRepository jobRepository, PlatformTransactionManager transactionManager) public Step storeStep(
throws Exception { JobRepository jobRepository, PlatformTransactionManager transactionManager) {
return new StepBuilder("storeStep", jobRepository) return new StepBuilder("storeStep", jobRepository)
.<StoreRequest, StoreRequest>chunk(10, transactionManager) .<StoreRequest, StoreRequest>chunk(10, transactionManager)
.reader(storeListReader()) .reader(storeListReader())
.processor(storeProcessor())
.writer(storeWriter()) .writer(storeWriter())
.build(); .build();
} }
@Bean @Bean
public Step userStep(JobRepository jobRepository, PlatformTransactionManager transactionManager) public Step userStep(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
throws Exception {
return new StepBuilder("userStep", jobRepository) return new StepBuilder("userStep", jobRepository)
.<UserRequest, UserRequest>chunk(10, transactionManager) .<UserRequest, UserRequest>chunk(10, transactionManager)
.reader(userListReader()) .reader(userListReader())
.processor(userProcessor())
.writer(userWriter()) .writer(userWriter())
.build(); .build();
} }
@Bean @Bean
public Step favoriteStep( public Step favoriteStep(
JobRepository jobRepository, PlatformTransactionManager transactionManager) throws Exception { JobRepository jobRepository, PlatformTransactionManager transactionManager) {
return new StepBuilder("favoriteStep", jobRepository) return new StepBuilder("favoriteStep", jobRepository)
.<StoreFavoriteRequest, StoreFavoriteRequest>chunk(10, transactionManager) .<StoreFavoriteRequest, StoreFavoriteRequest>chunk(10, transactionManager)
.reader(storeFavListReader()) .reader(storeFavListReader())
.processor(favoriteProcessor())
.writer(favoriteWriter()) .writer(favoriteWriter())
.build(); .build();
} }
private StoreSyncResponse fetchData() throws Exception { @Bean
@StepScope
// 데이터 읽기 public ItemReader<StoreRequest> storeListReader() {
SyncResponse syncResponse = new SyncResponse(); System.out.println("storeListReader 호출됨...");
StoreSyncResponse storeSyncResponse = new StoreSyncResponse(); return (storeSyncResponse != null && storeSyncResponse.getStoreList() != null)
? new ListItemReader<>(storeSyncResponse.getStoreList())
String strResponse = : new ListItemReader<>(Collections.emptyList());
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 @Bean
public ItemReader<StoreRequest> storeListReader() throws Exception { @StepScope
if (storeSyncResponse.getStoreList() == null) { public ItemReader<UserRequest> userListReader() {
storeSyncResponse.setStoreList(Collections.emptyList()); System.out.println("userListReader 호출됨...");
} return (storeSyncResponse != null && storeSyncResponse.getUserList() != null)
return new ListItemReader<>(storeSyncResponse.getStoreList()); ? new ListItemReader<>(storeSyncResponse.getUserList())
: new ListItemReader<>(Collections.emptyList());
} }
@Bean @Bean
public ItemReader<UserRequest> userListReader() throws Exception { @StepScope
if (storeSyncResponse.getUserList() == null) { public ItemReader<StoreFavoriteRequest> storeFavListReader() {
storeSyncResponse.setUserList(Collections.emptyList()); System.out.println("storeFavListReader 호출됨...");
} return (storeSyncResponse != null && storeSyncResponse.getStoreFavList() != null)
return new ListItemReader<>(storeSyncResponse.getUserList()); ? new ListItemReader<>(storeSyncResponse.getStoreFavList())
} : new ListItemReader<>(Collections.emptyList());
@Bean
public ItemReader<StoreFavoriteRequest> storeFavListReader() throws Exception {
if (storeSyncResponse.getStoreFavList() == null) {
storeSyncResponse.setStoreFavList(Collections.emptyList());
}
return new ListItemReader<>(storeSyncResponse.getStoreFavList());
}
@Bean
public ItemProcessor<StoreRequest, StoreRequest> storeProcessor() {
return item -> {
userMapper.setStoreSave(item); // 판매정 정보 동기화
userMapper.setStoreSapCdSave(item); // 판매점 custCd 동기화
userMapper.setStoreNorthModuleSave(item);
System.out.println("Processing store: " + item);
return item;
};
}
@Bean
public ItemProcessor<UserRequest, UserRequest> userProcessor() {
return item -> {
userMapper.setUserSave(item);
System.out.println("Processing user: " + item);
return item;
};
}
@Bean
public ItemProcessor<StoreFavoriteRequest, StoreFavoriteRequest> favoriteProcessor() {
return item -> {
storeFavoriteMapper.setStoreFavoriteSave(item);
System.out.println("Processing favorite: " + item);
return item;
};
} }
@Bean @Bean
public ItemWriter<StoreRequest> storeWriter() { public ItemWriter<StoreRequest> storeWriter() {
return items -> items.forEach(item -> System.out.println("Writing store: " + item)); return items -> {
try {
List<StoreRequest> storeRequestList =
(List<StoreRequest>) 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 @Bean
public ItemWriter<UserRequest> userWriter() { public ItemWriter<UserRequest> userWriter() {
return items -> items.forEach(item -> System.out.println("Writing user: " + item)); return items -> {
try {
List<UserRequest> userRequestList = (List<UserRequest>) items.getItems();
userService.setUserBatch(userRequestList);
System.out.println("userWriter: " + items.size() + " items 처리 완료");
} catch (Exception e) {
System.err.println("userWriter 오류: " + e.getMessage());
}
};
} }
@Bean @Bean
public ItemWriter<StoreFavoriteRequest> favoriteWriter() { public ItemWriter<StoreFavoriteRequest> favoriteWriter() {
return items -> items.forEach(item -> System.out.println("Writing favorite: " + item)); return items -> {
try {
List<StoreFavoriteRequest> storeFavoriteList =
(List<StoreFavoriteRequest>) items.getItems();
storeFavService.setStoreFavoriteBatch(storeFavoriteList);
System.out.println("favoriteWriter: " + items.size() + " items 처리 완료");
} catch (Exception e) {
System.err.println("favoriteWriter 오류: " + e.getMessage());
}
};
} }
} }

View File

@ -8,13 +8,16 @@ import com.interplug.qcast.config.Exception.ErrorCode;
import com.interplug.qcast.config.Exception.QcastException; import com.interplug.qcast.config.Exception.QcastException;
import com.interplug.qcast.config.message.Messages; import com.interplug.qcast.config.message.Messages;
import com.interplug.qcast.util.InterfaceQsp; import com.interplug.qcast.util.InterfaceQsp;
import java.util.List;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpMethod; import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.web.util.UriComponentsBuilder; import org.springframework.web.util.UriComponentsBuilder;
@Slf4j
@Service @Service
@RequiredArgsConstructor @RequiredArgsConstructor
public class StoreFavoriteService { public class StoreFavoriteService {
@ -77,4 +80,15 @@ public class StoreFavoriteService {
} }
return response; return response;
} }
public void setStoreFavoriteBatch(List<StoreFavoriteRequest> storeFavList) throws Exception {
// 즐겨찾기 동기화
for (StoreFavoriteRequest storeFavoriteRequest : storeFavList) {
try {
storeFavoriteMapper.setStoreFavoriteSave(storeFavoriteRequest);
} catch (Exception e) {
log.error(e.getMessage());
}
}
}
} }

View File

@ -4,8 +4,10 @@ import com.interplug.qcast.biz.user.dto.StoreRequest;
import com.interplug.qcast.biz.user.dto.UserRequest; import com.interplug.qcast.biz.user.dto.UserRequest;
import java.util.List; import java.util.List;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@Slf4j
@Service @Service
@RequiredArgsConstructor @RequiredArgsConstructor
public class UserService { public class UserService {
@ -52,4 +54,32 @@ public class UserService {
public int setStoreSapCdSave(StoreRequest storeReq) throws Exception { public int setStoreSapCdSave(StoreRequest storeReq) throws Exception {
return userMapper.setStoreSapCdSave(storeReq); return userMapper.setStoreSapCdSave(storeReq);
} }
/**
* @param storeList
* @throws Exception
*/
public void setStoreBatch(List<StoreRequest> 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<UserRequest> userList) throws Exception {
// 사용자 동기화
for (UserRequest userRequest : userList) {
try {
userMapper.setUserSave(userRequest);
} catch (Exception e) {
log.error(e.getMessage());
}
}
}
} }