Client-Server Architecture

Mathematical server

code

Registered processes

code

Distributed environments

Distributed mathematical server

A generic server

The code must expose the following features:

We will achieve all of this with approximately 20 lines of code!

Generic server's code

The engine of the server consists of a function F of the following type:

F :: (State,Data) -> (Result, NewState)
loop(State, F) ->
    receive
          stop -> true ;

          {update, From, Ref, NewF} ->
                   From ! {ok, Ref},
                   loop(State, NewF) ;

          {request, From, Ref, Data} ->
                    {R, NS} = F(State, Data),
                    From ! {result, Ref, R},
                    loop(NS, F)
    end.

Exceptions

The evaluation of expressions can fail

[] = [1].
** exception error: no match of right hand side value [1]
net_adm:ping(1,2).
** exception error: undefined function net_adm:ping/2
> catch(1/0).
{'EXIT',{badarith,[{erlang,'/',[1,0]},
                   {erl_eval,do_apply,5},
                   {erl_eval,expr,5},
                   {shell,exprs,7},
                   {shell,eval_exprs,7},
                   {shell,eval_loop,3}]}}
> catch([] = [1]).
{'EXIT',{{badmatch,[1]},[{erl_eval,expr,3}]}}
> catch(net_adm:ping(1,2)).
{'EXIT',{undef,[{net_adm,ping,[1,2]},
                {erl_eval,do_apply,5},
                {erl_eval,expr,5},
                {shell,exprs,7},
                {shell,eval_exprs,7},
                {shell,eval_loop,3}]}}
> 

Robust generic server

code

loop(State, F) ->
    receive
        stop -> true ;

        {update, From, Ref, NewF} ->
                 From ! {ok, Ref},
                 loop(State, NewF);

        {request, From, Ref, Data} ->
                  case catch(F(State, Data)) of
                      {'EXIT', Reason} ->
                             From!{exit, Ref, Reason},
                             loop(State, F);
                      {R, NewState} ->
                             From!{result, Ref, R},
                             loop(NewState, F)
                  end
    end.

Generic client

code

request(Pid, Data) ->
    Ref = make_ref(),
    Pid!{request, self(), Ref, Data},
    receive
        {result, Ref, Result} ->
            Result;
        {exit, Ref, Reason} ->
            exit(Reason)
    end.
update(Pid, Fun) ->
    Ref = make_ref(),
    Pid!{update, self(), Ref, Fun},
    receive
    {ok, Ref} ->
        ok
    end.

Mathematical server revisited

code