2013-01-13 2 views
2

복구 패턴을 만들어야합니다. 내 패턴으로는 주어진 시간 창에서만 작업을 시작할 수 있습니다. 작업이 실패하는 경우 다음 번 창에서만 다시 시작되며 완료되면이 창에 대해 미리 계획된 일정 작업을 시작하려고합니다. 작업 간의 유일한 차이점은 시간 창 매개 변수입니다.일괄 처리 : 작업을 다시 시작한 후 자동으로 다음 작업 시작

나는 JobExplorer와 함께 또는 Joblauncher를 재정 의하여 JobExecutionDecider에 대해 생각했다. 그러나 모든 것이 너무 관입 적이기도하다.

내 요구 사항에 맞는 예제를 찾지 못해서 어떤 아이디어라도 환영 할 것입니다.

답변

2

http://docs.spring.io/spring-batch/reference/htmlsingle/#external-flows 그냥 요약하자면 그것에 문서입니다. 아래와 비슷한 복구 과정을 만들었습니다. 복구 흐름은 내 실제 일괄 처리를 감싸고 올바른 작업 매개 변수를 내부 작업에만 제공하는 역할을합니다. 처음 실행시 초기 매개 변수, 정상 실행시 새 매개 변수 또는 마지막 실행이 실패한 경우 이전 매개 변수가 될 수 있습니다. 스프링 배치를 다시 시작 메커니즘을 사용하는 동안

<batch:job id="recoveryWrapper" 
     incrementer="wrapperRunIdIncrementer" 
     restartable="true"> 
    <batch:decision id="recoveryFlowDecision" decider="recoveryFlowDecider"> 
     <batch:next on="FIRST_RUN" to="defineParametersOnFirstRun" /> 
     <batch:next on="RECOVER" to="recover.batchJob " /> 
     <batch:next on="CURRENT" to="current.batchJob " /> 
    </batch:decision> 
    <batch:step id="defineParametersOnFirstRun" next="current.batchJob"> 
     <batch:tasklet ref="defineParametersOnFirstRunTasklet"/> 
    </batch:step> 
    <batch:step id="recover.batchJob " next="current.batchJob"> 
     <batch:job ref="batchJob" job-launcher="jobLauncher" 
          job-parameters-extractor="jobParametersExtractor" /> 
    </batch:step> 
    <batch:step id="current.batchJob" > 
     <batch:job ref="batchJob" job-launcher="jobLauncher" 
          job-parameters-extractor="jobParametersExtractor" /> 
    </batch:step> 
</batch:job> 

솔루션의 핵심은 JobParametersExtractorRecoveryFlowDecider입니다. RecoveryFlowDecider는 JobExplorer 및 JobRepository를 쿼리하여 마지막 실행시 오류가 발생했는지 확인합니다. JobParametersExtractor에서 나중에 사용할 래퍼의 실행 컨텍스트에 대한 마지막 실행을 배치합니다. runIdIncremeter를 사용하여 래퍼 작업을 다시 실행할 수 있습니다.

@Component 
public class RecoveryFlowDecider implements JobExecutionDecider { 
     private static final String FIRST_RUN = "FIRST_RUN"; 
     private static final String CURRENT = "CURRENT"; 
     private static final String RECOVER = "RECOVER"; 

     @Autowired 
     private JobExplorer jobExplorer; 
     @Autowired 
     private JobRepository jobRepository; 

