mirror of
https://github.com/benbusby/farside.git
synced 2025-06-08 10:26:36 +00:00
refactor, remove unnecessary dependencies, speed up instance check query
This commit is contained in:
parent
8fbe016cdb
commit
c1ec9e9a6b
15 changed files with 475 additions and 305 deletions
124
lib/farside/instance.ex
Normal file
124
lib/farside/instance.ex
Normal file
|
@ -0,0 +1,124 @@
|
|||
defmodule Farside.Instance do
|
||||
use GenServer
|
||||
|
||||
require Logger
|
||||
|
||||
@registry_name :servers
|
||||
|
||||
def child_spec(args) do
|
||||
%{
|
||||
id: __MODULE__,
|
||||
start: {__MODULE__, :start_link, [args]},
|
||||
type: :worker
|
||||
}
|
||||
end
|
||||
|
||||
def init(init_arg) do
|
||||
ref =
|
||||
:ets.new(String.to_atom(init_arg.type), [
|
||||
:set,
|
||||
:named_table,
|
||||
:public,
|
||||
read_concurrency: true,
|
||||
write_concurrency: true
|
||||
])
|
||||
|
||||
:ets.insert(ref, {:data, init_arg})
|
||||
|
||||
{:ok, %{type: init_arg.type, ref: ref}}
|
||||
end
|
||||
|
||||
def start_link(arg) do
|
||||
name = via_tuple(arg.type)
|
||||
GenServer.start_link(__MODULE__, arg, name: name)
|
||||
end
|
||||
|
||||
def shutdown() do
|
||||
GenServer.call(__MODULE__, :shutdown)
|
||||
end
|
||||
|
||||
def handle_call(
|
||||
:shutdown,
|
||||
_from,
|
||||
state
|
||||
) do
|
||||
{:stop, {:ok, "Normal Shutdown"}, state}
|
||||
end
|
||||
|
||||
def handle_cast(
|
||||
:shutdown,
|
||||
state
|
||||
) do
|
||||
{:stop, :normal, state}
|
||||
end
|
||||
|
||||
def handle_cast(
|
||||
:update,
|
||||
state
|
||||
) do
|
||||
service = :ets.lookup(String.to_atom(state.type), :data)
|
||||
|
||||
{_, service} = List.first(service)
|
||||
|
||||
queries = Application.fetch_env!(:farside, :queries)
|
||||
|
||||
request_urls =
|
||||
Enum.map(service.instances, fn x ->
|
||||
x <>
|
||||
EEx.eval_string(
|
||||
service.test_url,
|
||||
query: Enum.random(queries)
|
||||
)
|
||||
end)
|
||||
|
||||
tasks =
|
||||
for request_url <- request_urls do
|
||||
Task.async(fn ->
|
||||
reply = Farside.Http.request(request_url, service.type)
|
||||
{request_url, reply}
|
||||
end)
|
||||
end
|
||||
|
||||
tasks_with_results = Task.yield_many(tasks, 5000)
|
||||
|
||||
instances =
|
||||
Enum.map(tasks_with_results, fn {task, res} ->
|
||||
# Shut down the tasks that did not reply nor exit
|
||||
res || Task.shutdown(task, :brutal_kill)
|
||||
end)
|
||||
|> Enum.reject(fn x -> x == nil end)
|
||||
|> Enum.map(fn {_, value} -> value end)
|
||||
|> Enum.filter(fn {instance_url, value} ->
|
||||
value == :good
|
||||
end)
|
||||
|> Enum.map(fn {url, _} -> url end)
|
||||
|
||||
values = %{service | instances: instances}
|
||||
|
||||
:ets.delete_all_objects(String.to_atom(state.type))
|
||||
|
||||
:ets.insert(state.ref, {:data, values})
|
||||
|
||||
update_file = Application.fetch_env!(:farside, :update_file)
|
||||
|
||||
File.write(update_file, values.fallback)
|
||||
|
||||
{:noreply, state}
|
||||
end
|
||||
|
||||
@doc false
|
||||
def via_tuple(data, registry \\ @registry_name) do
|
||||
{:via, Registry, {registry, data}}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_info({:DOWN, ref, :process, _pid, _reason}, {names, refs}) do
|
||||
:ets.delete(names)
|
||||
{:noreply, {names, refs}}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_info(_msg, state) do
|
||||
{:noreply, state}
|
||||
end
|
||||
end
|
Loading…
Add table
Add a link
Reference in a new issue