package com.interplug.qcast.batch.master; import com.interplug.qcast.biz.specialNote.SpecialNoteService; import com.interplug.qcast.biz.specialNote.dto.SpecialNoteItemRequest; import com.interplug.qcast.biz.specialNote.dto.SpecialNoteRequest; import com.interplug.qcast.biz.specialNote.dto.SpecialNoteSyncResponse; import com.interplug.qcast.util.InterfaceQsp; import java.util.Collections; import java.util.List; import java.util.function.Consumer; import lombok.extern.slf4j.Slf4j; import org.springframework.batch.core.Job; import org.springframework.batch.core.JobExecution; import org.springframework.batch.core.JobExecutionListener; import org.springframework.batch.core.Step; 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.ItemReader; import org.springframework.batch.item.ItemWriter; import org.springframework.batch.item.support.ListItemReader; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpMethod; import org.springframework.transaction.PlatformTransactionManager; @Configuration @Slf4j public class SpecialNoteDispItemJobConfiguration implements JobExecutionListener { private final InterfaceQsp interfaceQsp; private final SpecialNoteService specialNoteService; @Value("${qsp.master-special-note-disp-item-batch-url}") private String qspMasterSpecialNoteDispItemBatchUrl; private SpecialNoteSyncResponse SpecialNoteDispItemSyncResponse; public SpecialNoteDispItemJobConfiguration( InterfaceQsp interfaceQsp, SpecialNoteService specialNoteService) { this.interfaceQsp = interfaceQsp; this.specialNoteService = specialNoteService; } @Override public void beforeJob(JobExecution jobExecution) { log.info("Job 시작: 초기화 메서드 호출 중..."); try { this.SpecialNoteDispItemSyncResponse = interfaceQsp.callApiData( HttpMethod.GET, qspMasterSpecialNoteDispItemBatchUrl, null, SpecialNoteSyncResponse.class); log.info( "API 호출 완료, 항목 수: {}", this.SpecialNoteDispItemSyncResponse.getSdOrderSpnList().size()); } catch (Exception e) { log.error("specialNoteDispItemSyncResponse 갱신 중 오류: {}", e.getMessage()); } } @Bean public Job specialNoteDispItemAdditionalJob( JobRepository jobRepository, Step specialNoteStep, Step specialNoteItemStep) { return new JobBuilder("specialNoteDispItemAdditionalJob", jobRepository) .start(specialNoteStep) .next(specialNoteItemStep) .listener(this) .build(); } private Step buildStep( String stepName, JobRepository jobRepository, PlatformTransactionManager transactionManager, ItemReader reader, ItemWriter writer) { return new StepBuilder(stepName, jobRepository) .chunk(10, transactionManager) .reader(reader) .writer(writer) .build(); } @Bean public Step specialNoteStep( JobRepository jobRepository, PlatformTransactionManager transactionManager) { return buildStep( "specialNoteStep", jobRepository, transactionManager, specialNoteListReader(), createWriter( (items) -> { try { log.debug("Special Note batch processing {} items", items.size()); specialNoteService.setSpecialNoteBatch(items); log.debug("Successfully processed Special Note batch"); } catch (Exception e) { log.error("Error processing Special Note batch: {}", e.getMessage(), e); throw new RuntimeException("Failed to process Special Note batch", e); } }, "specialNote")); } @Bean public Step specialNoteItemStep( JobRepository jobRepository, PlatformTransactionManager transactionManager) { return buildStep( "specialNoteItemStep", jobRepository, transactionManager, specialNoteItemListReader(), createWriter( (items) -> { try { log.debug("Special Note Item batch processing {} items", items.size()); specialNoteService.setSpecialNoteItemBatch(items); log.debug("Successfully processed Special Note Item batch"); } catch (Exception e) { log.error("Error processing Special Note Item batch: {}", e.getMessage(), e); throw new RuntimeException("Failed to process Special Note Item batch", e); } }, "specialNoteItem")); } private ListItemReader createReader(List items, String readerName) { log.info("{}Reader 호출됨...", readerName); return new ListItemReader<>(items != null ? items : Collections.emptyList()); } @Bean @StepScope public ListItemReader specialNoteListReader() { return createReader( SpecialNoteDispItemSyncResponse != null ? SpecialNoteDispItemSyncResponse.getSdOrderSpnList() : null, "specialNote"); } @Bean @StepScope public ListItemReader specialNoteItemListReader() { return createReader( SpecialNoteDispItemSyncResponse != null ? SpecialNoteDispItemSyncResponse.getSdOrderSpnItemList() : null, "specialNoteItem"); } private ItemWriter createWriter(Consumer> processor, String writerName) { return items -> { try { List itemList = (List) items.getItems(); processor.accept(itemList); log.info("{}Writer: {} items 처리 완료", writerName, items.size()); } catch (Exception e) { log.error("{}Writer 오류: {}", writerName, e.getMessage()); throw e; } }; } }