Work distribution: porting from AsyncSeq
See original GitHub issueI’m trying to port code from this blog post http://theimowski.com/blog/2016/04-27-dynamic-load-balancing-in-f/index.html:
open System
#r @"packages/FSharp.Control.AsyncSeq/lib/net45/FSharp.Control.AsyncSeq.dll"
open FSharp.Control
#r @"packages/FSharpx.Async/lib/net40/FSharpx.Async.dll"
open FSharpx.Control
let process machine input =
let url = sprintf "http://%s/webservice/endpoint" machine
async {
// call a web service with a given input (file)
return! callService url input
}
let renditions (machines: string list) (inputs: string list) =
let workersCount = 4
let renditionsCount = inputs.Length
asyncSeq {
let queue = BlockingQueueAgent<_>(renditionsCount)
let results = BlockingQueueAgent<_>(renditionsCount)
let rec worker machine = async {
let! input = queue.AsyncGet()
let! result = process machine input
do! results.AsyncAdd (result)
do! worker machine
}
for input in inputs do
do! queue.AsyncAdd(input)
for machine in machines do
for i in 0 .. workersCount - 1 do
worker machine |> Async.Start
for i in 0 .. renditionsCount - 1 do
let! result = results.AsyncGet()
yield result
}
|> AsyncSeq.toArrayAsync
|> Async.RunSynchronously
My attempt (I don’t use operators to keep it readable for normal people):
let callService url input =
job {
Console.WriteLine (sprintf "Calling %s with %s..." url input)
do! timeOutMillis 500
return input
}
let process' machine input =
let url = sprintf "http://%s/webservice/endpoint" machine
job {
// call a web service with a given input (file)
return! callService url input
}
let renditions (machines: string list) (inputs: string[]) =
job {
let! inputCh = Ch.create()
let! finished = IVar.create()
do! job { for input in inputs do
do! Ch.give inputCh input
Console.WriteLine (sprintf "%s has been given to input channel." input) }
|> Job.queue
let! resultVar = MVar.createFull (ResizeArray())
let worker machine =
Job.foreverServer <|
job {
let! input = Ch.take inputCh
let! res = process' machine input
let! results = MVar.take resultVar
results.Add res
do! MVar.fill resultVar results
if results.Count = inputs.Length then
do! IVar.fill finished ()
}
let workersCount = 4
for machine in machines do
for _ in 1..workersCount do
do! worker machine |> Job.queue
do! IVar.read finished
return! MVar.take resultVar |> Job.map Seq.toList
}
|> run
renditions ["host1"; "host2"] (Array.init 10 string)
I’m not sure it’s OK in any sense. I tried to use Streams, but they don’t seem to fit to the task at all. Any suggestions?
Issue Analytics
- State:
- Created 7 years ago
- Comments:13 (9 by maintainers)
Top Results From Across the Web
What's new in F# 6? - ParTech
These will be distributed via community packages like FSharp.Control.AsyncSeq and may be included in FSharp.Core in future editions.
Read more >F# Async Guide
This is a usage guide for asynchronous programming in F# using the Async type. The content should be helpful to existing F# Async...
Read more >FSharp.Control.AsyncSeq
FSharp.Control.AsyncSeq is a collection of asynchronous programming utilities for F#. An AsyncSeq is a sequence in which individual elements are retrieved using ...
Read more >Akka.NET Streams vs Hopac vs AsyncSeq
Akka.NET Streams is a port of its Scala/Java counterpart and intended to execute complex data processing graphs, optionally in parallel and ...
Read more >What's new in F# 6 - .NET Blog
Initially these will be delivered via community packages such as FSharp.Control.AsyncSeq. In future versions they may be integrated into FSharp.
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Here is another version of
renditions
compatible with vasily-kirichenko’sprocess'
:I don’t recommend using
run
as above, but this matches the type of the original.Note that outputs are not produced in the same order as inputs.
Hopac Streams: