<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Mario Mazo</title>
    <description>The latest articles on DEV Community by Mario Mazo (@mariomazo).</description>
    <link>https://dev.to/mariomazo</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F100108%2F1c217cdb-ce37-4c45-874b-7e48f0753fb5.jpeg</url>
      <title>DEV Community: Mario Mazo</title>
      <link>https://dev.to/mariomazo</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mariomazo"/>
    <language>en</language>
    <item>
      <title>Kinesis Advantage for elixir and ruby developers</title>
      <dc:creator>Mario Mazo</dc:creator>
      <pubDate>Mon, 18 Jan 2021 22:03:41 +0000</pubDate>
      <link>https://dev.to/mariomazo/kinesis-advantage-for-elixir-and-ruby-developers-cmc</link>
      <guid>https://dev.to/mariomazo/kinesis-advantage-for-elixir-and-ruby-developers-cmc</guid>
      <description>&lt;h1&gt;
  
  
  Keyboard remapping for elixir and ruby development on doom emacs or vim
&lt;/h1&gt;

&lt;p&gt;I got the &lt;code&gt;kinesis advantage 2&lt;/code&gt; keyboard some time ago I have to say is money well spent. My wrist pain is now minimal. As I spend my days doing &lt;code&gt;go&lt;/code&gt; and &lt;code&gt;elixir&lt;/code&gt; I have fine tuned my keyboard to increase my productivity. Here I will share the layout I use while developing in elixir using &lt;code&gt;doom emacs&lt;/code&gt;. But all the information here might as well apply to &lt;code&gt;ruby&lt;/code&gt; and &lt;code&gt;vim&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For this I have create a layer named &lt;code&gt;e_querty.txt&lt;/code&gt; that way all I have to do is &lt;code&gt;Progm+e&lt;/code&gt; to switch to &lt;em&gt;elixir&lt;/em&gt; mode. The layer looks as follows:&lt;/p&gt;

&lt;h2&gt;
  
  
  thumb keys layout
&lt;/h2&gt;

&lt;p&gt;I use a Mac so Im using the mac naming for the keys but you get the idea.&lt;/p&gt;

&lt;p&gt;So I replicated &lt;code&gt;Ctrl&lt;/code&gt;, &lt;code&gt;Option&lt;/code&gt;, &lt;code&gt;Command&lt;/code&gt; and &lt;code&gt;Shift&lt;/code&gt; on both sides of the keyboard because as a &lt;em&gt;doom emacs&lt;/em&gt; user with evil mode (vim style navigation) I need to have access to all letters and symbols while pressing Ctrl, Shift etc. and having them in only one side made some combos really hard to execute.&lt;br&gt;
So at the end the thumbkeys look as the on the following picture&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--c6e0vhRI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/kt29wckwgja9d2gpe2ao.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--c6e0vhRI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/kt29wckwgja9d2gpe2ao.png" alt="kinesis 2 mappings" width="880" height="450"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Key remapping
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Numbers
&lt;/h3&gt;

&lt;p&gt;So as I rarely use numbers in my normal workflow I decided to &lt;em&gt;invert&lt;/em&gt; the numbers into the symbols (Shift+) to speed up navigation in emacs/vim. When I need a number I can use &lt;code&gt;Shift+&amp;lt;symbol&amp;gt;&lt;/code&gt; to get the number.&lt;/p&gt;
&lt;h3&gt;
  
  
  Other keys
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Since elixir is snake case I inverted &lt;code&gt;-&lt;/code&gt; so now by default I get &lt;code&gt;_&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;|&lt;/code&gt; is way more used than &lt;code&gt;\&lt;/code&gt; so also inverted those.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;:&lt;/code&gt; is more used than &lt;code&gt;;&lt;/code&gt; so inverted as well&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;"&lt;/code&gt; more used than &lt;code&gt;'&lt;/code&gt;... inverted&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Esc&lt;/code&gt; replaced &lt;code&gt;CapsLock&lt;/code&gt; for easy escaping&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Layout file
&lt;/h3&gt;

