Open
Description
Hi!
In my work I sometimes need a function that takes asyncs and perform them in parallel, but with simultaneously performed asyncs count lesser than count of overall asyncs passed to function, and return results of asyncs as AsyncSeq in order to consumer can process the results as soon as they appear.
Maybe my explanation confusing, I will try express it in the code:
let getJobs () = asyncSeq {
// some jobs retrieve code here
return [1;2;3;4] |> AsyncSeq.ofSeq
}
let download job = async {
// some download code here
return 42
}
let downloadAll parallelCount = asyncSeq {
let jobs = getJobs() // overall jobs count far greater than parallelCount
let results = jobs |> AsyncSeq.requestedFunc parallelCount
return results
}
// consumer code
let maxParallel = 5
downloadAll maxParallel
|> AsyncSeq.toBlockingSeq
|> Seq.iter (fun result -> printfn "%A" result)
Here is my attempt to do so:
let downloadAllBad parallelCount = asyncSeq {
let jobs = getJobs()
let batches = jobs |> AsyncSeq.bufferByCount parallelCount
for batch in batches do
let! results =
batch
|> Seq.map download
|> Async.Parallel // bad: wait time of results = wait time of longer async in batch
for result in results do
yield result
}
There I forced to wait results of all asyncs in batch, but I want to recieve results as them appears.
In past I use MailboxProcessor's for this, one agent distrubutes tasks to a few worker agents.