What is the spec for the "_from" in GenServer.handle_call/3?

b GenServer.handle_call/3 just says that the from() spec is a tuple containing a PID and a term that identifies the call, but the format of that term is confusing…
When I inspected it, it was of the form:

{#PID<0.230.0>, [:alias | #Reference<0.234234234.234234234…>]}

the second element isn’t a type that looks familiar… is it a list, that has a join operator between an atom and an reference? How would I use this reference in practice? Is it just there to be a unique ID?


The [:alias | #Reference<0.234234234.234234234…>] term is an improper list.

I believe the tag (second element) is intended to be an opaque term that is used by :gen_server, not by a callback implementation.

1 Like

Not only is it opaque but I believe you are intended to be able to stuff data in there as you see fit if you need to implement more complicated forwarding schemes for clusters of custom GenServers, it’s opaque so that consumers of your services can use the standard calls, eg GenServer.reply, without caring about what you do with that reference token downstream.

For example, you have a genserver A that sends a message to a proxy genserver B that forwards to C, the pid of the reply should go back to the proxy, but, you could for example stuff {pid, ref} (the reply for A) into the opaque term so that the proxy can immediately relay the reply without having to keep a lookup table

Looking at the erlang gen_server documentation for handle_call/3 I see:

If {reply,Reply,NewState} is returned, {reply,Reply,NewState,Timeout} or {reply,Reply,NewState,hibernate}, Reply is given back to From as the return value of call/2,3 or included in the return value of multi_call/2,3,4. The gen_server process then continues executing with the possibly updated internal state NewState.)

Which doesn’t appear to suggest a mutated From can be used in a :reply for handle_call/3.

I guess you can do anything you like if you return :no_reply and then send a :reply although the documentation for reply/2 doesn’t make any reference to mutating From.

If it can indeed be used that way, that would be interesting. Could have potential uses in IoT devices, and routing. But how would customize what the from field would say to a message receiver?

no, you should NOT change a “from” once it’s been passed to you, I just meant that you can build a framework that sends a different “shape of from” to a generic handle_call handler, and it should work just fine, including with GenServer’s reply/2 function.

I used this in a library that I deployed in prod that might interest digitsu (could be used to route IoT devices; I used it to route to Virtual machines, which is a similar use case).