mirror of
https://github.com/benbusby/farside.git
synced 2025-04-19 14:55:50 -04:00
refactor
This commit is contained in:
parent
03e46f81f8
commit
84caea3af2
209
.credo.exs
Normal file
209
.credo.exs
Normal file
@ -0,0 +1,209 @@
|
||||
# This file contains the configuration for Credo and you are probably reading
|
||||
# this after creating it with `mix credo.gen.config`.
|
||||
#
|
||||
# If you find anything wrong or unclear in this file, please report an
|
||||
# issue on GitHub: https://github.com/rrrene/credo/issues
|
||||
#
|
||||
%{
|
||||
#
|
||||
# You can have as many configs as you like in the `configs:` field.
|
||||
configs: [
|
||||
%{
|
||||
#
|
||||
# Run any config using `mix credo -C <name>`. If no config name is given
|
||||
# "default" is used.
|
||||
#
|
||||
name: "default",
|
||||
#
|
||||
# These are the files included in the analysis:
|
||||
files: %{
|
||||
#
|
||||
# You can give explicit globs or simply directories.
|
||||
# In the latter case `**/*.{ex,exs}` will be used.
|
||||
#
|
||||
included: [
|
||||
"lib/",
|
||||
"src/",
|
||||
"test/",
|
||||
"web/",
|
||||
"apps/*/lib/",
|
||||
"apps/*/src/",
|
||||
"apps/*/test/",
|
||||
"apps/*/web/"
|
||||
],
|
||||
excluded: [
|
||||
~r"/_build/",
|
||||
~r"/deps/",
|
||||
~r"/node_modules/",
|
||||
~r"/package-lock.json",
|
||||
~r"/package.json"
|
||||
]
|
||||
},
|
||||
#
|
||||
# Load and configure plugins here:
|
||||
#
|
||||
plugins: [],
|
||||
#
|
||||
# If you create your own checks, you must specify the source files for
|
||||
# them here, so they can be loaded by Credo before running the analysis.
|
||||
#
|
||||
requires: [],
|
||||
#
|
||||
# If you want to enforce a style guide and need a more traditional linting
|
||||
# experience, you can change `strict` to `true` below:
|
||||
#
|
||||
strict: false,
|
||||
#
|
||||
# To modify the timeout for parsing files, change this value:
|
||||
#
|
||||
parse_timeout: 120_000,
|
||||
#
|
||||
# If you want to use uncolored output by default, you can change `color`
|
||||
# to `false` below:
|
||||
#
|
||||
color: true,
|
||||
#
|
||||
# You can customize the parameters of any check by adding a second element
|
||||
# to the tuple.
|
||||
#
|
||||
# To disable a check put `false` as second element:
|
||||
#
|
||||
# {Credo.Check.Design.DuplicatedCode, false}
|
||||
#
|
||||
checks: %{
|
||||
enabled: [
|
||||
#
|
||||
## Consistency Checks
|
||||
#
|
||||
{Credo.Check.Consistency.ExceptionNames, []},
|
||||
{Credo.Check.Consistency.LineEndings, []},
|
||||
{Credo.Check.Consistency.ParameterPatternMatching, []},
|
||||
{Credo.Check.Consistency.SpaceAroundOperators, []},
|
||||
{Credo.Check.Consistency.SpaceInParentheses, []},
|
||||
{Credo.Check.Consistency.TabsOrSpaces, []},
|
||||
|
||||
#
|
||||
## Design Checks
|
||||
#
|
||||
# You can customize the priority of any check
|
||||
# Priority values are: `low, normal, high, higher`
|
||||
#
|
||||
{Credo.Check.Design.AliasUsage,
|
||||
[priority: :low, if_nested_deeper_than: 2, if_called_more_often_than: 0]},
|
||||
# You can also customize the exit_status of each check.
|
||||
# set this value to 0 (zero).
|
||||
#
|
||||
{Credo.Check.Design.TagFIXME, []},
|
||||
|
||||
#
|
||||
## Readability Checks
|
||||
#
|
||||
{Credo.Check.Readability.AliasOrder, []},
|
||||
{Credo.Check.Readability.FunctionNames, []},
|
||||
{Credo.Check.Readability.LargeNumbers, []},
|
||||
{Credo.Check.Readability.ModuleAttributeNames, []},
|
||||
{Credo.Check.Readability.ModuleDoc, []},
|
||||
{Credo.Check.Readability.ModuleNames, []},
|
||||
{Credo.Check.Readability.ParenthesesInCondition, []},
|
||||
{Credo.Check.Readability.ParenthesesOnZeroArityDefs, []},
|
||||
{Credo.Check.Readability.PipeIntoAnonymousFunctions, []},
|
||||
{Credo.Check.Readability.PredicateFunctionNames, []},
|
||||
{Credo.Check.Readability.PreferImplicitTry, []},
|
||||
{Credo.Check.Readability.RedundantBlankLines, []},
|
||||
{Credo.Check.Readability.Semicolons, []},
|
||||
{Credo.Check.Readability.SpaceAfterCommas, []},
|
||||
{Credo.Check.Readability.StrictModuleLayout, []},
|
||||
{Credo.Check.Readability.StringSigils, []},
|
||||
{Credo.Check.Readability.TrailingBlankLine, []},
|
||||
{Credo.Check.Readability.TrailingWhiteSpace, []},
|
||||
{Credo.Check.Readability.UnnecessaryAliasExpansion, []},
|
||||
{Credo.Check.Readability.VariableNames, []},
|
||||
{Credo.Check.Readability.WithSingleClause, []},
|
||||
|
||||
#
|
||||
## Refactoring Opportunities
|
||||
#
|
||||
{Credo.Check.Refactor.Apply, []},
|
||||
# {Credo.Check.Refactor.CondStatements, []},
|
||||
# {Credo.Check.Refactor.CyclomaticComplexity, []},
|
||||
{Credo.Check.Refactor.FunctionArity, []},
|
||||
# should be activated after elixir version upgrade
|
||||
{Credo.Check.Refactor.MapInto, false},
|
||||
{Credo.Check.Refactor.MatchInCondition, []},
|
||||
{Credo.Check.Refactor.NegatedConditionsInUnless, []},
|
||||
{Credo.Check.Refactor.NegatedConditionsWithElse, []},
|
||||
# {Credo.Check.Refactor.Nesting, []},
|
||||
{Credo.Check.Refactor.UnlessWithElse, []},
|
||||
{Credo.Check.Refactor.WithClauses, []},
|
||||
{Credo.Check.Refactor.RedundantWithClauseResult, []},
|
||||
{Credo.Check.Refactor.FilterFilter, []},
|
||||
#
|
||||
## Warnings
|
||||
#
|
||||
{Credo.Check.Warning.BoolOperationOnSameValues, []},
|
||||
{Credo.Check.Warning.ExpensiveEmptyEnumCheck, []},
|
||||
{Credo.Check.Warning.IExPry, []},
|
||||
{Credo.Check.Warning.IoInspect, []},
|
||||
# should be activated after elixir version upgrade
|
||||
{Credo.Check.Warning.LazyLogging, false},
|
||||
{Credo.Check.Warning.OperationOnSameValues, []},
|
||||
{Credo.Check.Warning.OperationWithConstantResult, []},
|
||||
{Credo.Check.Warning.RaiseInsideRescue, []},
|
||||
{Credo.Check.Warning.SpecWithStruct, []},
|
||||
{Credo.Check.Warning.WrongTestFileExtension, []},
|
||||
{Credo.Check.Warning.UnusedEnumOperation, []},
|
||||
{Credo.Check.Warning.UnusedFileOperation, []},
|
||||
{Credo.Check.Warning.UnusedKeywordOperation, []},
|
||||
{Credo.Check.Warning.UnusedListOperation, []},
|
||||
{Credo.Check.Warning.UnusedPathOperation, []},
|
||||
{Credo.Check.Warning.UnusedRegexOperation, []},
|
||||
{Credo.Check.Warning.UnusedStringOperation, []},
|
||||
{Credo.Check.Warning.UnusedTupleOperation, []},
|
||||
{Credo.Check.Warning.UnsafeExec, []}
|
||||
|
||||
|
||||
#
|
||||
# Checks scheduled for next check update (opt-in for now, just replace `false` with `[]`)
|
||||
|
||||
#
|
||||
# Controversial and experimental checks (opt-in, just replace `false` with `[]`)
|
||||
#
|
||||
],
|
||||
disabled: [
|
||||
{Credo.Check.Design.TagTODO, false},
|
||||
{Credo.Check.Consistency.MultiAliasImportRequireUse, false},
|
||||
{Credo.Check.Consistency.UnusedVariableNames, false},
|
||||
{Credo.Check.Design.DuplicatedCode, false},
|
||||
{Credo.Check.Readability.AliasAs, false},
|
||||
{Credo.Check.Readability.BlockPipe, false},
|
||||
{Credo.Check.Readability.ImplTrue, false},
|
||||
{Credo.Check.Readability.MaxLineLength, false},
|
||||
{Credo.Check.Readability.MultiAlias, false},
|
||||
{Credo.Check.Readability.SeparateAliasRequire, false},
|
||||
{Credo.Check.Readability.SinglePipe, false},
|
||||
{Credo.Check.Readability.Specs, false},
|
||||
{Credo.Check.Readability.StrictModuleLayout, false},
|
||||
{Credo.Check.Readability.WithCustomTaggedTuple, false},
|
||||
{Credo.Check.Refactor.ABCSize, false},
|
||||
{Credo.Check.Refactor.AppendSingleItem, false},
|
||||
{Credo.Check.Refactor.DoubleBooleanNegation, false},
|
||||
{Credo.Check.Refactor.LongQuoteBlocks, false},
|
||||
{Credo.Check.Refactor.MapJoin, false},
|
||||
{Credo.Check.Refactor.ModuleDependencies, false},
|
||||
{Credo.Check.Refactor.NegatedIsNil, false},
|
||||
{Credo.Check.Refactor.PipeChainStart, false},
|
||||
{Credo.Check.Refactor.RejectReject, false},
|
||||
{Credo.Check.Refactor.VariableRebinding, false},
|
||||
{Credo.Check.Warning.LeakyEnvironment, false},
|
||||
{Credo.Check.Warning.MapGetUnsafePass, false},
|
||||
{Credo.Check.Warning.MixEnv, false},
|
||||
{Credo.Check.Warning.UnsafeToAtom, false},
|
||||
{Credo.Check.Warning.ApplicationConfigInModuleAttribute, false}
|
||||
]
|
||||
#
|
||||
# Custom checks can be created using `mix credo.gen.check`.
|
||||
#
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
@ -1,8 +1,6 @@
|
||||
import Config
|
||||
|
||||
config :farside,
|
||||
update_file: ".update-results",
|
||||
service_prefix: "service-",
|
||||
index: "index.eex",
|
||||
route: "route.eex",
|
||||
headers: [
|
||||
|
@ -1,9 +1,13 @@
|
||||
defmodule Farside do
|
||||
@service_prefix Application.fetch_env!(:farside, :service_prefix)
|
||||
@moduledoc """
|
||||
Farside
|
||||
main application functions
|
||||
|
||||
This is where we define relation between available services and their parent service.
|
||||
This enables Farside to redirect with links such as:
|
||||
farside.link/https://www.youtube.com/watch?v=dQw4w9WgXcQ
|
||||
"""
|
||||
|
||||
# Define relation between available services and their parent service.
|
||||
# This enables Farside to redirect with links such as:
|
||||
# farside.link/https://www.youtube.com/watch?v=dQw4w9WgXcQ
|
||||
@youtube_regex ~r/youtu(.be|be.com)|invidious|piped/
|
||||
@reddit_regex ~r/reddit.com|libreddit|teddit/
|
||||
@instagram_regex ~r/instagram.com|bibliogram/
|
||||
@ -35,42 +39,40 @@ defmodule Farside do
|
||||
alias Farside.LastUpdated
|
||||
|
||||
def get_services_map do
|
||||
services_map =
|
||||
Farside.Instance.Supervisor.list()
|
||||
|> Enum.map(fn service ->
|
||||
data = :ets.lookup(String.to_atom(service), :default) |> List.first()
|
||||
Farside.Instance.Supervisor.list()
|
||||
|> Enum.map(fn service ->
|
||||
data = :ets.lookup(String.to_atom(service), :default) |> List.first()
|
||||
|
||||
instances =
|
||||
case is_nil(data) do
|
||||
true ->
|
||||
[]
|
||||
case is_nil(data) do
|
||||
true ->
|
||||
[]
|
||||
|
||||
false ->
|
||||
{_, service} = data
|
||||
false ->
|
||||
{_, service} = data
|
||||
|
||||
registry = "#{service.type}_healthy"
|
||||
registry = "#{service.type}_healthy"
|
||||
|
||||
instances =
|
||||
for instance <- service.instances do
|
||||
matches = Registry.match(:status, registry, instance)
|
||||
instances =
|
||||
for instance <- service.instances do
|
||||
matches = Registry.match(:status, registry, instance)
|
||||
|
||||
{_, instance} =
|
||||
case Enum.count(matches) > 0 do
|
||||
true -> List.first(matches)
|
||||
false -> {:error, nil}
|
||||
end
|
||||
|
||||
instance
|
||||
{_, instance} =
|
||||
case Enum.count(matches) > 0 do
|
||||
true -> List.first(matches)
|
||||
false -> {:error, nil}
|
||||
end
|
||||
|> Enum.reject(fn x -> x == nil end)
|
||||
|
||||
Map.put(
|
||||
service,
|
||||
:instances,
|
||||
instances
|
||||
)
|
||||
end
|
||||
end)
|
||||
instance
|
||||
end
|
||||
|> Enum.reject(fn x -> x == nil end)
|
||||
|
||||
Map.put(
|
||||
service,
|
||||
:instances,
|
||||
instances
|
||||
)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
def get_service(service) do
|
||||
@ -149,18 +151,4 @@ defmodule Farside do
|
||||
instance
|
||||
end
|
||||
end
|
||||
|
||||
def save_results(file, data) do
|
||||
if System.get_env("MIX_ENV") == "dev" do
|
||||
{:ok, file} = File.open(file, [:append])
|
||||
bin = :erlang.term_to_binary(data)
|
||||
IO.binwrite(file, bin)
|
||||
File.close(file)
|
||||
end
|
||||
end
|
||||
|
||||
def restore_term(file) do
|
||||
{:ok, bin} = File.read(file)
|
||||
:erlang.binary_to_term(bin)
|
||||
end
|
||||
end
|
||||
|
@ -78,7 +78,18 @@ defmodule Farside.Application do
|
||||
|
||||
struct(%Service{}, service_atom)
|
||||
|> Farside.Instance.Supervisor.start()
|
||||
|> HealthyCheck.load()
|
||||
end
|
||||
|
||||
response
|
||||
|> maybe_run()
|
||||
end
|
||||
|
||||
def maybe_run(response) do
|
||||
if is_nil(System.get_env("FARSIDE_TEST")) do
|
||||
Task.start(fn ->
|
||||
Process.sleep(10_000)
|
||||
UnHealthyCheck.run()
|
||||
end)
|
||||
end
|
||||
|
||||
response
|
||||
|
@ -5,6 +5,8 @@ defmodule Farside.Server.DeadCheck do
|
||||
use Task
|
||||
alias Farside.LastUpdated
|
||||
|
||||
require Logger
|
||||
|
||||
def child_spec(args) do
|
||||
%{
|
||||
id: __MODULE__,
|
||||
@ -20,7 +22,7 @@ defmodule Farside.Server.DeadCheck do
|
||||
def poll() do
|
||||
receive do
|
||||
after
|
||||
1_200_000 ->
|
||||
86_400_000 ->
|
||||
run()
|
||||
poll()
|
||||
end
|
||||
@ -29,6 +31,8 @@ defmodule Farside.Server.DeadCheck do
|
||||
def run() do
|
||||
LastUpdated.value(DateTime.utc_now())
|
||||
|
||||
Logger.info("Dead Service Check Running")
|
||||
|
||||
Registry.dispatch(:status, "dead", fn entries ->
|
||||
for {pid, _} <- entries, do: GenServer.cast(pid, :check)
|
||||
end)
|
||||
|
@ -5,6 +5,8 @@ defmodule Farside.Server.HealthyCheck do
|
||||
use Task
|
||||
alias Farside.LastUpdated
|
||||
|
||||
require Logger
|
||||
|
||||
def child_spec(args) do
|
||||
%{
|
||||
id: __MODULE__,
|
||||
@ -20,27 +22,19 @@ defmodule Farside.Server.HealthyCheck do
|
||||
def poll() do
|
||||
receive do
|
||||
after
|
||||
90_000 ->
|
||||
300_000 ->
|
||||
run()
|
||||
poll()
|
||||
end
|
||||
end
|
||||
|
||||
def load(params) do
|
||||
Registry.dispatch(:status, "healthy", fn entries ->
|
||||
for {pid, url} <- entries do
|
||||
GenServer.cast(pid, :check)
|
||||
end
|
||||
end)
|
||||
|
||||
params
|
||||
end
|
||||
|
||||
def run() do
|
||||
LastUpdated.value(DateTime.utc_now())
|
||||
|
||||
Logger.info("Healthy Service Check Running")
|
||||
|
||||
Registry.dispatch(:status, "healthy", fn entries ->
|
||||
for {pid, url} <- entries do
|
||||
for {pid, _url} <- entries do
|
||||
GenServer.cast(pid, :check)
|
||||
end
|
||||
end)
|
||||
|
@ -1,6 +1,11 @@
|
||||
defmodule Farside.Http do
|
||||
require Logger
|
||||
|
||||
@moduledoc """
|
||||
Http
|
||||
the http client
|
||||
"""
|
||||
|
||||
@headers Application.fetch_env!(:farside, :headers)
|
||||
@queries Application.fetch_env!(:farside, :queries)
|
||||
@recv_timeout String.to_integer(Application.fetch_env!(:farside, :recv_timeout))
|
||||
@ -108,11 +113,11 @@ defmodule Farside.Http do
|
||||
nil
|
||||
end
|
||||
|
||||
unless is_nil(data) do
|
||||
if is_nil(data) do
|
||||
:bad
|
||||
else
|
||||
{_test_url, value, _service} = data
|
||||
value
|
||||
else
|
||||
:bad
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -1,9 +1,12 @@
|
||||
defmodule Farside.Instance do
|
||||
use GenServer
|
||||
|
||||
require Logger
|
||||
@moduledoc """
|
||||
Instance
|
||||
this will store the pointer to ets
|
||||
"""
|
||||
|
||||
alias Farside.Http
|
||||
require Logger
|
||||
|
||||
@registry_name :instance
|
||||
|
||||
@ -15,6 +18,7 @@ defmodule Farside.Instance do
|
||||
}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def init(init_arg) do
|
||||
ref =
|
||||
:ets.new(String.to_atom(init_arg.type), [
|
||||
@ -40,6 +44,7 @@ defmodule Farside.Instance do
|
||||
GenServer.call(__MODULE__, :shutdown)
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_call(
|
||||
:shutdown,
|
||||
_from,
|
||||
@ -48,6 +53,7 @@ defmodule Farside.Instance do
|
||||
{:stop, {:ok, "Normal Shutdown"}, state}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_cast(
|
||||
:shutdown,
|
||||
state
|
||||
@ -61,7 +67,7 @@ defmodule Farside.Instance do
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_info({:DOWN, ref, :process, _pid, _reason}, {names, refs}) do
|
||||
def handle_info({:DOWN, _ref, :process, _pid, _reason}, {names, refs}) do
|
||||
:ets.delete(names)
|
||||
{:noreply, {names, refs}}
|
||||
end
|
||||
|
@ -1,7 +1,11 @@
|
||||
defmodule Farside.Instance.Supervisor do
|
||||
use DynamicSupervisor
|
||||
|
||||
alias __MODULE__, as: SUPERVISOR
|
||||
@moduledoc """
|
||||
Instance Supervisor
|
||||
this will supervise the instance
|
||||
"""
|
||||
|
||||
alias Farside.Instance, as: SERVER
|
||||
|
||||
@name :instance_supervisor
|
||||
|
@ -1,6 +1,8 @@
|
||||
defmodule Farside.LastUpdated do
|
||||
use Agent
|
||||
|
||||
@moduledoc nil
|
||||
|
||||
def start_link(initial_value) do
|
||||
Agent.start_link(fn -> initial_value end, name: __MODULE__)
|
||||
end
|
||||
|
@ -1,6 +1,11 @@
|
||||
defmodule Farside.Service do
|
||||
use GenServer
|
||||
|
||||
@moduledoc """
|
||||
Service
|
||||
this will store the service state
|
||||
"""
|
||||
|
||||
require Logger
|
||||
|
||||
alias Farside.Http
|
||||
@ -21,19 +26,22 @@ defmodule Farside.Service do
|
||||
}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def init(data) do
|
||||
initial_state = %__MODULE__{
|
||||
url: data.url,
|
||||
type: data.type,
|
||||
test_url: data.test_url,
|
||||
last_update: nil,
|
||||
last_update:
|
||||
DateTime.utc_now()
|
||||
|> DateTime.add(-86_400, :second),
|
||||
status: []
|
||||
}
|
||||
|
||||
healthy = "#{data.type}_healthy"
|
||||
unhealthy = "#{data.type}_unhealthy"
|
||||
|
||||
Registry.register(:status, healthy, data.url)
|
||||
Registry.register(:status, "healthy", data.url)
|
||||
Registry.register(:status, unhealthy, data.url)
|
||||
Registry.register(:status, "unhealthy", data.url)
|
||||
{:ok, initial_state}
|
||||
end
|
||||
|
||||
@ -46,6 +54,7 @@ defmodule Farside.Service do
|
||||
GenServer.call(__MODULE__, :shutdown)
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_call(
|
||||
:shutdown,
|
||||
_from,
|
||||
@ -54,28 +63,6 @@ defmodule Farside.Service do
|
||||
{:stop, {:ok, "Normal Shutdown"}, state}
|
||||
end
|
||||
|
||||
def handle_cast(
|
||||
:shutdown,
|
||||
state
|
||||
) do
|
||||
{:stop, :normal, state}
|
||||
end
|
||||
|
||||
@doc false
|
||||
def via_tuple(id, registry \\ @registry_name) do
|
||||
{:via, Registry, {registry, id}}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_info({:DOWN, ref, :process, _pid, _reason}, data) do
|
||||
{:noreply, data}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_info(_msg, state) do
|
||||
{:noreply, state}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_cast(:load, state) do
|
||||
reply = Http.test_service(state)
|
||||
@ -91,57 +78,90 @@ defmodule Farside.Service do
|
||||
|
||||
@impl true
|
||||
def handle_cast(:check, state) do
|
||||
reply = Http.test_service(state)
|
||||
|
||||
status = state.status ++ [reply]
|
||||
|
||||
max_queue = Application.get_env(:farside, :max_fail_rate, 50) + 5
|
||||
|
||||
status =
|
||||
case Enum.count(status) < max_queue do
|
||||
true -> status
|
||||
false -> []
|
||||
end
|
||||
|
||||
state = %{state | status: status}
|
||||
|
||||
state = %{state | last_update: DateTime.utc_now()}
|
||||
|
||||
healthy = "#{state.type}_healthy"
|
||||
unhealthy = "#{state.type}_unhealthy"
|
||||
dead = "#{state.type}_dead"
|
||||
|
||||
Registry.unregister_match(:status, "healthy", state.url)
|
||||
Registry.unregister_match(:status, "unhealthy", state.url)
|
||||
Registry.unregister_match(:status, "dead", state.url)
|
||||
|
||||
Registry.unregister_match(:status, healthy, state.url)
|
||||
Registry.unregister_match(:status, unhealthy, state.url)
|
||||
Registry.unregister_match(:status, dead, state.url)
|
||||
dt =
|
||||
DateTime.utc_now()
|
||||
|> DateTime.add(-60, :second)
|
||||
|
||||
state =
|
||||
if reply != :good do
|
||||
filtered = Enum.reject(status, fn x -> x == :good end)
|
||||
case DateTime.compare(dt, state.last_update) do
|
||||
:gt ->
|
||||
reply = Http.test_service(state)
|
||||
|
||||
fails_before_death = Application.get_env(:farside, :max_fail_rate, 50)
|
||||
status = state.status ++ [reply]
|
||||
|
||||
case Enum.count(filtered) < fails_before_death do
|
||||
true ->
|
||||
Registry.register(:status, "unhealthy", state.url)
|
||||
Registry.register(:status, unhealthy, state.url)
|
||||
max_queue = Application.get_env(:farside, :max_fail_rate, 50) + 5
|
||||
|
||||
status =
|
||||
case Enum.count(status) < max_queue do
|
||||
true -> status
|
||||
false -> []
|
||||
end
|
||||
|
||||
state = %{state | status: status}
|
||||
|
||||
state = %{state | last_update: DateTime.utc_now()}
|
||||
|
||||
healthy = "#{state.type}_healthy"
|
||||
unhealthy = "#{state.type}_unhealthy"
|
||||
dead = "#{state.type}_dead"
|
||||
|
||||
Registry.unregister_match(:status, "healthy", state.url)
|
||||
Registry.unregister_match(:status, "unhealthy", state.url)
|
||||
Registry.unregister_match(:status, "dead", state.url)
|
||||
|
||||
Registry.unregister_match(:status, healthy, state.url)
|
||||
Registry.unregister_match(:status, unhealthy, state.url)
|
||||
Registry.unregister_match(:status, dead, state.url)
|
||||
|
||||
if reply != :good do
|
||||
filtered = Enum.reject(status, fn x -> x == :good end)
|
||||
|
||||
fails_before_death = Application.get_env(:farside, :max_fail_rate, 50)
|
||||
|
||||
case Enum.count(filtered) < fails_before_death do
|
||||
true ->
|
||||
Registry.register(:status, "unhealthy", state.url)
|
||||
Registry.register(:status, unhealthy, state.url)
|
||||
state
|
||||
|
||||
false ->
|
||||
Registry.register(:status, "dead", state.url)
|
||||
Registry.register(:status, dead, state.url)
|
||||
%{state | status: [:bad]}
|
||||
end
|
||||
else
|
||||
Registry.register(:status, "healthy", state.url)
|
||||
Registry.register(:status, healthy, state.url)
|
||||
state
|
||||
end
|
||||
|
||||
false ->
|
||||
Registry.register(:status, "dead", state.url)
|
||||
Registry.register(:status, dead, state.url)
|
||||
%{state | status: [:bad]}
|
||||
end
|
||||
else
|
||||
Registry.register(:status, "healthy", state.url)
|
||||
Registry.register(:status, healthy, state.url)
|
||||
state
|
||||
_ ->
|
||||
%{state | last_update: DateTime.utc_now()}
|
||||
end
|
||||
|
||||
{:noreply, state}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_cast(
|
||||
:shutdown,
|
||||
state
|
||||
) do
|
||||
{:stop, :normal, state}
|
||||
end
|
||||
|
||||
@doc false
|
||||
def via_tuple(id, registry \\ @registry_name) do
|
||||
{:via, Registry, {registry, id}}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_info({:DOWN, _ref, :process, _pid, _reason}, data) do
|
||||
{:noreply, data}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_info(_msg, state) do
|
||||
{:noreply, state}
|
||||
end
|
||||
end
|
||||
|
@ -1,6 +1,11 @@
|
||||
defmodule Farside.Service.Supervisor do
|
||||
use DynamicSupervisor
|
||||
|
||||
@moduledoc """
|
||||
Service Supervisor
|
||||
this will supervise the service
|
||||
"""
|
||||
|
||||
alias __MODULE__, as: SUPERVISOR
|
||||
alias Farside.Service, as: SERVER
|
||||
|
||||
|
@ -2,6 +2,8 @@ defmodule Farside.Throttle do
|
||||
import Plug.Conn
|
||||
use PlugAttack
|
||||
|
||||
@moduledoc nil
|
||||
|
||||
rule "throttle per ip", conn do
|
||||
# throttle to 1 request per second
|
||||
throttle(conn.remote_ip,
|
||||
|
@ -5,6 +5,8 @@ defmodule Farside.Server.UnHealthyCheck do
|
||||
use Task
|
||||
alias Farside.LastUpdated
|
||||
|
||||
require Logger
|
||||
|
||||
def child_spec(args) do
|
||||
%{
|
||||
id: __MODULE__,
|
||||
@ -20,7 +22,7 @@ defmodule Farside.Server.UnHealthyCheck do
|
||||
def poll() do
|
||||
receive do
|
||||
after
|
||||
120_000 ->
|
||||
200_000 ->
|
||||
run()
|
||||
poll()
|
||||
end
|
||||
@ -29,6 +31,8 @@ defmodule Farside.Server.UnHealthyCheck do
|
||||
def run() do
|
||||
LastUpdated.value(DateTime.utc_now())
|
||||
|
||||
Logger.info("Unhealthy Service Check Running")
|
||||
|
||||
Registry.dispatch(:status, "unhealthy", fn entries ->
|
||||
for {pid, _} <- entries, do: GenServer.cast(pid, :check)
|
||||
end)
|
||||
|
@ -1,4 +1,6 @@
|
||||
defmodule Service do
|
||||
@moduledoc nil
|
||||
|
||||
defstruct type: nil,
|
||||
test_url: nil,
|
||||
fallback: nil,
|
||||
|
2
mix.exs
2
mix.exs
@ -41,6 +41,8 @@ defmodule Farside.MixProject do
|
||||
{:jason, "~> 1.1"},
|
||||
{:plug_attack, "~> 0.4.2"},
|
||||
{:plug_cowboy, "~> 2.0"},
|
||||
{:credo, "~> 1.6.3", only: [:dev, :test], runtime: false},
|
||||
{:mix_audit, "~> 1.0.0", only: [:dev, :test], runtime: false},
|
||||
{:bakeware, runtime: false, only: :cli}
|
||||
]
|
||||
end
|
||||
|
6
mix.lock
6
mix.lock
@ -1,13 +1,16 @@
|
||||
%{
|
||||
"artificery": {:hex, :artificery, "0.4.3", "0bc4260f988dcb9dda4b23f9fc3c6c8b99a6220a331534fdf5bf2fd0d4333b02", [:mix], [], "hexpm", "12e95333a30e20884e937abdbefa3e7f5e05609c2ba8cf37b33f000b9ffc0504"},
|
||||
"bakeware": {:hex, :bakeware, "0.2.4", "0aaf49b34f4bab2aa433f9ff1485d9401e421603160abd6d269c469fc7b65212", [:make, :mix], [{:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "7b97bcf6fbeee53bb32441d6c495bf478d26f9575633cfef6831e421e86ada6d"},
|
||||
"bunt": {:hex, :bunt, "0.2.1", "e2d4792f7bc0ced7583ab54922808919518d0e57ee162901a16a1b6664ef3b14", [:mix], [], "hexpm", "a330bfb4245239787b15005e66ae6845c9cd524a288f0d141c148b02603777a5"},
|
||||
"certifi": {:hex, :certifi, "2.8.0", "d4fb0a6bb20b7c9c3643e22507e42f356ac090a1dcea9ab99e27e0376d695eba", [:rebar3], [], "hexpm", "6ac7efc1c6f8600b08d625292d4bbf584e14847ce1b6b5c44d983d273e1097ea"},
|
||||
"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"},
|
||||
"cowlib": {:hex, :cowlib, "2.11.0", "0b9ff9c346629256c42ebe1eeb769a83c6cb771a6ee5960bd110ab0b9b872063", [:make, :rebar3], [], "hexpm", "2b3e9da0b21c4565751a6d4901c20d1b4cc25cbb7fd50d91d2ab6dd287bc86a9"},
|
||||
"credo": {:hex, :credo, "1.6.7", "323f5734350fd23a456f2688b9430e7d517afb313fbd38671b8a4449798a7854", [:mix], [{:bunt, "~> 0.2.1", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2.8", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "41e110bfb007f7eda7f897c10bf019ceab9a0b269ce79f015d54b0dcf4fc7dd3"},
|
||||
"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"},
|
||||
"distillery": {:hex, :distillery, "2.1.1", "f9332afc2eec8a1a2b86f22429e068ef35f84a93ea1718265e740d90dd367814", [:mix], [{:artificery, "~> 0.2", [hex: :artificery, repo: "hexpm", optional: false]}], "hexpm", "bbc7008b0161a6f130d8d903b5b3232351fccc9c31a991f8fcbf2a12ace22995"},
|
||||
"elixir_make": {:hex, :elixir_make, "0.6.3", "bc07d53221216838d79e03a8019d0839786703129599e9619f4ab74c8c096eac", [:mix], [], "hexpm", "f5cbd651c5678bcaabdbb7857658ee106b12509cd976c2c2fca99688e1daf716"},
|
||||
"file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"},
|
||||
"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"},
|
||||
"httpoison": {:hex, :httpoison, "1.8.0", "6b85dea15820b7804ef607ff78406ab449dd78bed923a49c7160e1886e987a3d", [:mix], [{:hackney, "~> 1.17", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "28089eaa98cf90c66265b6b5ad87c59a3729bea2e74e9d08f9b51eb9729b3c3a"},
|
||||
@ -16,6 +19,7 @@
|
||||
"metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm", "69b09adddc4f74a40716ae54d140f93beb0fb8978d8636eaded0c31b6f099f16"},
|
||||
"mime": {:hex, :mime, "2.0.2", "0b9e1a4c840eafb68d820b0e2158ef5c49385d17fb36855ac6e7e087d4b1dcc5", [:mix], [], "hexpm", "e6a3f76b4c277739e36c2e21a2c640778ba4c3846189d5ab19f97f126df5f9b7"},
|
||||
"mimerl": {:hex, :mimerl, "1.2.0", "67e2d3f571088d5cfd3e550c383094b47159f3eee8ffa08e64106cdf5e981be3", [:rebar3], [], "hexpm", "f278585650aa581986264638ebf698f8bb19df297f66ad91b18910dfc6e19323"},
|
||||
"mix_audit": {:hex, :mix_audit, "1.0.1", "9dd114408961b8db214f42fee40b2f632ecd7e4fd29500403068c82c77db8361", [:make, :mix], [{:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: false]}, {:yaml_elixir, "~> 2.8.0", [hex: :yaml_elixir, repo: "hexpm", optional: false]}], "hexpm", "65066bb7757078aa49faaa2f7c1e2d52f56ff6fe6cff01723dbaf5be2a75771b"},
|
||||
"mustache": {:hex, :mustache, "0.3.1", "4c6ee79b13aae954035fe31b83c94480ddc7b536d09c44d4c65e61a9ead38d6b", [:mix], [], "hexpm", "8dc92b9b92a0d7449628f4fc981f8018a16a5b8c9907249e59db461482dac143"},
|
||||
"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"},
|
||||
@ -30,4 +34,6 @@
|
||||
"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"},
|
||||
"yamerl": {:hex, :yamerl, "0.10.0", "4ff81fee2f1f6a46f1700c0d880b24d193ddb74bd14ef42cb0bcf46e81ef2f8e", [:rebar3], [], "hexpm", "346adb2963f1051dc837a2364e4acf6eb7d80097c0f53cbdc3046ec8ec4b4e6e"},
|
||||
"yaml_elixir": {:hex, :yaml_elixir, "2.8.0", "c7ff0034daf57279c2ce902788ce6fdb2445532eb4317e8df4b044209fae6832", [:mix], [{:yamerl, "~> 0.8", [hex: :yamerl, repo: "hexpm", optional: false]}], "hexpm", "4b674bd881e373d1ac6a790c64b2ecb69d1fd612c2af3b22de1619c15473830b"},
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user