Current section
Files
Jump to
Current section
Files
lib/failover/primary.ex
defmodule Failover.Primary do
use GenServer
require Logger
def start_link(instance_pid, barrier_path) do
Logger.info("Initializing Primary")
GenServer.start_link(__MODULE__, {instance_pid, barrier_path})
end
def init({instance_pid, barrier_path}) do
Failover.init_state(instance_pid, barrier_path)
end
def handle_cast(:zk_session_ready, state) do
Logger.info("Received go-ahead from zk helper, preparing to start working")
{:ok, state} = prepare_failover(state)
{:noreply, state}
end
def handle_cast(:zk_state_uncertain, state) do
Logger.info("Unsafe to continue working, shutting down")
{:ok, state} = Failover.stop_app(state)
{:stop, :zk_disconnected, state}
end
defp prepare_failover(%{zk_barrier: zk_barrier, barrier_path: barrier_path}=state) do
Logger.info("Attempting to create barrier #{inspect barrier_path}")
res = GenServer.call(zk_barrier, {:create_barrier, barrier_path})
case res do
{:ok, path} ->
Logger.info("Created barrier #{path}, starting primary region")
{:ok, state} = Failover.start_app(state)
{:ok, state}
{:error, reason} ->
# For all the error reasons see:
# https://github.com/huaban/erlzk/blob/master/src/erlzk.erl#L154
#
# The error we will most likely receive is :node_exists.
# This can happen if the instance dies and restarts before the zk
# session expires. In that case the barrier node will still exist
# as the nodes life is tied to the session life.
#
# This can also happen if the primary instance is already running
#
# To handle this we crash and rely on the process manager to restart
# us, hopefully the situation is better on next startup
Logger.info("Failed to create barrier, reason: #{inspect reason}")
{:error, :failed_to_create_barrier, state}
end
end
end