2016-12-28 9 views
5

मुझे यह समझाया गया core.async/पाइप लाइन का उपयोग कर त्रुटियों को संभालने के लिए सही तरीका क्या कोशिश कर रहा हूँ, मेरे पाइपलाइन निम्नलिखित है:हैंडलिंग त्रुटियों

input  --> xf-run-computation --> first-out 
first-out --> xf-run-computation --> last-out 

कहाँ xf-run-computation एक http कॉल करना होगा और प्रतिक्रिया प्रतिक्रिया। हालांकि इनमें से कुछ प्रतिक्रियाएं एक त्रुटि लौटाएंगी। इन त्रुटियों को संभालने का सबसे अच्छा तरीका क्या है?

(let [[success-values1 error-values1] (split fn-to-split first-out) 
     [success-values2 error-values2] (split fn-to-split last-out) 
     errors (merge [error-values1 error-values2])] 
(pipeline 4 first-out xf-run-computation input) 
(pipeline 4 last-out xf-run-computation success-values1) 
[last-out errors]) 

तो मेरी समारोह पिछले परिणाम और त्रुटियों वापस आ जाएगी: मेरे समाधान success-values और error-values में आउटपुट चैनलों विभाजित और फिर उन्हें वापस विलय एक चैनल को करना है।

+0

धन्यवाद कि यह एक गलती है: 'त्रुटियां (विलय [त्रुटि-मूल्य त्रुटि-मान 2] ' –

+0

आपका प्रश्न अभी भी थोड़ा उलझन में है। आपने सभी' फर्स्ट-आउट 'को प्रसंस्करण के दूसरे चरण में रखा है, जिसमें सफल और असफल दोनों परिणाम शामिल हैं। क्या दूसरा चरण इनपुट केवल 'सफलता-मूल्य 1' नहीं होना चाहिए? –

+0

मैंने आउटपुट चैनल के रूप में' फर्स्ट-आउट 'रखा है, इसलिए जब भी' xf-run-computation' कुछ परिणाम प्रकाशित करता है तो ' fn-to-split' का मूल्यांकन किया जाएगा और परिणाम को 'सफलता-मूल्य 1' या' त्रुटि-मान 1' –

उत्तर

4

सामान्य शब्दों में, क्या है "" सही तरीका शायद आपके आवेदन आवश्यकताओं के आधार पर किया जाता है, लेकिन यह देखते हुए आपकी समस्या विवरण, मुझे लगता है कि तीन चीजें आप विचार करने की जरूरत नहीं है:

  1. xf-run-computation रिटर्न डेटा है कि आपके व्यापार तर्क त्रुटियों के रूप में देखना होगा,
  2. xf-run-computation एक अपवाद और
  3. फेंकता दिया http कॉल शामिल कर रहे हैं कि, xf-run-computation से कुछ रन कभी नहीं खत्म हो सकता है (या समय में खत्म नहीं)।
बिंदु 3. के बारे में

, पहली बात पर विचार करना चाहिए pipeline-blockingpipeline के बजाय उपयोग कर रहा है।

मुझे लगता है कि आपका प्रश्न ज्यादातर बिंदु 1 से संबंधित है। मूल विचार यह है कि xf-run-computation के परिणामस्वरूप डेटा संरचना (मानचित्र या रिकॉर्ड कहें) को वापस करने की आवश्यकता है, जो स्पष्ट रूप से एक त्रुटि या सफलता के रूप में परिणाम को चिह्नित करता है उदाहरण के लिए {:title nil :body nil :status "error"}। यह आपको स्थिति से निपटने का कुछ विकल्प दे देंगे:

  • अपने सभी बाद में कोड बस इनपुट डेटा जो :status "error" है पर ध्यान नहीं देता। यानी, अपने xf-run-computation

  • आप और आवश्यकतानुसार pipeline -calls के बीच सभी परिणामों पर एक फिल्टर चला सकते हैं उन्हें filter(when (not (= (:status input) "error")) (run-computation input)) तरह की एक पंक्ति, होते हैं (ध्यान दें कि filter भी एक पाइप लाइन में एक ट्रांसड्यूसर के रूप में इस्तेमाल किया जा सकता है, जिससे वर्ष filter> और filter<

  • core.async के कार्यों), तो आपको async/split का उपयोग जैसे आप का सुझाव दिया obliterating/एलन थॉम्पसन एक अलग त्रुटि चैनल में त्रुटि मानों को फ़िल्टर करने के लिए अपने जवाब में पता चलता है। यदि आप किसी भी तरह के मानों को मर्ज करने जा रहे हैं, तो दूसरी पाइपलाइन के लिए दूसरा त्रुटि चैनल होने की कोई वास्तविक आवश्यकता नहीं है, आप बस अपने त्रुटि चैनल का पुनः उपयोग कर सकते हैं।

बिंदु 2 के लिए।, समस्या यह है कि xf-run-computation में कोई भी अपवाद किसी अन्य थ्रेड में हो रहा है और केवल आपके कॉलिंग कोड पर प्रचारित नहीं होगा। लेकिन आप ex-handler तर्क pipeline (और pipeline-blocking) पर तर्क का उपयोग कर सकते हैं। आप या तो बस सभी अपवादों को फ़िल्टर कर सकते हैं, परिणाम को एक अलग अपवाद चैनल पर डाल सकते हैं या उन्हें पकड़ने की कोशिश कर सकते हैं और उन्हें त्रुटियों में बदल सकते हैं (संभावित रूप से उन्हें परिणाम या वापस एक अन्य त्रुटि चैनल पर डालना) - बाद वाला केवल समझ में आता है, अगर अपवाद आपको पर्याप्त जानकारी देता है, उदाहरण के लिए एक आईडी या कुछ जो अपवाद के कारण इनपुट के अपवाद को वापस करने की अनुमति देता है। आप इसे xf-run-computation (यानी catch में किसी तीसरे पक्ष की लाइब्रेरी से http कॉल की तरह फेंक दिया गया अपवाद) में व्यवस्थित कर सकते हैं।

बिंदु 3 के लिए, core.async में कैनोलिक उत्तर timeout चैनल को इंगित करना होगा, लेकिन pipeline के संबंध में यह अधिक समझ में नहीं आता है। एक बेहतर विचार यह है कि आपके http कॉल पर एक टाइमआउट सेट किया गया है, उदाहरण के लिए। http-kit या :socket-timeout और :conn-timeout क्लोज-http के :timeout विकल्प। ध्यान दें कि इन विकल्पों का आमतौर पर टाइमआउट पर अपवाद होगा।

+0

में निष्पक्ष होने के लिए मेरे पास कोई एप्लिकेशन आवश्यकता नहीं है, लेकिन बस मैं कैसे करने का सबसे अच्छा तरीका खोजने का प्रयास कर रहा हूं त्रुटियों को प्रसारित करें - असफलताओं को इंगित करें। मैं चन्नेल को विभाजित करने के बजाय मानचित्र/रिकॉर्ड का उपयोग करने की कोशिश करूंगा, बिंदु 2 और 3 के बारे में भी निश्चित रूप से कुछ जोड़ा जाना चाहिए! anks! –

1

यहां एक उदाहरण है जो आप सुझाव दे रहे हैं। (range 10) की शुरुआत के साथ यह पहली बार 5 के गुणकों, तो 3.

(ns tst.clj.core 
    (:use clj.core 
     clojure.test) 
    (:require 
    [clojure.core.async :as async] 
    [clojure.string :as str] 
) 
) 

(defn err-3 [x] 
    "'fail' for multiples of 3" 
    (if (zero? (mod x 3)) 
    (+ x 300)  ; error case 
    x))    ; non-error 

(defn err-5 [x] 
    "'fail' for multiples of 5" 
    (if (zero? (mod x 5)) 
    (+ x 500)  ; error case 
    x))    ; non-error 

(defn is-ok? 
    "Returns true if the value is not 'in error' (>=100)" 
    [x] 
    (< x 100)) 

(def ch-0 (async/to-chan (range 10))) 
(def ch-1 (async/chan 99)) 
(def ch-2 (async/chan 99)) 

(deftest t-2 
    (let [ 
     _       (async/pipeline 1 ch-1 (map err-5) ch-0) 
     [ok-chan-1 fail-chan-1] (async/split is-ok? ch-1 99 99) 
     _       (async/pipeline 1 ch-2 (map err-3) ok-chan-1) 
     [ok-chan-2 fail-chan-2] (async/split is-ok? ch-2 99 99) 

     ok-vec-2     (async/<!! (async/into [] ok-chan-2)) 
     fail-vec-1    (async/<!! (async/into [] fail-chan-1)) 
     fail-vec-2    (async/<!! (async/into [] fail-chan-2)) 
    ] 
    (is (= ok-vec-2 [1 2 4 7 8])) 
    (is (= fail-vec-1 [500 505])) 
    (is (= fail-vec-2 [303 306 309])))) 

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

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