2012-07-13 30 views
5

मैं Play 2.0 ढांचे की प्रतिक्रियाशील I/O अवधारणाओं को समझने की कोशिश कर रहा हूं। शुरुआत से बेहतर समझ प्राप्त करने के लिए मैंने फ्रेमवर्क के हेल्पर्स को अलग-अलग प्रकार के इटरेटेट बनाने और एकको स्क्रैच से लिखने के लिए अनुरोध किया है ताकि अनुरोध निकाय को पार्स करने के लिए BodyParser द्वारा उपयोग किया जा सके।बॉडीपार्सर Iteratee में कॉलिंग त्रुटि या निष्पादन क्यों करता है अनुरोध फ्रेम फ्रेम 2.0 में लटका है?

import play.api.mvc._ 
import play.api.mvc.Results._ 
import play.api.libs.iteratee.{Iteratee, Input} 
import play.api.libs.concurrent.Promise 
import play.api.libs.iteratee.Input.{El, EOF, Empty} 

01 object Upload extends Controller { 
02 def send = Action(BodyParser(rh => new SomeIteratee)) { request => 
03  Ok("Done") 
04 } 
05 } 
06 
07 case class SomeIteratee(state: Symbol = 'Cont, input: Input[Array[Byte]] = Empty, received: Int = 0) extends Iteratee[Array[Byte], Either[Result, Int]] { 
08 println(state + " " + input + " " + received) 
09 
10 def fold[B](
11  done: (Either[Result, Int], Input[Array[Byte]]) => Promise[B], 
12  cont: (Input[Array[Byte]] => Iteratee[Array[Byte], Either[Result, Int]]) => Promise[B], 
13  error: (String, Input[Array[Byte]]) => Promise[B] 
14 ): Promise[B] = state match { 
15  case 'Done => { println("Done"); done(Right(received), Input.Empty) } 
16  case 'Cont => cont(in => in match { 
17  case in: El[Array[Byte]] => copy(input = in, received = received + in.e.length) 
18  case Empty => copy(input = in) 
19  case EOF => copy(state = 'Done, input = in) 
20  case _ => copy(state = 'Error, input = in) 
21  }) 
22  case _ => { println("Error"); error("Some error.", input) } 
23 } 
24 } 

(टिप्पणी: सभी इन बातों ने मुझे के लिए नए हैं

जानकारी Iteratees और ScalaBodyParser डॉक्स और खेलने प्रतिक्रियाशील मैं के बारे में दो प्रस्तुतियों में उपलब्ध के साथ शुरू/ओ यह है कि क्या मैं के साथ आया है , तो कृपया क्षमा करें अगर इसके बारे में कुछ कुल बकवास है।) Iteratee बहुत गूंगा है, यह सिर्फ सभी हिस्सों को पढ़ता है, प्राप्त बाइट्स की संख्या बताता है और कुछ संदेशों को प्रिंट करता है। जब मैं कुछ डेटा के साथ नियंत्रक कार्रवाई को कॉल करता हूं तो सब कुछ अपेक्षित काम करता है - मैं देख सकता हूं कि सभी हिस्सों को इटरेटे द्वारा प्राप्त किया जाता है और जब सभी डेटा पढ़ा जाता है तो यह राज्य में स्विच हो जाता है और अनुरोध समाप्त होता है।

  • राज्य त्रुटि में स्विच करने से पहले सभी इनपुट पढ़ा जाता है:

    अब मैं क्योंकि मैं इन दो मामलों के लिए व्यवहार देखना चाहता था कोड के साथ चारों ओर खेलने के लिए शुरू कर दिया।

  • सभी इनपुट से पहले किए गए राज्य में स्विचिंग Int के बजाय Result को पढ़ और वापस कर रहा है।

ऊपर वर्णित दस्तावेज की मेरी समझ यह है कि दोनों संभव होना चाहिए लेकिन असल में मैं मनाए गए व्यवहार को समझने में सक्षम नहीं हूं। पहले मामले में मैं करने के लिए ऊपर दिए गए कोड की लाइन 17 बदल परीक्षण करने के लिए:

17  case in: El[Array[Byte]] => copy(state = if(received + in.e.length > 10000) 'Error else 'Cont, input = in, received = received + in.e.length) 

तो मैं सिर्फ एक शर्त है, तो 10000 से अधिक बाइट्स प्राप्त हुए थे त्रुटि राज्य में स्विच करने के लिए जोड़ा। मुझे प्राप्त होने वाला आउटपुट यह है:

'Cont Empty 0 
'Cont El([[email protected]) 8192 
'Error El([[email protected]) 16384 
Error 
Error 
Error 
Error 
Error 
Error 
Error 
Error 
Error 
Error 
Error 

फिर अनुरोध हमेशा के लिए लटकता है और कभी समाप्त नहीं होता है। उपरोक्त उल्लिखित दस्तावेज़ों से मेरी अपेक्षा यह थी कि जब मैं फ़ंक्शन को fold के अंदर एक Iteratee के अंदर दबाता हूं तो प्रसंस्करण को रोका जाना चाहिए। यहां क्या हो रहा है कि इटरेटे की फोल्ड विधि को error के बाद कई बार बुलाया जाता है - ठीक है और फिर अनुरोध लटकता है।

जब मैं सभी इनपुट पढ़ने से पहले किए गए राज्य में स्विच करता हूं तो व्यवहार काफी समान होता है।

15 case 'Done => { println("Done with " + input); done(if (input == EOF) Right(received) else Left(BadRequest), Input.Empty) } 

और लाइन से 17: करने के लिए लाइन 15 बदलने

17  case in: El[Array[Byte]] => copy(state = if(received + in.e.length > 10000) 'Done else 'Cont, input = in, received = received + in.e.length) 

निम्नलिखित उत्पादन का उत्पादन:

'Cont Empty 0 
'Cont El([[email protected]) 8192 
'Done El([[email protected]) 16384 
Done with El([[email protected]) 
Done with El([[email protected]) 
Done with El([[email protected]) 
Done with El([[email protected]) 

और फिर से अनुरोध हमेशा के लिए लटका हुआ है।

मेरा मुख्य प्रश्न यह है कि उपर्युक्त मामलों में अनुरोध क्यों लटक रहा है। अगर कोई इस पर प्रकाश डाल सकता है तो मैं इसकी सराहना करता हूं!

उत्तर

4

आपकी समझ पूरी तरह से सही है और मैं सिर्फ मास्टर करने के लिए एक ठीक धक्का है

https://github.com/playframework/Play20/commit/ef70e641d9114ff8225332bf18b4dd995bd39bcc

दोनों ही मामलों के साथ साथ Iteratees में अपवाद फिक्स्ड।

आईटरेट बीटीडब्ल्यू करने के लिए कक्षा में प्रतिलिपि का अच्छा उपयोग।

+0

फिक्स और दयालु शब्दों के लिए धन्यवाद, यह ठीक करने की कोशिश करेगा! – lost

0

चीजें 2.1 के साथ बदलनी चाहिए - वादा अब पैरामीट्रिक नहीं है, और यह उदाहरण अब संकलित नहीं है।