Reputation: 377
To feed Play response I want to pass Enumerator
to result's feed
method. I need to pass a state from produce/consume iteration step to the next step (or to keep state). Here
http://engineering.klout.com/2013/01/iteratees-in-big-data-at-klout/
I have found an example but am not sure it is thread-safe:
def pagingEnumerator(url:String):Enumerator[JsValue]={
var maybeNextUrl = Some(url) //Next url to fetch
Enumerator.fromCallback[JsValue] ( retriever = {
val maybeResponsePromise =
maybeNextUrl map { nextUrl=>
WS.url(nextUrl).get.map { reponse =>
val json = response.json
maybeNextUrl = (json \ "next_url").asOpt[String]
val code = response.status //Potential error handling here
json
}
}
maybeResponsePromise match {
case Some(responsePromise) => responsePromise map Some.apply
case None => PlayPromise pure None
}
})
}
What is you way to add a state to Play Enumerator
? Is this example thread-safe?
(in the above example old Play API related to Promise/Future is used; let's neglect this fact as far as it doesn't influence the issue itself)
Upvotes: 1
Views: 170
Reputation: 13667
You should use Enumerator.unfoldM
:
Enumerator.unfoldM(Some(firstURL)) { maybeNextUrl =>
maybeNextUrl map { nextUrl =>
WS.url(nextUrl).get.map { response =>
val json = response.json
val newUrl = (json \ "next_url").asOpt[String]
val code = response.status //Potential error handling here
Some((newUrl, json))
}
} getOrElse (Future.successful(None))
}
Upvotes: 2