Last active
May 31, 2016 09:09
-
-
Save santosh79/0018d228275da64679bc616d126245e4 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule MigratingProcesses.Manager do | |
use GenServer | |
def start_link do | |
GenServer.start_link __MODULE__, :ok, [name: :migration_manager] | |
end | |
def init(:ok) do | |
Process.flag :trap_exit, true | |
{:ok, %{}} | |
end | |
def start_worker(name) do | |
GenServer.call :migration_manager, {:start_worker, name} | |
end | |
def get_worker(worker_name) do | |
GenServer.call :migration_manager, {:get_worker, worker_name} | |
end | |
def clone_worker(old_worker_name) do | |
GenServer.call :migration_manager, {:clone_worker, old_worker_name} | |
end | |
def handle_cast({:change_state, old_worker_name, new_pid}, state) do | |
new_state = Dict.put(state, old_worker_name, new_pid) | |
{:noreply, new_state} | |
end | |
def handle_call({:clone_worker, old_worker_name}, _from, state) do | |
old_worker_pid = Dict.get old_worker_name | |
new_pid = MigratingProcesses.Worker.clone old_worker_pid | |
Process.link new_pid | |
master = self | |
spawn(fn -> | |
CHANGE_TIME = 5_000 | |
:timer.sleep CHANGE_TIME | |
GenServer.cast master, {:change_state, old_worker_name, new_pid} | |
end) | |
spawn(fn -> | |
CATCHUP_TIME = 10_000 | |
:timer.sleep CATCHUP_TIME | |
GenServer.stop old_worker_pid | |
end) | |
{:reply, :ok, new_state} | |
end | |
def handle_call({:get_worker, worker_name}, _from, state) do | |
worker = Dict.get(state, worker_name} | |
{:reply, worker, state} | |
end | |
def handle_call({:start_worker, name}, _from, state) do | |
{:ok, worker} = MigratingProcesses.Worker.start_link name | |
new_state = Dict.put(state, name, worker) | |
{:reply, :ok, new_state} | |
end | |
end | |
defmodule MigratingProcesses.Worker do | |
use GenServer | |
def start_link(name) do | |
GenServer.start_link __MODULE__, {:ok, name}, [] | |
end | |
def start(name) do | |
GenServer.start __MODULE__, {:ok, name}, [] | |
end | |
def start(_name, state) do | |
GenServer.start __MODULE__, {:ok, :state, state}, [] | |
end | |
def init({:ok, name}) do | |
{:ok, %{name: name}} | |
end | |
def init({:ok, :state, state}) do | |
{:ok, state} | |
end | |
def clone(pid) do | |
GenServer.call pid, :clone | |
end | |
def set(pid, val) do | |
GenServer.call pid, {:set, val} | |
end | |
def get(pid, val) do | |
GenServer.call pid, :get | |
end | |
def handle_call(args, _from, %{stale: true, new_pid: new_pid} = state) do | |
GenServer.call new_pid, args | |
end | |
def handle_call(:clone, _from, state) do | |
{:ok, pid} = MigratingProcesses.Worker.start name, state | |
new_state = Dict.merge(state, %{stale: true, new_pid: pid}) | |
{:reply, pid, new_state} | |
end | |
def handle_call(:get, _from, %{val: val} = state) do | |
{:reply, val, state} | |
end | |
def handle_call({:set, val}, _from, state) do | |
new_state = Dict.put(state, :val, val) | |
{:reply, :ok, new_state} | |
end | |
end | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment