2011-01-22 14 views
7

मुझे पता है कि एसटीएम लेनदेन के भीतर दुष्प्रभावों के साथ कार्यों को रखने के लिए आम तौर पर यह बुरा व्यवहार है, क्योंकि उन्हें संभावित रूप से पुनः प्रयास किया जा सकता है और कई बार बुलाया जा सकता है।एसटीएम लेनदेन में दुष्प्रभावों को पूरा करने के लिए एजेंटों का उपयोग

यह मेरे लिए होता है हालांकि आप एजेंटों का उपयोग यह सुनिश्चित करने के लिए कर सकते हैं कि लेनदेन सफलतापूर्वक पूरा होने के बाद साइड इफेक्ट्स निष्पादित हो जाएं।

उदा।

(dosync 
    // transactional stuff 
    (send some-agent #(function-with-side-effects params)) 
    // more transactional stuff 
) 

क्या यह अच्छा अभ्यास है?

पेशेवर/विपक्ष/नुकसान क्या हैं?

+0

एसटीएम के मूल विचारों में से एक विफलता परमाणुता है। इससे इससे कैसे मदद मिलेगी? –

+0

बिंदु साइड इफेक्ट्स के लिए है जो लेनदेन सफल होने के बाद होने की आवश्यकता है लेकिन लेनदेन का हिस्सा नहीं हैं, उदा। एक पुष्टिकरण ईमेल भेजना। जाहिर है, आप लेनदेन को फिर से हर बार ऐसा नहीं करना चाहते हैं या अन्यथा आप बहुत गुस्सा/भ्रमित प्राप्तकर्ता प्राप्त कर सकते हैं! – mikera

उत्तर

6

मूल:

लगता है कि जैसे मेरे लिए काम करना चाहिए। आपके साइड इफेक्ट्स के आधार पर, आप भेजने के बजाय (सीपीयू-बाध्य ऑप्स के लिए) भेजने के लिए (आईओ-बाउंड ओप के लिए) का उपयोग करना चाह सकते हैं। प्रेषण/प्रेषण कार्य को आंतरिक एजेंट निष्पादक पूल में से एक में संलग्न करेगा (सीपीयू के लिए एक निश्चित आकार पूल और आईओ ऑप्स के लिए असंबद्ध आकार पूल है)। एक बार कार्य को गोद लेने के बाद, काम dosync के धागे से बाहर है ताकि आप उस बिंदु पर डिस्कनेक्ट हो जाएं।

आपको लेनदेन के भीतर किसी भी मूल्य को निश्चित रूप से भेजे गए कार्यों में कैप्चर करने की आवश्यकता होगी। और आपको उस से निपटने की ज़रूरत है जो संभवतया रीट्रीज़ के कारण कई बार होती है।

अद्यतन (टिप्पणी देखें): जब तक रेफरी लेन-देन को सफलतापूर्वक पूरा

एजेंट रेफरी के लेन-देन के भीतर भेजता आयोजित कर रहे हैं और एक बार क्रियान्वित कर रहे हैं। तो उपर्युक्त मेरे उत्तर में, प्रेषण कई बार नहीं होगा, हालांकि यह रेफरी लेनदेन के दौरान नहीं होगा जो कि आप जो चाहते हैं वह नहीं हो सकता है (यदि आप लॉग इन करने या साइड-इफेक्टिव सामान करने की अपेक्षा करते हैं)।

+0

@ मिकरा, @ एलेक्स, भेजना लेनदेन सफल होने के बाद ही होने की गारंटी है, और कई बार नहीं होना चाहिए। (Http://clojure.org/agents में स्टेटमेंट 5) – bmillare

+0

@bmillare - मुझे लगता है कि आप किसी और चीज के बारे में बात कर रहे हैं। यह बयान संदर्भित करता है कि प्रेषण/प्रेषण में पारित कार्य निष्पादित किया जाएगा। मैं जो कह रहा हूं वह है कि रेफ लेनदेन के अंदर उस कॉल को बनाकर, * रेफरी लेनदेन * कई प्रेषण/प्रेषण कॉल के कारण पुनः प्रयास किया जा सकता है, जिनमें से प्रत्येक एक बार निष्पादित करता है। –

+0

@alex, क्षमा करें, मैंने गलत बिंदु का संदर्भ दिया, आगे पाठ में, यह कहता है "एजेंट एसटीएम के साथ एकीकृत होते हैं - लेन-देन में किए गए किसी भी प्रेषण को तब तक आयोजित किया जाता है जब तक यह काम नहीं करता है, और इसे वापस ले लिया जाता है या निरस्त कर दिया जाता है। " – bmillare

5

यह काम करता है और सामान्य अभ्यास है। हालांकि, जैसे एलेक्स ने सही तरीके से बताया कि आपको भेजने पर प्रेषण पर विचार करना चाहिए।

प्रतिबद्ध मूल्यों को पकड़ने और उन्हें लेनदेन से बाहर करने के कई तरीके हैं। उदाहरण के लिए आप उन्हें एक वेक्टर (या एक नक्शा या जो कुछ भी) में वापस कर सकते हैं।

(let [[x y z] (dosync 
       ; do stuff 
       [@x @y @z])] ; values of interest to sode effects 
    (side-effect x y z)) 

या आप रीसेट कॉल कर सकते हैं! एक स्थानीय परमाणु (कोर्स के डॉसिंक ब्लॉक के व्याख्यात्मक दायरे के बाहर परिभाषित) पर।

1

एजेंटों का उपयोग करने में कुछ भी गलत नहीं है, लेकिन साइड-इफेक्टिंग गणना के लिए आवश्यक लेनदेन मूल्यों से वापस लौटना अक्सर पर्याप्त होता है।

रेफ्स शायद ऐसा करने का सबसे साफ तरीका है, लेकिन आप इसे केवल परमाणुओं के साथ प्रबंधित भी कर सकते हैं!

(def work-queue-size (atom [0])) 

(defn add-job [thunk] 
    (let [[running accepted?] 
     (swap! work-queue-size 
       (fn [[active]] 
       (if (< active 3) 
        [(inc active) true] 
        [active false])))] 
    (println 
    (str "Your job has been " 
      (if accepted? 
      "queued, and there are " 
      "rejected - there are already ") 
      running 
      " total running jobs")))) 

swap! रूप में कई बार के रूप में की जरूरत पुन: प्रयास कर सकते हैं, लेकिन काम कतार तीन से बड़ा न हो, और आप हमेशा कि अपने काम आइटम की स्वीकृति के लिए सही ढंग से जुड़ा हुआ है ठीक एक बार संदेश प्रिंट होगा । "मूल डिजाइन" परमाणु में केवल एक ही int के लिए बुलाया जाता है, लेकिन आप गणना के बाहर दिलचस्प डेटा को पारित करने के लिए इसे एक जोड़ी में बदल सकते हैं।