69 lines
1.2 KiB
Elixir
69 lines
1.2 KiB
Elixir
defmodule Todo.Database do
|
|
alias Todo.DatabaseWorker
|
|
use GenServer
|
|
|
|
@db_folder "./persist"
|
|
@num_of_workers 3
|
|
|
|
def start do
|
|
GenServer.start(__MODULE__, nil, name: __MODULE__)
|
|
end
|
|
|
|
def store(key, data) do
|
|
GenServer.cast(__MODULE__, {:store, key, data})
|
|
end
|
|
|
|
def get(key) do
|
|
GenServer.call(__MODULE__, {:get, key})
|
|
end
|
|
|
|
@impl GenServer
|
|
def init(_) do
|
|
IO.puts("Starting #{__MODULE__}")
|
|
|
|
File.mkdir_p!(@db_folder)
|
|
|
|
{:ok, nil, {:continue, :init}}
|
|
end
|
|
|
|
@impl GenServer
|
|
def handle_continue(:init, nil) do
|
|
File.mkdir_p!(@db_folder)
|
|
|
|
workers =
|
|
0..(@num_of_workers - 1)
|
|
|> Enum.map(fn i ->
|
|
{:ok, pid} = Todo.DatabaseWorker.start(@db_folder)
|
|
{i, pid}
|
|
end)
|
|
|> Map.new()
|
|
|
|
{:noreply, workers}
|
|
end
|
|
|
|
@impl GenServer
|
|
def handle_cast({:store, key, data}, workers) do
|
|
workers
|
|
|> choose_worker(key)
|
|
|> DatabaseWorker.store(key, data)
|
|
|
|
{:noreply, workers}
|
|
end
|
|
|
|
@impl GenServer
|
|
def handle_call({:get, key}, _, workers) do
|
|
data =
|
|
workers
|
|
|> choose_worker(key)
|
|
|> DatabaseWorker.get(key)
|
|
|
|
{:reply, data, workers}
|
|
end
|
|
|
|
defp choose_worker(workers, key) do
|
|
id = :erlang.phash2(key, @num_of_workers)
|
|
|
|
Map.fetch!(workers, id)
|
|
end
|
|
end
|