2012-05-17 2 views
3

다음 예, 재생 프레임 워크의 문서에서 적응 :왜 반복자가 완료되기 전에 Play의 PushEnumerator를 닫아야합니까?

val enumerateUsers: Enumerator[String] = { 
    Enumerator("Guillaume", "Sadek", "Peter", "Erwan") 
} 
val consumeOne = Cont[String, String](in => 
    in match { 
    case Input.EOF => 
     Done("", Input.Empty) 
    case Input.Empty => 
     Done("", Input.Empty) 
    case Input.El(s) => 
     Done(s, Input.Empty) 
    }) 
println((enumerateUsers |>> consumeOne).flatMap(_.run).await.get) 

출력합니다 Guillaume. 나는 그 Enumerator 있도록 변경하면

그러나, PushEnumerator입니다 :

val enumerateUsers: PushEnumerator[String] = Enumerator.imperative[String]() 
// consumeOne as before 
val i = enumerateUsers |>> consumeOne 
enumerateUsers.push("Guillaume") 
enumerateUsers.push("Sadek") 
enumerateUsers.push("Peter") 
enumerateUsers.push("Erwan") 
println(i.flatMap(_.run).await.get) 
// Timeout exception 

은 내가 iteratee의 약속에 시간 제한 예외를 얻을.

이전과 동일하게하려면 PushEnumerator을 닫아야합니다.

val enumerateUsers: PushEnumerator[String] = Enumerator.imperative[String]() 
// consumeOne as before 
val i = enumerateUsers |>> consumeOne 
enumerateUsers.push("Guillaume") 
enumerateUsers.push("Sadek") 
enumerateUsers.push("Peter") 
enumerateUsers.push("Erwan") 
enumerateUsers.close() // <-- magic line 
println(i.flatMap(_.run).await.get) 

그리고 이것은 이전처럼 Guillaume을 인쇄합니다.

이유가 무엇인지 의미 차이가 무엇인지 알려주는 문서를 찾을 수 없습니다. 누군가 지적 할 수 있겠습니까?

편집 : 재생 소스에서 내 답변을 찾았습니다. 일부 사냥이 필요했습니다. @ huynhjl의 답을 올바른 것으로 표시하겠습니다. 그러나 내가 찾고 있었던 특정 답변이 맞습니다. 꽤 간단합니다. Play 구현은 부작용을 사용하여 소켓을 구동합니다. 이는 무리하지 않습니다. 단지 가정 한 것 (가정은 모든 것을 죽입니다 : D)입니다. play.core.server.netty.Helpers 안에는 socketOut[A](...)이라는 기능이 있습니다. socketOut[A](...)에는 step이라는 함수가 있으며,이 함수는 반복을 반환합니다. 이 Iteratee는 입력 사례가 El(e)과 일치 할 때 e을 출력 채널에 씁니다. 내 가정은 Iteratees가 값을 얻을 수있는 열거자를 부분적으로 소비 할 수 있다는 것이었지만 그럴 수있는 유일한 방법은 부작용을 통해 발생하는 것 같았습니다. 내 생각 엔 ...

답변

2

Enumerator의 역할 객체는 더 이상 요소가 없거나 iteratee가 완료 될 때까지 특정 순서로 iteratee에 요소를 공급 한 다음 해당 iteratee를 반환하는 것입니다. close() 호출은 iteratee 결과가 리턴 될 수 있도록 입력이 더 이상 없을 때를 나타냅니다. 을 닫지 않고이라고 부르지 않으면 더 많은 것을 밀어 낼 수 있습니다. 그래서 나는 시도하지 않은 그러나 나는 이것이 당신의 예에 해당 될 것으로 예상 :

val i = enumerateUsers |>> consumeOne 
i.flatMap(_.run).onRedeem(println) // we will have a result we want to print 
// now feed some data 
enumerateUsers.push("Guillaume") 
enumerateUsers.push("Sadek") 
enumerateUsers.push("Peter") 
enumerateUsers.push("Erwan") 
// no more input, trigger promise computation 
enumerateUsers.close() 

당신은 당신이 미리 그것을 얻을 필요가 얼마나 많은 요소 시간을 알 수없는 iteratee에 enumerateUsers을 적용 할 경우 더 의미 결과 (일반적인 경우).

+0

'WebSocket'과 어떻게 작동하는지 명확하지 않기 때문에 Play 소스를 조사해야 할 것입니다. 내가 아는 한 (나는 올바른 터미널 ATM에 있지 않다) 나는 WebSocket의 아웃 바운드 열거 자에게 '계속'푸시한다. 나는 철사로 물건을 만들기 위해 그것을 닫을 필요가 없다. 그러나 각각의 '푸시'가 생기는 것 같다. 그렇다면, 제가 놓친 몇 가지 메커니즘이 있습니다. –

+0

@DerekWyatt, 기술적으로 WebSocket은 요소가 푸시되고있는 한 iteratee의 결과를 추출하지 않아도됩니다. 그래서 그것이 필요하지 않은 이유 일 수 있습니다. – huynhjl

+0

제 질문에 대한 답변을 추가했습니다. –

관련 문제