Created
December 6, 2016 07:15
-
-
Save hodak/300c27f54a0a2809b5f7541e878a772c 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 WebDAVWorker do | |
use GenServer | |
# Client | |
def start_link do | |
GenServer.start_link(__MODULE__, []) | |
end | |
def run_action(pid, action_handler, args \\ [], delay \\ 0) do | |
GenServer.call(pid, {:run_action, action_handler, args, delay}) | |
end | |
# Server | |
def handle_call({:run_action, action_handler, args, delay}, from, actions) do | |
Process.send_after(self, :try_running, delay) | |
action = {action_handler, args, from} | |
{:noreply, [action | actions]} | |
end | |
def handle_info(:try_running, []) do | |
{:noreply, []} | |
end | |
def handle_info(:try_running, [{action_handler, _, _} | _] = actions) do | |
relevant_action? = fn({handler, _, _}) -> action_handler == handler end | |
relevant_actions = Enum.filter(actions, relevant_action?) | |
relevant_actions_args = Enum.map(relevant_actions, fn({_, arg, _}) -> arg end) | |
response = action_handler.(relevant_actions_args) | |
Enum.each(relevant_actions, fn({_, _, from}) -> GenServer.reply(from, response) end) | |
{:noreply, Enum.reject(actions, relevant_action?)} | |
end | |
end | |
defmodule WebDAVWorkerTest do | |
use ExUnit.Case | |
alias WebDAVWorker | |
setup do | |
{:ok, pid} = WebDAVWorker.start_link | |
[worker_pid: pid] | |
end | |
test "it runs action and returns its result", %{worker_pid: pid} do | |
action = fn(_) -> :ok end | |
assert :ok == WebDAVWorker.run_action(pid, action) | |
end | |
test "it receives an argument and passes it to handler as a list", %{worker_pid: pid} do | |
action = fn(arg) -> arg end | |
assert [:hodor] == WebDAVWorker.run_action(pid, action, :hodor) | |
end | |
test "it squashes actions and calls handler once with all the arguments", %{worker_pid: pid} do | |
self_pid = self | |
action = fn(args) -> send self_pid, args end | |
Enum.each([:a, :b], fn(arg) -> spawn fn -> WebDAVWorker.run_action(pid, action, arg, 1) end end) | |
assert_receive [:b, :a] | |
end | |
test "it squashes actions with the same handler", %{worker_pid: pid} do | |
self_pid = self | |
h1 = fn(args) -> send self_pid, args end | |
h2 = fn(args) -> send self_pid, args end | |
[{h1, :a}, {h2, :b}, {h1, :c}, {h2, :d}] | |
|> Enum.each(fn({handler, arg}) -> spawn fn -> WebDAVWorker.run_action(pid, handler, arg, 1) end end) | |
assert_receive [:c, :a] | |
assert_receive [:d, :b] | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment