<div dir="ltr"><div><div>Hey,<br><br></div>Just starting out on erlang, and trying to implement a message broker using erlang. I have a gen_fsm process for each client that handles the command and data receiving and I was wondering what is the best way to for the main broker process to send data to the client. <br><br>Do I just send a message to the client process and handle the sending inside `handle_info`? How would I handle race conditions in this case? E.g. When the client process terminates just after the main process sent the message.<br></div><div><br></div><div>My code looks something like this at the moment:<br><br>-module(pq_test).<br>-export([init/1,handle_info/3,handle_event/3]).<br>-export([start/0]).<br>-export([recv_cmd/2,recv_data/2]).<br><br>-record(state, {socket, buffer, current_command}).<br><br>start() -><br>    spawn_link(fun start_link/0).<br><br>start_link() -><br>    {ok, ListenSocket} = gen_tcp:listen(11880, [{active, false}, binary]),<br>    accept(ListenSocket).<br><br>accept(ListenSocket) -><br>    {ok, Socket} = gen_tcp:accept(ListenSocket),<br>    {ok, Pid} = gen_fsm:start_link({local, ?MODULE}, ?MODULE, Socket, []),<br>    erlang:display(Pid),<br>    gen_tcp:controlling_process(Socket, Pid),<br>    accept(ListenSocket).<br><br>init(Socket)-><br>    inet:setopts(Socket, [{active, true}]),<br>    {ok, recv_cmd, <br>     #state{socket = Socket, buffer = <<"">>, current_command = null}}.<br><br>cmd_parse(publish, [Topic, Key, Length], #state{socket = Socket})-><br>    {Len, _} = string:to_integer(Length),<br>    erlang:display(Len),<br>    io:format("Publish -~s- -~s- -~B-~n", [Topic, Key, Len]),<br>    {next_state, recv_data, <br>     #state{socket = Socket, buffer = <<"">>, current_command = {publish, Len}}};<br>cmd_parse(_, _, #state{socket = Socket}) -><br>    io:format("Unknown command~n"),<br>    {next_state, recv_cmd, <br>     #state{socket = Socket, buffer = <<"">>, current_command = null}}.<br><br>cmd_process(CommandLine, #state{socket = Socket} = State) -><br>    io:format("1~n"),<br>    case string:tokens(binary_to_list(CommandLine), [$\s, $\r, $\n]) of<br>    [Command | Args] -> <br>        cmd_parse(list_to_atom(Command), Args, State);<br>    _ -> {next_state, recv_cmd, <br>          #state{socket = Socket, buffer = <<"">>, current_command = null}}<br>    end.<br><br>cmd_more(CommandLine, #state{socket = Socket}) -><br>    {next_state, recv_cmd, <br>     #state{socket=Socket, buffer=CommandLine, current_command = null}}.<br><br>recv_cmd({data, Data}, #state{buffer = Buffer} = State) -><br>    CommandLine = <<Buffer/binary, Data/binary>>,<br>    Last = binary:last(CommandLine),<br>    case Last of<br>    $\n -> cmd_process(CommandLine, State);<br>    _  -> cmd_more(CommandLine, State)<br>    end.<br><br>recv_data({data, Data}, <br>      #state{socket = Socket, <br>         buffer = Buffer, <br>         current_command = {publish, Len}}) when Len > byte_size(Data) -><br>    {next_state, recv_data,<br>     #state{socket = Socket, buffer = <<Buffer/binary, Data/binary>>, <br>        current_command = {publish, Len - byte_size(Data)}}};<br>recv_data({data, Data}, #state{socket = Socket, buffer = Buffer}) -><br>    io:format("Got all data: ~s~n", [<<Buffer/binary, Data/binary>>]),<br>    {next_state, recv_cmd,<br>     #state{socket = Socket, buffer = <<"">>, current_command = null}}.<br><br>handle_info({tcp, _, Message}, StateName, State) -><br>    ?MODULE:StateName({data, Message}, State);<br>handle_info(Event, StateName, State) -><br>    io:format("handle info~n"),<br>    erlang:display(Event),<br>    {next_state, StateName, State}.<br><br>handle_event(_, _, _) -><br>    io:format("handle event").<br><br></div></div>