2010-12-10 16 views
16

चलो कहते हैं कि मैं एक ट्रिगर इस तरह से कॉन्फ़िगर किया करते हैं:क्वार्ट्ज पुन: प्रयास करें जब विफलता

<bean id="updateInsBBTrigger"   
    class="org.springframework.scheduling.quartz.CronTriggerBean"> 
    <property name="jobDetail" ref="updateInsBBJobDetail"/> 
    <!-- run every morning at 5 AM --> 
    <property name="cronExpression" value="0 0 5 * * ?"/> 
</bean> 

ट्रिगर एक और आवेदन के साथ कनेक्ट करने के लिए है और अगर कोई समस्या (कनेक्शन विफलता की तरह) है यह कार्य पुन: प्रयास करना चाहिए प्रत्येक 10 मिनट तक या सफलता तक पांच गुना तक। ट्रिगर को इस तरह काम करने के लिए कॉन्फ़िगर करने का कोई तरीका है?

उत्तर

16

स्रोत: Automatically Retry Failed Jobs in Quartz

तुम्हें नौकरी जो बार बार जब तक यह सफल होता है की कोशिश कर रखता है करना चाहते हैं, तुम सब करने की ज़रूरत एक ध्वज के साथ एक JobExecutionException फेंक यह आग अनुसूचक बताने के लिए है फिर जब यह विफल हो जाता है। निम्नलिखित कोड दिखाता है कि कैसे:

class MyJob implements Job { 

    public MyJob() { 
    } 

    public void execute(JobExecutionContext context) throws JobExecutionException { 

     try{ 
      //connect to other application etc 
     } 
     catch(Exception e){ 

      Thread.sleep(600000); //sleep for 10 mins 

      JobExecutionException e2 = new JobExecutionException(e); 
      //fire it again 
      e2.setRefireImmediately(true); 
      throw e2; 
     } 
    } 
} 

यदि आप एक निश्चित संख्या को फिर से प्रयास करना चाहते हैं तो यह थोड़ा और जटिल हो जाता है। आपको स्टेटफुल जॉब का उपयोग करना होगा और जॉबडाटा मैप में एक रेट्री काउंटर रखना होगा, जो नौकरी विफल होने पर आप बढ़ते हैं। यदि काउंटर अधिकतम संख्या में रीट्रीज़ से अधिक है, तो यदि आप चाहें तो आप नौकरी को अक्षम कर सकते हैं।

class MyJob implements StatefulJob { 

    public MyJob() { 
    } 

    public void execute(JobExecutionContext context) throws JobExecutionException { 
     JobDataMap dataMap = context.getJobDetail().getJobDataMap(); 
     int count = dataMap.getIntValue("count"); 

     // allow 5 retries 
     if(count >= 5){ 
      JobExecutionException e = new JobExecutionException("Retries exceeded"); 
      //make sure it doesn't run again 
      e.setUnscheduleAllTriggers(true); 
      throw e; 
     } 


     try{ 
      //connect to other application etc 

      //reset counter back to 0 
      dataMap.putAsString("count", 0); 
     } 
     catch(Exception e){ 
      count++; 
      dataMap.putAsString("count", count); 
      JobExecutionException e2 = new JobExecutionException(e); 

      Thread.sleep(600000); //sleep for 10 mins 

      //fire it again 
      e2.setRefireImmediately(true); 
      throw e2; 
     } 
    } 
} 
+0

धन्यवाद। यह वह है जिसे मैं ढूंढ रहा था। – Averroes

+43

-1, मैं इस दृष्टिकोण की अनुशंसा नहीं करता - यह 10 मिनट के लिए क्वार्ट्ज कार्यकर्ता धागे में से एक को अवरुद्ध करेगा।जाने का सही तरीका मौजूदा क्वार्ट्ज कार्यक्षमता को सुविधाजनक बनाना होगा - इसे किसी भी तरह से 10 मिनट के बाद एक ही नौकरी को दोबारा शुरू करने के लिए कहें - आखिरकार, यही वह है जो इसके लिए बनाया गया है। अगर हमें कुछ कोड और नींद चलाना है, तो पहले स्थान पर क्वार्ट्ज का उपयोग करने में कोई बात नहीं है। –

+1

अनुपूरक कि क्वार्ट्ज 2.0 (कम से कम .NET के लिए) में। स्टेटफुल जोब को 'PersistJobDataAfterExecutionAttribute' द्वारा प्रतिस्थापित किया गया है http://quartznet.sourceforge.net/apidoc/2.0/html/html/babe3560-218c-38de-031a-7fe1fdd569d2.htm – ossek

