<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="../assets/xml/rss.xsl" media="all"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Mariano Guerra's Log (Posts about riak)</title><link>http://marianoguerra.org/</link><description></description><atom:link href="http://marianoguerra.org/categories/riak.xml" rel="self" type="application/rss+xml"></atom:link><language>en</language><lastBuildDate>Mon, 18 Nov 2024 17:56:38 GMT</lastBuildDate><generator>Nikola (getnikola.com)</generator><docs>http://blogs.law.harvard.edu/tech/rss</docs><item><title>Multi-Paxos with riak_ensemble Part 2</title><link>http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-2/</link><dc:creator>Mariano Guerra</dc:creator><description>&lt;p&gt;In the &lt;a class="reference external" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-1/"&gt;previous post&lt;/a&gt; I showed how to use riak_ensemble from the interactive
shell, now I will show how to use rebar3 to use riak_ensemble from a real
project.&lt;/p&gt;
&lt;p&gt;This post assumes that you have erlang and rebar3 installed, I'm using erlang
19.3 and rebar3 3.4.3.&lt;/p&gt;
&lt;p&gt;The source code for this post is at &lt;a class="reference external" href="https://github.com/marianoguerra/cadena"&gt;https://github.com/marianoguerra/cadena&lt;/a&gt;
check the commits for the steps.&lt;/p&gt;
&lt;section id="create-project"&gt;
&lt;h2&gt;Create Project&lt;/h2&gt;
&lt;pre class="literal-block"&gt;rebar3 new app name=cadena
cd cadena&lt;/pre&gt;
&lt;p&gt;The project structure should look like this:&lt;/p&gt;
&lt;pre class="literal-block"&gt;.
├── LICENSE
├── README.md
├── rebar.config
└── src
        ├── cadena_app.erl
        ├── cadena.app.src
        └── cadena_sup.erl

1 directory, 6 files&lt;/pre&gt;
&lt;/section&gt;
&lt;section id="configuring-dev-release"&gt;
&lt;h2&gt;Configuring Dev Release&lt;/h2&gt;
&lt;p&gt;We do the following steps, check the links for comments on what's going on for
each step:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://github.com/marianoguerra/cadena/blob/75f04bd2787e45d407d3ff6f64d09040fee6b3e1/rebar.config#L6"&gt;Add Dependencies&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://github.com/marianoguerra/cadena/blob/75f04bd2787e45d407d3ff6f64d09040fee6b3e1/rebar.config#L12"&gt;Configure relx section&lt;/a&gt;&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Add overlay variables file &lt;a class="reference external" href="https://github.com/marianoguerra/cadena/blob/75f04bd2787e45d407d3ff6f64d09040fee6b3e1/config/vars.config"&gt;vars.config&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add &lt;a class="reference external" href="https://github.com/marianoguerra/cadena/blob/75f04bd2787e45d407d3ff6f64d09040fee6b3e1/config/sys.config"&gt;sys.config&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add &lt;a class="reference external" href="https://github.com/marianoguerra/cadena/blob/75f04bd2787e45d407d3ff6f64d09040fee6b3e1/config/vm.args"&gt;vm.args&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Build a release to test that everything is setup correctly:&lt;/p&gt;
&lt;pre class="literal-block"&gt;$ rebar3 release&lt;/pre&gt;
&lt;p&gt;Run the release interactively with a console:&lt;/p&gt;
&lt;pre class="literal-block"&gt;$ _build/default/rel/cadena/bin/cadena console&lt;/pre&gt;
&lt;p&gt;Output (edited and paths redacted for clarity):&lt;/p&gt;
&lt;pre class="literal-block"&gt;Exec: erlexec
        -boot _build/default/rel/cadena/releases/0.1.0/cadena
        -boot_var ERTS_LIB_DIR erts-8.3/../lib
        -mode embedded
        -config    _build/default/rel/cadena/generated.conf/app.1.config
        -args_file _build/default/rel/cadena/generated.conf/vm.1.args
        -vm_args   _build/default/rel/cadena/generated.conf/vm.1.args
        -- console

Root: _build/default/rel/cadena
Erlang/OTP 19 [erts-8.3] [source] [64-bit] [smp:4:4] [async-threads:64]
                      [kernel-poll:true]

18:31:12.150 [info] Application lager started on node 'cadena@127.0.0.1'
18:31:12.151 [info] Application cadena started on node 'cadena@127.0.0.1'
Eshell V8.3  (abort with ^G)
(cadena@127.0.0.1)1&amp;gt;&lt;/pre&gt;
&lt;p&gt;Quit:&lt;/p&gt;
&lt;pre class="literal-block"&gt;(cadena@127.0.0.1)1&amp;gt; q().
ok&lt;/pre&gt;
&lt;p&gt;Non interactive start:&lt;/p&gt;
&lt;pre class="literal-block"&gt;$ _build/default/rel/cadena/bin/cadena start&lt;/pre&gt;
&lt;p&gt;No output is generated if it's started, we can check if it's running by pinging
the application:&lt;/p&gt;
&lt;pre class="literal-block"&gt;$ _build/default/rel/cadena/bin/cadena ping&lt;/pre&gt;
&lt;p&gt;We should get:&lt;/p&gt;
&lt;pre class="literal-block"&gt;pong&lt;/pre&gt;
&lt;p&gt;If we want we can attach a console to the running system:&lt;/p&gt;
&lt;pre class="literal-block"&gt;$ _build/default/rel/cadena/bin/cadena attach&lt;/pre&gt;
&lt;p&gt;Output:&lt;/p&gt;
&lt;pre class="literal-block"&gt;Attaching to /tmp/erl_pipes/cadena@127.0.0.1/erlang.pipe.1 (^D to exit)

(cadena@127.0.0.1)1&amp;gt;&lt;/pre&gt;
&lt;p&gt;If we press Ctrl+d we can dettach the console without stopping the system:&lt;/p&gt;
&lt;pre class="literal-block"&gt;(cadena@127.0.0.1)1&amp;gt; [Quit]&lt;/pre&gt;
&lt;p&gt;We can stop the system whenever we want issuing the stop command:&lt;/p&gt;
&lt;pre class="literal-block"&gt;$ _build/default/rel/cadena/bin/cadena stop&lt;/pre&gt;
&lt;p&gt;Output:&lt;/p&gt;
&lt;pre class="literal-block"&gt;ok&lt;/pre&gt;
&lt;aside class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Use Ctrl+d to exit, if we write &lt;cite&gt;q().&lt;/cite&gt; not only we dettach the
console but we also stop the system!&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;Let's try it.&lt;/p&gt;
&lt;p&gt;Non interactive start:&lt;/p&gt;
&lt;pre class="literal-block"&gt;$ _build/default/rel/cadena/bin/cadena start&lt;/pre&gt;
&lt;p&gt;No output is generated if it's started, we can check if it's running by pinging
the application:&lt;/p&gt;
&lt;pre class="literal-block"&gt;$ _build/default/rel/cadena/bin/cadena ping&lt;/pre&gt;
&lt;p&gt;We should get:&lt;/p&gt;
&lt;pre class="literal-block"&gt;pong&lt;/pre&gt;
&lt;p&gt;If we want we can attach a console to the running system:&lt;/p&gt;
&lt;pre class="literal-block"&gt;$ _build/default/rel/cadena/bin/cadena attach&lt;/pre&gt;
&lt;p&gt;Output:&lt;/p&gt;
&lt;pre class="literal-block"&gt;Attaching to /tmp/erl_pipes/cadena@127.0.0.1/erlang.pipe.1 (^D to exit)

(cadena@127.0.0.1)1&amp;gt;&lt;/pre&gt;
&lt;p&gt;Now let's quit with q():&lt;/p&gt;
&lt;pre class="literal-block"&gt;(cadena@127.0.0.1)1&amp;gt; q().&lt;/pre&gt;
&lt;p&gt;Output:&lt;/p&gt;
&lt;pre class="literal-block"&gt;ok&lt;/pre&gt;
&lt;p&gt;Now let's see if it's alive:&lt;/p&gt;
&lt;pre class="literal-block"&gt;$ _build/default/rel/cadena/bin/cadena ping