&lt;p&gt;Here is my &lt;code&gt;e_qwerty.txt&lt;/code&gt; just drop it in you keyboards &lt;code&gt;active&lt;/code&gt; directory and you will get the mapping&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[scroll]&amp;gt;[shutdn]
{1}&amp;gt;{speed5}{-rshift}{1}{+rshift}
{rshift}{1}&amp;gt;{speed5}{1}
{lshift}{1}&amp;gt;{speed5}{1}
{2}&amp;gt;{speed5}{-rshift}{2}{+rshift}
{rshift}{2}&amp;gt;{speed5}{2}
{lshift}{2}&amp;gt;{speed5}{2}
{3}&amp;gt;{speed5}{-rshift}{3}{+rshift}
{rshift}{3}&amp;gt;{speed5}{3}
{lshift}{3}&amp;gt;{speed5}{3}
{4}&amp;gt;{speed5}{-rshift}{4}{+rshift}
{rshift}{4}&amp;gt;{speed5}{4}
{lshift}{4}&amp;gt;{speed5}{4}
{5}&amp;gt;{speed5}{-rshift}{5}{+rshift}
{rshift}{5}&amp;gt;{speed5}{5}
{lshift}{5}&amp;gt;{speed5}{5}
{6}&amp;gt;{speed5}{-lshift}{6}{+lshift}
{rshift}{6}&amp;gt;{speed5}{6}
{lshift}{6}&amp;gt;{speed5}{6}
{7}&amp;gt;{speed5}{-lshift}{7}{+lshift}
{rshift}{7}&amp;gt;{speed5}{7}
{lshift}{7}&amp;gt;{speed5}{7}
{8}&amp;gt;{speed5}{-lshift}{8}{+lshift}
{rshift}{8}&amp;gt;{speed5}{8}
{lshift}{8}&amp;gt;{speed5}{8}
{9}&amp;gt;{speed5}{-lshift}{9}{+lshift}
{rshift}{9}&amp;gt;{speed5}{9}
{lshift}{9}&amp;gt;{speed5}{9}
{0}&amp;gt;{speed5}{-lshift}{0}{+lshift}
{rshift}{0}&amp;gt;{speed5}{0}
{lshift}{0}&amp;gt;{speed5}{0}
{hyphen}&amp;gt;{speed5}{-lshift}{hyphen}{+lshift}
{lshift}{hyphen}&amp;gt;{speed5}{hyphen}
{rshift}{hyphen}&amp;gt;{speed5}{hyphen}
{\}&amp;gt;{speed5}{-lshift}{\}{+lshift}
{lshift}{\}&amp;gt;{speed5}{\}
{rshift}{\}&amp;gt;{speed5}{\}
[caps]&amp;gt;[escape]
[lctrl]&amp;gt;[lwin]
[rwin]&amp;gt;[lalt]
[rctrl]&amp;gt;[rwin]
{;}&amp;gt;{speed5}{-lshift}{;}{+lshift}
{rshift}{;}&amp;gt;{speed5}{;}
{lshift}{;}&amp;gt;{speed5}{;}
{'}&amp;gt;{speed5}{-lshift}{'}{+lshift}
{lshift}{'}&amp;gt;{speed5}{'}
{rshift}{'}&amp;gt;{speed5}{'}
[home]&amp;gt;[rctrl]
[pup]&amp;gt;[rctrl]
[end]&amp;gt;[lshift]
[pdown]&amp;gt;[rshift]
[kp-lctrl]&amp;gt;[lwin]
[kp-rwin]&amp;gt;[rctrl]
[kp-rctrl]&amp;gt;[rwin]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  closing remarks
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;why 4 shifts? no idea I have no use for those "external" shifts so I keep them there&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Got some tips for the kinesis advantage, emacs/vim or elixir/ruby productivity? just comment&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>keyboard</category>
      <category>productivity</category>
      <category>emacs</category>
      <category>vim</category>
    </item>
    <item>
      <title>Elixir and DooM Emacs</title>
      <dc:creator>Mario Mazo</dc:creator>
      <pubDate>Fri, 15 Jan 2021 20:14:29 +0000</pubDate>
      <link>https://dev.to/mariomazo/elixir-and-doom-emacs-m29</link>
      <guid>https://dev.to/mariomazo/elixir-and-doom-emacs-m29</guid>
      <description>&lt;h1&gt;
  
  
  Genesis
&lt;/h1&gt;

&lt;p&gt;Recently I gave up on configuring &lt;code&gt;vim&lt;/code&gt; and &lt;code&gt;spacevim&lt;/code&gt; over and over, and I decided to try emacs... a piece of tech I have avoided for over 20 years. My goal was to have something that worked out of the box, with all the nice stuff that vim provides. After some searching I found &lt;a href="https://github.com/hlissner/doom-emacs"&gt;doom emacs&lt;/a&gt; so I installed emacs for the first time in my live in my 20+ years of *nix, ops and programming career.&lt;/p&gt;

