elixir-todo-list/lib/todo/database.ex

69 lines
1.2 KiB
Elixir
Raw Normal View History

2024-08-07 00:09:00 +02:00
defmodule Todo.Database do
2024-08-07 00:48:49 +02:00
alias Todo.DatabaseWorker
2024-08-07 00:09:00 +02:00
use GenServer
@db_folder "./persist"
2024-08-07 00:48:49 +02:00
@num_of_workers 3
2024-08-07 00:09:00 +02:00
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
2024-08-07 08:21:57 +02:00
IO.puts("Starting #{__MODULE__}")
2024-08-07 00:09:00 +02:00
File.mkdir_p!(@db_folder)
2024-08-07 00:48:49 +02:00
{:ok, nil, {:continue, :init}}
2024-08-07 00:09:00 +02:00
end
@impl GenServer
2024-08-07 00:48:49 +02:00
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()
2024-08-07 00:09:00 +02:00
2024-08-07 00:48:49 +02:00
{:noreply, workers}
2024-08-07 00:09:00 +02:00
end
@impl GenServer
2024-08-07 00:48:49 +02:00
def handle_cast({:store, key, data}, workers) do
workers
2024-08-07 08:21:57 +02:00
|> choose_worker(key)
2024-08-07 00:48:49 +02:00
|> DatabaseWorker.store(key, data)
{:noreply, workers}
end
2024-08-07 00:09:00 +02:00
2024-08-07 00:48:49 +02:00
@impl GenServer
def handle_call({:get, key}, _, workers) do
data =
workers
2024-08-07 08:21:57 +02:00
|> choose_worker(key)
2024-08-07 00:48:49 +02:00
|> DatabaseWorker.get(key)
2024-08-07 00:09:00 +02:00
2024-08-07 00:48:49 +02:00
{:reply, data, workers}
2024-08-07 00:09:00 +02:00
end
2024-08-07 00:48:49 +02:00
defp choose_worker(workers, key) do
id = :erlang.phash2(key, @num_of_workers)
Map.fetch!(workers, id)
2024-08-07 00:09:00 +02:00
end
end