diff --git a/config/config.exs b/config/config.exs new file mode 100644 index 0000000..44b3af8 --- /dev/null +++ b/config/config.exs @@ -0,0 +1,7 @@ +import Config + +config :privacy_revolver, + redis_conn: "redis://localhost:6379", + fallback_str: "-fallback", + update_file: ".update-results", + services_json: "services.json" diff --git a/lib/privacy_revolver/application.ex b/lib/privacy_revolver/application.ex index e303646..04b7540 100644 --- a/lib/privacy_revolver/application.ex +++ b/lib/privacy_revolver/application.ex @@ -1,4 +1,5 @@ defmodule PrivacyRevolver.Application do + @redis_conn Application.fetch_env!(:privacy_revolver, :redis_conn) @moduledoc false use Application @@ -7,7 +8,7 @@ defmodule PrivacyRevolver.Application do def start(_type, _args) do children = [ Plug.Cowboy.child_spec(scheme: :http, plug: PrivacyRevolver.Router, options: [port: 4001]), - {Redix, {"redis://localhost:6379", [name: :redix]}} + {Redix, {@redis_conn, [name: :redix]}} ] opts = [strategy: :one_for_one, name: PrivacyRevolver.Supervisor] diff --git a/lib/privacy_revolver/router.ex b/lib/privacy_revolver/router.ex index c2c1c61..7d4e82f 100644 --- a/lib/privacy_revolver/router.ex +++ b/lib/privacy_revolver/router.ex @@ -1,9 +1,15 @@ defmodule PrivacyRevolver.Router do + @fallback_str Application.fetch_env!(:privacy_revolver, :fallback_str) + use Plug.Router plug :match plug :dispatch + get "/" do + send_resp(conn, 200, "") + end + get "/ping" do # Useful for app healthcheck {:ok, resp} = Redix.command(:redix, ["PING"]) @@ -11,19 +17,30 @@ defmodule PrivacyRevolver.Router do end get "/:service/*glob" do - full_path = "/" <> Enum.join(glob, "/") - {:ok, instances} = Redix.command(:redix, ["LRANGE", service, "0", "-1"]) + path = Enum.join(glob, "/") + {:ok, instances} = Redix.command( + :redix, + ["LRANGE", service, "0", "-1"] + ) - # Either pick a random available instance, or fall back to the default one + # Either pick a random available instance, + # or fall back to the default one instance = if Enum.count(instances) > 0 do Enum.random(instances) else - Redix.command(:redix, ["GET", service <> "-fallback"]) + {:ok, result} = Redix.command( + :redix, + ["GET", "#{service}#{@fallback_str}"] + ) + result end # Redirect to the available instance conn |> Plug.Conn.resp(:found, "") |> - Plug.Conn.put_resp_header("location", instance <> full_path) + Plug.Conn.put_resp_header( + "location", + "#{instance}/#{path}" + ) end end diff --git a/update.exs b/update.exs index 65110f6..9ed320d 100644 --- a/update.exs +++ b/update.exs @@ -8,6 +8,15 @@ defmodule Service do end defmodule Instances do + @fallback_str Application.fetch_env!(:privacy_revolver, :fallback_str) + @update_file Application.fetch_env!(:privacy_revolver, :update_file) + @services_json Application.fetch_env!(:privacy_revolver, :services_json) + + def init() do + File.rename(@update_file, "#{@update_file}-prev") + update(@services_json) + end + def request(url) do case HTTPoison.get(url) do {:ok, %HTTPoison.Response{status_code: 200}} -> @@ -19,10 +28,6 @@ defmodule Instances do end def update(filename) do - {:ok, conn} = Redix.start_link( - "redis://localhost:6379", - name: :redix - ) {:ok, file} = File.read(filename) {:ok, json} = Poison.decode(file, as: [%Service{}]) @@ -32,20 +37,20 @@ defmodule Instances do request(instance_url <> service.test_url) == :good end) - add_to_redis(conn, service, result) + add_to_redis(service, result) log_results(service.type, result) end end - def add_to_redis(conn, service, instances) do + def add_to_redis(service, instances) do # Remove previous list of instances - Redix.command(conn, [ + Redix.command(:redix, [ "DEL", service.type ]) # Update with new list of available instances - Redix.command(conn, [ + Redix.command(:redix, [ "LPUSH", service.type ] ++ instances) @@ -53,26 +58,25 @@ defmodule Instances do # Set fallback to one of the available instances, # or the default instance if all are "down" if Enum.count(instances) > 0 do - Redix.command(conn, [ + Redix.command(:redix, [ "SET", - service.type <> "-fallback", + "#{service.type}#{@fallback_str}", Enum.random(instances) ]) else - Redix.command(conn, [ + Redix.command(:redix, [ "SET", - service.type <> "-fallback", + "#{service.type}#{@fallback_str}", service.fallback ]) end end def log_results(service_name, results) do - {:ok, file} = File.open(".update-results", [:append, {:delayed_write, 100, 20}]) - IO.write(file, service_name <> ": " <> inspect(results) <> "\n") + {:ok, file} = File.open(@update_file, [:append, {:delayed_write, 100, 20}]) + IO.write(file, "#{service_name}: #{inspect(results)}\n") File.close(file) end end -File.rename(".update-results", ".update-results-prev") -Instances.update("services.json") +Instances.init()