&lt;p&gt;So first things first; &lt;code&gt;doom emacs&lt;/code&gt; is freaking amazing, now I feel bad for all the time I wasted tuning vim and vscode, with doom 99% of the things worked out of the box, some minor relearning was needed, but was some &lt;em&gt;love at first sight&lt;/em&gt; kind of thing, only thing left was having full integration with my favourite programming language &lt;a href="https://github.com/hlissner/doom-emacs"&gt;elixir&lt;/a&gt; to have a nice IDE like experience&lt;/p&gt;

&lt;h1&gt;
  
  
  Nice soap opera dude! Where is the elixir-ls part?
&lt;/h1&gt;

&lt;p&gt;So I began reading how to integrate elixir and I found a lot of tutorials but seems like doom moves fast and almost of all them were outdated, did not work and were quite long. So here is they simplest way i have found to integrate &lt;a href="https://github.com/elixir-lsp/elixir-ls"&gt;elixir-ls&lt;/a&gt; with doom emacs and turned out it was super simple.&lt;/p&gt;

&lt;h1&gt;
  
  
  Elixir-ls in doom emacs
&lt;/h1&gt;

&lt;h2&gt;
  
  
  install elixir-ls
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone https://github.com/elixir-lsp/elixir-ls.git ~/.elixir-ls
cd ~/.elixir-ls
mix deps.get
MIX_ENV=prod mix compile
MIX_ENV=prod mix elixir_ls.release -o release
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  add elixir-ls to your path
&lt;/h2&gt;

&lt;p&gt;Add elixir-ls to your &lt;code&gt;PATH&lt;/code&gt;&lt;br&gt;
in your shell rc, in my case &lt;code&gt;.bashrc&lt;/code&gt; or &lt;code&gt;.zshrc&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export PATH=$PATH:$HOME/.elixir-ls/release
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  add your env variables to doom
&lt;/h2&gt;

&lt;p&gt;I use a mac so the &lt;code&gt;emacs.app&lt;/code&gt; starts isolated and the &lt;code&gt;PATH&lt;/code&gt; is not the same as the one in your shell. Also i almost never start emacs from the command line so the path to the elixir-ls has to be in your doom &lt;code&gt;env&lt;/code&gt; variables&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/.emacs.d/bin/doom env
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;you can validate that the &lt;code&gt;elixir-ls&lt;/code&gt; path is in &lt;code&gt;~/.emacs.d/.local/env&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  activite lsp and elixir with lsp support
&lt;/h2&gt;

&lt;p&gt;In the &lt;code&gt;config.el&lt;/code&gt; uncomment &lt;code&gt;lsp&lt;/code&gt;, &lt;code&gt;tree-sitter&lt;/code&gt; and replace &lt;code&gt;elixir&lt;/code&gt; as follows&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight common_lisp"&gt;&lt;code&gt;&lt;span class="nv"&gt;tree-sitter&lt;/span&gt;
&lt;span class="nv"&gt;lsp&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;elixir&lt;/span&gt; &lt;span class="nv"&gt;+lsp&lt;/span&gt; &lt;span class="nv"&gt;+tree-sitter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  sync doom
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/.emacs.d/bin/doom sync
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;restart emacs... profit&lt;br&gt;
you should see a little 🚀 (rocket) in your status bar that means is connected to the lsp server, and you get auto-complete and all other good stuff.&lt;/p&gt;

&lt;h2&gt;
  
  
  troubleshooting
&lt;/h2&gt;

&lt;p&gt;you can use &lt;code&gt;SPC b B&lt;/code&gt; and search for a buffer &lt;code&gt;*lsp-log*&lt;/code&gt; to see error messages&lt;/p&gt;

&lt;h1&gt;
  
  
  Closing notes
&lt;/h1&gt;

&lt;p&gt;This gives the basic set up to start working, you can customize the &lt;code&gt;lsp&lt;/code&gt; with &lt;code&gt;lsp-ui&lt;/code&gt; but I dont know how and Im not that interested in fine tuning every single piece of it. This is enough to get me up and running.&lt;/p&gt;

&lt;p&gt;Also make sure you keep your elixir-ls up to date. And if you have multiple &lt;code&gt;erlang/OTP&lt;/code&gt; versions is very likely you will need a compiled elixir-lsp to each specific version.&lt;/p&gt;

