Created
August 24, 2016 08:44
-
-
Save ubourdon/b9c24bdb25badac1c8363c7a3d27da12 to your computer and use it in GitHub Desktop.
feed a scalaz Process with recursive async function
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| My problem is: | |
| I have a function getData[A](params ...): Task[List[A]] that return asynchronously data | |
| But this data is big so I cut the call in several step playing with params | |
| In term of API, I want expose a function stream[A]: Process[Task, A] | |
| I see Process.repeatEval & stream.async.unboundedQueue API from scalaz | |
| but I don't understand how to use it to produce this result | |
| */ | |
| object Feed[A] { | |
| // return a piece of needed data | |
| private def getData(start: Int, chunk: Int): Task[List[A]] = ??? | |
| // the public API I want to expose | |
| def stream: Process[Task, A] | |
| } |
Author
Si getData ne renvoi plus que une liste de E mais un résultat plus complexe qui contient notamment la condition de sorti de la récursion.
J'ai tenté ça. J'ai bon ?
trait Feed[A] {
case class ComplexResult[A](result: List[A], nextChunk: Int, endOfData: Boolean)
protected def getData(start: Int, chunk: Int): Task[ComplexResult[A]]
protected def isEnd(i: Int): Boolean
// we do the recursion at the Process level instead, halting when necessary
private def getChunks(start: Int, chunk: Int, end: Boolean): Process[Task, A] =
if (end) Process.halt
else {
val chunk: Task[ReadStreamEventsCompleted] = processChunk(streamUid, nextEventNumber, chunkSize)
chunk.map { result =>
Process.emitAll(readEvent(result)) ++ getChunks(streamUid, result.nextChunk, chunkSize, result.endOfData)
} |> flattenTaskProcess
}
private def flattenTaskProcess[A](f: Task[Process[Task, A]]): Process[Task, A] = Process eval(f) flatMap(x => x)
def stream: Process[Task, A] = getChunks(0, 250, false)
}
Author
When the end of recursion is decide by getData result :
private def getChunks(start: Int, chunk: Int): Process[Task, ComplexResult] =
Process.await(getData(start, start + chunk))({ c: ComplexResult =>
val next = if (c.endOfData) Process.halt else getChunks(start + chunk, chunk)
Process.emit(c) ++ next
})
Author
private def getChunks(start: Int, chunk: Int): Process[Task, ComplexResult] =
Process.await(getData(start, start + chunk))({ c: ComplexResult =>
val next = if (c.endOfData) Process.halt else getChunks(start + chunk, chunk)
Process.emit(c) ++ next
})
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Two things:
Tasklevel, that is, within a singleTask! Remember, aTaskis like aFuture, it only returns a value once, at the end of whatever computation it was doing, hence why you have nothing actually streaming.This should explain better: