Communicating between multiple phoenix applications

Hey!

I have two phoenix applications and would like to transfer data between them. What is the most efficient way to do this?

The first approach I thought about was to make http requests to each app via the already existing rest apis. I usually try not to make rest api calls to communicate within my micro services, as I feel they add an extra overhead in this case. But I am open to use it if there isn’t a better way.

I my search I came across this post
Efficient way to establishing communication between Phoenix applictions

One of the comments mentioned that Distributed Erlang could be used to communicate between two nodes. This was pretty exciting as I thought I could call a function in App1 from App2, kinda like rpc which was exactly what I was looking for.

So I connected both the apps in the same cluster and ran them in iex. I tried calling a function in App Foo from the iex in App Bar but I got Foo.Context is not available.

defmodule Foo.Context do
  def func(), do: "Hello"
end

Is it possible to just call a function from another phoenix app like

defmodule Bar.Context do
  def func(),  do: Foo.Context.func()
end

I was only able to find examples where functions from a different node were called from iex but nothing from the code. Is this even possible?

I am pretty new to elixir and phoenix, so please correct me if I got something wrong.

So you can call some code on a remote node using the RPC module’s call/4 function, but I think a better method is to use a GenServer process that is registered on both nodes. Then you’ll have a well defined handler to use on either node when you want to transfer data. The function GenServer.call/3 function’s first argument is a server() type. Most examples send pass a pid or name as the first argument, like:

{:ok, _} = GenServer.start_link(Stack, [:hello], name: MyServer)
GenServer.call(MyServer, :message)

However, instead of MyServer, you can pass a tuple of {atom(), node()}. So you can change the call to

GenServer.call({MyServer, :node2}, :message)

replacing :node2 with the name of the other node.

3 Likes

I like this GenServer process approach. I haven’t used GenServer before, but I will give it shot.

Thanks a lot!

1 Like

What @mpope wrote will be the answer.

I just want to mention Erlang global module which can be used to register a name globally in a cluster.

As a note, if you want to register an OTP behavior using :global, pass {:via, :global, SomeName} as name to start_link function

1 Like

global works, but I think I’d reach for pg for their brief problem statement.

1 Like