farside/update.exs
Ben Busby 39c244d970
Skip querying all instances w/ "test mode"
Now allows setting FARSIDE_TEST to skip individually fetching each
instance, and instead just adds all of them to redis instantly. This
allows for an easier time in CI builds, for both the sake of speed and
to prevent a scenario where many simultaneous builds have a noticeable
impact on actual instances.
2021-11-09 15:12:58 -07:00

98 lines
2.4 KiB
Elixir

defmodule Service do
defstruct [
type: nil,
test_url: nil,
fallback: nil,
instances: []
]
end
defmodule Instances do
@fallback_str Application.fetch_env!(:farside, :fallback_str)
@update_file Application.fetch_env!(:farside, :update_file)
@services_json Application.fetch_env!(:farside, :services_json)
@service_prefix Application.fetch_env!(:farside, :service_prefix)
def init() do
File.rename(@update_file, "#{@update_file}-prev")
update(@services_json)
end
def request(url) do
cond do
System.get_env("FARSIDE_TEST") ->
:good
true ->
case HTTPoison.get(url) do
{:ok, %HTTPoison.Response{status_code: 200}} ->
# TODO: Add validation of results, not just status code
:good
_ ->
:bad
end
end
end
def update(filename) do
{:ok, file} = File.read(filename)
{:ok, json} = Poison.decode(file, as: [%Service{}])
# Loop through all instances and check each for availability
for service <- json do
IO.puts "======== " <> service.type
result = Enum.filter(service.instances, fn(instance_url) ->
IO.puts " " <> instance_url
request(instance_url <> service.test_url) == :good
end)
add_to_redis(service, result)
log_results(service.type, result)
end
end
def add_to_redis(service, instances) do
# Remove previous list of instances
Redix.command(:redix, [
"DEL",
"#{@service_prefix}#{service.type}"
])
# Update with new list of available instances
Redix.command(:redix, [
"LPUSH",
"#{@service_prefix}#{service.type}"
] ++ instances)
# Set fallback to one of the available instances,
# or the default instance if all are "down"
if Enum.count(instances) > 0 do
Redix.command(:redix, [
"SET",
"#{service.type}#{@fallback_str}",
Enum.random(instances)
])
else
Redix.command(:redix, [
"SET",
"#{service.type}#{@fallback_str}",
service.fallback
])
end
end
def log_results(service_name, results) do
{:ok, file} = File.open(@update_file, [:append, {:delayed_write, 100, 20}])
IO.write(file, "#{service_name}: #{inspect(results)}\n")
File.close(file)
end
end
Instances.init()
# Add UTC time of last update
Redix.command(:redix, [
"SET",
"last_updated",
Calendar.strftime(DateTime.utc_now(), "%c")
])