alvises

alvises

Code and patterns for an article about KV store engine with logs, in elixir

Hi everyone,

It has been a while I wanted to write a series of articles on how to implement a working (an simple!) kv store engine using logs and elixir. I’m writing the first article, which it’s an intro of the different concepts and I was thinking to write a first super simple implementation with just one writer (with one log file), one index and a reader.

Since the article is becoming long, I wanted to keep the code as simple as possible to focus on the storage engine. To make it as easy as possible, at the beginning I was thinking force the name of process, and avoiding in general to put the pid argument in the server interface functions, like this:

defmodule LogKV.Index do
  use GenServer

  def start_link([]) do
    GenServer.start_link(__MODULE__, :empty, name: __MODULE__)
  end

  def init(:empty), do: {:ok, %{}}
  
  def update(key, offset, size) do
    GenServer.call(__MODULE__, {:update, key, offset, size})
  end

  def lookup(key) do
    GenServer.call(__MODULE__, {:lookup, key})
  end

  def handle_call({:update, key, offset, size}, _from, index_map) do
    {:reply, :ok, Map.put(index_map, key, {offset, size})}
  end

  def handle_call({:lookup, key}, _from, index_map) do
    {:reply, get_key_offset_size(key, index_map), index_map}
  end

  defp get_key_offset_size(key, index_map) do
    case Map.get(index_map, key) do
      {_offset, _size} = offset_size -> {:ok, offset_size}
      nil -> {:error, :not_found}
    end
  endend

full code with docs here: logkv_articles/lib/logkv/index.ex at 90a980eccc06d2bb55fa8f491de63916ae75d6f3 · alvises/logkv_articles · GitHub

As you can see the update/3 function doesn’t have the pid parameter. This permits me, in the article, to focus more on the functionalities rather then processes. I don’t know if this is considered an anti-pattern, but for sure brings issues with unit testing and running the tests in parallel, since I can’t run multiple processes and can’t specify multiple pids.

I then have another module, the Writer which uses the Index. Having a simple interface with just one index with an harcoded name put me in the easy position to not having to introduce in the code registry etc.. the idea is to bring all this as long as the implementation improves during the different parts.

Can you please tell me what’s your opinion about this? Should I make the code a bit more complicated introducing using Registry and making the code less coupled, or for sake of simplicity of the article I can leave the interface as it is?

If you want to have a better idea of what I’m talking about and take a look at the draft I’m writing, here’s the link: https://www.poeticoding.com/p/31d01f68-f853-48fc-93ad-8c097204af6b/
password to see the page: elixir_forum

Thanks

Alvise

Most Liked

tty

tty

The more common idioms are:

  1. name the process the same as the module if only one such process is expected in a node
  2. the name in provided if several similar processes would run on the same node and you need access to a specific process
  3. have several start_link/start to simplify usage in the console and test

I’ve seen unique process names pulled from sys.config or a database in production code. As long as you are consistent about it.

The benefit of Registry is non-atom names.

Where Next?

Popular in Questions Top

senggen
Erlang/OTP 25 [erts-13.2.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] 15:22:35.803 [error] gen_event {lager_file_backend...
New
Tee
can someone please explain to me how Enum.reduce works with maps
New
Kurisu
For example for a current url like http://localhost:4000/cosmetic/products?_utf8=✓&query=perfume&page=2, I would like to get: ...
New
myronmarston
The Elixir Typespec docs show the following syntax for keyword lists in typespecs: # ... | [key: type] # keyword lists...
New
shahryarjb
Hello, I have map which I want to convert it to string like this: the map: %{last_name: "tavakkoli", name: "shahryar"} the string I ne...
New
mgjohns61585
Could someone help me? I’m making my first elixir program, number guessing game. I can’t figure out how to convert the user’s guess from ...
New
ycv005
I have followed this StackOverflow post to install the specific version of Erlang. And When I am running mix ecto.setup then getting fol...
New
fayddelight
I tried installing elixir 1.11.2 erlang 23.3.4 via asdf in my zsh shell. Enabled the versions locally and globally. When I list them ...
New
script
If I have a string “1000 cfu/ml” . I want to remove the characters and / and space . So the string is like this "1000" What is the ...
New
shijith.k
I am trying to start a new phoenix project with elixir 1.9, but mix phx.new does not work. It says that ** (Mix) The task "phx.new" could...
New

Other popular topics Top

9mm
I am constructing a JSON object (map) and I need to conditionally set a field. I’m trying to write proper elixir-way code… and I’m at a l...
New
sorentwo
Hello! tl;dr Announcing Oban, an Ecto based job processing library with a focus on reliability and historical observability. After spen...
985 43657 311
New
WestKeys
Currently suffering from paralysis by [HTTP client] analysis. This is rather unusual in Elixirland as there tends to be consensus on the ...
New
baxterw3b
Hi guys, i’m new in the Elixir world, and i have to say, that i love it! i’m having some problem to understand anonymous functions with ...
New
greenz1
I have a phoenix application from which a user can download multiple(5-6) files of size 1MB. I couldn’t find anything related to sending ...
New
chrismccord
Phoenix 1.4.0 released Phoenix 1.4 is out! This release ships with exciting new features, most notably with HTTP2 support, improved deve...
688 31194 112
New
grych
Hi folks, Few months ago I have announced the proof-of-concept of the library to manipulate the browsers DOM objects directly from Elixi...
639 52774 488
New
fayddelight
I tried installing elixir 1.11.2 erlang 23.3.4 via asdf in my zsh shell. Enabled the versions locally and globally. When I list them ...
New
jaysoifer
Is there a way to rollback a specific migration and only that one (“skipping” all the other ones)? Would mix ecto.rollback -v 200809061...
New
dogweather
I wrote this comment on r/haskell, and it’s not popular there. :wink: But I think I’m on to something… Haskell reminds me of Java, and e...
New

We're in Beta

About us Mission Statement