Node 'cadena@127.0.0.1' not responding to pings.&lt;/pre&gt;
&lt;p&gt;Be careful with how you quit attached consoles in production systems :)&lt;/p&gt;
&lt;/section&gt;
&lt;section id="configure-prod-and-dev-cluster-releases"&gt;
&lt;h2&gt;Configure Prod and Dev Cluster Releases&lt;/h2&gt;
&lt;section id="building-prod-release"&gt;
&lt;h3&gt;Building Prod Release&lt;/h3&gt;
&lt;p&gt;We start by adding a new section to rebar.config called &lt;a class="reference external" href="https://github.com/marianoguerra/cadena/blob/2acf599320bed53c003cfd266a597acd2488caac/rebar.config#L40"&gt;profiles&lt;/a&gt;, and define
4 profiles that override the default release config with specific values,
let's start by trying the &lt;a class="reference external" href="https://github.com/marianoguerra/cadena/blob/2acf599320bed53c003cfd266a597acd2488caac/rebar.config#L48"&gt;prod profile&lt;/a&gt;, which we will use to create production
releases of the project:&lt;/p&gt;
&lt;pre class="literal-block"&gt;rebar3 as prod release&lt;/pre&gt;
&lt;p&gt;Output:&lt;/p&gt;
&lt;pre class="literal-block"&gt;===&amp;gt; Verifying dependencies...
...
===&amp;gt; Compiling cadena
===&amp;gt; Running cuttlefish schema generator
===&amp;gt; Starting relx build process ...
===&amp;gt; Resolving OTP Applications from directories:
          _build/prod/lib
          erl-19.3/lib
===&amp;gt; Resolved cadena-0.1.0
===&amp;gt; Including Erts from erl-19.3
===&amp;gt; release successfully created!&lt;/pre&gt;
&lt;p&gt;Notice now that we have a new folder in the _build directory:&lt;/p&gt;
&lt;pre class="literal-block"&gt;$ ls -1 _build&lt;/pre&gt;
&lt;p&gt;Output:&lt;/p&gt;
&lt;pre class="literal-block"&gt;default
prod&lt;/pre&gt;
&lt;p&gt;The results of the commands run "as prod" are stored in the prod folder.&lt;/p&gt;
&lt;p&gt;You will notice if you explore the prod/rel/cadena folder that there's a folder
called erts-8.3 (the version may differ if you are using a different erlang
version), that folder is there because of the &lt;cite&gt;include_erts&lt;/cite&gt; option we overrided
in the prod profile.&lt;/p&gt;
&lt;p&gt;This means you can zip the _build/prod/rel/cadena folder, upload it to a server
that doesn't have erlang installed in it and still run your release there.&lt;/p&gt;
&lt;p&gt;This is a good way to be sure that the version running in production is the
same you use in development or at build time in your build server.&lt;/p&gt;
&lt;p&gt;Just be careful with deploying to an operating system too different to the one
you used to create the release becase you may have problems with bindings like
libc or openssl.&lt;/p&gt;
&lt;p&gt;Running it is done as usual, only the path changes:&lt;/p&gt;
&lt;pre class="literal-block"&gt;_build/prod/rel/cadena/bin/cadena console

_build/prod/rel/cadena/bin/cadena start
_build/prod/rel/cadena/bin/cadena ping
_build/prod/rel/cadena/bin/cadena attach
_build/prod/rel/cadena/bin/cadena stop&lt;/pre&gt;
&lt;/section&gt;
&lt;section id="building-dev-cluster-releases"&gt;
&lt;h3&gt;Building Dev Cluster Releases&lt;/h3&gt;
&lt;p&gt;To build a cluster we need at least 3 nodes, that's why the last 3 profiles
are &lt;a class="reference external" href="https://github.com/marianoguerra/cadena/blob/2acf599320bed53c003cfd266a597acd2488caac/rebar.config#L61"&gt;node1&lt;/a&gt;, &lt;a class="reference external" href="https://github.com/marianoguerra/cadena/blob/2acf599320bed53c003cfd266a597acd2488caac/rebar.config#L76"&gt;node2&lt;/a&gt; and &lt;a class="reference external" href="https://github.com/marianoguerra/cadena/blob/2acf599320bed53c003cfd266a597acd2488caac/rebar.config#L80"&gt;node3&lt;/a&gt;, they need to have different node names, for that
we use the overlay var files to override the name of each, that is achieved
on &lt;a class="reference external" href="https://github.com/marianoguerra/cadena/blob/2acf599320bed53c003cfd266a597acd2488caac/config/vars_node1.config"&gt;config/vars_node1.config&lt;/a&gt; for node1,
&lt;a class="reference external" href="https://github.com/marianoguerra/cadena/blob/2acf599320bed53c003cfd266a597acd2488caac/config/vars_node2.config"&gt;config/vars_node2.config&lt;/a&gt; for node2 and
&lt;a class="reference external" href="https://github.com/marianoguerra/cadena/blob/2acf599320bed53c003cfd266a597acd2488caac/config/vars_node3.config"&gt;config/vars_node3.config&lt;/a&gt; for node3.&lt;/p&gt;
&lt;p&gt;Now let's build them:&lt;/p&gt;
&lt;pre class="literal-block"&gt;rebar3 as node1 release
rebar3 as node2 release
rebar3 as node3 release&lt;/pre&gt;
&lt;p&gt;The output for each should be similar to the one for the prod release.&lt;/p&gt;
&lt;p&gt;Now on three different shells start each node:&lt;/p&gt;
&lt;pre class="literal-block"&gt;./_build/node1/rel/cadena/bin/cadena console&lt;/pre&gt;
&lt;p&gt;Check the name of the node in the shell:&lt;/p&gt;
&lt;pre class="literal-block"&gt;(node1@127.0.0.1)1&amp;gt;&lt;/pre&gt;
&lt;p&gt;Do the same for node2 and node3 on different shells:&lt;/p&gt;
&lt;pre class="literal-block"&gt;./_build/node2/rel/cadena/bin/cadena console
./_build/node3/rel/cadena/bin/cadena console&lt;/pre&gt;
&lt;p&gt;You should get respectively:&lt;/p&gt;
&lt;pre class="literal-block"&gt;(node2@127.0.0.1)1&amp;gt;&lt;/pre&gt;
&lt;p&gt;And:&lt;/p&gt;
&lt;pre class="literal-block"&gt;(node3@127.0.0.1)1&amp;gt;&lt;/pre&gt;
&lt;p&gt;In case you don't remember, you can quit with &lt;cite&gt;q().&lt;/cite&gt;&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="joining-the-cluster-together"&gt;
&lt;h2&gt;Joining the Cluster Together&lt;/h2&gt;
&lt;p&gt;Until here we built 3 releases of the same code with slight modifications to
allow running a cluster on one computer, but 3 nodes running doesn't mean
we have a cluster, for that we need to use what we learned in the &lt;a class="reference external" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-1/"&gt;Multi-Paxos with riak_ensemble Part 1&lt;/a&gt; but now on code and not interactively.&lt;/p&gt;
&lt;p&gt;For that we will create a &lt;a class="reference external" href="https://github.com/marianoguerra/cadena/blob/4d44a0b022a7bf7855062d601834f084bafec7f9/src/cadena_console.erl"&gt;cadena_console module&lt;/a&gt; that we will use to make calls
from the outside and trigger actions on each node, the code is similar to the
one presented in &lt;a class="reference external" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-1/"&gt;Multi-Paxos with riak_ensemble Part 1&lt;/a&gt;.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code erlang"&gt;&lt;a id="rest_code_bc5fa069397a4905b09645118f21aa54-1" name="rest_code_bc5fa069397a4905b09645118f21aa54-1" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-2/#rest_code_bc5fa069397a4905b09645118f21aa54-1"&gt;&lt;/a&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nv"&gt;NodeStr&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
&lt;a id="rest_code_bc5fa069397a4905b09645118f21aa54-2" name="rest_code_bc5fa069397a4905b09645118f21aa54-2" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-2/#rest_code_bc5fa069397a4905b09645118f21aa54-2"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c"&gt;% node name comes as a list string, we need it as an atom&lt;/span&gt;
&lt;a id="rest_code_bc5fa069397a4905b09645118f21aa54-3" name="rest_code_bc5fa069397a4905b09645118f21aa54-3" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-2/#rest_code_bc5fa069397a4905b09645118f21aa54-3"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;Node&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;list_to_atom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;NodeStr&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;a id="rest_code_bc5fa069397a4905b09645118f21aa54-4" name="rest_code_bc5fa069397a4905b09645118f21aa54-4" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-2/#rest_code_bc5fa069397a4905b09645118f21aa54-4"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c"&gt;% check that the node exists and is alive&lt;/span&gt;
&lt;a id="rest_code_bc5fa069397a4905b09645118f21aa54-5" name="rest_code_bc5fa069397a4905b09645118f21aa54-5" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-2/#rest_code_bc5fa069397a4905b09645118f21aa54-5"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;net_adm&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nf"&gt;ping&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;Node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;of&lt;/span&gt;
&lt;a id="rest_code_bc5fa069397a4905b09645118f21aa54-6" name="rest_code_bc5fa069397a4905b09645118f21aa54-6" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-2/#rest_code_bc5fa069397a4905b09645118f21aa54-6"&gt;&lt;/a&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c"&gt;% if not, return an error&lt;/span&gt;
&lt;a id="rest_code_bc5fa069397a4905b09645118f21aa54-7" name="rest_code_bc5fa069397a4905b09645118f21aa54-7" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-2/#rest_code_bc5fa069397a4905b09645118f21aa54-7"&gt;&lt;/a&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;pang&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
&lt;a id="rest_code_bc5fa069397a4905b09645118f21aa54-8" name="rest_code_bc5fa069397a4905b09645118f21aa54-8" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-2/#rest_code_bc5fa069397a4905b09645118f21aa54-8"&gt;&lt;/a&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;not_reachable&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;a id="rest_code_bc5fa069397a4905b09645118f21aa54-9" name="rest_code_bc5fa069397a4905b09645118f21aa54-9" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-2/#rest_code_bc5fa069397a4905b09645118f21aa54-9"&gt;&lt;/a&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c"&gt;% if it replies, let's join him passing our node reference&lt;/span&gt;
&lt;a id="rest_code_bc5fa069397a4905b09645118f21aa54-10" name="rest_code_bc5fa069397a4905b09645118f21aa54-10" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-2/#rest_code_bc5fa069397a4905b09645118f21aa54-10"&gt;&lt;/a&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;pong&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
&lt;a id="rest_code_bc5fa069397a4905b09645118f21aa54-11" name="rest_code_bc5fa069397a4905b09645118f21aa54-11" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-2/#rest_code_bc5fa069397a4905b09645118f21aa54-11"&gt;&lt;/a&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nn"&gt;riak_ensemble_manager&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;Node&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;node&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;a id="rest_code_bc5fa069397a4905b09645118f21aa54-12" name="rest_code_bc5fa069397a4905b09645118f21aa54-12" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-2/#rest_code_bc5fa069397a4905b09645118f21aa54-12"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;a id="rest_code_bc5fa069397a4905b09645118f21aa54-13" name="rest_code_bc5fa069397a4905b09645118f21aa54-13" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-2/#rest_code_bc5fa069397a4905b09645118f21aa54-13"&gt;&lt;/a&gt;
&lt;a id="rest_code_bc5fa069397a4905b09645118f21aa54-14" name="rest_code_bc5fa069397a4905b09645118f21aa54-14" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-2/#rest_code_bc5fa069397a4905b09645118f21aa54-14"&gt;&lt;/a&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;([])&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
&lt;a id="rest_code_bc5fa069397a4905b09645118f21aa54-15" name="rest_code_bc5fa069397a4905b09645118f21aa54-15" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-2/#rest_code_bc5fa069397a4905b09645118f21aa54-15"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c"&gt;% enable riak_ensemble_manager&lt;/span&gt;
&lt;a id="rest_code_bc5fa069397a4905b09645118f21aa54-16" name="rest_code_bc5fa069397a4905b09645118f21aa54-16" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-2/#rest_code_bc5fa069397a4905b09645118f21aa54-16"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nn"&gt;riak_ensemble_manager&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nf"&gt;enable&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
&lt;a id="rest_code_bc5fa069397a4905b09645118f21aa54-17" name="rest_code_bc5fa069397a4905b09645118f21aa54-17" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-2/#rest_code_bc5fa069397a4905b09645118f21aa54-17"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c"&gt;% wait until it stabilizes&lt;/span&gt;
&lt;a id="rest_code_bc5fa069397a4905b09645118f21aa54-18" name="rest_code_bc5fa069397a4905b09645118f21aa54-18" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-2/#rest_code_bc5fa069397a4905b09645118f21aa54-18"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;wait_stable&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;
&lt;a id="rest_code_bc5fa069397a4905b09645118f21aa54-19" name="rest_code_bc5fa069397a4905b09645118f21aa54-19" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-2/#rest_code_bc5fa069397a4905b09645118f21aa54-19"&gt;&lt;/a&gt;
&lt;a id="rest_code_bc5fa069397a4905b09645118f21aa54-20" name="rest_code_bc5fa069397a4905b09645118f21aa54-20" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-2/#rest_code_bc5fa069397a4905b09645118f21aa54-20"&gt;&lt;/a&gt;&lt;span class="nf"&gt;cluster_status&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
&lt;a id="rest_code_bc5fa069397a4905b09645118f21aa54-21" name="rest_code_bc5fa069397a4905b09645118f21aa54-21" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-2/#rest_code_bc5fa069397a4905b09645118f21aa54-21"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;riak_ensemble_manager&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nf"&gt;enabled&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;of&lt;/span&gt;
&lt;a id="rest_code_bc5fa069397a4905b09645118f21aa54-22" name="rest_code_bc5fa069397a4905b09645118f21aa54-22" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-2/#rest_code_bc5fa069397a4905b09645118f21aa54-22"&gt;&lt;/a&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;false&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
&lt;a id="rest_code_bc5fa069397a4905b09645118f21aa54-23" name="rest_code_bc5fa069397a4905b09645118f21aa54-23" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-2/#rest_code_bc5fa069397a4905b09645118f21aa54-23"&gt;&lt;/a&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;not_enabled&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;a id="rest_code_bc5fa069397a4905b09645118f21aa54-24" name="rest_code_bc5fa069397a4905b09645118f21aa54-24" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-2/#rest_code_bc5fa069397a4905b09645118f21aa54-24"&gt;&lt;/a&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;true&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
&lt;a id="rest_code_bc5fa069397a4905b09645118f21aa54-25" name="rest_code_bc5fa069397a4905b09645118f21aa54-25" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-2/#rest_code_bc5fa069397a4905b09645118f21aa54-25"&gt;&lt;/a&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nv"&gt;Nodes&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;lists&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nf"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;riak_ensemble_manager&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nf"&gt;cluster&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt;
&lt;a id="rest_code_bc5fa069397a4905b09645118f21aa54-26" name="rest_code_bc5fa069397a4905b09645118f21aa54-26" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-2/#rest_code_bc5fa069397a4905b09645118f21aa54-26"&gt;&lt;/a&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nn"&gt;io&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Nodes in cluster: &lt;/span&gt;&lt;span class="si"&gt;~p~n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,[&lt;/span&gt;&lt;span class="nv"&gt;Nodes&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
&lt;a id="rest_code_bc5fa069397a4905b09645118f21aa54-27" name="rest_code_bc5fa069397a4905b09645118f21aa54-27" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-2/#rest_code_bc5fa069397a4905b09645118f21aa54-27"&gt;&lt;/a&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nv"&gt;LeaderNode&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;riak_ensemble_manager&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nf"&gt;get_leader_pid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
&lt;a id="rest_code_bc5fa069397a4905b09645118f21aa54-28" name="rest_code_bc5fa069397a4905b09645118f21aa54-28" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-2/#rest_code_bc5fa069397a4905b09645118f21aa54-28"&gt;&lt;/a&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nn"&gt;io&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Leader: &lt;/span&gt;&lt;span class="si"&gt;~p~n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,[&lt;/span&gt;&lt;span class="nv"&gt;LeaderNode&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;a id="rest_code_bc5fa069397a4905b09645118f21aa54-29" name="rest_code_bc5fa069397a4905b09645118f21aa54-29" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-2/#rest_code_bc5fa069397a4905b09645118f21aa54-29"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We also need to add the riak_ensemble supervisor to our supervisor tree in &lt;a class="reference external" href="https://github.com/marianoguerra/cadena/blob/4d44a0b022a7bf7855062d601834f084bafec7f9/src/cadena_sup.erl"&gt;cadena_sup&lt;/a&gt;:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code erlang"&gt;&lt;a id="rest_code_018f29100a4d4128a3bd13cf968383b9-1" name="rest_code_018f29100a4d4128a3bd13cf968383b9-1" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-2/#rest_code_018f29100a4d4128a3bd13cf968383b9-1"&gt;&lt;/a&gt;&lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;([])&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
&lt;a id="rest_code_018f29100a4d4128a3bd13cf968383b9-2" name="rest_code_018f29100a4d4128a3bd13cf968383b9-2" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-2/#rest_code_018f29100a4d4128a3bd13cf968383b9-2"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c"&gt;% get the configuration from sys.config&lt;/span&gt;
&lt;a id="rest_code_018f29100a4d4128a3bd13cf968383b9-3" name="rest_code_018f29100a4d4128a3bd13cf968383b9-3" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-2/#rest_code_018f29100a4d4128a3bd13cf968383b9-3"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;DataRoot&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;application&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nf"&gt;get_env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;riak_ensemble&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data_root&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"./data"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;a id="rest_code_018f29100a4d4128a3bd13cf968383b9-4" name="rest_code_018f29100a4d4128a3bd13cf968383b9-4" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-2/#rest_code_018f29100a4d4128a3bd13cf968383b9-4"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c"&gt;% create a unique path for each node to avoid clashes if running more&lt;/span&gt;
&lt;a id="rest_code_018f29100a4d4128a3bd13cf968383b9-5" name="rest_code_018f29100a4d4128a3bd13cf968383b9-5" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-2/#rest_code_018f29100a4d4128a3bd13cf968383b9-5"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c"&gt;% than one node in the same computer&lt;/span&gt;
&lt;a id="rest_code_018f29100a4d4128a3bd13cf968383b9-6" name="rest_code_018f29100a4d4128a3bd13cf968383b9-6" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-2/#rest_code_018f29100a4d4128a3bd13cf968383b9-6"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;NodeDataDir&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;DataRoot&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;atom_to_list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;node&lt;/span&gt;&lt;span class="p"&gt;())),&lt;/span&gt;
&lt;a id="rest_code_018f29100a4d4128a3bd13cf968383b9-7" name="rest_code_018f29100a4d4128a3bd13cf968383b9-7" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-2/#rest_code_018f29100a4d4128a3bd13cf968383b9-7"&gt;&lt;/a&gt;
&lt;a id="rest_code_018f29100a4d4128a3bd13cf968383b9-8" name="rest_code_018f29100a4d4128a3bd13cf968383b9-8" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-2/#rest_code_018f29100a4d4128a3bd13cf968383b9-8"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;Ensemble&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;riak_ensemble_sup&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;a id="rest_code_018f29100a4d4128a3bd13cf968383b9-9" name="rest_code_018f29100a4d4128a3bd13cf968383b9-9" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-2/#rest_code_018f29100a4d4128a3bd13cf968383b9-9"&gt;&lt;/a&gt;&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;riak_ensemble_sup&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;start_link&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;a id="rest_code_018f29100a4d4128a3bd13cf968383b9-10" name="rest_code_018f29100a4d4128a3bd13cf968383b9-10" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-2/#rest_code_018f29100a4d4128a3bd13cf968383b9-10"&gt;&lt;/a&gt;&lt;span class="w"&gt;                 &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;NodeDataDir&lt;/span&gt;&lt;span class="p"&gt;]},&lt;/span&gt;
&lt;a id="rest_code_018f29100a4d4128a3bd13cf968383b9-11" name="rest_code_018f29100a4d4128a3bd13cf968383b9-11" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-2/#rest_code_018f29100a4d4128a3bd13cf968383b9-11"&gt;&lt;/a&gt;&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="n"&gt;permanent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;20000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;supervisor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;riak_ensemble_sup&lt;/span&gt;&lt;span class="p"&gt;]},&lt;/span&gt;
&lt;a id="rest_code_018f29100a4d4128a3bd13cf968383b9-12" name="rest_code_018f29100a4d4128a3bd13cf968383b9-12" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-2/#rest_code_018f29100a4d4128a3bd13cf968383b9-12"&gt;&lt;/a&gt;
&lt;a id="rest_code_018f29100a4d4128a3bd13cf968383b9-13" name="rest_code_018f29100a4d4128a3bd13cf968383b9-13" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-2/#rest_code_018f29100a4d4128a3bd13cf968383b9-13"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;one_for_all&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;Ensemble&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}.&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Before building the dev cluster we need to add the &lt;cite&gt;crypto&lt;/cite&gt; app to &lt;a class="reference external" href="https://github.com/marianoguerra/cadena/blob/4d44a0b022a7bf7855062d601834f084bafec7f9/src/cadena.app.src#L9"&gt;cadena.app.src&lt;/a&gt;
since it's needed by riak_ensemble to create the cluster.&lt;/p&gt;
&lt;p&gt;Now let's build the dev cluster, I created a Makefile to make it simpler:&lt;/p&gt;
&lt;pre class="literal-block"&gt;make devrel&lt;/pre&gt;
&lt;p&gt;On three different shells run one command on each:&lt;/p&gt;
&lt;pre class="literal-block"&gt;make node1-console
make node2-console
make node3-console&lt;/pre&gt;
&lt;p&gt;Let's make an rpc call to enable the riak_ensemble cluster on node1:&lt;/p&gt;
&lt;pre class="literal-block"&gt;./_build/node1/rel/cadena/bin/cadena rpc cadena_console create&lt;/pre&gt;
&lt;p&gt;On node1 you should see something like:&lt;/p&gt;
&lt;pre class="literal-block"&gt;[info] {root,'node1@127.0.0.1'}: Leading&lt;/pre&gt;
&lt;p&gt;Let's join node2 to node1:&lt;/p&gt;
&lt;pre class="literal-block"&gt;./_build/node2/rel/cadena/bin/cadena rpc cadena_console join node1@127.0.0.1&lt;/pre&gt;
&lt;p&gt;On node1 you should see:&lt;/p&gt;
&lt;pre class="literal-block"&gt;[info] join(Vsn): {1,152} :: 'node2@127.0.0.1' :: ['node1@127.0.0.1']&lt;/pre&gt;
&lt;p&gt;On node2:&lt;/p&gt;
&lt;pre class="literal-block"&gt;[info] JOIN: success&lt;/pre&gt;
&lt;p&gt;Finally let's join node3:&lt;/p&gt;
&lt;pre class="literal-block"&gt;./_build/node3/rel/cadena/bin/cadena rpc cadena_console join node1@127.0.0.1&lt;/pre&gt;
&lt;p&gt;Output on node1:&lt;/p&gt;
&lt;pre class="literal-block"&gt;[info] join(Vsn): {1,453} :: 'node3@127.0.0.1' :: ['node1@127.0.0.1','node2@127.0.0.1']&lt;/pre&gt;
&lt;p&gt;On node3:&lt;/p&gt;
&lt;pre class="literal-block"&gt;[info] JOIN: success&lt;/pre&gt;
&lt;p&gt;Let's check that the 3 nodes have the same view of the cluster, let's ask node1
what's the ensemble status:&lt;/p&gt;
&lt;pre class="literal-block"&gt;./_build/node1/rel/cadena/bin/cadena rpc cadena_console ensemble_status&lt;/pre&gt;
&lt;pre class="literal-block"&gt;Nodes in cluster: ['node1@127.0.0.1','node2@127.0.0.1','node3@127.0.0.1']
Leader: 'node1@127.0.0.1'&lt;/pre&gt;
&lt;p&gt;node2:&lt;/p&gt;
&lt;pre class="literal-block"&gt;$ ./_build/node2/rel/cadena/bin/cadena rpc cadena_console ensemble_status&lt;/pre&gt;
&lt;pre class="literal-block"&gt;Nodes in cluster: ['node1@127.0.0.1','node2@127.0.0.1','node3@127.0.0.1']
Leader: 'node1@127.0.0.1'&lt;/pre&gt;
&lt;p&gt;node3:&lt;/p&gt;
&lt;pre class="literal-block"&gt;$ ./_build/node3/rel/cadena/bin/cadena rpc cadena_console ensemble_status&lt;/pre&gt;
&lt;pre class="literal-block"&gt;Nodes in cluster: ['node1@127.0.0.1','node2@127.0.0.1','node3@127.0.0.1']
Leader: 'node1@127.0.0.1'&lt;/pre&gt;
&lt;p&gt;Everything looks right, stop the 3 nodes (&lt;cite&gt;q().&lt;/cite&gt;) and start them again, you
will see that after starting up node1 logs:&lt;/p&gt;
&lt;pre class="literal-block"&gt;[info] {root,'node1@127.0.0.1'}: Leading&lt;/pre&gt;
&lt;p&gt;And if you call ensemble_status on any node you get the same outputs as before,
this means they remember the cluster topology even after restarts.&lt;/p&gt;
&lt;/section&gt;</description><category>erlang</category><category>riak</category><category>riak_ensemble</category><guid>http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-2/</guid><pubDate>Sat, 16 Sep 2017 17:29:18 GMT</pubDate></item><item><title>Multi-Paxos with riak_ensemble Part 1</title><link>http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-1/</link><dc:creator>Mariano Guerra</dc:creator><description>&lt;p&gt;In this post I will do the initial steps to setup a project using riak_ensemble
and use its core APIs, we will do it manually in the shell on purpose, later
(I hope) I will post how to build it properly in code.&lt;/p&gt;
&lt;p&gt;First we create a new project, I'm using erlang 19.3 and rebar3 3.4.3:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code sh"&gt;&lt;a id="rest_code_a7d0d8e347c644c8933d6fbc4a0e0e19-1" name="rest_code_a7d0d8e347c644c8933d6fbc4a0e0e19-1" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-1/#rest_code_a7d0d8e347c644c8933d6fbc4a0e0e19-1"&gt;&lt;/a&gt;rebar3&lt;span class="w"&gt; &lt;/span&gt;new&lt;span class="w"&gt; &lt;/span&gt;app&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;cadena
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Then add riak_ensemble dependency to rebar.config, it should look like this:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code erlang"&gt;&lt;a id="rest_code_2edcc5e061c044449a026788d69d5590-1" name="rest_code_2edcc5e061c044449a026788d69d5590-1" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-1/#rest_code_2edcc5e061c044449a026788d69d5590-1"&gt;&lt;/a&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;erl_opts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;debug_info&lt;/span&gt;&lt;span class="p"&gt;]}.&lt;/span&gt;
&lt;a id="rest_code_2edcc5e061c044449a026788d69d5590-2" name="rest_code_2edcc5e061c044449a026788d69d5590-2" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-1/#rest_code_2edcc5e061c044449a026788d69d5590-2"&gt;&lt;/a&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;deps&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="n"&gt;riak_ensemble_ng&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"2.4.0"&lt;/span&gt;&lt;span class="p"&gt;}]}.&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now on 3 different terminals start 3 erlang nodes:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code sh"&gt;&lt;a id="rest_code_877be0ef124d40308156612e26470dd3-1" name="rest_code_877be0ef124d40308156612e26470dd3-1" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-1/#rest_code_877be0ef124d40308156612e26470dd3-1"&gt;&lt;/a&gt;rebar3&lt;span class="w"&gt; &lt;/span&gt;shell&lt;span class="w"&gt; &lt;/span&gt;--name&lt;span class="w"&gt; &lt;/span&gt;node1@127.0.0.1
&lt;a id="rest_code_877be0ef124d40308156612e26470dd3-2" name="rest_code_877be0ef124d40308156612e26470dd3-2" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-1/#rest_code_877be0ef124d40308156612e26470dd3-2"&gt;&lt;/a&gt;rebar3&lt;span class="w"&gt; &lt;/span&gt;shell&lt;span class="w"&gt; &lt;/span&gt;--name&lt;span class="w"&gt; &lt;/span&gt;node2@127.0.0.1
&lt;a id="rest_code_877be0ef124d40308156612e26470dd3-3" name="rest_code_877be0ef124d40308156612e26470dd3-3" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-1/#rest_code_877be0ef124d40308156612e26470dd3-3"&gt;&lt;/a&gt;rebar3&lt;span class="w"&gt; &lt;/span&gt;shell&lt;span class="w"&gt; &lt;/span&gt;--name&lt;span class="w"&gt; &lt;/span&gt;node3@127.0.0.1
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Run the following in every node:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code erlang"&gt;&lt;a id="rest_code_10902f31ace84b4aae817bff06b3e05e-1" name="rest_code_10902f31ace84b4aae817bff06b3e05e-1" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-1/#rest_code_10902f31ace84b4aae817bff06b3e05e-1"&gt;&lt;/a&gt;&lt;span class="nv"&gt;Timeout&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;a id="rest_code_10902f31ace84b4aae817bff06b3e05e-2" name="rest_code_10902f31ace84b4aae817bff06b3e05e-2" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-1/#rest_code_10902f31ace84b4aae817bff06b3e05e-2"&gt;&lt;/a&gt;&lt;span class="nv"&gt;Ensemble&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;a id="rest_code_10902f31ace84b4aae817bff06b3e05e-3" name="rest_code_10902f31ace84b4aae817bff06b3e05e-3" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-1/#rest_code_10902f31ace84b4aae817bff06b3e05e-3"&gt;&lt;/a&gt;&lt;span class="nv"&gt;K1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="s"&gt;"k1"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;a id="rest_code_10902f31ace84b4aae817bff06b3e05e-4" name="rest_code_10902f31ace84b4aae817bff06b3e05e-4" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-1/#rest_code_10902f31ace84b4aae817bff06b3e05e-4"&gt;&lt;/a&gt;
&lt;a id="rest_code_10902f31ace84b4aae817bff06b3e05e-5" name="rest_code_10902f31ace84b4aae817bff06b3e05e-5" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-1/#rest_code_10902f31ace84b4aae817bff06b3e05e-5"&gt;&lt;/a&gt;&lt;span class="nn"&gt;application&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nf"&gt;set_env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;riak_ensemble&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data_root&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"data/"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;atom_to_list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;node&lt;/span&gt;&lt;span class="p"&gt;())).&lt;/span&gt;
&lt;a id="rest_code_10902f31ace84b4aae817bff06b3e05e-6" name="rest_code_10902f31ace84b4aae817bff06b3e05e-6" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-1/#rest_code_10902f31ace84b4aae817bff06b3e05e-6"&gt;&lt;/a&gt;&lt;span class="nn"&gt;application&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nf"&gt;ensure_all_started&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;riak_ensemble&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We are setting a variable telling riak_ensemble where to store the data for
each node, node1 will store it under &lt;a class="reference external" href="mailto:data/node1@127.0.0.1"&gt;data/node1@127.0.0.1&lt;/a&gt; node2 on &lt;a class="reference external" href="mailto:data/node2@127.0.0.1"&gt;data/node2@127.0.0.1&lt;/a&gt; and node3 on &lt;a class="reference external" href="mailto:data/node3@127.0.0.1"&gt;data/node3@127.0.0.1&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;After that we ensure all apps that riak_ensemble requires to run are started.&lt;/p&gt;
&lt;p&gt;You should see something like this:&lt;/p&gt;
&lt;pre class="literal-block"&gt;ok

18:05:50.548 [info] Application lager started on node 'node1@127.0.0.1'
18:05:50.558 [info] Application riak_ensemble started on node 'node1@127.0.0.1'
{ok,[syntax_tools,compiler,goldrush,lager,riak_ensemble]}&lt;/pre&gt;
&lt;p&gt;Now on node1 run:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code erlang"&gt;&lt;a id="rest_code_0d06743cf4d840a197b0f285027d2a69-1" name="rest_code_0d06743cf4d840a197b0f285027d2a69-1" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-1/#rest_code_0d06743cf4d840a197b0f285027d2a69-1"&gt;&lt;/a&gt;&lt;span class="nn"&gt;riak_ensemble_manager&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nf"&gt;enable&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Output:&lt;/p&gt;
&lt;pre class="literal-block"&gt;ok&lt;/pre&gt;
&lt;p&gt;We start the riak_ensemble_manager in one node only.&lt;/p&gt;
&lt;p&gt;Then on node2 we join node1 and node3:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code erlang"&gt;&lt;a id="rest_code_b93e40ac715448a09af4a2984031f7cf-1" name="rest_code_b93e40ac715448a09af4a2984031f7cf-1" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-1/#rest_code_b93e40ac715448a09af4a2984031f7cf-1"&gt;&lt;/a&gt;&lt;span class="nn"&gt;riak_ensemble_manager&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;'node1@127.0.0.1'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nb"&gt;node&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;
&lt;a id="rest_code_b93e40ac715448a09af4a2984031f7cf-2" name="rest_code_b93e40ac715448a09af4a2984031f7cf-2" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-1/#rest_code_b93e40ac715448a09af4a2984031f7cf-2"&gt;&lt;/a&gt;&lt;span class="nn"&gt;riak_ensemble_manager&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;'node3@127.0.0.1'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nb"&gt;node&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Output on node2:&lt;/p&gt;
&lt;pre class="literal-block"&gt;18:06:39.285 [info] JOIN: success
ok
remote_not_enabled&lt;/pre&gt;
&lt;p&gt;This command also generates output on node1:&lt;/p&gt;
&lt;pre class="literal-block"&gt;18:06:24.008 [info] {root,'node1@127.0.0.1'}: Leading
18:06:39.281 [info] join(Vsn): {1,64} :: 'node2@127.0.0.1' :: ['node1@127.0.0.1']&lt;/pre&gt;
&lt;p&gt;On node3 we join node1 and node2:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code erlang"&gt;&lt;a id="rest_code_d0d9807f333b474eab786c436c00e08f-1" name="rest_code_d0d9807f333b474eab786c436c00e08f-1" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-1/#rest_code_d0d9807f333b474eab786c436c00e08f-1"&gt;&lt;/a&gt;&lt;span class="nn"&gt;riak_ensemble_manager&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;'node1@127.0.0.1'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nb"&gt;node&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;
&lt;a id="rest_code_d0d9807f333b474eab786c436c00e08f-2" name="rest_code_d0d9807f333b474eab786c436c00e08f-2" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-1/#rest_code_d0d9807f333b474eab786c436c00e08f-2"&gt;&lt;/a&gt;&lt;span class="nn"&gt;riak_ensemble_manager&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;'node2@127.0.0.1'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nb"&gt;node&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Output on node 3:&lt;/p&gt;
&lt;pre class="literal-block"&gt;18:07:36.078 [info] JOIN: success
ok&lt;/pre&gt;
&lt;p&gt;Output on node 1:&lt;/p&gt;
&lt;pre class="literal-block"&gt;18:07:36.069 [info] join(Vsn): {1,291} :: 'node3@127.0.0.1' :: ['node1@127.0.0.1','node2@127.0.0.1']
18:07:36.074 [info] join(Vsn): {1,292} :: 'node3@127.0.0.1' :: ['node1@127.0.0.1','node2@127.0.0.1','node3@127.0.0.1']&lt;/pre&gt;
&lt;p&gt;Run this on all nodes:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code erlang"&gt;&lt;a id="rest_code_1d2bf705b6c640ce886e40ee637c26d5-1" name="rest_code_1d2bf705b6c640ce886e40ee637c26d5-1" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-1/#rest_code_1d2bf705b6c640ce886e40ee637c26d5-1"&gt;&lt;/a&gt;&lt;span class="nn"&gt;riak_ensemble_manager&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nf"&gt;check_quorum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;Ensemble&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;Timeout&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;
&lt;a id="rest_code_1d2bf705b6c640ce886e40ee637c26d5-2" name="rest_code_1d2bf705b6c640ce886e40ee637c26d5-2" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-1/#rest_code_1d2bf705b6c640ce886e40ee637c26d5-2"&gt;&lt;/a&gt;&lt;span class="nn"&gt;riak_ensemble_peer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nf"&gt;stable_views&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;Ensemble&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;Timeout&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;
&lt;a id="rest_code_1d2bf705b6c640ce886e40ee637c26d5-3" name="rest_code_1d2bf705b6c640ce886e40ee637c26d5-3" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-1/#rest_code_1d2bf705b6c640ce886e40ee637c26d5-3"&gt;&lt;/a&gt;&lt;span class="nn"&gt;riak_ensemble_manager&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nf"&gt;cluster&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Output:&lt;/p&gt;
&lt;pre class="literal-block"&gt;true
{ok,true}
['node1@127.0.0.1','node2@127.0.0.1','node3@127.0.0.1']&lt;/pre&gt;
&lt;p&gt;Everything seems to be ok, we have a cluster!&lt;/p&gt;
&lt;p&gt;Now we can write something, let's set key "k1" to value "v1" on all nodes using
paxos for consensus.&lt;/p&gt;
&lt;p&gt;On node1 run:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code erlang"&gt;&lt;a id="rest_code_09e94750a96a4bf8839ffa2b9e486757-1" name="rest_code_09e94750a96a4bf8839ffa2b9e486757-1" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-1/#rest_code_09e94750a96a4bf8839ffa2b9e486757-1"&gt;&lt;/a&gt;&lt;span class="nv"&gt;V1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="s"&gt;"v1"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;a id="rest_code_09e94750a96a4bf8839ffa2b9e486757-2" name="rest_code_09e94750a96a4bf8839ffa2b9e486757-2" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-1/#rest_code_09e94750a96a4bf8839ffa2b9e486757-2"&gt;&lt;/a&gt;&lt;span class="nn"&gt;riak_ensemble_client&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nf"&gt;kover&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;node&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;Ensemble&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;K1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;V1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;Timeout&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Output:&lt;/p&gt;
&lt;pre class="literal-block"&gt;{ok,{obj,1,729,&amp;lt;&amp;lt;"k1"&amp;gt;&amp;gt;,&amp;lt;&amp;lt;"v1"&amp;gt;&amp;gt;}}&lt;/pre&gt;
&lt;p&gt;We can check on node2 that the value is available:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code erlang"&gt;&lt;a id="rest_code_ce1bd1e954544157b201e33266bf52bb-1" name="rest_code_ce1bd1e954544157b201e33266bf52bb-1" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-1/#rest_code_ce1bd1e954544157b201e33266bf52bb-1"&gt;&lt;/a&gt;&lt;span class="nn"&gt;riak_ensemble_client&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nf"&gt;kget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;node&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;Ensemble&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;K1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;Timeout&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Output:&lt;/p&gt;
&lt;pre class="literal-block"&gt;{ok,{obj,1,729,&amp;lt;&amp;lt;"k1"&amp;gt;&amp;gt;,&amp;lt;&amp;lt;"v1"&amp;gt;&amp;gt;}}&lt;/pre&gt;
&lt;p&gt;Now we can try a different way to update a value, let's say we want to set a new
value but depending on the current value or only if the current value is set to
something specific, for that we use kmodify, which receives a function and calls
us with the current value and sets the key to the value we return.&lt;/p&gt;
&lt;p&gt;On node3 run:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code erlang"&gt;&lt;a id="rest_code_7a233b4aedca4397bf98e74aa05ab2cf-1" name="rest_code_7a233b4aedca4397bf98e74aa05ab2cf-1" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-1/#rest_code_7a233b4aedca4397bf98e74aa05ab2cf-1"&gt;&lt;/a&gt;&lt;span class="nv"&gt;V2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="s"&gt;"v2"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;a id="rest_code_7a233b4aedca4397bf98e74aa05ab2cf-2" name="rest_code_7a233b4aedca4397bf98e74aa05ab2cf-2" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-1/#rest_code_7a233b4aedca4397bf98e74aa05ab2cf-2"&gt;&lt;/a&gt;&lt;span class="nv"&gt;DefaultVal&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="s"&gt;"v0"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;a id="rest_code_7a233b4aedca4397bf98e74aa05ab2cf-3" name="rest_code_7a233b4aedca4397bf98e74aa05ab2cf-3" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-1/#rest_code_7a233b4aedca4397bf98e74aa05ab2cf-3"&gt;&lt;/a&gt;&lt;span class="nv"&gt;ModifyTimeout&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;a id="rest_code_7a233b4aedca4397bf98e74aa05ab2cf-4" name="rest_code_7a233b4aedca4397bf98e74aa05ab2cf-4" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-1/#rest_code_7a233b4aedca4397bf98e74aa05ab2cf-4"&gt;&lt;/a&gt;
&lt;a id="rest_code_7a233b4aedca4397bf98e74aa05ab2cf-5" name="rest_code_7a233b4aedca4397bf98e74aa05ab2cf-5" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-1/#rest_code_7a233b4aedca4397bf98e74aa05ab2cf-5"&gt;&lt;/a&gt;&lt;span class="nn"&gt;riak_ensemble_peer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nf"&gt;kmodify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;node&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;Ensemble&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;K1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;a id="rest_code_7a233b4aedca4397bf98e74aa05ab2cf-6" name="rest_code_7a233b4aedca4397bf98e74aa05ab2cf-6" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-1/#rest_code_7a233b4aedca4397bf98e74aa05ab2cf-6"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;fun&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nv"&gt;Epoch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;Seq&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;CurVal&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
&lt;a id="rest_code_7a233b4aedca4397bf98e74aa05ab2cf-7" name="rest_code_7a233b4aedca4397bf98e74aa05ab2cf-7" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-1/#rest_code_7a233b4aedca4397bf98e74aa05ab2cf-7"&gt;&lt;/a&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nn"&gt;io&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"CurVal: &lt;/span&gt;&lt;span class="si"&gt;~p&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="si"&gt;~p&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="si"&gt;~p&lt;/span&gt;&lt;span class="s"&gt; to &lt;/span&gt;&lt;span class="si"&gt;~p~n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;Epoch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;Seq&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;CurVal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;V2&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
&lt;a id="rest_code_7a233b4aedca4397bf98e74aa05ab2cf-8" name="rest_code_7a233b4aedca4397bf98e74aa05ab2cf-8" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-1/#rest_code_7a233b4aedca4397bf98e74aa05ab2cf-8"&gt;&lt;/a&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;V2&lt;/span&gt;
&lt;a id="rest_code_7a233b4aedca4397bf98e74aa05ab2cf-9" name="rest_code_7a233b4aedca4397bf98e74aa05ab2cf-9" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-1/#rest_code_7a233b4aedca4397bf98e74aa05ab2cf-9"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;a id="rest_code_7a233b4aedca4397bf98e74aa05ab2cf-10" name="rest_code_7a233b4aedca4397bf98e74aa05ab2cf-10" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-1/#rest_code_7a233b4aedca4397bf98e74aa05ab2cf-10"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;DefaultVal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;ModifyTimeout&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Output on node 3:&lt;/p&gt;
&lt;pre class="literal-block"&gt;{ok,{obj,1,914,&amp;lt;&amp;lt;"k1"&amp;gt;&amp;gt;,&amp;lt;&amp;lt;"v2"&amp;gt;&amp;gt;}}&lt;/pre&gt;
&lt;p&gt;Output on node 1:&lt;/p&gt;
&lt;pre class="literal-block"&gt;CurVal: 1 914 &amp;lt;&amp;lt;"v1"&amp;gt;&amp;gt; to &amp;lt;&amp;lt;"v2"&amp;gt;&amp;gt;&lt;/pre&gt;
&lt;p&gt;The call with a function as parameter was done on node3 but it ran on node1,
that's the advantage of using the Erlang virtual machine to build distributed
systems.&lt;/p&gt;
&lt;p&gt;Now let's check if the value was set on all nodes by checking it on node2:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code erlang"&gt;&lt;a id="rest_code_44547b647d52484f9a75fef31599ecb2-1" name="rest_code_44547b647d52484f9a75fef31599ecb2-1" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-1/#rest_code_44547b647d52484f9a75fef31599ecb2-1"&gt;&lt;/a&gt;&lt;span class="nn"&gt;riak_ensemble_client&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nf"&gt;kget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;node&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;Ensemble&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;K1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;Timeout&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Output:&lt;/p&gt;
&lt;pre class="literal-block"&gt;{ok,{obj,1,914,&amp;lt;&amp;lt;"k1"&amp;gt;&amp;gt;,&amp;lt;&amp;lt;"v2"&amp;gt;&amp;gt;}}&lt;/pre&gt;
&lt;p&gt;Now let's quit on all nodes:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code erlang"&gt;&lt;a id="rest_code_242467bc07cb434e82d1ed577a5f94ef-1" name="rest_code_242467bc07cb434e82d1ed577a5f94ef-1" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-1/#rest_code_242467bc07cb434e82d1ed577a5f94ef-1"&gt;&lt;/a&gt;&lt;span class="nf"&gt;q&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Let's start the cluster again to see if riak_ensemble rememers things, in 3
different terminals run:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code sh"&gt;&lt;a id="rest_code_b4d027c5a25d4bef9845f8d09fbcba7b-1" name="rest_code_b4d027c5a25d4bef9845f8d09fbcba7b-1" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-1/#rest_code_b4d027c5a25d4bef9845f8d09fbcba7b-1"&gt;&lt;/a&gt;rebar3&lt;span class="w"&gt; &lt;/span&gt;shell&lt;span class="w"&gt; &lt;/span&gt;--name&lt;span class="w"&gt; &lt;/span&gt;node1@127.0.0.1
&lt;a id="rest_code_b4d027c5a25d4bef9845f8d09fbcba7b-2" name="rest_code_b4d027c5a25d4bef9845f8d09fbcba7b-2" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-1/#rest_code_b4d027c5a25d4bef9845f8d09fbcba7b-2"&gt;&lt;/a&gt;rebar3&lt;span class="w"&gt; &lt;/span&gt;shell&lt;span class="w"&gt; &lt;/span&gt;--name&lt;span class="w"&gt; &lt;/span&gt;node2@127.0.0.1
&lt;a id="rest_code_b4d027c5a25d4bef9845f8d09fbcba7b-3" name="rest_code_b4d027c5a25d4bef9845f8d09fbcba7b-3" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-1/#rest_code_b4d027c5a25d4bef9845f8d09fbcba7b-3"&gt;&lt;/a&gt;rebar3&lt;span class="w"&gt; &lt;/span&gt;shell&lt;span class="w"&gt; &lt;/span&gt;--name&lt;span class="w"&gt; &lt;/span&gt;node3@127.0.0.1
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;On every node:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code erlang"&gt;&lt;a id="rest_code_c4596e1640c24dba9c9a95c9ff271256-1" name="rest_code_c4596e1640c24dba9c9a95c9ff271256-1" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-1/#rest_code_c4596e1640c24dba9c9a95c9ff271256-1"&gt;&lt;/a&gt;&lt;span class="nv"&gt;Timeout&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;a id="rest_code_c4596e1640c24dba9c9a95c9ff271256-2" name="rest_code_c4596e1640c24dba9c9a95c9ff271256-2" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-1/#rest_code_c4596e1640c24dba9c9a95c9ff271256-2"&gt;&lt;/a&gt;&lt;span class="nv"&gt;Ensemble&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;a id="rest_code_c4596e1640c24dba9c9a95c9ff271256-3" name="rest_code_c4596e1640c24dba9c9a95c9ff271256-3" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-1/#rest_code_c4596e1640c24dba9c9a95c9ff271256-3"&gt;&lt;/a&gt;&lt;span class="nv"&gt;K1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="s"&gt;"k1"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;a id="rest_code_c4596e1640c24dba9c9a95c9ff271256-4" name="rest_code_c4596e1640c24dba9c9a95c9ff271256-4" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-1/#rest_code_c4596e1640c24dba9c9a95c9ff271256-4"&gt;&lt;/a&gt;
&lt;a id="rest_code_c4596e1640c24dba9c9a95c9ff271256-5" name="rest_code_c4596e1640c24dba9c9a95c9ff271256-5" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-1/#rest_code_c4596e1640c24dba9c9a95c9ff271256-5"&gt;&lt;/a&gt;&lt;span class="nn"&gt;application&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nf"&gt;set_env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;riak_ensemble&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data_root&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"data/"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;atom_to_list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;node&lt;/span&gt;&lt;span class="p"&gt;())).&lt;/span&gt;
&lt;a id="rest_code_c4596e1640c24dba9c9a95c9ff271256-6" name="rest_code_c4596e1640c24dba9c9a95c9ff271256-6" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-1/#rest_code_c4596e1640c24dba9c9a95c9ff271256-6"&gt;&lt;/a&gt;&lt;span class="nn"&gt;application&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nf"&gt;ensure_all_started&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;riak_ensemble&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We set the data_root again and start riak_enseble and its dependencies,
after that on node1 we should see:&lt;/p&gt;
&lt;pre class="literal-block"&gt;18:11:55.286 [info] {root,'node1@127.0.0.1'}: Leading&lt;/pre&gt;
&lt;p&gt;Now let's check that the cluster was initialized correctly:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code erlang"&gt;&lt;a id="rest_code_8225d58274fd40ff89f2e54d4eef932c-1" name="rest_code_8225d58274fd40ff89f2e54d4eef932c-1" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-1/#rest_code_8225d58274fd40ff89f2e54d4eef932c-1"&gt;&lt;/a&gt;&lt;span class="nn"&gt;riak_ensemble_manager&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nf"&gt;check_quorum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;Ensemble&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;Timeout&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;
&lt;a id="rest_code_8225d58274fd40ff89f2e54d4eef932c-2" name="rest_code_8225d58274fd40ff89f2e54d4eef932c-2" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-1/#rest_code_8225d58274fd40ff89f2e54d4eef932c-2"&gt;&lt;/a&gt;&lt;span class="nn"&gt;riak_ensemble_peer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nf"&gt;stable_views&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;Ensemble&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;Timeout&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;
&lt;a id="rest_code_8225d58274fd40ff89f2e54d4eef932c-3" name="rest_code_8225d58274fd40ff89f2e54d4eef932c-3" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-1/#rest_code_8225d58274fd40ff89f2e54d4eef932c-3"&gt;&lt;/a&gt;&lt;span class="nn"&gt;riak_ensemble_manager&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nf"&gt;cluster&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Output:&lt;/p&gt;
&lt;pre class="literal-block"&gt;true
{ok,true}
['node1@127.0.0.1','node2@127.0.0.1','node3@127.0.0.1']&lt;/pre&gt;
&lt;p&gt;You can now check on any node you want if the key is still set:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code erlang"&gt;&lt;a id="rest_code_f29dd31f9bc74c43a0a80175afea000e-1" name="rest_code_f29dd31f9bc74c43a0a80175afea000e-1" href="http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-1/#rest_code_f29dd31f9bc74c43a0a80175afea000e-1"&gt;&lt;/a&gt;&lt;span class="nn"&gt;riak_ensemble_client&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nf"&gt;kget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;node&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;Ensemble&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;K1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;Timeout&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Output should be:&lt;/p&gt;
&lt;pre class="literal-block"&gt;{ok,{obj,2,275,&amp;lt;&amp;lt;"k1"&amp;gt;&amp;gt;,&amp;lt;&amp;lt;"v2"&amp;gt;&amp;gt;}}&lt;/pre&gt;
&lt;p&gt;Check the generated files under the data folder:&lt;/p&gt;
&lt;pre class="literal-block"&gt;$ tree data

