mirror of
https://github.com/benbusby/farside.git
synced 2025-03-15 03:36:33 -04:00

Once a list of available URLs has been determined for a particular service, the list is written as "service -> [list of instances]" to a local redis connection. These can then be used in the greater routing logic to pick a random instance from the list, or use a fallback instance if none are determined to be available.
71 lines
1.5 KiB
Elixir
71 lines
1.5 KiB
Elixir
defmodule Service do
|
|
defstruct [
|
|
type: nil,
|
|
test_url: nil,
|
|
fallback: nil,
|
|
instances: []
|
|
]
|
|
end
|
|
|
|
defmodule Instances do
|
|
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, conn} = Redix.start_link(
|
|
"redis://localhost:6379",
|
|
name: :redix
|
|
)
|
|
{: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(conn, service, result)
|
|
end
|
|
end
|
|
|
|
def add_to_redis(conn, service, instances) do
|
|
# Remove previous list of instances
|
|
Redix.command(conn, [
|
|
"DEL",
|
|
service.type
|
|
])
|
|
|
|
# Update with new list of available instances
|
|
Redix.command(conn, [
|
|
"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(conn, [
|
|
"SET",
|
|
service.type <> "-fallback",
|
|
Enum.random(instances)
|
|
])
|
|
else
|
|
Redix.command(conn, [
|
|
"SET",
|
|
service.type <> "-fallback",
|
|
service.fallback
|
|
])
|
|
end
|
|
end
|
|
end
|
|
|
|
Instances.update("services.json")
|