diff --git a/app.json b/app.json index 825aa87..c41be98 100644 --- a/app.json +++ b/app.json @@ -4,7 +4,18 @@ "repository": "https://github.com/data-twister/farside", "logo": "", "keywords": ["elixir", "farside" ], - "addons": [ "heroku-postgresql"], + "env": { + "MIX_ENV": "prod", + "FARSIDE_PORT": { + "description": "The Port Farside is running on", + "value": "443" + }, + "FARSIDE_SERVICES_JSON": { + "description": "The json of services available", + "value": "", + "required": false + } + }, "buildpacks": [ { "url": "https://github.com/HashNuke/heroku-buildpack-elixir.git" diff --git a/config/config.exs b/config/config.exs index eaabb0d..1324272 100644 --- a/config/config.exs +++ b/config/config.exs @@ -14,4 +14,5 @@ config :farside, queries: [ "weather", "time" - ] + ], + services_json_data: System.get_env("FARSIDE_SERVICES_JSON") || "" diff --git a/config/runtime.exs b/config/runtime.exs index e4491ff..1fce4a3 100644 --- a/config/runtime.exs +++ b/config/runtime.exs @@ -2,5 +2,4 @@ import Config config :farside, port: System.get_env("FARSIDE_PORT", "4001"), - redis_conn: "redis://localhost:#{System.get_env("FARSIDE_REDIS_PORT", "6379")}", services_json: System.get_env("FARSIDE_SERVICES_JSON", "services.json") diff --git a/heroku.yml b/heroku.yml new file mode 100644 index 0000000..aa12458 --- /dev/null +++ b/heroku.yml @@ -0,0 +1,10 @@ +setup: +build: + docker: + web: Dockerfile + run: + web: exec /opt/app/bin/server start + config: + MIX_ENV: prod + FARSIDE_PORT: $FARSIDE_PORT + FARSIDE_SERVICES_JSON: $FARSIDE_SERVICES_JSON \ No newline at end of file diff --git a/lib/farside/application.ex b/lib/farside/application.ex index 251764d..dbeb0ce 100644 --- a/lib/farside/application.ex +++ b/lib/farside/application.ex @@ -1,6 +1,4 @@ defmodule Farside.Application do - # @farside_port Application.fetch_env!(:farside, :port) - # @redis_conn Application.fetch_env!(:farside, :redis_conn) @moduledoc false use Application @@ -9,6 +7,7 @@ defmodule Farside.Application do alias Farside.LastUpdated alias Farside.Sync + alias Farside.Http @impl true def start(_type, _args) do @@ -48,11 +47,21 @@ defmodule Farside.Application do end def load(response) do - services_json = Application.fetch_env!(:farside, :services_json) + services_json_data = Application.fetch_env!(:farside, :services_json_data) queries = Application.fetch_env!(:farside, :queries) - {:ok, file} = File.read(services_json) - {:ok, json} = Jason.decode(file) + reply = + case String.length(services_json_data) < 10 do + true -> + file = Application.fetch_env!(:farside, :services_json) + {:ok, data} = File.read(file) + data + + false -> + services_json_data + end + + {:ok, json} = Jason.decode(reply) for service_json <- json do service_atom = @@ -60,48 +69,9 @@ defmodule Farside.Application do {String.to_existing_atom(key), val} end - service = struct(%Service{}, service_atom) - - test_urls = - Enum.map(service.instances, fn x -> - test_url = - x <> - EEx.eval_string( - service.test_url, - query: Enum.random(queries) - ) - - {test_url, x} - end) - - tasks = - for {test_url, instance} <- test_urls do - Task.async(fn -> - reply = Farside.Http.request(test_url, service.type) - {test_url, reply, instance} - end) - end - - tasks_with_results = Task.yield_many(tasks, 5000) - - instances = - Enum.map(tasks_with_results, fn {task, res} -> - # Shut down the tasks that did not reply nor exit - res || Task.shutdown(task, :brutal_kill) - end) - |> Enum.reject(fn x -> x == nil end) - |> Enum.filter(fn {_, data} -> - {_test_url, value, _instance} = data - value == :good - end) - |> Enum.map(fn {_, data} -> - {_test_url, _value, instance} = data - instance - end) - - service = %{service | instances: instances} - - Farside.Instance.Supervisor.start(service) + struct(%Service{}, service_atom) + |> Http.fetch_instances() + |> Farside.Instance.Supervisor.start() end LastUpdated.value(DateTime.utc_now()) diff --git a/lib/farside/http.ex b/lib/farside/http.ex index cb35200..0bf4764 100644 --- a/lib/farside/http.ex +++ b/lib/farside/http.ex @@ -2,6 +2,7 @@ defmodule Farside.Http do require Logger @headers Application.fetch_env!(:farside, :headers) + @queries Application.fetch_env!(:farside, :queries) def request(url) do cond do @@ -44,4 +45,37 @@ defmodule Farside.Http do end end end + + def fetch_instances(service) do + instances = + Enum.map(service.instances, fn instance -> + test_url = + instance <> + EEx.eval_string( + service.test_url, + query: Enum.random(@queries) + ) + + Task.async(fn -> + reply = request(test_url, service.type) + {test_url, reply, instance} + end) + end) + |> Task.yield_many(5000) + |> Enum.map(fn {task, res} -> + # Shut down the tasks that did not reply nor exit + res || Task.shutdown(task, :brutal_kill) + end) + |> Enum.reject(fn x -> x == nil end) + |> Enum.filter(fn {_, data} -> + {_test_url, value, _instance} = data + value == :good + end) + |> Enum.map(fn {_, data} -> + {_test_url, _value, instance} = data + instance + end) + + %{service | instances: instances} + end end diff --git a/lib/farside/instance.ex b/lib/farside/instance.ex index 9c32747..14bd3a8 100644 --- a/lib/farside/instance.ex +++ b/lib/farside/instance.ex @@ -3,7 +3,10 @@ defmodule Farside.Instance do require Logger + alias Farside.Http + @registry_name :servers + @update_file Application.fetch_env!(:farside, :update_file) def child_spec(args) do %{ @@ -60,54 +63,13 @@ defmodule Farside.Instance do {_, service} = List.first(service) - queries = Application.fetch_env!(:farside, :queries) - - test_urls = - Enum.map(service.instances, fn x -> - test_url = - x <> - EEx.eval_string( - service.test_url, - query: Enum.random(queries) - ) - - {test_url, x} - end) - - tasks = - for {test_url, instance} <- test_urls do - Task.async(fn -> - reply = Farside.Http.request(test_url, service.type) - {test_url, reply, instance} - end) - end - - tasks_with_results = Task.yield_many(tasks, 5000) - - instances = - Enum.map(tasks_with_results, fn {task, res} -> - # Shut down the tasks that did not reply nor exit - res || Task.shutdown(task, :brutal_kill) - end) - |> Enum.reject(fn x -> x == nil end) - |> Enum.filter(fn {_, data} -> - {_test_url, value, _instance} = data - value == :good - end) - |> Enum.map(fn {_, data} -> - {_test_url, _value, instance} = data - instance - end) - - values = %{service | instances: instances} + service = Http.fetch_instances(service) :ets.delete_all_objects(String.to_atom(state.type)) - :ets.insert(state.ref, {:data, values}) + :ets.insert(state.ref, {:data, service}) - update_file = Application.fetch_env!(:farside, :update_file) - - File.write(update_file, values.fallback) + File.write(@update_file, service.fallback) {:noreply, state} end diff --git a/mix.exs b/mix.exs index fbd15b9..408d455 100644 --- a/mix.exs +++ b/mix.exs @@ -25,7 +25,8 @@ defmodule Farside.MixProject do {:httpoison, "~> 1.8"}, {:jason, "~> 1.1"}, {:plug_attack, "~> 0.4.2"}, - {:plug_cowboy, "~> 2.0"} + {:plug_cowboy, "~> 2.0"}, + {:distillery, "~> 2.1"} ] end end diff --git a/mix.lock b/mix.lock index 5f327f5..276f9f3 100644 --- a/mix.lock +++ b/mix.lock @@ -1,9 +1,11 @@ %{ + "artificery": {:hex, :artificery, "0.4.3", "0bc4260f988dcb9dda4b23f9fc3c6c8b99a6220a331534fdf5bf2fd0d4333b02", [:mix], [], "hexpm", "12e95333a30e20884e937abdbefa3e7f5e05609c2ba8cf37b33f000b9ffc0504"}, "certifi": {:hex, :certifi, "2.8.0", "d4fb0a6bb20b7c9c3643e22507e42f356ac090a1dcea9ab99e27e0376d695eba", [:rebar3], [], "hexpm", "6ac7efc1c6f8600b08d625292d4bbf584e14847ce1b6b5c44d983d273e1097ea"}, "cowboy": {:hex, :cowboy, "2.9.0", "865dd8b6607e14cf03282e10e934023a1bd8be6f6bacf921a7e2a96d800cd452", [:make, :rebar3], [{:cowlib, "2.11.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "1.8.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "2c729f934b4e1aa149aff882f57c6372c15399a20d54f65c8d67bef583021bde"}, "cowboy_telemetry": {:hex, :cowboy_telemetry, "0.4.0", "f239f68b588efa7707abce16a84d0d2acf3a0f50571f8bb7f56a15865aae820c", [:rebar3], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7d98bac1ee4565d31b62d59f8823dfd8356a169e7fcbb83831b8a5397404c9de"}, "cowlib": {:hex, :cowlib, "2.11.0", "0b9ff9c346629256c42ebe1eeb769a83c6cb771a6ee5960bd110ab0b9b872063", [:make, :rebar3], [], "hexpm", "2b3e9da0b21c4565751a6d4901c20d1b4cc25cbb7fd50d91d2ab6dd287bc86a9"}, "crontab": {:hex, :crontab, "1.1.10", "dc9bb1f4299138d47bce38341f5dcbee0aa6c205e864fba7bc847f3b5cb48241", [:mix], [{:ecto, "~> 1.0 or ~> 2.0 or ~> 3.0", [hex: :ecto, repo: "hexpm", optional: true]}], "hexpm", "1347d889d1a0eda997990876b4894359e34bfbbd688acbb0ba28a2795ca40685"}, + "distillery": {:hex, :distillery, "2.1.1", "f9332afc2eec8a1a2b86f22429e068ef35f84a93ea1718265e740d90dd367814", [:mix], [{:artificery, "~> 0.2", [hex: :artificery, repo: "hexpm", optional: false]}], "hexpm", "bbc7008b0161a6f130d8d903b5b3232351fccc9c31a991f8fcbf2a12ace22995"}, "gen_stage": {:hex, :gen_stage, "1.1.2", "b1656cd4ba431ed02c5656fe10cb5423820847113a07218da68eae5d6a260c23", [:mix], [], "hexpm", "9e39af23140f704e2b07a3e29d8f05fd21c2aaf4088ff43cb82be4b9e3148d02"}, "hackney": {:hex, :hackney, "1.18.0", "c4443d960bb9fba6d01161d01cd81173089686717d9490e5d3606644c48d121f", [:rebar3], [{:certifi, "~>2.8.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~>6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~>1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~>1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.3.1", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~>1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~>0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "9afcda620704d720db8c6a3123e9848d09c87586dc1c10479c42627b905b5c5e"}, "httpoison": {:hex, :httpoison, "1.8.0", "6b85dea15820b7804ef607ff78406ab449dd78bed923a49c7160e1886e987a3d", [:mix], [{:hackney, "~> 1.17", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "28089eaa98cf90c66265b6b5ad87c59a3729bea2e74e9d08f9b51eb9729b3c3a"},