The intent of call/3 is to implement a synchronous protocol on top of a native asynchronous one.
call boils down to the client sending a request and then blocking until a reply for that exact request arrives - ignoring any other messages that may arrive in the meantime.
Now typically the server processes the request immediately in handle_call/3 and responds with a :reply.
So the intent behind call/handle_call is to implement a synchronous protocol.
Now the server has some wiggleroom as it can finish handle_call with :noreply to delay emitting a reply until later with reply/2 but that doesn’t change the synchronous client experience (the server might do this to stop the same client from sending additional requests).
The “spawn to call” tactic is used as a countermeasure by a client process which doesn’t wish to have the “synchronous experience” that call enforces.
Using “spawn to call” within the “service” (rather than on the client-side) may give the client process the illusion of asynchronous communication (while still leaving the burden of setting up the monitor and dealing with monitor messages) - but call still implements a synchronous protocol; for what purpose?
(My guess is that the dispatcher core has been designed/written in terms of handle_call which means that the dispatcher implementation is in fact synchronous. Such an implementation could be, not necessarily, but quite possibly blocked while processing a single request rather than servicing other requests asynchronously.)
If the dispatcher is asynchronous and the clients need to deal with it asynchronously then simply have the dispatcher serve/implement cast/handle_cast instead (while the dispatcher casts its reply back to the client) to fully reveal the dispatcher’s asynchronous nature.


















