Как добавить состояние в перечислитель воспроизведения?

Чтобы передать ответ Play, я хочу передать Enumerator методу результата feed. Мне нужно передать состояние от шага итерации производства/потребления к следующему шагу (или сохранить состояние). Здесь http://engineering.klout.com/2013/01/iteratees-in-big-data-at-klout/ Я нашел пример, но не уверен, что он потокобезопасен:

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
        }
    })
}

Как вы можете добавить состояние в Play Enumerator? Является ли этот пример потокобезопасным?

(в приведенном выше примере используется старый Play API, относящийся к Promise/Future; опустим этот факт, поскольку он не влияет на саму проблему)


person Andrew Gaydenko    schedule 13.05.2014    source источник


Ответы (1)


Вы должны использовать 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))
}
person wingedsubmariner    schedule 13.05.2014
comment
Мне просто пришлось биться головой об API, пока я его не получил. - person Ryan; 14.05.2014