Output available instances and fallback URL to redis

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.
This commit is contained in:
Ben Busby 2021-10-22 17:15:40 -06:00
parent b0953f0777
commit 4949ae22bb
No known key found for this signature in database
GPG key ID: 339B7B7EB5333D14
5 changed files with 70 additions and 29 deletions

View file

@ -1,18 +0,0 @@
[
{
"instance_type": "reddit",
"instance_test": "/r/popular",
"instance_list": [
"https://libredd.it",
"https://libreddit.spike.codes"
]
},
{
"instance_type": "instagram",
"instance_test": "/taylorswift",
"instance_list": [
"https://bibliogram.art/u",
"https://bibliogram.snopyta.org/u"
]
}
]

View file

@ -25,7 +25,8 @@ defmodule RouterExample.MixProject do
{:jason, "~> 1.1"},
{:plug_cowboy, "~> 2.0"},
{:poison, "~> 5.0"},
{:httpoison, "~> 1.8"}
{:httpoison, "~> 1.8"},
{:redix, "~> 1.1"}
]
end
end

View file

@ -16,6 +16,7 @@
"plug_crypto": {:hex, :plug_crypto, "1.2.2", "05654514ac717ff3a1843204b424477d9e60c143406aa94daf2274fdd280794d", [:mix], [], "hexpm", "87631c7ad914a5a445f0a3809f99b079113ae4ed4b867348dd9eec288cecb6db"},
"poison": {:hex, :poison, "5.0.0", "d2b54589ab4157bbb82ec2050757779bfed724463a544b6e20d79855a9e43b24", [:mix], [{:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "11dc6117c501b80c62a7594f941d043982a1bd05a1184280c0d9166eb4d8d3fc"},
"ranch": {:hex, :ranch, "1.8.0", "8c7a100a139fd57f17327b6413e4167ac559fbc04ca7448e9be9057311597a1d", [:make, :rebar3], [], "hexpm", "49fbcfd3682fab1f5d109351b61257676da1a2fdbe295904176d5e521a2ddfe5"},
"redix": {:hex, :redix, "1.1.4", "d66fc83d2d4f136c838568d1ec8b0c1a72acfcecfac88a40f86f60aaee883c93", [:mix], [{:castore, "~> 0.1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "515eff055b7de8967e835f4de22a6cfe8311bc1b8fe72f48200238fb43f6a803"},
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.6", "cf344f5692c82d2cd7554f5ec8fd961548d4fd09e7d22f5b62482e5aeaebd4b0", [:make, :mix, :rebar3], [], "hexpm", "bdb0d2471f453c88ff3908e7686f86f9be327d065cc1ec16fa4540197ea04680"},
"telemetry": {:hex, :telemetry, "1.0.0", "0f453a102cdf13d506b7c0ab158324c337c41f1cc7548f0bc0e130bbf0ae9452", [:rebar3], [], "hexpm", "73bc09fa59b4a0284efb4624335583c528e07ec9ae76aca96ea0673850aec57a"},
"unicode_util_compat": {:hex, :unicode_util_compat, "0.7.0", "bc84380c9ab48177092f43ac89e4dfa2c6d62b40b8bd132b1059ecc7232f9a78", [:rebar3], [], "hexpm", "25eee6d67df61960cf6a794239566599b09e17e668d3700247bc498638152521"},

20
services.json Normal file
View file

@ -0,0 +1,20 @@
[
{
"type": "reddit",
"test_url": "/r/popular",
"fallback": "https://libredd.it",
"instances": [
"https://libredd.it",
"https://libreddit.spike.codes"
]
},
{
"type": "instagram",
"test_url": "/taylorswift",
"fallback": "https://bibliogram.art/u",
"instances": [
"https://bibliogram.art/u",
"https://bibliogram.snopyta.org/u"
]
}
]

View file

@ -1,8 +1,9 @@
defmodule Instance do
defmodule Service do
defstruct [
instance_type: nil,
instance_test: nil,
instance_list: []
type: nil,
test_url: nil,
fallback: nil,
instances: []
]
end
@ -18,16 +19,52 @@ 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: [%Instance{}])
{:ok, json} = Poison.decode(file, as: [%Service{}])
# Loop through all instances and check each for availability
for service <- json do
result = Enum.filter(service.instance_list, fn(url) ->
request(url <> service.instance_test) == :good
result = Enum.filter(service.instances, fn(instance_url) ->
request(instance_url <> service.test_url) == :good
end)
# TODO: Output result to redis
IO.inspect(result)
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("instances.json")
Instances.update("services.json")