Remove Redis dep, replace w/ native Elixir lib

This removes the dependency on Redis for core app functionality. Rather
than using the key/value store provided by Redis, Farside now uses a
key/val store provided by [cubdb](https://github.com/lucaong/cubdb) for
identical functionality but without reliance on a non-Elixir service.

This solution was chosen instead of ets, because storing instance data
in memory leads to a period of broken functionality whenever the app
restarts and hasn't re-populated instance data yet. It was also chosen
instead of dets, because the documentation for dets was pretty hard to
understand at first glance.

Tests and the CI build were updated to reflect the removed dependency on
Redis.

New environment variable `FARSIDE_DATA_DIR` can be used to point to a
directory where the instance data can be stored by cubdb.

Co-authored-by: Jason Clark <mithereal@gmail.com>
This commit is contained in:
Ben Busby 2022-10-31 16:45:31 -06:00
parent 540822d867
commit e58d6e23ed
No known key found for this signature in database
GPG Key ID: B9B7231E01D924A1
11 changed files with 45 additions and 130 deletions

View File

@ -28,9 +28,6 @@ jobs:
key: ${{ runner.os }}-mix-${{ hashFiles('**/mix.lock') }} key: ${{ runner.os }}-mix-${{ hashFiles('**/mix.lock') }}
restore-keys: ${{ runner.os }}-mix- restore-keys: ${{ runner.os }}-mix-
- name: Start Redis
uses: supercharge/redis-github-action@1.2.0
- name: Install dependencies - name: Install dependencies
run: mix deps.get run: mix deps.get

1
.gitignore vendored
View File

@ -15,3 +15,4 @@ erl_crash.dump
*.rdb *.rdb
.idea/ .idea/
*.iml *.iml
*.cub

View File

@ -28,7 +28,7 @@ distribute traffic more evenly across all instances and avoid performance
bottlenecks and rate-limiting. bottlenecks and rate-limiting.
Farside also integrates smoothly with basic redirector extensions in most Farside also integrates smoothly with basic redirector extensions in most
browsers. For an simple example setup, browsers. For an simple example setup,
[refer to the wiki](https://github.com/benbusby/farside/wiki/Browser-Extension). [refer to the wiki](https://github.com/benbusby/farside/wiki/Browser-Extension).
## Demo ## Demo
@ -126,8 +126,6 @@ Farside's routing is very minimal, with only the following routes:
- `/` - `/`
- The app home page, displaying all live instances for every service - The app home page, displaying all live instances for every service
- `/ping`
- A passthrough "ping" to redis to ensure both app and redis are working
- `/:service/*glob` - `/:service/*glob`
- The main endpoint for redirecting a user to a working instance of a - The main endpoint for redirecting a user to a working instance of a
particular service with the specified path particular service with the specified path
@ -147,8 +145,8 @@ Farside's routing is very minimal, with only the following routes:
- *Note: Uses Javascript to preserve the page in history* - *Note: Uses Javascript to preserve the page in history*
When a service is requested with the `/:service/...` endpoint, Farside requests When a service is requested with the `/:service/...` endpoint, Farside requests
the list of working instances from Redis and returns a random one from the list the list of working instances from the db and returns a random one from the list
and adds that instance as a new entry in Redis to remove from subsequent and adds that instance as a new entry in the db to remove from subsequent
requests for that service. For example: requests for that service. For example:
A user navigates to `/nitter` and is redirected to `nitter.net`. The next user A user navigates to `/nitter` and is redirected to `nitter.net`. The next user
@ -178,12 +176,10 @@ that their mission to centralize the entire web behind their service ultimately
goes against what Farside is trying to solve. Use at your own discretion. goes against what Farside is trying to solve. Use at your own discretion.
## Development ## Development
- Install [redis](https://redis.io)
- Install [elixir](https://elixir-lang.org/install.html) - Install [elixir](https://elixir-lang.org/install.html)
- (on Debian systems) Install [erlang-dev](https://packages.debian.org/sid/erlang-dev) - (on Debian systems) Install [erlang-dev](https://packages.debian.org/sid/erlang-dev)
- Start redis: `redis-server`
- Install dependencies: `mix deps.get` - Install dependencies: `mix deps.get`
- Initialize redis contents: `mix run -e Farside.Instances.sync` - Initialize db contents: `mix run -e Farside.Instances.sync`
- Run Farside: `mix run --no-halt` - Run Farside: `mix run --no-halt`
- Uses localhost:4001 - Uses localhost:4001
@ -203,8 +199,8 @@ goes against what Farside is trying to solve. Use at your own discretion.
<td>The port to run Farside on (default: `4001`)</td> <td>The port to run Farside on (default: `4001`)</td>
</tr> </tr>
<tr> <tr>
<td>FARSIDE_REDIS_PORT</td> <td>FARSIDE_DATA_DIR</td>
<td>The Redis server port to use (default: `6379`, same as the default for Redis)</td> <td>The path to the directory to use for storing instance data (default: `/tmp`)</td>
</tr> </tr>
<tr> <tr>
<td>FARSIDE_SERVICES_JSON</td> <td>FARSIDE_SERVICES_JSON</td>

View File

@ -2,5 +2,5 @@ import Config
config :farside, config :farside,
port: System.get_env("FARSIDE_PORT", "4001"), port: System.get_env("FARSIDE_PORT", "4001"),
redis_conn: "redis://localhost:#{System.get_env("FARSIDE_REDIS_PORT", "6379")}", services_json: System.get_env("FARSIDE_SERVICES_JSON", "services.json"),
services_json: System.get_env("FARSIDE_SERVICES_JSON", "services.json") data_dir: System.get_env("FARSIDE_DATA_DIR", File.cwd!)

View File

@ -35,15 +35,14 @@ defmodule Farside do
} }
def get_services_map do def get_services_map do
{:ok, service_list} = Redix.command(:redix, ["KEYS", "#{@service_prefix}*"]) service_list = CubDB.select(CubDB)
|> Stream.map(fn {key, _value} -> key end)
|> Stream.filter(fn key -> String.starts_with?(key, @service_prefix) end)
|> Enum.to_list
# Match service name to list of available instances # Match service name to list of available instances
Enum.reduce(service_list, %{}, fn service, acc -> Enum.reduce(service_list, %{}, fn service, acc ->
{:ok, instance_list} = instance_list = CubDB.get(CubDB, service)
Redix.command(
:redix,
["LRANGE", service, "0", "-1"]
)
Map.put( Map.put(
acc, acc,
@ -58,7 +57,7 @@ defmodule Farside do
end end
def get_service(service) do def get_service(service) do
# Check if service has an entry in Redis, otherwise try to # Check if service has an entry in the db, otherwise try to
# match against available parent services # match against available parent services
service_name = cond do service_name = cond do
!check_service(service) -> !check_service(service) ->
@ -76,42 +75,18 @@ defmodule Farside do
def check_service(service) do def check_service(service) do
# Checks to see if a specific service has instances available # Checks to see if a specific service has instances available
# in redis instances = CubDB.get(CubDB, "#{@service_prefix}#{service}")
{:ok, instances} =
Redix.command(
:redix,
[
"LRANGE",
"#{@service_prefix}#{service}",
"0",
"-1"
]
)
Enum.count(instances) > 0 instances != nil && Enum.count(instances) > 0
end end
def last_instance(service) do def last_instance(service) do
# Fetches the last selected instance for a particular service # Fetches the last selected instance for a particular service
{:ok, previous} = CubDB.get(CubDB, "#{service}#{@previous_suffix}")
Redix.command(
:redix,
["GET", "#{service}#{@previous_suffix}"]
)
previous
end end
def pick_instance(service) do def pick_instance(service) do
{:ok, instances} = instances = CubDB.get(CubDB, "#{@service_prefix}#{service}")
Redix.command(
:redix,
[
"LRANGE",
"#{@service_prefix}#{service}",
"0",
"-1"
]
)
# Either pick a random available instance, # Either pick a random available instance,
# or fall back to the default one # or fall back to the default one
@ -127,21 +102,12 @@ defmodule Farside do
Enum.filter(instances, &(&1 != last_instance(service))) Enum.filter(instances, &(&1 != last_instance(service)))
|> Enum.random() |> Enum.random()
Redix.command( CubDB.put(CubDB, "#{service}#{@previous_suffix}", instance)
:redix,
["SET", "#{service}#{@previous_suffix}", instance]
)
instance instance
end end
else else
{:ok, result} = CubDB.get(CubDB, "#{service}#{@fallback_suffix}")
Redix.command(
:redix,
["GET", "#{service}#{@fallback_suffix}"]
)
result
end end
instance instance
end end
@ -165,12 +131,6 @@ defmodule Farside do
end end
def get_last_updated do def get_last_updated do
{:ok, last_updated} = CubDB.get(CubDB, "last_updated")
Redix.command(
:redix,
["GET", "last_updated"]
)
last_updated
end end
end end

View File

@ -1,16 +1,13 @@
defmodule Farside.Application do defmodule Farside.Application do
#@farside_port Application.fetch_env!(:farside, :port)
#@redis_conn Application.fetch_env!(:farside, :redis_conn)
@moduledoc false @moduledoc false
use Application use Application
@impl true @impl true
def start(_type, _args) do def start(_type, _args) do
redis_conn = Application.fetch_env!(:farside, :redis_conn)
farside_port = Application.fetch_env!(:farside, :port) farside_port = Application.fetch_env!(:farside, :port)
data_dir = Application.fetch_env!(:farside, :data_dir)
IO.puts "Running on http://localhost:#{farside_port}" IO.puts "Running on http://localhost:#{farside_port}"
IO.puts "Redis conn: #{redis_conn}"
children = [ children = [
Plug.Cowboy.child_spec( Plug.Cowboy.child_spec(
@ -21,7 +18,7 @@ defmodule Farside.Application do
] ]
), ),
{PlugAttack.Storage.Ets, name: Farside.Throttle.Storage, clean_period: 60_000}, {PlugAttack.Storage.Ets, name: Farside.Throttle.Storage, clean_period: 60_000},
{Redix, {redis_conn, [name: :redix]}}, {CubDB, [data_dir: data_dir, name: CubDB]},
Farside.Scheduler, Farside.Scheduler,
Farside.Server Farside.Server
] ]

View File

@ -12,11 +12,7 @@ defmodule Farside.Instances do
update() update()
# Add UTC time of last update # Add UTC time of last update
Redix.command(:redix, [ CubDB.put(CubDB, "last_updated", Calendar.strftime(DateTime.utc_now(), "%c"))
"SET",
"last_updated",
Calendar.strftime(DateTime.utc_now(), "%c")
])
end end
def request(url) do def request(url) do
@ -69,41 +65,24 @@ defmodule Farside.Instances do
request(request_url) == :good request(request_url) == :good
end) end)
add_to_redis(service, result) add_to_db(service, result)
log_results(service.type, result) log_results(service.type, result)
end end
end end
def add_to_redis(service, instances) do def add_to_db(service, instances) do
# Remove previous list of instances # Remove previous list of instances
Redix.command(:redix, [ CubDB.delete(CubDB, "#{@service_prefix}#{service.type}")
"DEL",
"#{@service_prefix}#{service.type}"
])
# Update with new list of available instances # Update with new list of available instances
Redix.command( CubDB.put(CubDB, "#{@service_prefix}#{service.type}", instances)
:redix,
[
"LPUSH",
"#{@service_prefix}#{service.type}"
] ++ instances
)
# Set fallback to one of the available instances, # Set fallback to one of the available instances,
# or the default instance if all are "down" # or the default instance if all are "down"
if Enum.count(instances) > 0 do if Enum.count(instances) > 0 do
Redix.command(:redix, [ CubDB.put(CubDB, "#{service.type}#{@fallback_suffix}", Enum.random(instances))
"SET",
"#{service.type}#{@fallback_suffix}",
Enum.random(instances)
])
else else
Redix.command(:redix, [ CubDB.put(CubDB, "#{service.type}#{@fallback_suffix}", service.fallback)
"SET",
"#{service.type}#{@fallback_suffix}",
service.fallback
])
end end
end end

View File

@ -29,12 +29,6 @@ defmodule Farside.Router do
send_resp(conn, 200, resp) send_resp(conn, 200, resp)
end end
get "/ping" do
# Useful for app healthcheck
{:ok, resp} = Redix.command(:redix, ["PING"])
send_resp(conn, 200, resp)
end
get "/_/:service/*glob" do get "/_/:service/*glob" do
r_path = String.slice(conn.request_path, 2..-1) r_path = String.slice(conn.request_path, 2..-1)

View File

@ -27,7 +27,7 @@ defmodule Farside.MixProject do
{:plug_attack, "~> 0.4.2"}, {:plug_attack, "~> 0.4.2"},
{:plug_cowboy, "~> 2.0"}, {:plug_cowboy, "~> 2.0"},
{:quantum, "~> 3.0"}, {:quantum, "~> 3.0"},
{:redix, "~> 1.1"} {:cubdb, "~> 2.0.1"}
] ]
end end
end end

View File

@ -1,29 +1,27 @@
%{ %{
"certifi": {:hex, :certifi, "2.8.0", "d4fb0a6bb20b7c9c3643e22507e42f356ac090a1dcea9ab99e27e0376d695eba", [:rebar3], [], "hexpm", "6ac7efc1c6f8600b08d625292d4bbf584e14847ce1b6b5c44d983d273e1097ea"}, "certifi": {:hex, :certifi, "2.9.0", "6f2a475689dd47f19fb74334859d460a2dc4e3252a3324bd2111b8f0429e7e21", [:rebar3], [], "hexpm", "266da46bdb06d6c6d35fde799bcb28d36d985d424ad7c08b5bb48f5b5cdd4641"},
"cowboy": {:hex, :cowboy, "2.9.0", "865dd8b6607e14cf03282e10e934023a1bd8be6f6bacf921a7e2a96d800cd452", [:make, :rebar3], [{:cowlib, "2.11.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "1.8.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "2c729f934b4e1aa149aff882f57c6372c15399a20d54f65c8d67bef583021bde"}, "cowboy": {:hex, :cowboy, "2.9.0", "865dd8b6607e14cf03282e10e934023a1bd8be6f6bacf921a7e2a96d800cd452", [:make, :rebar3], [{:cowlib, "2.11.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "1.8.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "2c729f934b4e1aa149aff882f57c6372c15399a20d54f65c8d67bef583021bde"},
"cowboy_telemetry": {:hex, :cowboy_telemetry, "0.4.0", "f239f68b588efa7707abce16a84d0d2acf3a0f50571f8bb7f56a15865aae820c", [:rebar3], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7d98bac1ee4565d31b62d59f8823dfd8356a169e7fcbb83831b8a5397404c9de"}, "cowboy_telemetry": {:hex, :cowboy_telemetry, "0.4.0", "f239f68b588efa7707abce16a84d0d2acf3a0f50571f8bb7f56a15865aae820c", [:rebar3], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7d98bac1ee4565d31b62d59f8823dfd8356a169e7fcbb83831b8a5397404c9de"},
"cowlib": {:hex, :cowlib, "2.11.0", "0b9ff9c346629256c42ebe1eeb769a83c6cb771a6ee5960bd110ab0b9b872063", [:make, :rebar3], [], "hexpm", "2b3e9da0b21c4565751a6d4901c20d1b4cc25cbb7fd50d91d2ab6dd287bc86a9"}, "cowlib": {:hex, :cowlib, "2.11.0", "0b9ff9c346629256c42ebe1eeb769a83c6cb771a6ee5960bd110ab0b9b872063", [:make, :rebar3], [], "hexpm", "2b3e9da0b21c4565751a6d4901c20d1b4cc25cbb7fd50d91d2ab6dd287bc86a9"},
"crontab": {:hex, :crontab, "1.1.10", "dc9bb1f4299138d47bce38341f5dcbee0aa6c205e864fba7bc847f3b5cb48241", [:mix], [{:ecto, "~> 1.0 or ~> 2.0 or ~> 3.0", [hex: :ecto, repo: "hexpm", optional: true]}], "hexpm", "1347d889d1a0eda997990876b4894359e34bfbbd688acbb0ba28a2795ca40685"}, "crontab": {:hex, :crontab, "1.1.11", "4028ced51b813a5061f85b689d4391ef0c27550c8ab09aaf139e4295c3d93ea4", [:mix], [{:ecto, "~> 1.0 or ~> 2.0 or ~> 3.0", [hex: :ecto, repo: "hexpm", optional: true]}], "hexpm", "ecb045f9ac14a3e2990e54368f70cdb6e2f2abafc5bc329d6c31f0c74b653787"},
"cubdb": {:hex, :cubdb, "2.0.1", "24cab8fb4128df704c52ed641f5ed70af352f7a3a80cebbb44c3bbadc3fd5f45", [:mix], [], "hexpm", "57cf25aebfc34f4580d9075da06882b4fe3e0739f5353d4dcc213e9cc1b10cdf"},
"gen_stage": {:hex, :gen_stage, "1.1.2", "b1656cd4ba431ed02c5656fe10cb5423820847113a07218da68eae5d6a260c23", [:mix], [], "hexpm", "9e39af23140f704e2b07a3e29d8f05fd21c2aaf4088ff43cb82be4b9e3148d02"}, "gen_stage": {:hex, :gen_stage, "1.1.2", "b1656cd4ba431ed02c5656fe10cb5423820847113a07218da68eae5d6a260c23", [:mix], [], "hexpm", "9e39af23140f704e2b07a3e29d8f05fd21c2aaf4088ff43cb82be4b9e3148d02"},
"hackney": {:hex, :hackney, "1.18.0", "c4443d960bb9fba6d01161d01cd81173089686717d9490e5d3606644c48d121f", [:rebar3], [{:certifi, "~>2.8.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~>6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~>1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~>1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.3.1", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~>1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~>0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "9afcda620704d720db8c6a3123e9848d09c87586dc1c10479c42627b905b5c5e"}, "hackney": {:hex, :hackney, "1.18.1", "f48bf88f521f2a229fc7bae88cf4f85adc9cd9bcf23b5dc8eb6a1788c662c4f6", [:rebar3], [{:certifi, "~>2.9.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~>6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~>1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~>1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.3.1", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~>1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~>0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "a4ecdaff44297e9b5894ae499e9a070ea1888c84afdd1fd9b7b2bc384950128e"},
"httpoison": {:hex, :httpoison, "1.8.0", "6b85dea15820b7804ef607ff78406ab449dd78bed923a49c7160e1886e987a3d", [:mix], [{:hackney, "~> 1.17", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "28089eaa98cf90c66265b6b5ad87c59a3729bea2e74e9d08f9b51eb9729b3c3a"}, "httpoison": {:hex, :httpoison, "1.8.2", "9eb9c63ae289296a544842ef816a85d881d4a31f518a0fec089aaa744beae290", [:mix], [{:hackney, "~> 1.17", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "2bb350d26972e30c96e2ca74a1aaf8293d61d0742ff17f01e0279fef11599921"},
"idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~>0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"}, "idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~>0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"},
"jason": {:hex, :jason, "1.2.2", "ba43e3f2709fd1aa1dce90aaabfd039d000469c05c56f0b8e31978e03fa39052", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "18a228f5f0058ee183f29f9eae0805c6e59d61c3b006760668d8d18ff0d12179"}, "jason": {:hex, :jason, "1.4.0", "e855647bc964a44e2f67df589ccf49105ae039d4179db7f6271dfd3843dc27e6", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "79a3791085b2a0f743ca04cec0f7be26443738779d09302e01318f97bdb82121"},
"metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm", "69b09adddc4f74a40716ae54d140f93beb0fb8978d8636eaded0c31b6f099f16"}, "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm", "69b09adddc4f74a40716ae54d140f93beb0fb8978d8636eaded0c31b6f099f16"},
"mime": {:hex, :mime, "2.0.2", "0b9e1a4c840eafb68d820b0e2158ef5c49385d17fb36855ac6e7e087d4b1dcc5", [:mix], [], "hexpm", "e6a3f76b4c277739e36c2e21a2c640778ba4c3846189d5ab19f97f126df5f9b7"}, "mime": {:hex, :mime, "2.0.3", "3676436d3d1f7b81b5a2d2bd8405f412c677558c81b1c92be58c00562bb59095", [:mix], [], "hexpm", "27a30bf0db44d25eecba73755acf4068cbfe26a4372f9eb3e4ea3a45956bff6b"},
"mimerl": {:hex, :mimerl, "1.2.0", "67e2d3f571088d5cfd3e550c383094b47159f3eee8ffa08e64106cdf5e981be3", [:rebar3], [], "hexpm", "f278585650aa581986264638ebf698f8bb19df297f66ad91b18910dfc6e19323"}, "mimerl": {:hex, :mimerl, "1.2.0", "67e2d3f571088d5cfd3e550c383094b47159f3eee8ffa08e64106cdf5e981be3", [:rebar3], [], "hexpm", "f278585650aa581986264638ebf698f8bb19df297f66ad91b18910dfc6e19323"},
"mustache": {:hex, :mustache, "0.3.1", "4c6ee79b13aae954035fe31b83c94480ddc7b536d09c44d4c65e61a9ead38d6b", [:mix], [], "hexpm", "8dc92b9b92a0d7449628f4fc981f8018a16a5b8c9907249e59db461482dac143"},
"parse_trans": {:hex, :parse_trans, "3.3.1", "16328ab840cc09919bd10dab29e431da3af9e9e7e7e6f0089dd5a2d2820011d8", [:rebar3], [], "hexpm", "07cd9577885f56362d414e8c4c4e6bdf10d43a8767abb92d24cbe8b24c54888b"}, "parse_trans": {:hex, :parse_trans, "3.3.1", "16328ab840cc09919bd10dab29e431da3af9e9e7e7e6f0089dd5a2d2820011d8", [:rebar3], [], "hexpm", "07cd9577885f56362d414e8c4c4e6bdf10d43a8767abb92d24cbe8b24c54888b"},
"phoenix_view": {:hex, :phoenix_view, "1.0.0", "fea71ecaaed71178b26dd65c401607de5ec22e2e9ef141389c721b3f3d4d8011", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}], "hexpm", "82be3e2516f5633220246e2e58181282c71640dab7afc04f70ad94253025db0c"}, "plug": {:hex, :plug, "1.14.0", "ba4f558468f69cbd9f6b356d25443d0b796fbdc887e03fa89001384a9cac638f", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "bf020432c7d4feb7b3af16a0c2701455cbbbb95e5b6866132cb09eb0c29adc14"},
"plug": {:hex, :plug, "1.12.1", "645678c800601d8d9f27ad1aebba1fdb9ce5b2623ddb961a074da0b96c35187d", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "d57e799a777bc20494b784966dc5fbda91eb4a09f571f76545b72a634ce0d30b"},
"plug_attack": {:hex, :plug_attack, "0.4.3", "88e6c464d68b1491aa083a0347d59d58ba71a7e591a7f8e1b675e8c7792a0ba8", [:mix], [{:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "9ed6fb8a6f613a36040f2875130a21187126c5625092f24bc851f7f12a8cbdc1"}, "plug_attack": {:hex, :plug_attack, "0.4.3", "88e6c464d68b1491aa083a0347d59d58ba71a7e591a7f8e1b675e8c7792a0ba8", [:mix], [{:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "9ed6fb8a6f613a36040f2875130a21187126c5625092f24bc851f7f12a8cbdc1"},
"plug_cowboy": {:hex, :plug_cowboy, "2.5.2", "62894ccd601cf9597e2c23911ff12798a8a18d237e9739f58a6b04e4988899fe", [:mix], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:cowboy_telemetry, "~> 0.3", [hex: :cowboy_telemetry, repo: "hexpm", optional: false]}, {:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "ea6e87f774c8608d60c8d34022a7d073bd7680a0a013f049fc62bf35efea1044"}, "plug_cowboy": {:hex, :plug_cowboy, "2.6.0", "d1cf12ff96a1ca4f52207c5271a6c351a4733f413803488d75b70ccf44aebec2", [:mix], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:cowboy_telemetry, "~> 0.3", [hex: :cowboy_telemetry, repo: "hexpm", optional: false]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "073cf20b753ce6682ed72905cd62a2d4bd9bad1bf9f7feb02a1b8e525bd94fa6"},
"plug_crypto": {:hex, :plug_crypto, "1.2.2", "05654514ac717ff3a1843204b424477d9e60c143406aa94daf2274fdd280794d", [:mix], [], "hexpm", "87631c7ad914a5a445f0a3809f99b079113ae4ed4b867348dd9eec288cecb6db"}, "plug_crypto": {:hex, :plug_crypto, "1.2.3", "8f77d13aeb32bfd9e654cb68f0af517b371fb34c56c9f2b58fe3df1235c1251a", [:mix], [], "hexpm", "b5672099c6ad5c202c45f5a403f21a3411247f164e4a8fab056e5cd8a290f4a2"},
"poison": {:hex, :poison, "5.0.0", "d2b54589ab4157bbb82ec2050757779bfed724463a544b6e20d79855a9e43b24", [:mix], [{:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "11dc6117c501b80c62a7594f941d043982a1bd05a1184280c0d9166eb4d8d3fc"}, "quantum": {:hex, :quantum, "3.5.0", "8d2c5ba68c55991e8975aca368e3ab844ba01f4b87c4185a7403280e2c99cf34", [:mix], [{:crontab, "~> 1.1", [hex: :crontab, repo: "hexpm", optional: false]}, {:gen_stage, "~> 0.14 or ~> 1.0", [hex: :gen_stage, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:telemetry_registry, "~> 0.2", [hex: :telemetry_registry, repo: "hexpm", optional: false]}], "hexpm", "cab737d1d9779f43cb1d701f46dd05ea58146fd96238d91c9e0da662c1982bb6"},
"quantum": {:hex, :quantum, "3.4.0", "5a53c3c52b0d55f2323940232ba6ab4c98e7e14c73dfacbba3a1ed799b037ce5", [:mix], [{:crontab, "~> 1.1", [hex: :crontab, repo: "hexpm", optional: false]}, {:gen_stage, "~> 0.14 or ~> 1.0", [hex: :gen_stage, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "d0eb64957d3dc49c8ed730cc2203108334226496535965b8dfa3f3dbcf430f87"},
"ranch": {:hex, :ranch, "1.8.0", "8c7a100a139fd57f17327b6413e4167ac559fbc04ca7448e9be9057311597a1d", [:make, :rebar3], [], "hexpm", "49fbcfd3682fab1f5d109351b61257676da1a2fdbe295904176d5e521a2ddfe5"}, "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"}, "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"}, "telemetry": {:hex, :telemetry, "1.1.0", "a589817034a27eab11144ad24d5c0f9fab1f58173274b1e9bae7074af9cbee51", [:rebar3], [], "hexpm", "b727b2a1f75614774cff2d7565b64d0dfa5bd52ba517f16543e6fc7efcc0df48"},
"telemetry_registry": {:hex, :telemetry_registry, "0.3.0", "6768f151ea53fc0fbca70dbff5b20a8d663ee4e0c0b2ae589590e08658e76f1e", [:mix, :rebar3], [{:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "492e2adbc609f3e79ece7f29fec363a97a2c484ac78a83098535d6564781e917"},
"unicode_util_compat": {:hex, :unicode_util_compat, "0.7.0", "bc84380c9ab48177092f43ac89e4dfa2c6d62b40b8bd132b1059ecc7232f9a78", [:rebar3], [], "hexpm", "25eee6d67df61960cf6a794239566599b09e17e668d3700247bc498638152521"}, "unicode_util_compat": {:hex, :unicode_util_compat, "0.7.0", "bc84380c9ab48177092f43ac89e4dfa2c6d62b40b8bd132b1059ecc7232f9a78", [:rebar3], [], "hexpm", "25eee6d67df61960cf6a794239566599b09e17e668d3700247bc498638152521"},
} }

View File

@ -40,13 +40,6 @@ defmodule FarsideTest do
assert conn.status == 200 assert conn.status == 200
end end
test "/ping" do
conn = test_conn("/ping")
assert conn.state == :sent
assert conn.status == 200
assert conn.resp_body == "PONG"
end
test "/:service" do test "/:service" do
services_json = Application.fetch_env!(:farside, :services_json) services_json = Application.fetch_env!(:farside, :services_json)
{:ok, file} = File.read(services_json) {:ok, file} = File.read(services_json)