Skip to content

Latest commit

 

History

History
164 lines (124 loc) · 3.14 KB

distributed.md

File metadata and controls

164 lines (124 loc) · 3.14 KB

Distributed

We can start 4 node. To work in a distributed way, we need to set name to the node, to do taht we need to execute iex in this way:

iex --sname master
iex --sname s1
iex --sname s2
iex --sname s3

Check the name of the node and the list of connected nodes:

node
Node.list

To connect to other nodes you can execute (tardis is the name of my machine):

# from master
Node.connect(:s1@tardis)
Node.list

#from s1
Node.list
Node.connect(:s2@tardis)
Node.list

#from master
Node.list

Every node is connected with the others. Now from one node we can send node to other nodes. Copy the code in every nodes.

defmodule PingPong do
  def start_ping_with(node_name) do
    pid = spawn(fn ->
      send({:pingpong, node_name}, {:ping, self})
      run()
    end)
    Process.register(pid, :pingpong)
  end

  def start_listen() do
    Process.register(spawn(PingPong, :run, []), :pingpong)
  end

  def run do
    receive do
      {:pong, from} ->
        log(:pong, from)
        send(from, {:ping, self})
      {:ping, from} ->
        log(:ping, from)
        send(from, {:pong, self})
      _ -> IO.pus "Unknown message"
    end
    run
  end

  defp log(msg, from) do
    IO.puts "Receive message: #{inspect msg} from: #{inspect from}"
  end
end

Auto connect:

PingPong.start_listen
PingPong.start_ping_with :master@tardis
PingPong.start_ping_with :s1@tardis
PingPong.start_ping_with :master@tardis

Do you remember the GenServer?

defmodule GreaterServer do
  use GenServer

  def start_link(name, opts \\ []) do
    GenServer.start_link(__MODULE__, name, opts)
  end

  def say(pid, message) do
    GenServer.call(pid, {:say, message})
  end

  def handle_call({:say, message}, from, name) do
    IO.puts "#{name} say: #{message} from: #{inspect from}"
    {:reply, nil, name}
  end
end

# locally in s1@tardis

{:ok, pid} = GreaterServer.start_link("Gino")

GreaterServer.say(pid, "Ciao")

Process.register(pid, :greater_server)

GreaterServer.say(:greater_server, "Ciao")

On other node master@tardis

GreaterServer.say({:greater_server, :s1@tardis}, "Ciao")

Process.register is not the only way to send message between nodes. Close the nodes

defmodule GreaterServer do
  use GenServer

  def start_link(name, opts \\ []) do
    GenServer.start_link(__MODULE__, [name: name, lmf: nil], opts)
  end

  def say(pid, message) do
    GenServer.call(pid, {:say, message})
  end

  def last_message_from(pid) do
    {pid, _} = GenServer.call(pid, {:lmf})
    pid
  end

  def handle_call({:say, message}, from, [name: name, lmf: lmf]) do
    IO.puts "#{name} say: #{message} from: #{inspect from}"
    {:reply, nil, [name: name, lmf: from]}
  end

  def handle_call({:lmf}, from, [name: name, lmf: lmf]) do
    {:reply, lmf, [name: name, lmf: lmf]}
  end

end

# on s1
{:ok, pid} = GreaterServer.start_link("Gino", [name: :greater_server])
GreaterServer.say(pid, "Ciao")
GreaterServer.say(:greater_server, "Ciao")

# on master
GreaterServer.say({:greater_server, :s1@tardis}, "Ciao")

# on s1
from = GreaterServer.last_message_from(pid)
send(from, "RESPONSE!!!!")

#on master
flush