     @Override 
     public FlowExecutionStatus decide(JobExecution jobExecution 
             ,StepExecution stepExecution) { 
      // the wrapper is named as the wrapped job + WRAPPER 
      String wrapperJobName = jobExecution.getJobInstance().getJobName(); 
      String jobName; 
      jobName = wrapperJobName.substring(0,wrapperJobName.indexOf(EtlConstants.WRAPPER)); 
      List<JobInstance> instances = jobExplorer.getJobInstances(jobName, 0, 1); 
       JobInstance internalJobInstance = instances.size() > 0 ? instances.get(0) : null; 

      if (null == internalJobInstance) { 
       return new FlowExecutionStatus(FIRST_RUN); 
      } 
      JobExecution lastExecution = jobRepository.getLastJobExecution(internalJobInstance.getJobName() 
    ,internalJobInstance.getJobParameters()); 
      //place the last execution on the context (wrapper context to use later) 
      jobExecution.getExecutionContext().put(EtlConstants.LAST_EXECUTION, lastExecution); 
       ExitStatus exitStatus = lastExecution.getExitStatus(); 

      if (ExitStatus.FAILED.equals(exitStatus) || ExitStatus.UNKNOWN.equals(exitStatus)) { 
       return new FlowExecutionStatus(RECOVER); 
      }else if(ExitStatus.COMPLETED.equals(exitStatus)){ 
       return new FlowExecutionStatus(CURRENT);  
      } 
      //We should never get here unless we have a defect 
      throw new RuntimeException("Unexpecded batch status: "+exitStatus+" in decider!"); 

     } 

} 

그런 다음 JobParametersExtractor는, 마지막 실행의 결과를 다시 테스트합니다 실패한 작업의 경우는 봄 Bacth 다시 시작 메커니즘을 트리거 실패한 작업을 실행하는 데 사용되는 원래의 매개 변수를 제공합니다. 그렇지 않으면 새로운 매개 변수 집합이 생성되고 정상적인 과정에서 실행됩니다.

@Component 
    public class JobExecutionWindowParametersExtractor implements 
      JobParametersExtractor { 
     @Override 
     public JobParameters getJobParameters(Job job, StepExecution stepExecution) { 

      // Read the last execution from the wrapping job 
      // in order to build Next Execution Window 
      JobExecution lastExecution= (JobExecution) stepExecution.getJobExecution().getExecutionContext().get(EtlConstants.LAST_EXECUTION);; 

      if(null!=lastExecution){ 
       if (ExitStatus.FAILED.equals(lastExecution.getExitStatus())) { 
        JobInstance instance = lastExecution.getJobInstance(); 
        JobParameters parameters = instance.getJobParameters();     
           return parameters; 
       } 
      }  
      //We do not have failed execution or have no execution at all we need to create a new execution window 
      return buildJobParamaters(lastExecution,stepExecution); 
     } 
... 
} 
0

반대의 방식으로 처리 할 수 ​​있습니까?

매 시간 창마다 해당 시간대의 작업을 제출하십시오.

그러나 작업의 첫 번째 단계는 이전 시간 창의 작업이 성공적으로 완료되었는지 확인해야합니다. 이전에 실패한 경우 이전 작업을 제출하고 완료 될 때까지 기다린 후 논리를 작성하십시오.

2

JobStep을 고려하셨습니까? 즉, 단계는 실행할 추가 작업이 있는지 판별합니다. 이 값은 StepExecutionContext로 설정됩니다. JobExecutionDecider는이 값을 검사합니다. 존재하는 경우 작업을 시작하는 JobStep으로 이동합니다.

여기에 실제로 incomplete-co.de에 의해 제공되는 조언에 따라 이루어졌다 것을

+0

감사 : JobSteps 좋은 생각처럼 소리 나는 이미 (실행을 실패하고 새로운 실행 기준) 예상 매개 변수로 날을 제공 jobParametersExtractor을 썼다. 이제 외부 작업의 결정자를 기반으로 두 도구를 통합하는 것이 좋습니다. 논리적으로 들립니까? –

+0

예 - 결정자가 JobStep을 가져 왔는지 여부를 결정하고 프로그래밍 방식으로 흐름 논리를 표현하도록 열어 둡니다.Rememmber는 생성자에서 원하는 문자열을 전달하여 자신의 FlowExecutionStatus를 만들 수 있으며 XML 라우팅에서 사용할 수있는 값이 될 것이라고 전합니다. –

관련 문제