&lt;p&gt;If you know useful cool tricks for doom+elixir please do share them! Im kind of new in this :D&lt;/p&gt;

</description>
      <category>elixir</category>
      <category>emacs</category>
      <category>doomemacs</category>
    </item>
    <item>
      <title>Mutual exclusion using go and consul</title>
      <dc:creator>Mario Mazo</dc:creator>
      <pubDate>Thu, 13 Sep 2018 09:38:11 +0000</pubDate>
      <link>https://dev.to/mariomazo/mutual-exclusion-using-go-and-consul-4gf6</link>
      <guid>https://dev.to/mariomazo/mutual-exclusion-using-go-and-consul-4gf6</guid>
      <description>&lt;h1&gt;
  
  
  Mutually exclusive workers using golang and consul
&lt;/h1&gt;

&lt;p&gt;Implementing mutually exclusive workers is fun and useful. In this post I will show how to do a naive implementation (DO NOT use this in production) of this pattern using client side &lt;a href="https://www.consul.io/docs/guides/leader-election.html" rel="noopener noreferrer"&gt;leader election&lt;/a&gt; with consul.&lt;/p&gt;

&lt;p&gt;The reason I chose consul for this task is because it was already available in our infrastructure, but the same could be achieved with different tools, for example &lt;code&gt;AWS dynamoDB&lt;/code&gt;. Basically you just need a &lt;code&gt;Key-Value&lt;/code&gt; store that support locks.&lt;/p&gt;

&lt;p&gt;All the code snippets in the post are taken from a &lt;a href="https://github.com/mario-mazo/mutual-exclusion-consul" rel="noopener noreferrer"&gt;sample github repo&lt;/a&gt; where you can find the full implementation.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;We had a &lt;code&gt;job&lt;/code&gt; server that each hour would connect to a postgreSQL database read some tasks then it would proceed the execute the tasks created in the last hour, and then it would write back to the database if the task was succefully finished.&lt;/p&gt;

&lt;p&gt;The problem with this is that it doesn't scale. The jobs began to take longer and longer and if machine crashed all tasks were not executed&lt;/p&gt;

&lt;h2&gt;
  
  
  The solution - Mutually exclusive workers (Distributed Locks)
&lt;/h2&gt;

&lt;p&gt;We knew we needed to run multiple instances of the job server. But each task could only be executed once. So we decided to use &lt;code&gt;distributed locks&lt;/code&gt; with &lt;code&gt;consul&lt;/code&gt;. After a quick search we realized that implenting the &lt;a href="https://www.consul.io/docs/guides/leader-election.html" rel="noopener noreferrer"&gt;leader election&lt;/a&gt; &lt;em&gt;algorithm&lt;/em&gt; was the best solution for us.&lt;/p&gt;

&lt;p&gt;So the whole concept is quite simple. All job servers get a list of tasks to be executed, then they iterate over the tasks list, get a &lt;code&gt;lock&lt;/code&gt; on the task&lt;br&gt;
so all other job servers skip that task, and move on to the next task. This way we can have multiple nodes working at the same all working on different tasks.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fmario-mazo%2Fmutual-exclusion-consul%2Fmaster%2Fassets%2Fmutual-exclusion.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fmario-mazo%2Fmutual-exclusion-consul%2Fmaster%2Fassets%2Fmutual-exclusion.jpg" title="architecture" alt="Architecture"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the image we see that &lt;code&gt;serverA&lt;/code&gt; locks &lt;code&gt;task1&lt;/code&gt; and &lt;em&gt;executes&lt;/em&gt; the task sending it down that pipe with a solid arrow. &lt;code&gt;ServerB&lt;/code&gt; and &lt;code&gt;ServerC&lt;/code&gt; have dashed arrows what I mean is that &lt;code&gt;task1&lt;/code&gt; could not be executed by those 2 servers. Later on &lt;code&gt;serverB&lt;/code&gt; would lock another task and so on.&lt;/p&gt;
&lt;h3&gt;
  
  
  Client side leader election
&lt;/h3&gt;

