farside/update.exs
Ben Busby 76faebd234
Move constants to config, update string formatting
Not sure if this is the Elixir-y way to do this, but seems more logical
than hardcoding values such as redis connection.

Also went through and improved how string formatting was performed
throughout the app. Rather than "combining" <> "strings" this way, I'm
now just doing "#${variable}#{formatting}", which looks a lot cleaner.
2021-10-22 20:07:07 -06:00

83 lines
2 KiB
Elixir

defmodule Service do
defstruct [
type: nil,
test_url: nil,
fallback: nil,
instances: []
]
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}} ->
# TODO: Add validation of results, not just status code
:good
_ ->
:bad
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
result = Enum.filter(service.instances, fn(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.type
])
# Update with new list of available instances
Redix.command(:redix, [
"LPUSH",
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()