I was testing inter-node function call (rpc) like this:
defmodule RpcTest do
def run do
Task.Supervisor.async( {DBServer.DistSupervisor, :'dbserver@hostname'}, fn -> "test" end)
|> Task.await
|> IO.inspect
end
end
Then I run dbserver
node, call Task.Supervisor.start_link(name: DBServer.DistSupervisor)
in the dbserver
to receive rcp, and execute the code above in another node dbclient
It could run the rpc correctly as below.
dbserver
$ iex --sname dbserver --cookie a -S mix
Erlang/OTP 18 [erts-7.3] [source] [64-bit] [smp:8:8] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]
Compiling 1 file (.ex)
Interactive Elixir (1.3.1) - press Ctrl+C to exit (type h() ENTER for help)
iex(dbserver@hostname)1> Task.Supervisor.start_link(name: DBServer.DistSupervisor)
{:ok, #PID<0.101.0>}
iex(dbserver@hostname)2>
dbclient
$ elixir --sname dbclient --cookie a -S mix run -e RpcTest.run
"test"
However, after I change the code from "test"
to "test test
", the dbclient node does not work.
Here is the error message
dbserver
iex(dbserver@hostname)2>
12:54:57.430 [error] Task #PID<0.110.0> started from {:"dbclient@hostname", #PID<13423.52.0>} terminating
** (BadFunctionError) expected a function, got: #Function<0.113878361/0 in RpcTest>
:erlang.apply/2
(elixir) lib/task/supervised.ex:94: Task.Supervised.do_apply/2
(elixir) lib/task/supervised.ex:45: Task.Supervised.reply/5
(stdlib) proc_lib.erl:240: :proc_lib.init_p_do_apply/3
Function: #Function<0.113878361/0 in RpcTest>
Args: []
dbclient
$ elixir --sname dbclient --cookie a -S mix run -e RpcTest.run
Compiling 1 file (.ex)
** (EXIT from #PID<0.52.0>) an exception was raised:
** (BadFunctionError) expected a function, got: #Function<0.113878361/0 in RpcTest.run/0>
:erlang.apply/2
(elixir) lib/task/supervised.ex:94: Task.Supervised.do_apply/2
(elixir) lib/task/supervised.ex:45: Task.Supervised.reply/5
(stdlib) proc_lib.erl:240: :proc_lib.init_p_do_apply/3
Moreover, it does work after dbserver
restarts manually.
Interestingly, it does work with iex
whatever the code is.
$ iex --sname dbclient --cookie a -S mix
Erlang/OTP 18 [erts-7.3] [source] [64-bit] [smp:8:8] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]
Compiling 1 file (.ex)
Interactive Elixir (1.3.1) - press Ctrl+C to exit (type h() ENTER for help)
iex(dbclient@hostname)1> Task.Supervisor.async( {DBServer.DistSupervisor, :'dbserver@hostname'}, fn -> "test" end) |>
...(dbclient@hostname)1> Task.await |>
...(dbclient@hostname)1> IO.inspect
"test"
"test"
iex(dbclient@hostname)2> Task.Supervisor.async( {DBServer.DistSupervisor, :'dbserver@hostname'}, fn -> "test test" end) |>
...(dbclient@hostname)2> Task.await |>
...(dbclient@hostname)2> IO.inspect
"test test"
"test test"
My question is,
- is it the wrong way to call the function in a node from another node?
- when using inter-node function call, do I have to re-execute the callee node every time I changed the client code?
- why are the behaviors different between
iex
andelixir script
?
The code and the whole project are uploaded here: https://github.com/ayamamori/rpc_test/blob/master/lib/rpc_test.ex
Thanks in advance!