&lt;p&gt;The &lt;a href="https://www.consul.io/docs/guides/leader-election.html" rel="noopener noreferrer"&gt;leader election&lt;/a&gt; &lt;em&gt;algorithm&lt;/em&gt; is quite simple its just two steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a session in consul&lt;/li&gt;
&lt;li&gt;Try to put a &lt;code&gt;Lock&lt;/code&gt; on that session. If you succeed you are &lt;code&gt;leader&lt;/code&gt; if not... well you are not &lt;code&gt;leader&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
  
  
  &lt;em&gt;Step 1:&lt;/em&gt; Creating the session
&lt;/h4&gt;

&lt;p&gt;First we will create a small wrapper function around the session creation. So&lt;br&gt;
we always create a session no matter if we can work on a specific task or not.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ec&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;exclusiveWorker&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;createSession&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;sessinConf&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SessionEntry&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;TTL&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;      &lt;span class="n"&gt;ec&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sessionTimeout&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;Behavior&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"delete"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;sessionID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;ec&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Session&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sessinConf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"sessionID:"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sessionID&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;ec&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sessionID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sessionID&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We will pass to configuration parameters to the &lt;a href="https://github.com/hashicorp/consul/api" rel="noopener noreferrer"&gt;go consul client&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;TTL&lt;/code&gt;: This is the time out for the session. After this time has passed, consul will execute the &lt;em&gt;behavior&lt;/em&gt;. I have set &lt;code&gt;15s&lt;/code&gt;for this example&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;Behavior&lt;/code&gt;: This &lt;code&gt;delete&lt;/code&gt; behavior means that after the TTL has been reached the session is deleted and the Key associated with it&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you want to better understand how &lt;code&gt;behaviors&lt;/code&gt; work please read the official &lt;a href="https://www.consul.io/docs/internals/sessions.html" rel="noopener noreferrer"&gt;consul sessions&lt;/a&gt; documentation. But the main take is this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If the release behavior is being used, any of the locks held in association with the session are released, and the ModifyIndex of the key is incremented. Alternatively, if the delete behavior is used, the key corresponding to any of the held locks is simply deleted. This can be used to create ephemeral entries that are automatically deleted by Consul.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  &lt;em&gt;Step 2:&lt;/em&gt; Acquire the session
&lt;/h4&gt;

&lt;p&gt;Once we have a session we try to aquire the session. If we succed put a &lt;code&gt;Lock&lt;/code&gt; on it and return &lt;em&gt;success&lt;/em&gt;. We are leaders. If we failt to acquire the lock it means that the &lt;em&gt;task&lt;/em&gt; is already being executed by another server. Here is were the mutual exlusitivy happens.&lt;/p&gt;

&lt;p&gt;Again we are going to wrap this in a simple funcion for easy handling&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ec&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;exclusiveWorker&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;acquireSession&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;KVpair&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;KVPair&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Key&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;     &lt;span class="n"&gt;ec&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;   &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ec&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sessionID&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;Session&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ec&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sessionID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;aquired&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;ec&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;KV&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Acquire&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;KVpair&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;aquired&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We are going to need to pass 3 values to the consul client&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Key&lt;/code&gt;: This is the indentifier of the tasks. To follow conventions I chose &lt;code&gt;service/&amp;lt;TASK_NAME&amp;gt;/leader&lt;/code&gt; but could be anything that better fit your needs. I really thought about using &lt;code&gt;service/&amp;lt;APP_NAME&amp;gt;/&amp;lt;TASK_NAME&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Value&lt;/code&gt;: This is really unimportant when you are using consul for distributed locks. I chose the current &lt;code&gt;sessionID&lt;/code&gt; (which is nothing but an UUID) for easy debugging. But could well be &lt;code&gt;rambo&lt;/code&gt; or &lt;code&gt;goku&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Session&lt;/code&gt;: is the ID of the session we are going to try to &lt;em&gt;Lock&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;em&gt;Step 3:&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;There is no step 3. That's all is there for the leader election part. But we still need a couple of helper functions we are going to need to make this work in a more realistic way.&lt;/p&gt;

&lt;h4&gt;
  
  
  Destroy session
&lt;/h4&gt;

&lt;p&gt;Once our task is done we have to be nice and release the lock. We could wait for the &lt;code&gt;TTL&lt;/code&gt; and &lt;code&gt;beahvior&lt;/code&gt; to kick in, but that's not nice. So let's implement&lt;br&gt;
a basic destroy session function we can call when our task is finished, and all we need is the sessionID.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ec&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;exclusiveWorker&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;destroySession&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;ec&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Session&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Destroy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ec&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sessionID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;erroMsg&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ERROR cannot delete key %s: %s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ec&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;erroMsg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Renew session
&lt;/h4&gt;

