Skip to content

Instantly share code, notes, and snippets.

Last active Dec 20, 2018
What would you like to do?
Simple distributed greeting system
# machine 1
# start up with `iex --name m1@ --cookie greeter`
# This isn't really necessary but it won't hurt anything
Node.connect :"m1@"
# All `Node.connect/1` calls can go to the same machine and every machine
# in the cluster will automatically be connected.
# machine 2
# start up with `iex --name m2@ --cookie greeter`
Node.connect :"m1@"
# machine 3
# start up with `iex --name m3@ --cookie greeter`
Node.connect :"m1@"
# Back on machine 1
greeter = fn ->
name = node() |> to_string |> String.split("@") |> List.first
System.cmd "say", ["hello", name]
# Everyone says hello at the same time
Node.list |> Enum.each(fn n -> Node.spawn(n, greeter) end)
# Need custom code to make the machines work together
defmodule Greeter do
use GenServer
# Start up pointing at the next greeter in the ring
def start_link(next) do
GenServer.start_link __MODULE__, next
def handle_cast(:greet, next) do
name = node() |> to_string |> String.split("@") |> List.first
System.cmd "say", ["Hi my name is", name]
GenServer.cast next, :greet
{:noreply, next}
# On iex console, grab bytecode (number 33 will vary)
{:module, Greeter, bytecode, _} = v(33)
# Need to load bytecode on all remote machines
# GOTCHA: Ensure to use single quotes when dealing with erlang!
:rpc.multicall :code, :load_binary, [Greeter, 'greeter.ex', bytecode]
# End of the chain will be the current machine
{:ok, greeter_pid} = Greeter.start_link nil
# Start up a greeter on every machine
Node.list |> Enum.reduce(greeter_pid, fn(n, pid)->
me = self
Node.spawn(n, fn ->
{:ok, p} = Greeter.start_link(pid)
send(me, p)
receive do
p -> p
# Now to have everyone introduce themselves one after another...
# (number 44 will vary, should be the returned pid from above)
GenServer.cast v(44), :greet
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment