1

I asked a similar question yesterday about using one application inside another.
Let's say I want to use an application called x inside a new module y.
x is already compiled and for the sake of simplicity, lets assume it is already running on localhost, and that the objective is to run both components in different nodes.

How can I call functions of x from within y?
Would something like rpc:call(Node, x, Fun, Param) work?

Furthermore, is any (network) setup necessary in order to use the rpc module?

Important

If you are not able to test connections between two nodes, make sure that you use the command line flag -name and that you include the whole name in your net_adm:ping/1 call. e.g. if you named your node x@localhost, you must ping x from another module by executing net_adm('x@localhost').. Notice the single-quotes. See this question for more details.

Community
  • 1
  • 1
goncalotomas
  • 1,000
  • 1
  • 12
  • 29

1 Answers1

3

How you call x depends both on its APIs and on whether or not x is running in the same node as y.

  • If x is running in the same node as y and your application dependencies are declared such that x starts before y starts, you can simply call into a module of x the same as calling any other local module.

  • If x is in a different node, then yes, using the rpc module to call into it is one viable option. As long as the y node can connect to the x node via Distributed Erlang, rpc will work without any extra setup.

I mention the API because it's frequently the case that modules do their work by registering their process ids into some sort of name registry, such as the local registry via erlang:register/2, the global registry, or alternative registries such as gproc, and callers may need to first access the registry directly or indirectly to find the target they're trying to call. For example, when calling a gen_server instance you typically need to pass as an argument the name or pid of the instance you're trying to call, and for remote calls, the target node name is needed as well.

Steve Vinoski
  • 19,847
  • 3
  • 31
  • 46
  • 1
    Thank you!! The nodes are supposed to be different, I forgot to mention that. However useful your answer is, I'm trying to connect to the `x` node by initiating a new shell with `erl -name y@127.0.0.1 -setcookie y`. I try to ping `x` using `net_adm:ping(x).` but it responds with `pang`. Do you have any idea what I could be doing wrong? – goncalotomas Mar 28 '16 at 23:27
  • 2
    What is the name of the `x` node? If you have an Erlang shell open on the `x` node its name should be in the shell prompt. Was `x` started with short names (using `-sname`) or long names (using `-name`)? Are you sure it's using the same cookie? If you run `epmd -names` does it list the `x` node? Just a guess but I suspect the `127.0.0.1` part should be the hostname instead. – Steve Vinoski Mar 29 '16 at 00:17
  • Running `node().` on `x` outputs `x@127.0.0.1`. That's why I named `y` `y@127.0.0.1`. I believe both are using long names (`-name`), not short ones. I fetch the cookie from `x` by running `erlang:get_cookie().` on its console, which outputs `x`. So I start `y` with `erl -name y@127.0.0.1 -setcookie x`, but results remain the same. What also intrigues me is that running `net_adm:names()` outputs `{ok,[{"x",58521},{"y",58920}]}` and `epmd -names` outputs `name y at port 58920`, `name x at port 58521`. – goncalotomas Mar 29 '16 at 00:32
  • I figured it out. I have to use `net_adm:ping('x@127.0.0.1').`. I thought that `net_adm:ping(x).` would be enough, but apparently not! I got the idea from [this question](http://stackoverflow.com/questions/2136918/getting-two-erl-shells-to-talk-on-os-x). – goncalotomas Mar 29 '16 at 00:47
  • I'll buy you a round of beers if you come to Lisbon anytime soon. Thank you again for all your help. You are awesome. – goncalotomas Mar 29 '16 at 00:59
  • Glad you figured out the ping problem, and you're welcome for the help. – Steve Vinoski Mar 29 '16 at 01:12