Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Erlang asynchronous message handling with gen_server:cast/2

I'm looking for good examples of Erlang asynchronous message handling with gen_server:cast/2.

I've seen an example in the OTP ssh module, which receives a request through Module:handle_cast/2, holding it in a local queue of the module, and sending back a reply message corresponding to the request later, by explicitly sending a message to the caller. When I tried to read it, I could barely keep track of the code, and wasn't able to grasp the idea.

A piece of pseudo code is appreciated.

like image 750
jj1bdx Avatar asked Jan 19 '23 12:01

jj1bdx


1 Answers

I believe you're referring to the ssh_connection_manager module.

When you perform a gen_server:cast/2, the request is handled in the Module:handle_cast/2 function. A couple of things to notice here:

  • In the handle_cast parameters you don't have information about the sender, so you cannot - unless you send this information within the message itself - send back some result to it.
  • The client, after issuing a gen_server:cast/2, won't wait for a reply. Actually, it doesn't even care if the message arrived or not (with some exceptions).
  • In an handle_cast/2, you can just return a noreply or a stop tuple, so no way to return a reply there.

Said that, the idea behind the code you've been looking at should be (simplifying things):

  • An initial synchronous gen_server:call/2 is made
  • The client's From is passed to the server and saved into its state (in reality, an extra process seems to be created with that argument). This trick is useful when you are not able to compute the return value at the time of the handle_call.
  • At this point you have to two possibilities, depending if you need more information to compute your result from other clients (A) or from the same client (B):

    • A. Return something like {noreply NewState} in the handle_call. This will give you the possibility to handle other requests while the client is still holding. When the result is ready you can send it back to the client using a gen_server:reply().
    • B. Return {reply, ok, State} to the client. The client will continue execution, maybe performing a series of cast/2. Then, the client will ask you the final result with a new gen_server:call/2.
like image 150
Roberto Aloi Avatar answered Apr 30 '23 23:04

Roberto Aloi