Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create an agent where only some messages get responses?

Is it possible to create a mailbox agent that only sometimes posts replies? From the looks of it, It seems to me that you have to always send an async reply channel if you want to ever post replies.

For my use case I'd really like to be able to have the flexibility that some messages only need to be delivered to the agent, whereas other messages I'd like to get either a synchronous or asynchronous reply back.

like image 686
devshorts Avatar asked Jan 13 '23 06:01

devshorts


1 Answers

I'm not sure if I understand the question correctly - but you can certainly use a discriminated union as a type of your messages. Then you can have some cases (message types) that contain AsyncReplyChannel<T> and some other messages that do not carry it (and do not require a reply).

For example, for a simple agent that adds numbers, you can have Add (which does not need response) and Get which does need a response. In addition, Get carries a Boolean that specifies whether we should reset the state back to zero:

type Message = 
  | Add of int
  | Get of bool * AsyncReplyChannel<int>

The agent then receives messages repeatedly and if the message is Get then it sends a reply:

let counter = MailboxProcessor.Start(fun inbox -> 
  let rec loop count = async {
    let! msg = inbox.Receive()
    match msg with 
    | Add n -> return! loop (count + n) // Just update the number
    | Get (reset, repl) ->
        repl.Reply(count)               // Reply to the caller 
        let count = if reset then 0 else count // get new state
        return! loop count }            // .. and continue in the new state
  loop 0 )

You can then use Post method to send message that does not require a reply and PostAndReply to send a message that returns something via an async reply channel:

counter.Post(Add 10)
counter.PostAndReply(fun r -> Get(true, r))
counter.PostAndReply(fun r -> Get(false, r))
like image 189
Tomas Petricek Avatar answered Feb 02 '23 19:02

Tomas Petricek