From b5eca5326fcf8dc15a895b5300e52a7d33b88090 Mon Sep 17 00:00:00 2001 From: Joao P Dubas Date: Fri, 20 Sep 2024 21:54:20 +0000 Subject: [PATCH] feat: configure dnscluster to allow multi-node * Configure `docker-compose` to scale at least 2 nodes. * Add script to start service with proper naming * Create custom resolver. * This is not strictly necessary. --- config/dev.exs | 4 ++++ config/runtime.exs | 2 ++ docker-compose.yml | 2 ++ lib/wabanex/application.ex | 4 ++++ lib/wabanex/dev_dns_cluster_resolver.ex | 26 ++++++++++++++++++++++++ mix.exs | 1 + mix.lock | 1 + priv/docker/service/docker-entrypoint.sh | 2 ++ 8 files changed, 42 insertions(+) create mode 100644 lib/wabanex/dev_dns_cluster_resolver.ex create mode 100755 priv/docker/service/docker-entrypoint.sh diff --git a/config/dev.exs b/config/dev.exs index 1faf08e..955f22a 100644 --- a/config/dev.exs +++ b/config/dev.exs @@ -1,5 +1,9 @@ import Config +config :wabanex, + dns_cluster_query: :ignore, + dns_cluster_resolver: Wabanex.DevDNSClusterResolver + # Configure your database config :wabanex, Wabanex.Repo, database: "wabanex_dev", diff --git a/config/runtime.exs b/config/runtime.exs index 7120844..90fc85f 100644 --- a/config/runtime.exs +++ b/config/runtime.exs @@ -1,5 +1,7 @@ import Config +config :wabanex, dns_cluster_query: System.get_env("DNS_CLUSTER_QUERY") || :ignore + config :wabanex, Wabanex.Repo, username: System.get_env("POSTGRES_USER") || "postgres", password: System.get_env("POSTGRES_PASS") || "postgres", diff --git a/docker-compose.yml b/docker-compose.yml index 052ec9c..c4a520f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -43,12 +43,14 @@ services: - path: ./mix.lock action: rebuild environment: &app_environment + DNS_CLUSTER_QUERY: *app_host POSTGRES_HOST: *db_host POSTGRES_USER: *db_user POSTGRES_PASS: *db_pass POSTGRES_NAME: wabanex_dev working_dir: /opt/app restart: unless-stopped + scale: 2 entrypoint: sleep command: infinity db_setup: diff --git a/lib/wabanex/application.ex b/lib/wabanex/application.ex index 2960117..536404e 100644 --- a/lib/wabanex/application.ex +++ b/lib/wabanex/application.ex @@ -15,6 +15,10 @@ defmodule Wabanex.Application do WabanexWeb.Telemetry, # Start the PubSub system {Phoenix.PubSub, name: Wabanex.PubSub}, + {DNSCluster, + query: Application.get_env(:wabanex, :dns_cluster_query) || :ignore, + log: :info, + resolver: Application.get_env(:wabanex, :dns_cluster_resolver) || DNSCluster.Resolver}, # Start the Endpoint (http/https) WabanexWeb.Endpoint # Start a worker by calling: Wabanex.Worker.start_link(arg) diff --git a/lib/wabanex/dev_dns_cluster_resolver.ex b/lib/wabanex/dev_dns_cluster_resolver.ex new file mode 100644 index 0000000..a802fe0 --- /dev/null +++ b/lib/wabanex/dev_dns_cluster_resolver.ex @@ -0,0 +1,26 @@ +defmodule Wabanex.DevDNSClusterResolver do + @moduledoc """ + Local DNS resolver for cluster query. + """ + require Record + + Record.defrecord(:hostent, Record.extract(:hostent, from_lib: "kernel/include/inet.hrl")) + + def basename(node_name) when is_atom(node_name) do + [basename, _] = node_name |> to_string() |> String.split("@") + basename + end + + def connect_node(node_name) when is_atom(node_name) do + Node.connect(node_name) + end + + def list_nodes, do: Node.list(:visible) + + def lookup(query, type) when is_binary(query) and type in [:a, :aaaa] do + case :inet_res.getbyname(~c"#{query}", type) do + {:ok, hostent(h_addr_list: addr_list)} -> addr_list + {:error, _} -> [] + end + end +end diff --git a/mix.exs b/mix.exs index edb04fb..3323f16 100644 --- a/mix.exs +++ b/mix.exs @@ -36,6 +36,7 @@ defmodule Wabanex.MixProject do {:credo, "~> 1.7.0", only: [:dev, :test], runtime: false}, {:crudry, "~> 2.4.0"}, {:dialyxir, "~> 1.4.0", only: [:dev, :test], runtime: false}, + {:dns_cluster, "~> 0.1.1"}, {:ecto_sql, "~> 3.12.0"}, {:gettext, "~> 0.25.0"}, {:jason, "~> 1.4.0"}, diff --git a/mix.lock b/mix.lock index 6a6d8e5..e75b24d 100644 --- a/mix.lock +++ b/mix.lock @@ -11,6 +11,7 @@ "db_connection": {:hex, :db_connection, "2.7.0", "b99faa9291bb09892c7da373bb82cba59aefa9b36300f6145c5f201c7adf48ec", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "dcf08f31b2701f857dfc787fbad78223d61a32204f217f15e881dd93e4bdd3ff"}, "decimal": {:hex, :decimal, "2.1.1", "5611dca5d4b2c3dd497dec8f68751f1f1a54755e8ed2a966c2633cf885973ad6", [:mix], [], "hexpm", "53cfe5f497ed0e7771ae1a475575603d77425099ba5faef9394932b35020ffcc"}, "dialyxir": {:hex, :dialyxir, "1.4.3", "edd0124f358f0b9e95bfe53a9fcf806d615d8f838e2202a9f430d59566b6b53b", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "bf2cfb75cd5c5006bec30141b131663299c661a864ec7fbbc72dfa557487a986"}, + "dns_cluster": {:hex, :dns_cluster, "0.1.3", "0bc20a2c88ed6cc494f2964075c359f8c2d00e1bf25518a6a6c7fd277c9b0c66", [:mix], [], "hexpm", "46cb7c4a1b3e52c7ad4cbe33ca5079fbde4840dedeafca2baf77996c2da1bc33"}, "ecto": {:hex, :ecto, "3.12.0", "9014a3ccac7f91e680b9d237d461ebe3d4e16d62ca8e355d540e2c6afdc28309", [:mix], [{:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "41e781a76e131093af8e1edf68b1319bf320878faff58da41ffa4b10fc6ff678"}, "ecto_sql": {:hex, :ecto_sql, "3.12.0", "73cea17edfa54bde76ee8561b30d29ea08f630959685006d9c6e7d1e59113b7d", [:mix], [{:db_connection, "~> 2.4.1 or ~> 2.5", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.12", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.7", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.19 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1 or ~> 2.2", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "dc9e4d206f274f3947e96142a8fdc5f69a2a6a9abb4649ef5c882323b6d512f0"}, "erlex": {:hex, :erlex, "0.2.7", "810e8725f96ab74d17aac676e748627a07bc87eb950d2b83acd29dc047a30595", [:mix], [], "hexpm", "3ed95f79d1a844c3f6bf0cea61e0d5612a42ce56da9c03f01df538685365efb0"}, diff --git a/priv/docker/service/docker-entrypoint.sh b/priv/docker/service/docker-entrypoint.sh new file mode 100755 index 0000000..f359da7 --- /dev/null +++ b/priv/docker/service/docker-entrypoint.sh @@ -0,0 +1,2 @@ +#!/usr/bin/env bash +elixir --name ${HOSTNAME}@$(hostname -i | cut -d ' ' -f1) --cookie ${1} -S mix phx.server