Packages
islands_engine
0.1.61
0.2.65
0.2.64
0.2.63
0.2.62
0.2.61
0.2.60
0.2.59
0.2.58
0.2.56
0.2.55
0.2.54
0.2.53
0.2.52
0.2.51
0.2.50
0.2.49
0.2.48
0.2.47
0.2.46
0.2.45
0.2.44
0.2.43
0.2.42
0.2.41
0.2.40
0.2.39
0.2.38
0.2.37
0.2.36
0.2.35
0.2.34
0.2.33
0.2.32
0.2.31
0.2.30
0.2.29
0.2.28
0.2.27
0.2.25
0.2.24
0.2.23
0.2.22
0.2.21
0.2.20
0.2.19
0.2.18
0.2.17
0.2.16
0.2.15
0.2.13
0.2.12
0.2.10
0.2.9
0.2.8
0.2.7
0.2.6
0.2.5
0.2.4
0.2.3
0.2.2
0.2.1
0.2.0
0.1.81
0.1.80
0.1.79
0.1.78
0.1.77
0.1.76
0.1.75
0.1.73
0.1.72
0.1.71
0.1.70
0.1.69
0.1.68
0.1.67
0.1.66
0.1.65
0.1.64
0.1.63
0.1.62
0.1.61
0.1.60
0.1.59
0.1.58
0.1.57
0.1.56
0.1.55
0.1.54
0.1.53
0.1.52
0.1.51
0.1.50
0.1.49
0.1.48
0.1.47
0.1.46
0.1.45
0.1.44
0.1.43
0.1.42
0.1.41
0.1.40
0.1.39
0.1.38
0.1.37
0.1.36
0.1.35
0.1.34
0.1.33
0.1.32
0.1.31
0.1.30
0.1.29
0.1.28
0.1.27
0.1.26
0.1.25
0.1.24
0.1.23
0.1.22
0.1.21
0.1.20
0.1.19
0.1.18
0.1.17
0.1.16
0.1.15
0.1.14
0.1.13
0.1.12
0.1.11
0.1.10
0.1.9
0.1.8
0.1.7
0.1.6
0.1.5
0.1.4
0.1.0
Models the Game of Islands.
Current section
Files
Jump to
Current section
Files
lib/islands/engine/proxy.ex
defmodule Islands.Engine.Proxy do
@moduledoc """
Runs function `GenServer.call` on behalf of module `Islands.Engine`
while providing increased fault-tolerance capability.
"""
alias __MODULE__.{Error, GameNotStarted, Info}
alias IO.ANSI.Plus, as: ANSI
alias Islands.Engine.Game.{Server, Tally}
alias Islands.Engine
@timeout 10
@times 5
@spec call(tuple, String.t()) :: Tally.t() | :ok
def call(request, game_name) do
game_name |> Server.via() |> GenServer.call(request)
catch
:exit, reason ->
Error.log(:exit, reason)
wait_and_call(request, game_name, reason)
end
@spec stop(atom, String.t()) :: :ok
def stop(reason, game_name) do
game_name |> Server.via() |> GenServer.stop(reason)
catch
:exit, exit_reason ->
Error.log(:exit, exit_reason)
wait_and_stop(reason, game_name, exit_reason)
end
## Private functions
@spec wait_and_call(tuple, String.t(), term) :: Tally.t() | :ok
defp wait_and_call(request, game_name, reason) do
game_name |> wait(reason, @times) |> Server.via() |> GenServer.call(request)
catch
:exit, reason ->
Error.log(:exit, reason)
game_name |> GameNotStarted.message() |> ANSI.puts()
end
@spec wait_and_stop(atom, String.t(), term) :: :ok
defp wait_and_stop(reason, game_name, exit_reason) do
game_name
|> wait(exit_reason, @times)
|> Server.via()
|> GenServer.stop(reason)
catch
:exit, exit_reason ->
Error.log(:exit, exit_reason)
game_name |> GameNotStarted.message() |> ANSI.puts()
end
# On restarts, wait if name not yet registered...
@spec wait(String.t(), term, non_neg_integer) :: String.t()
defp wait(game_name, _reason, 0), do: game_name
defp wait(game_name, reason, times_left) do
Info.log(:game_not_registered, game_name, @timeout, times_left, reason)
Process.sleep(@timeout)
case Engine.game_pid(game_name) do
pid when is_pid(pid) ->
Info.log(:game_registered, game_name, pid, times_left, reason)
game_name
nil ->
wait(game_name, reason, times_left - 1)
end
end
end