I want to write a simple load balancer for some requests coming into a C# web api app.
(I only use the C# stuff as a convenient way to create a web server).
Whats the best way to approach this? (I havent really done any mailbox stuff in F#) If I were to use mailboxes/agents...then I post the request as a message, fine...but how do I get the response back to web api request handler?
Isnt it all fire and forget? (I have, ironically, done some erlang)
(I CAN have a simple mutable global index of which is the next worker service to handle the request...but this is my opportunity to do it nicely).
actually I think I may have done something very similar to this in erlang, and I think the initiator would pass a return address where to send the message back (and the return address was the process id of the initiator), it would then wait for the response, and when it gets it (or times out), it would then do whatever it needed to do.
Is that a sensible mechanism in F#?
------------------------ edit ------------------------
So, https://www.codemag.com/Article/1707051/Writing-Concurrent-Programs-Using-F describes a similar set up and it seems I need to use, and actually this works, but it ISNT quite the same mechanism as my Erlang suggestion about. Here each client sends a PostAndReply, and then waits for the response before replying back.....that seems unnecessary, ideally the reply would go all the way back to the origin, and the intermediaries would fire and forget in between.
open System
type Message = string * AsyncReplyChannel<string>
[<EntryPoint>]
let main argv =
let myFirstAgent =
MailboxProcessor<Message>.Start(fun inbox ->
let rec loop () =
async {
let! (message, replyChannel) = inbox.Receive()
replyChannel.Reply (String.Format ("1. Received message: {0}", message))
do! loop ()
}
loop ())
let mySecondAgent =
MailboxProcessor<Message>.Start(fun inbox ->
let rec loop () =
async {
let! (message, replyChannel) = inbox.Receive()
replyChannel.Reply (String.Format ("2. Received message: {0}", message))
do! loop ()
}
loop ())
let agents = [ myFirstAgent; mySecondAgent ]
let replyAgent =
MailboxProcessor<Message>.Start(fun inbox ->
let rec loop index =
async {
let! (message, replyChannel) = inbox.Receive()
let reply = (agents.Item index).PostAndReply(fun rc -> message,rc)
replyChannel.Reply reply
do! loop ((index + 1) % 2)
}
loop 0)
let foo = replyAgent.PostAndReply(fun rc -> "Hello", rc)
let foo1 = replyAgent.PostAndReply(fun rc -> "Hello", rc)
let foo2 = replyAgent.PostAndReply(fun rc -> "Hello", rc)
let foo3 = replyAgent.PostAndReply(fun rc -> "Hello", rc)
let foo4 = replyAgent.PostAndReply(fun rc -> "Hello", rc)
//myFirstAgent.Post "Hello!"
printfn "Hello World from F#!"
System.Console.ReadLine() |> ignore
0 // return an integer exit code