Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ erl_crash.dump

# Static artifacts
/node_modules
/assets/node_modules

# Since we are building assets from web/static,
# we ignore priv/static. You may want to comment
Expand Down
6 changes: 6 additions & 0 deletions config/prod.exs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,12 @@ config :gigalixir_getting_started, GigalixirGettingStarted.Repo,

config :libcluster,
topologies: [
gigalixir_example: [
strategy: GigalixirGettingStarted.Libcluster.Strategy,
config: [
url: "https://bar.gigalixirapp.com/nodes"
]
],
k8s_example: [
strategy: Cluster.Strategy.Kubernetes,
config: [
Expand Down
64 changes: 64 additions & 0 deletions lib/gigalixir_getting_started/libcluster/strategy.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
defmodule GigalixirGettingStarted.Libcluster.Strategy do
use GenServer
use Cluster.Strategy
import Cluster.Logger

alias Cluster.Strategy.State

@default_polling_interval 5_000

def start_link(opts), do: GenServer.start_link(__MODULE__, opts)
def init(opts) do
state = %State{
topology: Keyword.fetch!(opts, :topology),
connect: Keyword.fetch!(opts, :connect),
disconnect: Keyword.fetch!(opts, :disconnect),
config: Keyword.fetch!(opts, :config),
meta: MapSet.new([])
}
{:ok, state, 0}
end

def handle_info(:timeout, state) do
handle_info(:load, state)
end
def handle_info(:load, %State{topology: topology, connect: connect, disconnect: disconnect} = state) do
new_nodelist = MapSet.new(get_nodes(state))
added = MapSet.difference(new_nodelist, state.meta)
removed = MapSet.difference(state.meta, new_nodelist)
new_nodelist = case Cluster.Strategy.disconnect_nodes(topology, disconnect, MapSet.to_list(removed)) do
:ok ->
new_nodelist
{:error, bad_nodes} ->
# Add back the nodes which should have been removed, but which couldn't be for some reason
Enum.reduce(bad_nodes, new_nodelist, fn {n, _}, acc ->
MapSet.put(acc, n)
end)
end
new_nodelist = case Cluster.Strategy.connect_nodes(topology, connect, MapSet.to_list(added)) do
:ok ->
new_nodelist
{:error, bad_nodes} ->
# Remove the nodes which should have been added, but couldn't be for some reason
Enum.reduce(bad_nodes, new_nodelist, fn {n, _}, acc ->
MapSet.delete(acc, n)
end)
end
Process.send_after(self(), :load, Keyword.get(state.config, :polling_interval, @default_polling_interval))
{:noreply, %{state | :meta => new_nodelist}}
end
def handle_info(_, state) do
{:noreply, state}
end

@spec get_nodes(State.t) :: [atom()]
defp get_nodes(%State{topology: topology, config: config}) do
config
|> Keyword.get(:url)
|> HTTPoison.get!
|> Map.get(:body)
|> Poison.decode!
|> Map.get("data")
|> Enum.map(&String.to_atom/1)
end
end
3 changes: 2 additions & 1 deletion mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ defmodule GigalixirGettingStarted.Mixfile do
def application do
[mod: {GigalixirGettingStarted, []},
applications: [:phoenix, :phoenix_pubsub, :phoenix_html, :cowboy, :logger, :gettext,
:phoenix_ecto, :postgrex, :libcluster, :ssl, :runtime_tools]]
:phoenix_ecto, :postgrex, :libcluster, :ssl, :runtime_tools, :httpoison]]
end

# Specifies which paths to compile per environment.
Expand All @@ -36,6 +36,7 @@ defmodule GigalixirGettingStarted.Mixfile do
{:postgrex, ">= 0.13.3"},
{:phoenix_html, "~> 2.6"},
{:phoenix_live_reload, "~> 1.0", only: :dev},
{:httpoison, "~> 0.13"},
{:gettext, "~> 0.11"},
{:cowboy, "~> 1.0"},
{:libcluster, "~> 2.0.3"},
Expand Down
12 changes: 10 additions & 2 deletions mix.lock
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
%{"connection": {:hex, :connection, "1.0.4", "a1cae72211f0eef17705aaededacac3eb30e6625b04a6117c1b2db6ace7d5976", [:mix], []},
%{"certifi": {:hex, :certifi, "2.0.0", "a0c0e475107135f76b8c1d5bc7efb33cd3815cb3cf3dea7aefdd174dabead064", [], [], "hexpm"},
"connection": {:hex, :connection, "1.0.4", "a1cae72211f0eef17705aaededacac3eb30e6625b04a6117c1b2db6ace7d5976", [:mix], []},
"cowboy": {:hex, :cowboy, "1.0.4", "a324a8df9f2316c833a470d918aaf73ae894278b8aa6226ce7a9bf699388f878", [:make, :rebar], [{:cowlib, "~> 1.0.0", [hex: :cowlib, optional: false]}, {:ranch, "~> 1.0", [hex: :ranch, optional: false]}]},
"cowlib": {:hex, :cowlib, "1.0.2", "9d769a1d062c9c3ac753096f868ca121e2730b9a377de23dec0f7e08b1df84ee", [:make], []},
"db_connection": {:hex, :db_connection, "1.1.2", "2865c2a4bae0714e2213a0ce60a1b12d76a6efba0c51fbda59c9ab8d1accc7a8", [], [{:connection, "~> 1.0.2", [hex: :connection, repo: "hexpm", optional: false]}, {:poolboy, "~> 1.5", [hex: :poolboy, repo: "hexpm", optional: true]}, {:sbroker, "~> 1.0", [hex: :sbroker, repo: "hexpm", optional: true]}], "hexpm"},
Expand All @@ -7,8 +8,13 @@
"ecto": {:hex, :ecto, "2.1.2", "8d7bde4170b33e1049850a5dbe0112bfd232824e63c73ee63383df4c6ffd4064", [:mix], [{:db_connection, "~> 1.1", [hex: :db_connection, optional: true]}, {:decimal, "~> 1.2", [hex: :decimal, optional: false]}, {:mariaex, "~> 0.8.0", [hex: :mariaex, optional: true]}, {:poison, "~> 2.2 or ~> 3.0", [hex: :poison, optional: true]}, {:poolboy, "~> 1.5", [hex: :poolboy, optional: false]}, {:postgrex, "~> 0.13.0", [hex: :postgrex, optional: true]}, {:sbroker, "~> 1.0", [hex: :sbroker, optional: true]}]},
"fs": {:hex, :fs, "0.9.2", "ed17036c26c3f70ac49781ed9220a50c36775c6ca2cf8182d123b6566e49ec59", [:rebar], []},
"gettext": {:hex, :gettext, "0.13.0", "daafbddc5cda12738bb93b01d84105fe75b916a302f1c50ab9fb066b95ec9db4", [:mix], []},
"hackney": {:hex, :hackney, "1.9.0", "51c506afc0a365868469dcfc79a9d0b94d896ec741cfd5bd338f49a5ec515bfe", [], [{:certifi, "2.0.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "5.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "1.0.1", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "1.0.2", [hex: :mimerl, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "1.1.1", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm"},
"httpoison": {:hex, :httpoison, "0.13.0", "bfaf44d9f133a6599886720f3937a7699466d23bb0cd7a88b6ba011f53c6f562", [], [{:hackney, "~> 1.8", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm"},
"idna": {:hex, :idna, "5.1.0", "d72b4effeb324ad5da3cab1767cb16b17939004e789d8c0ad5b70f3cea20c89a", [], [{:unicode_util_compat, "0.3.1", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm"},
"libcluster": {:hex, :libcluster, "2.0.3", "be2b31161f14ff95c092431acfa5259d8e5d98be31dab634591f0033caca0848", [:mix], [{:poison, "~> 2.2", [hex: :poison, optional: false]}]},
"metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [], [], "hexpm"},
"mime": {:hex, :mime, "1.0.1", "05c393850524767d13a53627df71beeebb016205eb43bfbd92d14d24ec7a1b51", [:mix], []},
"mimerl": {:hex, :mimerl, "1.0.2", "993f9b0e084083405ed8252b99460c4f0563e41729ab42d9074fd5e52439be88", [], [], "hexpm"},
"phoenix": {:hex, :phoenix, "1.2.1", "6dc592249ab73c67575769765b66ad164ad25d83defa3492dc6ae269bd2a68ab", [:mix], [{:cowboy, "~> 1.0", [hex: :cowboy, optional: true]}, {:phoenix_pubsub, "~> 1.0", [hex: :phoenix_pubsub, optional: false]}, {:plug, "~> 1.1", [hex: :plug, optional: false]}, {:poison, "~> 1.5 or ~> 2.0", [hex: :poison, optional: false]}]},
"phoenix_ecto": {:hex, :phoenix_ecto, "3.2.1", "6cf11d590c61977f50fcb98ad8a10ee90ba8670a82cbf5eaf49cfaee2e95e8b7", [:mix], [{:ecto, "~> 2.1", [hex: :ecto, optional: false]}, {:phoenix_html, "~> 2.9", [hex: :phoenix_html, optional: false]}, {:plug, "~> 1.0", [hex: :plug, optional: false]}]},
"phoenix_html": {:hex, :phoenix_html, "2.9.2", "371160b30cf4e10443b015efce6f03e1f19aae98ff6487620477b13a5b2ef660", [:mix], [{:plug, "~> 1.0", [hex: :plug, optional: false]}]},
Expand All @@ -18,4 +24,6 @@
"poison": {:hex, :poison, "2.2.0", "4763b69a8a77bd77d26f477d196428b741261a761257ff1cf92753a0d4d24a63", [:mix], []},
"poolboy": {:hex, :poolboy, "1.5.1", "6b46163901cfd0a1b43d692657ed9d7e599853b3b21b95ae5ae0a777cf9b6ca8", [:rebar], []},
"postgrex": {:hex, :postgrex, "0.13.3", "c277cfb2a9c5034d445a722494c13359e361d344ef6f25d604c2353185682bfc", [], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}, {:db_connection, "~> 1.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: false]}], "hexpm"},
"ranch": {:hex, :ranch, "1.2.1", "a6fb992c10f2187b46ffd17ce398ddf8a54f691b81768f9ef5f461ea7e28c762", [:make], []}}
"ranch": {:hex, :ranch, "1.2.1", "a6fb992c10f2187b46ffd17ce398ddf8a54f691b81768f9ef5f461ea7e28c762", [:make], []},
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.1", "28a4d65b7f59893bc2c7de786dec1e1555bd742d336043fe644ae956c3497fbe", [], [], "hexpm"},
"unicode_util_compat": {:hex, :unicode_util_compat, "0.3.1", "a1f612a7b512638634a603c8f401892afbf99b8ce93a45041f8aaca99cadb85e", [], [], "hexpm"}}
21 changes: 21 additions & 0 deletions web/controllers/page_controller.ex
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,25 @@ defmodule GigalixirGettingStarted.PageController do
def index(conn, _params) do
render conn, "index.html"
end

def nodes(conn, params) do
json conn, %{
data: Node.list ++ [Node.self]
}
end

def connect(conn, params) do
result = params
|> Map.get("url")
|> HTTPoison.get!
|> Map.get(:body)
|> Poison.decode!
|> Map.get("data")
|> Enum.map(&String.to_atom/1)
|> Enum.map(&Node.connect/1)

json conn, %{
data: result
}
end
end
2 changes: 2 additions & 0 deletions web/router.ex
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ defmodule GigalixirGettingStarted.Router do
pipe_through :browser # Use the default browser stack

get "/", PageController, :index
get "/nodes", PageController, :nodes
get "/connect", PageController, :connect
end

# Other scopes may use custom stacks.
Expand Down