exactor
exactor copied to clipboard
Possibility of custom process registration dispatching logic?
Right now, it is possible to either return a PID, or to register using :global
or :via
. However, this needs to be given as option when ExActor.GenServer
is included (use
d).
This unfortunately which means that it is impossible to build custom logic, to e.g. register at {:via, Registry, {MyRegistry, "user_#{user_id}"}}
.
Maybe, a possibility would be to allow users to write a custom export
function, which is used for the different functions to transform the first argument into a term like above that could be used to do the actual GenServer dispatching on.
It is possible to use via tuple by using private macros (defstartp
, defcastp
, ...), but this requires additional wrapping, and pretty much makes ExActor as noisy as GenServer. I discussed this in #26.
Your proposal is very interesting, and at first glance I like it. We could support a callback function (e.g. server_pid/1
), which would by default be an identity function. It could be overridable, so in the implementation you can override the behaviour and turn it into e.g. a via tuple. The function should be invoked only if export
option is not provided.
Would you be willing to make a PR? The code is somewhat convoluted, what with all the macro logic, so if you don't feel like it, I could give it a stab.
Yes, I am willing to give the creation of a PR a go :-).
Good luck :-) If you get stuck somewhere, feel free to ask.
I think the cleanest way would be to just define server_pid
as a normal function that can be overridden (by ExActor specifying defoverridable [server_pid: 1]
) by the user. Do you agree?
Yeah, that's what I thought as well.
All right.
I worked a little bit on this today, as I finally had some spare time.
However, I'm still unable to find the proper location to add the new logic.
I am guessing it is close to Exactor.Operations.server_ref/2, but I am unsure what server
refers to in the quote(do: server)
statements. (Is this a snippet that is inserted somewhere else in an unhygienic way?)
I pushed a small refactoring commit into a separate branch. With that change, the definition of the interface function for calls/casts is now done in the single place.
Roughly speaking, you need to do the following. If type
is neither :multicall
nor :abcast
, and :export
option is nil
or false
, you need to do something along the lines of:
- Split
gen_server_args
into head/tail (outside of the quoted block). - Inside the quoted block invoke the new callback with injected head from step 1.
- Modify the invocation in line 587 and pass the result from step 2 followed by
unquote_splicing(tail_from_step_1)
.
If type
is :multicall
or :abcast
, or :export
option is neither nil
nor false
, you should use the same quoted code as in line 587. So you'll add an if before line 586, and then either return the verbatim copy of the existing quote block, or a more elaborate quote block as described above.
I didn't try this out, so I might have missed some possible problems or fine-print details :-)
You can cherry pick my commit into your branch, and then try to see if my proposal takes off.