7

मैं अपने डीबी दो ऑफसेट में और अधिक लचीलापन और बेहतर दुकान में configurability के लिए सुझाव है: repeatOffset जो आप कितनी देर तक काम फिर से प्रयास किया जाना चाहिए और trialPeriodOffset रखेंगे जिसके बाद बता देंगे समय खिड़की की जानकारी कि नौकरी को पुनर्निर्धारित करने की अनुमति है।

String repeatOffset = yourDBUtilsDao.getConfigParameter(..); 
String trialPeriodOffset = yourDBUtilsDao.getConfigParameter(..); 

फिर काम के बजाय काउंटर यह initalAttempt याद करने की आवश्यकता होगी याद करने के लिए:

Long initialAttempt = null; 
initialAttempt = (Long) existingJobDetail.getJobDataMap().get("firstAttempt"); 

और प्रदर्शन तो फिर तुम जैसे ये दो पैरामीटर प्राप्त कर सकते हैं (मैं आप वसंत का उपयोग कर रहे मान) निम्नलिखित की जांच की तरह कुछ:

long allowedThreshold = initialAttempt + Long.parseLong(trialPeriodOffset); 
     if (System.currentTimeMillis() > allowedThreshold) { 
      //We've tried enough, time to give up 
      log.warn("The job is not going to be rescheduled since it has reached its trial period threshold"); 
      sched.deleteJob(jobName, jobGroup); 
      return YourResultEnumHere.HAS_REACHED_THE_RESCHEDULING_LIMIT; 
     } 

यह एक अच्छा विचार प्रयास का परिणाम है कि अपनेके मूल कार्यप्रवाह करने के लिए वापस लौटाए जाने के लिए एक enum बनाने के लिए किया जाएगाउपरोक्त की तरह आवेदन।

Date startTime = null; 
startTime = new Date(System.currentTimeMillis() + Long.parseLong(repeatOffset)); 

String triggerName = "Trigger_" + jobName; 
String triggerGroup = "Trigger_" + jobGroup; 

Trigger retrievedTrigger = sched.getTrigger(triggerName, triggerGroup); 
if (!(retrievedTrigger instanceof SimpleTrigger)) { 
      log.error("While rescheduling the Quartz Job retrieved was not of SimpleTrigger type as expected"); 
      return YourResultEnumHere.ERROR; 
} 

     ((SimpleTrigger) retrievedTrigger).setStartTime(startTime); 
     sched.rescheduleJob(triggerName, triggerGroup, retrievedTrigger); 
     return YourResultEnumHere.RESCHEDULED; 
2

मैं इस तरह एक कार्यान्वयन की सिफारिश काम के बाद एक असफल ठीक करने के लिए होगा::

final JobDataMap jobDataMap = jobCtx.getJobDetail().getJobDataMap(); 
// the keys doesn't exist on first retry 
final int retries = jobDataMap.containsKey(COUNT_MAP_KEY) ? jobDataMap.getIntValue(COUNT_MAP_KEY) : 0; 

// to stop after awhile 
if (retries < MAX_RETRIES) { 
    log.warn("Retry job " + jobCtx.getJobDetail()); 

    // increment the number of retries 
    jobDataMap.put(COUNT_MAP_KEY, retries + 1); 

    final JobDetail job = jobCtx 
     .getJobDetail() 
     .getJobBuilder() 
     // to track the number of retries 
     .withIdentity(jobCtx.getJobDetail().getKey().getName() + " - " + retries, "FailingJobsGroup") 
     .usingJobData(jobDataMap) 
     .build(); 

    final OperableTrigger trigger = (OperableTrigger) TriggerBuilder 
     .newTrigger() 
     .forJob(job) 
     // trying to reduce back pressure, you can use another algorithm 
     .startAt(new Date(jobCtx.getFireTime().getTime() + (retries*100))) 
     .build(); 

    try { 
    // schedule another job to avoid blocking threads 
    jobCtx.getScheduler().scheduleJob(job, trigger); 
    } catch (SchedulerException e) { 
    log.error("Error creating job"); 
    throw new JobExecutionException(e); 
    } 
} 

क्यों

फिर पुनर्निर्धारण समय का निर्माण?

  1. यह क्वार्ट्ज श्रमिक
  2. ब्लॉक नहीं यह वापस दबाव से बचने होगा। SetRefire के साथ तुरंत नौकरी तुरंत निकाल दी जाएगी और इससे पीछे दबाव के मुद्दों का कारण बन सकता है
संबंधित मुद्दे