&lt;p&gt;If the tasks is taking more than the &lt;code&gt;TTL&lt;/code&gt; the session and key are deleted by the &lt;code&gt;behavior&lt;/code&gt;. If this happens a different server could lock exactly the same task and you would execute 2 times the same task which is what we are trying to avoid.&lt;/p&gt;

&lt;p&gt;So we need to renew the session constanly to avoid triggering the &lt;code&gt;behavior&lt;/code&gt;. The consul client comes with a handy function &lt;code&gt;RenewPeriodic()&lt;/code&gt; that does exactly that. So lets write the wrapper:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ec&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;exclusiveWorker&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;renewSession&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;doneChan&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="k"&gt;chan&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;ec&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Session&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RenewPeriodic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ec&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sessionTimeout&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ec&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sessionID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;doneChan&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we need 3 things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;sessionTimeout&lt;/code&gt;: This is the original &lt;code&gt;TTL&lt;/code&gt;. The client will use this to refresh the session each &lt;code&gt;TTL/2&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sessionID&lt;/code&gt;: Id of the session we want to renew&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;doneChan&lt;/code&gt;: Is a channel we use the signal that we need to keep renewing the session or if we close the channel we mean that we are done with the task and we don't need to renew the session anymore&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;In the accompanying &lt;a href="https://github.com/mario-mazo/mutual-exclusion-consul" rel="noopener noreferrer"&gt;github repo&lt;/a&gt; There is a fully working implementation of this. It's also very simple and intended for learning purporses.&lt;br&gt;
You will need a work go installation to be able to compile the code and &lt;code&gt;docker&lt;/code&gt; with &lt;code&gt;docker-compose&lt;/code&gt; to be able to run a consul server. So lets see the demo:&lt;br&gt;
First launch consul&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker-compose up
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then open 2 terminals and in the first run the code and you should see something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;go run main.go
sessionID: bac7cf19-285e-9907-98ad-e8189a07cbd9
I can work. YAY!!!
Starting to work
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;you now can check the web interface of consul &lt;a href="http://localhost:8500/ui/dc1/kv" rel="noopener noreferrer"&gt;http://localhost:8500/ui/dc1/kv&lt;/a&gt;&lt;br&gt;
to verify that the keys are created, locked and destroyed either by &lt;code&gt;TTL&lt;/code&gt;, finishing the task or interrupting the task.&lt;/p&gt;

&lt;p&gt;in the second one if you run the code you can see the code exiting while the task is executed&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;go run main.go
sessionID: d0f26b95-11cb-236c-bba7-601441f2ae74
I can NOT work. YAY!!!
&lt;span class="err"&gt;$&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;if you interrupt the task by doing &lt;code&gt;Ctrl+C&lt;/code&gt; you should see the cleanup happening&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;go run main.go
sessionID: 4685d391-251d-9f6d-1c2c-5ab6fdbd9f98
I can work. YAY!!!
Starting to work
^C2018/09/13 11:16:04 Job interrupted. Cleaning up
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;if you try to connect right after the task is finised you will notice you cannot conect. This is due to &lt;code&gt;lock-delay&lt;/code&gt; which is documented in the &lt;a href="https://www.consul.io/docs/internals/sessions.html" rel="noopener noreferrer"&gt;sessions&lt;/a&gt; section of the consul documentation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;I invite you to check the &lt;a href="https://github.com/mario-mazo/mutual-exclusion-consul" rel="noopener noreferrer"&gt;github repo&lt;/a&gt; as the code there is full of notes about implementation that could be useful for a real implementation.&lt;/p&gt;

&lt;p&gt;Also there are things I did not implement like &lt;code&gt;stop()&lt;/code&gt; or &lt;code&gt;Discovering the Leader&lt;/code&gt;, but implementation should be simple. Feel free to submit a pull requres.&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.consul.io/docs/guides/leader-election.html" rel="noopener noreferrer"&gt;https://www.consul.io/docs/guides/leader-election.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.consul.io/docs/internals/sessions.html" rel="noopener noreferrer"&gt;https://www.consul.io/docs/internals/sessions.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/mario-mazo/mutual-exclusion-consul" rel="noopener noreferrer"&gt;https://github.com/mario-mazo/mutual-exclusion-consul&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>go</category>
      <category>consul</category>
    </item>
  </channel>
</rss>
