Create a riak_core application in Elixir (Part 1)

The 3rd December I talked at NoSlidesConf and as example for my application I create this simple application in Elixir to show some features of riak_core.

After that I decided to write a tutorial about the use of riak_core in Elixir. It is true that it’s very simple to use an Erlang library from an Elixir application, this app is an example, but a lot of examples are in Erlang and a lot of alchemists are not so familiar with Erlang syntax, which is a shame :-(.

In this first post I’ll describe how to create an empty Elixir application that can be started as multiple nodes on the same machine without any functionality. You should wait for the next part to have some useful features :-).

How to start

Riak_core is a library developed by basho, this library was extracted as a stand-alone library from riakKV/riakTS. The repo from basho is not easily usable from Elixir app, but you can check out the code as the “main source”. As an alchemist you are probably familiar with https://hex.pm/ (and if you are not you should :-)), if you search riak_core there you find riak_core_ng that is a fork form the original library, maintained by Heinz N. Gies.

Before starting, some notes about the version of Erlang and Elixir. In all these posts I used Elixir v1.3.4 and Erlang 18.3. In my test I was not able to use Erlang 19 for riak_core. If you check the basho repo and riak_core_ng repo you can see some work to port the libraries to Erlang v19 but, until now, the work is not finished. To manage different versions of Erlang I suggest to use kerl or asdf and, if you want use observer ( and you want use it :-)), I suggest you to build the version of Erlang OTP with wx enabled. You can check here if you are on OSX and here if you are on linux; if you are on other OS, try to google it.

So let’s start, create a new mix application with --sup parameter:

$ mix new no_slides --sup

In this way we have created an empty app, the first thing to do is to add the riak_core to the dependencies as OTP app to start automatically, so in mix.exs file add this lines:

def application do
[applications: [:riak_core, :logger],
mod: {NoSlides, []}]
end
# ...
defp deps do
[
{:riak_core, "~> 2.2.8", hex: :riak_core_ng}
]
end

Remember to insert :riak_core as the first application in application function otherwise some strange things could occur :-D.

After that, as usually, get the dependencies:

$ mix deps.get

and now you can run your first riak_core app, if you do it for example in this way:

$ iex -S mix run

you will get a lot of errors. First of all you should execute the node using the parameter --name <node_name>, I can run it in this way:

$ iex --name gpad@127.0.0.1 -S mix run

In this way I’m running the application with a full name, but if you try, you will get another error. You need to set the schema of your node and some other configurations. You can find the schema in deps/riak_core/priv directory: copy it in your priv directory with this command:

$ cp -r deps/riak_core/priv .

The last thing to do is give to riak_core some info about how manage this node. I suggest to add these lines in file config/config.exs

config :riak_core,
ring_state_dir: 'ring_data_dir',
handoff_port: 8099,
handoff_ip: '127.0.0.1',
schema_dirs: ['priv']
config :sasl,
errlog_type: :error

The config of riak_core is necessary to riak_core to start as single node (we modify a little bit when we will run a multinodes), we tell riak_core where to save all the ring data (cluster configuration), what is the IP/port to manage the handoff and where to find the schema of the config. Last but not least, we tell the sasl application to only print error logs.

Now you should be able to execute a single node riak_core application:

$ iex --name gpad@127.0.0.1 -S mix run

Hooray!!!

Multinodes environment

With riak_core we want create a distributed application, so our application should be executed in some different nodes. When we develop our application it is simpler to run more nodes on the same machine. To do it, it’s necessary to execute every node with some different configuration, and we can achieve this result using the environments support of mix. We identify every node with a different environment and we add a different config file for every environment. In my example I call every env as gpad_1, gpad_2 and gpad_3. I suggest to add three files in config directory called gpad_1.exs, gpad_2.exs and gpad_3.exs. Modify config.exs adding this line to the end of the file:

import_config “#{Mix.env}.exs”

In every new file you should set the config of riak_core in a way that can’t conflict with other nodes that run on the same machine, so we have:

gpad_1.exs

use Mix.Config
config :riak_core,
node: 'gpad_1@127.0.0.1',
web_port: 8198,
handoff_port: 8199,
ring_state_dir: 'ring_data_dir_1',
platform_data_dir: 'data_1'

gpad_2.exs

use Mix.Config
config :riak_core,
node: 'gpad_2@127.0.0.1',
web_port: 8298,
handoff_port: 8299,
ring_state_dir: 'ring_data_dir_2',
platform_data_dir: 'data_2'

gpad_3.exs

use Mix.Config
config :riak_core,
node: 'gpad_3@127.0.0.1',
web_port: 8398,
handoff_port: 8399,
ring_state_dir: 'ring_data_dir_3',
platform_data_dir: 'data_3'

Now you have three different environment and you can start it in three different console, before start remember to use Erlang 18 because we need to recompile the application for the three different environment, so start every line in a different console:

# this is node 1
MIX_ENV=gpad_1 iex --name gpad_1@127.0.0.1 -S mix run
# this is node 2
MIX_ENV=gpad_2 iex --name gpad_2@127.0.0.1 -S mix run
# this is node 3
MIX_ENV=gpad_3 iex --name gpad_3@127.0.0.1 -S mix run

If you want to continue to run a single node as before using command iex --name gpad@127.0.0.1 -S mix run, you should add a file named dev.exs with inside only this line:

use Mix.Config

Now you should be able to run three different node on the same machine.

Good job!!!

In the next post we try to add a simple ping functionality and join the three nodes together.

Before concluding I need to say a lot of “thank you” to:

Stay tuned, see you next time!!!