Extract tracker into supervision tree.

This commit is contained in:
Nathan Walker
2017-04-25 20:45:48 -05:00
parent b71221977c
commit b2dfc28650
4 changed files with 35 additions and 28 deletions

View File

@@ -6,7 +6,8 @@ defmodule ElixirKoans do
import Supervisor.Spec import Supervisor.Spec
children = [ children = [
worker(Display, []) worker(Display, []),
worker(Tracker, [])
] ]
opts = [strategy: :one_for_one, name: ElixirKoans.Supervisor] opts = [strategy: :one_for_one, name: ElixirKoans.Supervisor]

View File

@@ -17,11 +17,13 @@ defmodule Mix.Tasks.Meditate do
Display.disable_clear() Display.disable_clear()
end end
Options.initial_koan modules = Options.initial_koan
|> ok? |> ok?
|> Runner.modules_to_run |> Runner.modules_to_run
|> Tracker.start
|> Runner.run Tracker.set_total(modules)
Runner.run(modules)
if Tracker.complete? do if Tracker.complete? do
Display.congratulate Display.congratulate

View File

@@ -1,22 +1,27 @@
defmodule Tracker do defmodule Tracker do
def start(modules) do alias __MODULE__
total = modules
|> Enum.flat_map(&(&1.all_koans))
|> Enum.count
Agent.start_link(fn -> %{total: total, defstruct total: 0, koans: MapSet.new(), visited_modules: MapSet.new()
koans: MapSet.new(),
visited_modules: MapSet.new()} end, name: __MODULE__) def start_link do
modules Agent.start_link(fn -> %Tracker{} end, name: __MODULE__)
end end
defp get(), do: Agent.get(__MODULE__, &(&1)) def set_total(modules) do
total = modules
|> Enum.flat_map(&(&1.all_koans))
|> Enum.count
Agent.update(__MODULE__, fn _ -> %Tracker{total: total} end)
end
def completed(module, koan) do def completed(module, koan) do
Agent.update(__MODULE__, fn(%{koans: completed, visited_modules: modules} = all) -> Agent.update(__MODULE__, &mark_koan_completed(&1, module, koan))
%{ all | koans: MapSet.put(completed, koan), end
visited_modules: MapSet.put(modules, module)}
end) defp mark_koan_completed(state, module, koan) do
%{state | koans: MapSet.put(state.koans, koan),
visited_modules: MapSet.put(state.visited_modules, module)}
end end
def visited do def visited do
@@ -28,14 +33,13 @@ defmodule Tracker do
total == completed total == completed
end end
def summarize, do: get() |> summarize() def summarize do
defp summarize(%{total: total, state = Agent.get(__MODULE__, &(&1))
koans: completed,
visited_modules: modules}) do
%{ %{
total: total, total: state.total,
current: MapSet.size(completed), current: MapSet.size(state.koans),
visited_modules: MapSet.to_list(modules) visited_modules: MapSet.to_list(state.visited_modules)
} }
end end
end end

View File

@@ -4,25 +4,25 @@ defmodule TrackerTest do
@sample_modules [SampleKoan, PassingKoan] @sample_modules [SampleKoan, PassingKoan]
test "can start" do test "can start" do
Tracker.start(@sample_modules) Tracker.set_total(@sample_modules)
assert Tracker.summarize == %{total: 2, current: 0, visited_modules: []} assert Tracker.summarize == %{total: 2, current: 0, visited_modules: []}
end end
test "can be notified of completed koans" do test "can be notified of completed koans" do
Tracker.start(@sample_modules) Tracker.set_total(@sample_modules)
Tracker.completed(SampleKoan, :"Hi there") Tracker.completed(SampleKoan, :"Hi there")
assert Tracker.summarize == %{total: 2, current: 1, visited_modules: [SampleKoan]} assert Tracker.summarize == %{total: 2, current: 1, visited_modules: [SampleKoan]}
end end
test "multiple comletions of the same koan count only once" do test "multiple comletions of the same koan count only once" do
Tracker.start(@sample_modules) Tracker.set_total(@sample_modules)
Tracker.completed(SampleKoan, :"Hi there") Tracker.completed(SampleKoan, :"Hi there")
Tracker.completed(SampleKoan, :"Hi there") Tracker.completed(SampleKoan, :"Hi there")
assert Tracker.summarize == %{total: 2, current: 1, visited_modules: [SampleKoan]} assert Tracker.summarize == %{total: 2, current: 1, visited_modules: [SampleKoan]}
end end
test "knows when koans are not complete" do test "knows when koans are not complete" do
Tracker.start(@sample_modules) Tracker.set_total(@sample_modules)
refute Tracker.complete? refute Tracker.complete?
end end
end end