feat: add database workers
parent
a408a38ffb
commit
1550e896a0
|
@ -1,7 +1,9 @@
|
||||||
defmodule Todo.Database do
|
defmodule Todo.Database do
|
||||||
|
alias Todo.DatabaseWorker
|
||||||
use GenServer
|
use GenServer
|
||||||
|
|
||||||
@db_folder "./persist"
|
@db_folder "./persist"
|
||||||
|
@num_of_workers 3
|
||||||
|
|
||||||
def start do
|
def start do
|
||||||
GenServer.start(__MODULE__, nil, name: __MODULE__)
|
GenServer.start(__MODULE__, nil, name: __MODULE__)
|
||||||
|
@ -19,33 +21,47 @@ defmodule Todo.Database do
|
||||||
def init(_) do
|
def init(_) do
|
||||||
File.mkdir_p!(@db_folder)
|
File.mkdir_p!(@db_folder)
|
||||||
|
|
||||||
{:ok, nil}
|
{:ok, nil, {:continue, :init}}
|
||||||
end
|
end
|
||||||
|
|
||||||
@impl GenServer
|
@impl GenServer
|
||||||
def handle_cast({:store, key, data}, state) do
|
def handle_continue(:init, nil) do
|
||||||
key
|
File.mkdir_p!(@db_folder)
|
||||||
|> file_name()
|
|
||||||
|> File.write!(:erlang.term_to_binary(data))
|
|
||||||
|
|
||||||
{:noreply, state}
|
workers =
|
||||||
|
0..(@num_of_workers - 1)
|
||||||
|
|> Enum.map(fn i ->
|
||||||
|
{:ok, pid} = Todo.DatabaseWorker.start(@db_folder)
|
||||||
|
{i, pid}
|
||||||
|
end)
|
||||||
|
|> Map.new()
|
||||||
|
|
||||||
|
IO.inspect(workers)
|
||||||
|
{:noreply, workers}
|
||||||
end
|
end
|
||||||
|
|
||||||
@impl GenServer
|
@impl GenServer
|
||||||
def handle_call({:get, key}, _, state) do
|
def handle_cast({:store, key, data}, workers) do
|
||||||
|
workers
|
||||||
|
|> get_worker(key)
|
||||||
|
|> DatabaseWorker.store(key, data)
|
||||||
|
|
||||||
|
{:noreply, workers}
|
||||||
|
end
|
||||||
|
|
||||||
|
@impl GenServer
|
||||||
|
def handle_call({:get, key}, _, workers) do
|
||||||
data =
|
data =
|
||||||
case File.read(file_name(key)) do
|
workers
|
||||||
{:ok, contents} ->
|
|> get_worker(key)
|
||||||
:erlang.binary_to_term(contents)
|
|> DatabaseWorker.get(key)
|
||||||
|
|
||||||
_ ->
|
{:reply, data, workers}
|
||||||
nil
|
|
||||||
end
|
|
||||||
|
|
||||||
{:reply, data, state}
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def file_name(key) do
|
defp choose_worker(workers, key) do
|
||||||
Path.join(@db_folder, to_string(key))
|
id = :erlang.phash2(key, @num_of_workers)
|
||||||
|
|
||||||
|
Map.fetch!(workers, id)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
defmodule Todo.DatabaseWorker do
|
||||||
|
use GenServer
|
||||||
|
|
||||||
|
def start(db_folder) do
|
||||||
|
GenServer.start(__MODULE__, db_folder)
|
||||||
|
end
|
||||||
|
|
||||||
|
def store(pid, key, data) do
|
||||||
|
GenServer.cast(pid, {:store, key, data})
|
||||||
|
end
|
||||||
|
|
||||||
|
def get(pid, key) do
|
||||||
|
GenServer.call(pid, {:get, key})
|
||||||
|
end
|
||||||
|
|
||||||
|
@impl GenServer
|
||||||
|
def init(db_folder) do
|
||||||
|
{:ok, db_folder}
|
||||||
|
end
|
||||||
|
|
||||||
|
@impl GenServer
|
||||||
|
def handle_cast({:store, key, data}, db_folder) do
|
||||||
|
{db_folder, key}
|
||||||
|
|> file_name()
|
||||||
|
|> File.write!(:erlang.term_to_binary(data))
|
||||||
|
|
||||||
|
{:noreply, db_folder}
|
||||||
|
end
|
||||||
|
|
||||||
|
@impl GenServer
|
||||||
|
def handle_call({:get, key}, _, db_folder) do
|
||||||
|
data =
|
||||||
|
case File.read(file_name({db_folder, key})) do
|
||||||
|
{:ok, contents} ->
|
||||||
|
:erlang.binary_to_term(contents)
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
|
||||||
|
{:reply, data, db_folder}
|
||||||
|
end
|
||||||
|
|
||||||
|
def file_name({db_folder, key}) do
|
||||||
|
Path.join(db_folder, to_string(key))
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
Loading…
Reference in New Issue