Packages
tai
0.0.71
0.0.75
0.0.74
0.0.73
0.0.72
0.0.71
0.0.70
0.0.69
0.0.68
0.0.67
0.0.66
0.0.65
0.0.64
0.0.63
0.0.62
0.0.61
0.0.60
0.0.59
0.0.58
0.0.57
0.0.56
0.0.55
0.0.54
0.0.53
0.0.52
0.0.51
0.0.50
0.0.49
0.0.48
0.0.47
0.0.46
0.0.45
0.0.44
0.0.43
0.0.42
0.0.41
0.0.40
0.0.39
0.0.38
0.0.37
0.0.36
0.0.35
0.0.34
0.0.33
0.0.32
0.0.31
0.0.30
0.0.29
0.0.28
0.0.27
0.0.26
0.0.25
0.0.24
0.0.23
0.0.22
0.0.21
0.0.20
0.0.19
0.0.18
0.0.17
0.0.16
0.0.15
0.0.14
0.0.13
0.0.12
0.0.11
0.0.10
0.0.9
0.0.8
0.0.7
0.0.6
0.0.5
0.0.4
0.0.3
0.0.2
0.0.1
A composable, real time, market data and trade execution toolkit
Current section
Files
Jump to
Current section
Files
lib/tai/boot.ex
defmodule Tai.Boot do
use GenServer
require Logger
defmodule State do
@enforce_keys ~w[config venues venue_replies]a
defstruct ~w[config venues venue_replies]a
end
@type id :: atom
@type venue :: Tai.Venue.t()
@default_id :default
def child_spec(opts) do
%{
id: __MODULE__,
start: {__MODULE__, :start_link, [opts]},
shutdown: 5_000,
restart: :transient,
type: :worker
}
end
def start_link(args) do
id = Keyword.get(args, :id, @default_id)
config = Keyword.get(args, :config, Tai.Config.parse())
name = to_name(id)
state = %State{config: config, venues: %{}, venue_replies: %{}}
GenServer.start_link(__MODULE__, state, name: name)
end
@spec to_name(id) :: atom
def to_name(id) do
:"#{__MODULE__}_#{id}"
end
@spec register_venue(venue) :: {:ok, venue}
@spec register_venue(venue, id) :: {:ok, venue}
def register_venue(venue, id \\ @default_id) do
id
|> to_name
|> GenServer.call({:register_venue, venue})
end
@spec close_registration :: :ok
@spec close_registration(id) :: :ok
def close_registration(id \\ @default_id) do
id
|> to_name
|> GenServer.cast(:close_registration)
end
@events [Tai.Events.VenueStart, Tai.Events.VenueStartError]
def init(state) do
Enum.each(@events, &TaiEvents.subscribe/1)
{:ok, state}
end
def handle_call({:register_venue, venue}, _from, state) do
state = %{
state
| venues: Map.put(state.venues, venue.id, venue)
}
{:reply, {:ok, venue}, state}
end
def handle_cast(:close_registration, state) do
{
:noreply,
state,
{:continue, :check_replies_for_completion}
}
end
def handle_info({TaiEvents.Event, %Tai.Events.VenueStart{} = event, :info}, state) do
state = %{
state
| venue_replies: Map.put(state.venue_replies, event.venue, event)
}
{
:noreply,
state,
{:continue, :check_replies_for_completion}
}
end
def handle_info({TaiEvents.Event, %Tai.Events.VenueStartError{} = event, :error}, state) do
state = %{
state
| venue_replies: Map.put(state.venue_replies, event.venue, event)
}
{
:noreply,
state,
{:continue, :check_replies_for_completion}
}
end
def handle_continue(:check_replies_for_completion, state) do
state
|> all_venues_replied?()
|> check_replies()
|> case do
:noop -> {:noreply, state}
:stop -> {:stop, :normal, state}
end
end
def all_venues_replied?(state) do
if Enum.count(state.venue_replies) == Enum.count(state.venues) do
{:ok, state}
else
{:noop, state}
end
end
defp check_replies({:ok, state}) do
state.venue_replies
|> all_venue_replies_started?()
|> case do
true ->
{:ok, {loaded_fleets, loaded_advisors}} = Tai.Fleets.load(state.config.fleets)
{advisors_started, _} = Tai.Advisors.start(where: [start_on_boot: true])
%Tai.Events.BootAdvisors{
loaded_fleets: loaded_fleets,
loaded_advisors: loaded_advisors,
started_advisors: advisors_started
}
|> TaiEvents.info()
state.config.after_boot
|> case do
{mod, func_name} -> apply(mod, func_name, [])
{mod, func_name, args} -> apply(mod, func_name, [args])
_ -> nil
end
false ->
error_event = %Tai.Events.BootAdvisorsError{reason: venue_errors(state.venue_replies)}
TaiEvents.error(error_event)
state.config.after_boot_error
|> case do
{mod, func_name} -> apply(mod, func_name, [error_event])
_ -> nil
end
end
:stop
end
defp check_replies({:noop, _}), do: :noop
defp all_venue_replies_started?(venue_replies) do
venue_replies
|> Enum.all?(fn
{_, %r{}} -> r == Tai.Events.VenueStart
end)
end
defp venue_errors(venue_replies) do
venue_replies
|> Enum.map(fn
{venue_id, %Tai.Events.VenueStartError{reason: reason}} ->
{venue_id, reason}
{_venue_id, %Tai.Events.VenueStart{}} ->
nil
end)
|> Enum.filter(& &1)
end
end