sasa1977 / exactor

Helpers for simpler implementation of GenServer based processes
MIT License
683 stars 23 forks source link

Can this be used with a via_tuple? #26

Closed Trevoke closed 7 years ago

Trevoke commented 7 years ago

I am using Elixir's Registry (though I don't think this matters) to keep track of multiple processes born from the same module all with a different id. I'm not sure I can do this cleanly with this package. Is that true, or am I missing the option that allows it? All I saw was use ExActor.GenServer, export: {:global, :global_registered_name} but it doesn't look like it will work if I need to spawn two of this kind of process and give them different names?

sasa1977 commented 7 years ago

You can pass a gen_server_opts: :runtime to defstart:

def MyServer do
  defstart start_link(arg1, arg2), gen_server_opts: :runtime do
    # ...
  end
  # ...
end

Now, your start_link accepts three arguments: arg1, arg2, and GenServer options, so you can do the following:

MyServer.start_link(arg1, arg2, name: {:via, Registry, {MyRegistry, some_name}})
Trevoke commented 7 years ago

I see; and how do use defcast and defcast so I can pass in the name via the API function?

On Sat, May 27, 2017, 09:19 Saša Jurić notifications@github.com wrote:

You can pass a gen_server_opts: :runtime to defstart:

def MyServer do defstart start_link(arg1, arg2), gen_server_opts: :runtime do # ... end # ...end

Now, your start_link accepts three arguments: arg1, arg2, and GenServer options, so you can do the following:

MyServer.start_link(arg1, arg2, name: {:via, Registry, {MyRegistry, some_name}})

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/sasa1977/exactor/issues/26#issuecomment-304458472, or mute the thread https://github.com/notifications/unsubscribe-auth/AAEJSavBxK61fGQd0veZrrq-71wqWW3pks5r-D8TgaJpZM4NoPJc .

sasa1977 commented 7 years ago

Normally, defcast and defcall take the server as the first argument, so you can pass the same via tuple as in start_link. That's of course clumsy, because the clients must be aware of the exact shape of the via tuple.

If you want to wrap that knowledge inside the GenServer module, you can use private versions of defcastp and defcallp and wrap them with a plain function:

def MyServer do
  def some_op(name, arg1, arg2), do: some_op_cast(via_tuple(name), arg1, arg2)

  defcastp some_op_cast(arg1, arg2, ...) do
    # ...
  end

  defp via_tuple(name), do:
    {:via, Registry, {MyRegistry, some_name}}
end

Unfortunately, at this point ExActor doesn't really give you much compared to plain GenServer. ExActor only helps for the simplest cases where all arguments are passed as is. As soon as you somehow need to transform those arguments, it will be pretty much the same amount of code as with GenServer. This is the reason why I mostly stopped using ExActor myself. It sometimes help, but not always, so it seems to me that using a plain GenServer is generally a better way, because it's less magical and standard part of Elixir.

Trevoke commented 7 years ago

nod I understand, thank you.