From 1550e896a072869fdd966d511ebc68d1b408ae50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moritz=20B=C3=B6hme?= Date: Wed, 7 Aug 2024 00:48:49 +0200 Subject: [PATCH] feat: add database workers --- lib/todo/database.ex | 50 ++++++++++++++++++++++++------------ lib/todo/database_worker.ex | 48 ++++++++++++++++++++++++++++++++++ persist/a | Bin 0 -> 198 bytes 3 files changed, 81 insertions(+), 17 deletions(-) create mode 100644 lib/todo/database_worker.ex create mode 100644 persist/a diff --git a/lib/todo/database.ex b/lib/todo/database.ex index 07862fd..b67dfb8 100644 --- a/lib/todo/database.ex +++ b/lib/todo/database.ex @@ -1,7 +1,9 @@ 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__) @@ -19,33 +21,47 @@ defmodule Todo.Database do def init(_) do File.mkdir_p!(@db_folder) - {:ok, nil} + {:ok, nil, {:continue, :init}} end @impl GenServer - def handle_cast({:store, key, data}, state) do - key - |> file_name() - |> File.write!(:erlang.term_to_binary(data)) + def handle_continue(:init, nil) do + File.mkdir_p!(@db_folder) - {: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 @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 = - case File.read(file_name(key)) do - {:ok, contents} -> - :erlang.binary_to_term(contents) + workers + |> get_worker(key) + |> DatabaseWorker.get(key) - _ -> - nil - end - - {:reply, data, state} + {:reply, data, workers} end - def file_name(key) do - Path.join(@db_folder, to_string(key)) + defp choose_worker(workers, key) do + id = :erlang.phash2(key, @num_of_workers) + + Map.fetch!(workers, id) end end diff --git a/lib/todo/database_worker.ex b/lib/todo/database_worker.ex new file mode 100644 index 0000000..8a2e265 --- /dev/null +++ b/lib/todo/database_worker.ex @@ -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 diff --git a/persist/a b/persist/a new file mode 100644 index 0000000000000000000000000000000000000000..dca63f37477f53429f5e68755f2497b2cc76cffd GIT binary patch literal 198 zcmZ9G!3x4K5JaanrA04-|IwdN4}#!9?_t|rXdq1?U7mHF1L`lMbWBBp>eS1azM0O`kTwNb)FxQ|07EP}dH?_b literal 0 HcmV?d00001