2012-03-06 18 views
10

मैं एक संदेश कतार बनाने के लिए Django और RabbitMQ के साथ अजवाइन उपयोग कर रहा हूँ। मेरे पास एक कार्यकर्ता भी है, जो एक अलग मशीन से निकल रहा है।अजवाइन - काम पर कॉल समारोह किया

def processtask(request, name): 
    args = ["ls", "-l"] 
    MyTask.delay(args) 
    return HttpResponse("Task set to execute.") 

मेरे काम को इस तरह कॉन्फ़िगर किया गया है: एक Django ध्यान में रखते हुए मैं इस तरह एक प्रक्रिया शुरू कर

class MyTask(Task): 
    def run(self, args): 
    p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 
    (out, err) = p.communicate() 
    return out 

मेरा प्रश्न अब कैसे एक दलाल (मेरे Django परियोजना) अब प्राप्त कर सकते हैं "ls -l" कमांड से आउटपुट जिसे कर्मचारी ने अपने कंप्यूटर पर निष्पादित किया था। मुझे लगता है कि जब भी यह निष्पादित आदेश से उत्पादन भेजने के लिए तैयार है कार्यकर्ता दलाल में एक समारोह कॉल करने के लिए सबसे अच्छी बात होगी।

मैं अतुल्यकालिक रूप से कार्यकर्ता से उत्पादन प्राप्त करने के लिए, तो उत्पादन के साथ वेब पेज को अद्यतन करना चाहते हैं, लेकिन है कि एक और समय के लिए है। अभी के लिए मैं केवल कार्यकर्ता से आउटपुट प्राप्त करना चाहता हूं।

अद्यतन

अभी मैं एक HTTP GET अनुरोध है कि कार्य के अंत में शुरू हो रहा है कि काम किया जाता है वेब अनुप्रयोग को अधिसूचित जोड़ दिया है - मैं भी HTTP GET में task_id भेज रहा । HTTP GET प्रणाली Django दृश्य कहता है, जो AsyncResult बनाता है और परिणाम हो जाता है, लेकिन समस्या यह है कि जब result.get() कॉल मैं निम्नलिखित त्रुटि मिलती है:

/usr/lib64/python2.6/site-packages/django_celery-2.5.1-py2.6.egg/djcelery/managers.py:178: TxIsolationWarning: Polling results with transaction isolation level repeatable-read within the same transaction may give outdated results. Be sure to commit the transaction for each poll iteration. 
    "Polling results with transaction isolation level" 

कोई भी विचार क्यों? मैं डेटाबेस का उपयोग नहीं कर रहा हूं, क्योंकि मैं एएमक्यूपी के साथ खरगोश का उपयोग कर रहा हूं।

अद्यतन। छोटे और बड़े वापसी मूल्यों के लिए -

मैं बहुत ज्यादा तीसरा विकल्प है, जो सबसे अच्छा विकल्प की तरह लगता है का उपयोग करना चाहते हैं। मेरा पूरा काम इस तरह दिखता है:

class MyTask(Task): 
    def __call__(self, *args, **kwargs): 
    return self.run(*args, **kwargs) 

    def after_return(self, status, retval, task_id, args, kwargs, einfo): 
    if self.webhost is not None: 
     conn = httplib.HTTPConnection(self.webhost, self.webport) 
     conn.request("HEAD", "/vuln/task/output/"+task_id) 

    def run(self, args, webhost=None, webport=None): 
    self.webhost = webhost 
    self.webport = webport 
    r = "This is a basic result string used for code clarity" 
    return r 

तो मैं after_return समारोह है, जो भी मेरी काम पर अवरोध खोल चाहिए अधिरोहित किया है, काम की दौड़() फ़ंक्शन पहले से ही एक के बाद से मान दिया। HEAD अनुरोध में मैं मूल रूप से एक django फ़ंक्शन को कॉल कर रहा हूं, जो task_id पर AsyncResult को कॉल करता है, जो कार्य के परिणाम के साथ प्रदान करना चाहिए। मैंने अपने मामले में परीक्षण उद्देश्यों के लिए मनमाना परिणाम का उपयोग किया है, क्योंकि यह केवल परीक्षण के लिए है।

