Skip to content

Instantly share code, notes, and snippets.

@RudolfMan
Created September 28, 2022 03:50
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save RudolfMan/fd6047e57af5093af3148fa74dfe45da to your computer and use it in GitHub Desktop.
Save RudolfMan/fd6047e57af5093af3148fa74dfe45da to your computer and use it in GitHub Desktop.
ClusterPlayground.hello()
# => :world
# Start peer node
{:ok, peer, node_name} = :peer.start(%{connection: :standard_io})
# try call some functions
:peer.call(peer, :rand, :uniform, [100])
:peer.call(peer, ClusterPlayground, :hello, [])
:peer.call(peer, Map, :get, [%{foo: :bar}, :foo])
# Oops!
# let's take a look at locally loaded modules
:erlang.loaded()
:erlang.loaded() |> length()
# and modules loaded for peer
:peer.call(peer, :erlang, :loaded, [])
:peer.call(peer, :erlang, :loaded, []) |> length()
# let's look at the observer
:observer.start()
:peer.call(peer, :observer, :start, [])
# load the same code
:peer.call(peer, :code, :add_paths, [:code.get_path()])
# start a global agent
Agent.start(fn -> [] end, name: {:global, :rudolf})
:peer.call(peer, Agent, :start, [fn -> [] end, [name: {:global, :rudolf}]])
# Turn node into a distributed node with the given long name
:net_kernel.start([:"primary@127.0.0.1"])
Node.list()
# => []
:peer.call(peer, :net_kernel, :start, [[:"peer1@127.0.0.1"]])
Node.list()
# Still empty => []
Node.connect(:"peer1@127.0.0.1")
# =INFO REPORT==== 27-Sep-2022::13:17:31.060397 ===
# global: Name conflict terminating {rudolf,<17133.150.0>}
:global.whereis_name(:rudolf)
:net_kernel.stop()
:global.whereis_name(:rudolf)
# Some helpers shamelessly adapted from
# [Phoenix.PubSub.Cluster](https://github.com/phoenixframework/phoenix_pubsub/blob/master/test/support/cluster.ex)
for {app_name, _, _} <- Application.loaded_applications() do
for {key, val} <- Application.get_all_env(app_name) do
:peer.call(peer, Application, :put_env, [app_name, key, val])
end
end
# ensure_applications_started
# for each peer node dialyxir is throwing a warning:
#
# Warning: the `dialyxir` application's start function was called,
# which likely means you did not add the dependency with the
# `runtime: false` flag.
#
# we don't really need dialyxir in peer nodes for testing purposes
@exclude_apps [:dialyxir]
:peer.call(peer, Application, :ensure_all_started, [:mix])
:peer.call(peer, Mix, :env, [Mix.env()])
for {app_name, _, _} <- Application.loaded_applications(),
app_name not in @exclude_apps do
:peer.call(peer, Application, :ensure_all_started, [app_name])
end
for file <- files do
:peer.call(peer, Code, :require_file, [file])
end
setup %{nodes: nodes} do
peers = Cluster.spawn_many(nodes, require_files: [__ENV__.file])
...
end
defmodule Cluster do
def spawn_many(nodes, opts \\ []) do
for node <- nodes do
:peer.start_link(%{
connection: :standard_io,
# ...
wait_boot: {self(), :booted}
})
end
receive do
{:booted, {:started, ^node_name, ^peer}} ->
add_code_paths(peer)
transfer_configs(peer)
ensure_applications_started(peer)
require_files(peer, Keyword.get(opts, :require_files, []))
end
...\
end
end
defmodule DummyModule do
def process(msg, sender) do
send(sender, :done)
end
end
test "" do
start_processor(DummyModule, :process, self())
function_that_eventually_calls_dummy_module()
assert_receive :done
:net_kernel.stop()
function_that_eventually_calls_dummy_module()
assert_receive :done
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment