2014-09-16 8 views
9

पर त्रुटि मैं एक एसिंक कार्य बनाने की कोशिश कर रहा हूं जो अनुरोध को अवरुद्ध नहीं करेगा। उपयोगकर्ता अनुरोध करता है, कार्य शुरू हो जाएगा, और नियंत्रक "नौकरी चल रहा है ..." प्रस्तुत करेगा, यह कार्य को पूरा करने के लिए अवरुद्ध होने वाले अनुरोध से बचने के लिए है। एक बार काम खत्म है, यह onComplete निष्पादित और उस कार्य के परिणाम के साथ कुछ करना होगाएसिंक नौकरी

| Error 2014-09-16 17:38:56,721 [Actor Thread 3] ERROR gpars.LoggingPoolFactory - Async execution error: null 

(उदाहरण के लिए एक सेवा है कि एक उपयोगकर्ता के लिए एक मेल भेजेगा कहते हैं) कोड निम्नलिखित है:

package testasync 

import static grails.async.Promises.* 

class TestController { 

    def index() { 
    //Create the job 
    def job1 = task { 
     println 'Waiting 10 seconds' 
     Thread.sleep(10000) 
     return 'Im done' 
    } 
    //On error 
    job1.onError { Throwable err -> 
     println "An error occured ${err.message}" 
    } 
    //On success 
    job1.onComplete { result -> 
     println "Promise returned $result" 
    } 
    render 'Job is running...' 
    } 

पूरा स्टैकट्रेस: ​​

| Error 2014-09-17 10:35:24,522 [Actor Thread 3] ERROR gpars.LoggingPoolFactory - Async execution error: null 
Message: null 
    Line | Method 
->> 72 | doCall in org.grails.async.factory.gpars.GparsPromise$_onError_closure2 
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
    |  62 | run  in groovyx.gpars.dataflow.DataCallback$1 
    | 1145 | runWorker in java.util.concurrent.ThreadPoolExecutor 
    | 615 | run  in java.util.concurrent.ThreadPoolExecutor$Worker 
^ 745 | run . . . in java.lang.Thread 
+0

वहाँ एक पूरा का पता लगाने है? – cfrick

+0

ने पूर्ण stacktrace – agusluc

उत्तर

3

मैंने अंगूर-निष्पादक प्लगइन के साथ निष्पादक ढांचे का उपयोग समाप्त कर दिया। मैंने यहां एक बहुत ही बुनियादी उदाहरण अपलोड किया: https://github.com/agusl88/grails-async-job-queuqe

वह कोड grails-execor प्लगइन के "कस्टम" संस्करण का उपयोग कर रहा है, मैंने कुछ पीआर प्लगइन रेपो से विलय कर लिया है और प्रोपस का परीक्षण करने के लिए जार के रूप में पैक किया है। प्लगइन का रेपो यह है: https://github.com/basejump/grails-executor

0

जब एक नियंत्रक आप वास्तव मेंफोन करके प्रतिक्रिया वापस लौटाना होगा अंदर एक वादा async कार्य बनाने कार्य परविधि, या onError और onComplete विधियों को कभी भी नहीं कहा जाएगा। जोड़ना:

job1.get() 

render करने के लिए अपने कॉल करने से पहले इस मुद्दे को हल करेंगे।

+2

जोड़ा लेकिन प्राप्त() वर्तमान अनुरोध को ब्लॉक करता है, इसलिए रेंडर निष्पादित नहीं किया जाता है जब तक कि एसिंक कार्य पूरा नहीं हो जाता है। मैं कार्य शुरू करना चाहता हूं, अनुरोध समाप्त करें (उपयोगकर्ता के अंत में प्रतीक्षा समय से बचने के लिए), और जब कार्य खत्म हो जाए, तो परिणाम को पूर्ण के साथ चुनें। – agusluc

+0

@agusluc क्या आपको इसका कोई समाधान मिला है? मुझे grails के साथ एक ही समस्या का सामना करना पड़ रहा है 2.4.4 –

+0

@ShashankAgrawal मैंने पाया समाधान के साथ एक प्रतिक्रिया जोड़ा। उम्मीद है कि यह – agusluc

1

मैं onComplete और onError कॉल को हटाकर नियंत्रक में इस अपवाद से छुटकारा पाने में सक्षम था। मुझे लगता है कि अपवाद होता है क्योंकि जब आप render कहते हैं तो पैरेंट थ्रेड समाप्त हो जाता है।

तो अपने:

Promise p = task { 
    complexAsyncMethodCall(); // (1) do stuff 
} 
.onComplete { result -> println result } // (2) on success 
.onError { Throwable t -> System.err.println("Error: " + t) } // (3) on error 

बन जाता है:

Promise p = task { 
    try { 
     def result = complexAsyncMethodCall(); // (1) do stuff 
     println result // (2) on success 
    } catch(Throwable t) { 
     System.err.println("Error: " + t) // (3) on error 
    } 
} 

यह आपके काम (1) और परिणाम प्रसंस्करण (2 और 3) के बीच युग्मन कहते हैं, लेकिन आप लिख कर इस पर काबू पाने सकता है आपके स्वयं Closure रैपर जो तर्क के रूप में अतिरिक्त क्लोजर लेता है। कुछ इस तरह:

// may not work! written off the top of my head 
class ProcessableClosure<V> extends Closure<V> { 
    Closure<V> work; 
    Closure<?> onError; 
    Closure<?> onComplete; 

    @Override 
    public V call(Object... args) { 
     try { 
      def result = work.call(args); // (1) do stuff 
      onComplete.call(result); // (2) on complete 
     } catch(Exception e) { 
      onError.call(result); // (3) on error 
     } 
    } 
} 

कि अपने कोड अधिक पठनीय बनाता है:

Closure doWork = { complexAsyncMethodCall(); } // (1) do stuff 
Closure printResult = { println it } // (2) on complete 
Closure logError = { Throwable t -> log.error t } // (3) on error 
Closure runEverythingNicely = new ProcessableClosure(work: doWork, onComplete: printResult, onError: logError) 
Promise p = task { runEverythingNicely }