मैं चाहते हैं पता करने के लिए क्यों उपरोक्त कोड काम नहीं करता। मैं on_success उपयोग कर सकते हैं, लेकिन मुझे नहीं लगता कि यह एक फर्क होगा - या होगा यह?

+0

क्या आप डेटाबेस में कमांड का आउटपुट सहेज सकते हैं? – jpic

+0

हाय, नहीं, क्योंकि श्रमिकों को ब्रोकर के डेटाबेस तक पहुंच नहीं है और न ही मैं उन्हें एक्सेस करना चाहता हूं। मुझे निश्चित रूप से परिणाम वापस भेजने की आवश्यकता है और फिर इसे ब्रोकर में संसाधित करना होगा। – eleanor

+1

शायद आप परिणाम वापस भेजने के लिए एक HTTP एपीआई बना सकते हैं? Django में ऐसा करने के कुछ आसान तरीके हैं। – jpic

उत्तर

14

आप here आप निम्नलिखित मिलेगा देखें तो:

Django-अजवाइन MySQL का उपयोग करता है सभी कार्य/परिणाम, खरगोश-MQ का ट्रैक रखने के लिए एक संचार बस मूल रूप से के रूप में प्रयोग किया जाता है।

क्या वास्तव में हो रहा है कि आप कार्यकर्ता की ASyncResult लाने के लिए है, जबकि कार्य अभी भी चल रहा है कोशिश कर रहे हैं (कार्य अपने सर्वर पर एक HTTP अनुरोध लागू और के बाद से यह अभी तक वापस नहीं किया था, डाटाबेस से सत्र ताला लगा कार्यकर्ता अभी भी सक्रिय है और परिणाम पंक्ति अभी भी बंद है)। जब Django कार्य परिणाम (इसके राज्य और रन फ़ंक्शन का वास्तविक वापसी मूल्य) पढ़ने की कोशिश करता है तो यह पंक्ति को लॉक करता है और आपको चेतावनी देता है।

इस समाधान के बारे में जाने के लिए कुछ तरीके हैं:

  1. परिणाम काटते हैं और यह आपके प्रसंस्करण कार्य करने के लिए श्रृंखला के लिए एक और अजवाइन कार्य निर्धारित करें। इस तरह मूल कार्य खत्म हो जाएगा, डीबी पर लॉक जारी करेगा और नया इसे हासिल करेगा, परिणाम django में पढ़ें और जो कुछ भी आपको करने की ज़रूरत है उसे करें। इस पर अजवाइन दस्तावेज़ देखें।

  2. बिल्कुल परेशान न करें, और डीबीओ के माध्यम से इसे लाने की कोशिश करने के बजाय, पूर्ण प्रसंस्करण परिणाम के साथ डीजेगो को पोस्ट करें।

  3. अपने कार्य वर्ग में on_success ओवरराइड करें और Django को अपना अधिसूचना अनुरोध पोस्ट करें, उस बिंदु पर लॉक को डीबी तालिका पर रिलीज़ किया जाना चाहिए।

ध्यान दें कि आपको रन विधि (संभावित रूप से मसालेदार) की वापसी में पूरे प्रसंस्करण परिणाम (चाहे कितना बड़ा हो) स्टोर करने की आवश्यकता हो। आपने उल्लेख नहीं किया कि नतीजा कितना बड़ा हो सकता है, इसलिए यह वास्तव में केवल परिदृश्य # 2 (जो मैं करता हूं) करने के लिए समझ में आता हूं। वैकल्पिक रूप से मैं # 3 के साथ जाऊंगा। साथ ही अपने काम में ऑनफाइल विधि को संभालना न भूलें।

+0

आपकी टिप्पणी के लिए धन्यवाद। मैंने अतिरिक्त प्रश्न पूछने के लिए अपना जवाब अपडेट कर दिया है, जिसे मुझे आपके उत्तर को स्वीकार करने से पहले उत्तर देने की आवश्यकता है, जो वास्तव में अच्छा बीटीडब्ल्यू है। – eleanor

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