2011-06-27 14 views
17

से अधिक विफल रहा है मैं एक वेब सेवा को अतुल्यकालिक रूप से उपभोग करने का प्रयास कर रहा हूं क्योंकि इसे वापस करने में 45 सेकंड तक लगते हैं। दुर्भाग्यवश, यह वेब सेवा कुछ हद तक अविश्वसनीय है और त्रुटियों को फेंक सकती है। मैंने django-celery सेट अप किया है और मेरे कार्यों को निष्पादित कर रहा है, जो तब तक ठीक काम करता है जब तक कार्य max_retries से अधिक विफल हो जाता है।कार्य से पुनर्प्राप्त max_retries

यहाँ मैं अब तक है:

@task(default_retry_delay=5, max_retries=10) 
def request(xml): 
    try: 
     server = Client('https://www.whatever.net/RealTimeService.asmx?wsdl') 
     xml = server.service.RunRealTimeXML(
      username=settings.WS_USERNAME, 
      password=settings.WS_PASSWORD, 
      xml=xml 
     ) 
    except Exception, e: 
     result = Result(celery_id=request.request.id, details=e.reason, status="i") 
     result.save() 
     try: 
      return request.retry(exc=e) 
     except MaxRetriesExceededError, e: 
      result = Result(celery_id=request.request.id, details="Max Retries Exceeded", status="f") 
      result.save() 
      raise 
    result = Result(celery_id=request.request.id, details=xml, status="s") 
    result.save() 
    return result 

दुर्भाग्य से, MaxRetriesExceededErrorretry() द्वारा फेंका नहीं किया जा रहा है, तो मैं कैसे इस कार्य की असफलता को संभालने के लिए यकीन नहीं है। Django पहले ही क्लाइंट को एचटीएमएल वापस कर चुका है, और मैं AJAX के माध्यम से Result की सामग्री की जांच कर रहा हूं, जो पूर्ण विफल f स्थिति में कभी विफल नहीं हो रहा है।

तो सवाल यह है कि: जब सेलेरी कार्य max_retries से अधिक हो गया है तो मैं अपने डेटाबेस को कैसे अपडेट कर सकता हूं?

उत्तर

14

आप अजवाइन काम वर्ग के after_return विधि ओवरराइड कर सकते हैं, इस विधि कार्य जो कुछ सेवानिवृत्त स्थिति है के निष्पादन के बाद कहा जाता है (सफलता, विफल, पुन: प्रयास)

class MyTask(celery.task.Task) 

    def run(self, xml, **kwargs) 
     #Your stuffs here 

    def after_return(self, status, retval, task_id, args, kwargs, einfo=None): 
     if self.max_retries == int(kwargs['task_retries']): 
      #If max retries are equals to task retries do something 
     if status == "FAILURE": 
      #You can do also something if the tasks fail instead of check the retries 

http://readthedocs.org/docs/celery/en/latest/reference/celery.task.base.html#celery.task.base.BaseTask.after_return

http://celery.readthedocs.org/en/latest/reference/celery.app.task.html?highlight=after_return#celery.app.task.Task.after_return

+0

के बाद से लिंक जाहिरा तौर पर अब अप्रचलित है, [यहाँ है एक नया] [http://celery.readthedocs.org/en/latest/reference/celery.app.task.html?highlight=after_return#celery.app.task.Task.after_return) – rschwieb

+0

धन्यवाद, उत्तर अपडेट किया गया। –

15
अजवाइन संस्करण 2.3.2 इस दृष्टिकोण के साथ

मेरे लिए अच्छी तरह से काम किया है:

class MyTask(celery.task.Task): 
    abstract = True 

    def after_return(self, status, retval, task_id, args, kwargs, einfo): 
     if self.max_retries == self.request.retries: 
      #If max retries is equal to task retries do something 

@task(base=MyTask, default_retry_delay=5, max_retries=10) 
def request(xml): 
    #Your stuff here 
6

मैं अभी इसके साथ जा रहा हूं, मुझे कार्य को सबक्लासिंग का काम बचाता है और आसानी से समझा जाता है।

# auto-retry with delay as defined below. After that, hook is disabled. 
@celery.shared_task(bind=True, max_retries=5, default_retry_delay=300) 
def post_data(self, hook_object_id, url, event, payload): 
    headers = {'Content-type': 'application/json'} 
    try: 
     r = requests.post(url, data=payload, headers=headers) 
     r.raise_for_status() 
    except requests.exceptions.RequestException as e: 
     if self.request.retries >= self.max_retries: 
      log.warning("Auto-deactivating webhook %s for event %s", hook_object_id, event) 
      Webhook.objects.filter(object_id=hook_object_id).update(active=False) 
      return False 
     raise self.retry(exc=e) 
    return True 
8

मुद्दा यह है कि अजवाइन फिर से सीमा को हिट करते समय आपके द्वारा पारित अपवाद को फिर से उठाने का प्रयास कर रहा है। इस फिर से स्थापना करने के लिए कोड यहाँ है: https://github.com/celery/celery/blob/v3.1.20/celery/app/task.py#L673-L681

इस के आसपास सबसे आसान तरीका अजवाइन सब पर अपने अपवादों को प्रबंधित कर सिर्फ नहीं है:

@task(max_retries=10) 
def mytask(): 
    try: 
     do_the_thing() 
    except Exception as e: 
     try: 
      mytask.retry() 
     except MaxRetriesExceededError: 
      do_something_to_handle_the_error() 
      logger.exception(e) 
+1

यह मूल समस्या के लिए सही समाधान है। –

संबंधित मुद्दे