data
├── node1@127.0.0.1
│   └── ensembles
│       ├── 1394851733385875569783788015140658786474476408261_kv
│       ├── ensemble_facts
│       └── ensemble_facts.backup
├── node2@127.0.0.1
│   └── ensembles
│       ├── ensemble_facts
│       └── ensemble_facts.backup
└── node3@127.0.0.1
    └── ensembles
            ├── ensemble_facts
            └── ensemble_facts.backup

6 directories, 7 files&lt;/pre&gt;
&lt;p&gt;To sum up, we created a project, added riak_ensemble as a dependency, started a
3 node cluster, joined all the nodes, wrote a key with a value, checked that it
was available on all nodes, updated the value with a "compare and swap"
operation, stopped the cluster, started it again and checked that the cluster
was restarted as it was and the value was still there.&lt;/p&gt;</description><category>erlang</category><category>riak</category><category>riak_ensemble</category><guid>http://marianoguerra.org/posts/multi-paxos-with-riak_ensemble-part-1/</guid><pubDate>Thu, 31 Aug 2017 08:55:18 GMT</pubDate></item><item><title>How to build Riak TS (Time Series Database) from Source</title><link>http://marianoguerra.org/posts/how-to-build-riak-ts-time-series-database-from-source/</link><dc:creator>Mariano Guerra</dc:creator><description>&lt;p&gt;To build riak ts we need some basic build tools installed, like compilers and tools.&lt;/p&gt;
&lt;p&gt;On ubuntu/debian an derivatives:&lt;/p&gt;
&lt;pre class="literal-block"&gt;sudo apt-get update
sudo apt-get install build-essential autoconf git libncurses5-dev libssl-dev libpam0g-dev&lt;/pre&gt;
&lt;p&gt;On RHEL, Centos, Oracle Linux and derivatives:&lt;/p&gt;
&lt;pre class="literal-block"&gt;sudo yum update -y
sudo yum groupinstall "Development Tools" -y
sudo yum install openssl-devel ncurses-devel git autoconf pam-devel -y&lt;/pre&gt;
&lt;p&gt;A quick description of each so you can map to your OS:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;build-essential: a group of tools to build stuff (duh!)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;autoconf: needed to build &lt;a class="reference external" href="https://github.com/basho/otp"&gt;basho's erlang OTP version&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;git: to fetch repos&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;libcurses and libssl: to have curses and ssl support on erlang&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;libpam0g-dev: required to compile a riak module (canola)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;not sure about the RHEL equivalent, try pam-devel&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now clone the riak repo:&lt;/p&gt;
&lt;pre class="literal-block"&gt;git clone https://github.com/basho/riak.git
cd riak&lt;/pre&gt;
&lt;p&gt;Checkout the Riak TS tag:&lt;/p&gt;
&lt;pre class="literal-block"&gt;git checkout riak_ts-1.3.0&lt;/pre&gt;
&lt;p&gt;Download and install &lt;a class="reference external" href="https://github.com/kerl/kerl"&gt;kerl&lt;/a&gt; to build the correct erlang OTP version:&lt;/p&gt;
&lt;pre class="literal-block"&gt;mkdir -p ~/bin
wget https://raw.githubusercontent.com/kerl/kerl/master/kerl -O ~/bin/kerl
chmod u+x ~/bin/kerl
export PATH=$PATH:$HOME/bin&lt;/pre&gt;
&lt;p&gt;Build OTP_R16B02_basho10 erlang version (notice that this won't interfere with your local erlang installation, see kerl readme for details):&lt;/p&gt;
&lt;pre class="literal-block"&gt;kerl build git git://github.com/basho/otp.git OTP_R16B02_basho10 R16B02-basho10
mkdir -p ~/soft/erlang-releases/R16B02-basho10
kerl install R16B02-basho10 ~/soft/erlang-releases/R16B02-basho10
. ~/soft/erlang-releases/R16B02-basho10/activate
export PATH=$HOME/soft/erlang-releases/R16B02-basho10/bin:$PATH&lt;/pre&gt;
&lt;p&gt;Now build Riak TS:&lt;/p&gt;
&lt;pre class="literal-block"&gt;make locked-deps
make rel&lt;/pre&gt;
&lt;p&gt;And run it:&lt;/p&gt;
&lt;pre class="literal-block"&gt;cd rel/riak
./bin/riak console&lt;/pre&gt;</description><category>build</category><category>compile</category><category>howto</category><category>riak</category><guid>http://marianoguerra.org/posts/how-to-build-riak-ts-time-series-database-from-source/</guid><pubDate>Fri, 03 Jun 2016 15:31:45 GMT</pubDate></item></channel></rss>