<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

 <title>Manoj Awasthi</title>
 <link href="https://awmanoj.github.io/atom.xml" rel="self"/>
 <link href="https://awmanoj.github.io/"/>
 <updated>2024-06-08T17:36:04+00:00</updated>
 <id>https://awmanoj.github.io</id>
 <author>
   <name>Manoj Awasthi</name>
   <email></email>
 </author>

 
 <entry>
   <title>Programmability in nginx config using map</title>
   <link href="https://awmanoj.github.io/tech/2024/06/08/programmability-in-nginx-config-using-map/"/>
   <updated>2024-06-08T00:00:00+00:00</updated>
   <id>https://awmanoj.github.io/tech/2024/06/08/programmability-in-nginx-config-using-map</id>
   <content type="html">&lt;p&gt;NGINX is one of the most beautiful piece of tech that I explored briefly in 2011-12 and heavily 2016 onwards while scaling an ecommerce platform at work in Indonesia. It is so simple and so powerful that it is hard to not fall in love with it. Primarily, it is an HTTP reverse proxy server and can be used to serve static and dynamic content behind web services with excellent inbuilt support for load balancing, caching, logging, rate limiting, and even request mirroring.&lt;/p&gt;

&lt;p&gt;For a more elaborate understanding of the feature set it comes with, head to &lt;a href=&quot;https://nginx.org/en/&quot;&gt;NGINX documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Most of the features in NGINX are controlled through easily configurable NGINX configuration that usually sits at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/nginx/nginx.conf&lt;/code&gt; and extended by included files in the configuration (including &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/nginx/&amp;lt;sites&amp;gt;/&amp;lt;site.example.com&amp;gt;&lt;/code&gt;). This ability to modify the conf file followed by a simple config test and reload as follows is what makes it so easy to operate:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
..
$ nginx -s reload
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Don’t get disheartened.&lt;/p&gt;

&lt;p&gt;This post is not a general manual for NGINX. It is about something I discovered today while experimenting on something for a friend. This person wants to run a simple web tool and serve it on different end points for different employees.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;http://example.com/it/review-1
http://example.com/it/review-2
http://example.com/it/review-3
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;All the three sites are similar in nature. They have some logic to fetch some data and present on the web page in a form, which when submitted post review gets submitted to backend and redirected back to the original endpoint for fetching more data for review.&lt;/p&gt;

&lt;p&gt;Initially they set up three endpoints in the config as following:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;	location /it/review-1/ {
		proxy_pass http://localhost:5000/?param=1;
    	}
	location /it/review-2/ {
		proxy_pass http://localhost:5000/?param=2;
    	}
	location /it/review-3/ {
		proxy_pass http://localhost:5000/?param=3;
    	}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now they want to expand it to 10 endpoints. So, one way was to simply proceed with duplicating the endpoints in NGINX config. So, he asked me if there is a more elegant solution to this. And as I researched I found about &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;map&lt;/code&gt; in NGINX which I’d never used.&lt;/p&gt;

&lt;h2 id=&quot;map-in-nginx&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;map&lt;/code&gt; in NGINX&lt;/h2&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;map&lt;/code&gt; coupled with excellent support for regex in NGINX made it possible to avoid all duplication and enable a very elegant solution.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# Define this in http block but outside the server block
# Define a map to extract the 'param' parameter based on the URL path
map $request_uri $param {
	default 0; # Set default value to 0
	~^/it/review-(\d+)/ $1;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This assigns &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;param&lt;/code&gt; variable to a default value of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt; and otherwise parse it from the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;request_uri&lt;/code&gt;. So a request to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/it/review-2&lt;/code&gt; will assign &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;param&lt;/code&gt; a value of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;2&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Next step is to use it for the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;location&lt;/code&gt; block:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;        location ~ ^/it/review-(\d+)/ {
            # Extract the param parameter
            set $param_value $param;
	    
            # Use the odd parameter in the proxy_pass directive
            proxy_pass http://127.0.0.1:5000/?param=$param_value;
	}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;But then I realised that this will lead to a situation where even unintended endpoints like beyond ten (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;10&lt;/code&gt;) will work e.g. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/it/review-12&lt;/code&gt;. For handling that I needed to check for the value and return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;501 (Not Implemented)&lt;/code&gt; for the requests of that nature.&lt;/p&gt;

&lt;p&gt;So, the question was HOW!?&lt;/p&gt;

&lt;p&gt;And again the superhero to the rescue is our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;map&lt;/code&gt;. Following code helped do the validation and set a variable for every request if the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;param&lt;/code&gt; value is greater than &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;10&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# Define a map to check if param_value is &amp;gt;= 10
map $param $param_ge_10 {
	default 0;
	~^[1-9]$ 0; # Param value is less than 10
	~^1[0-9]$ 1; # Param value is greater than or equal to 10
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Finally, we can use this for additional logic in the location block:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;        location ~ ^/it/review-(\d+)/ {
            # Extract the param parameter
            set $param_value $param;
	
            # Return 501 Not Implemented if param_value is &amp;gt;= 10
            if ($param_ge_10) {
                return 501;
            }
    
            # Use the odd parameter in the proxy_pass directive
            proxy_pass http://127.0.0.1:5000/?param=$param_value;
	}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And that was it.&lt;/p&gt;

&lt;p&gt;Quite a learning, followed by the excitement to share it and hence this post!!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Probability of death by different causes</title>
   <link href="https://awmanoj.github.io/life,/death/2022/08/04/probability-of-death-by-different-causes/"/>
   <updated>2022-08-04T00:00:00+00:00</updated>
   <id>https://awmanoj.github.io/life,/death/2022/08/04/probability-of-death-by-different-causes</id>
   <content type="html">&lt;p&gt;The discussion about death is usually considered morbid and is avoided in most cultures that I’ve grown in despite the fact that it remains the most certain and inescapable event for all mortals.&lt;/p&gt;

&lt;p&gt;While walking today, I thought I would go and read about the odds of dying from different causes. Looks like, lot of studies have happened in different parts of the world.&lt;/p&gt;

&lt;p&gt;Following is a summary of some of the probabilities of deaths in United States per 2020:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Cause of Death&lt;/th&gt;
      &lt;th&gt;Probability&lt;/th&gt;
      &lt;th&gt;Odds (x in y)&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Heart Disease&lt;/td&gt;
      &lt;td&gt;16%&lt;/td&gt;
      &lt;td&gt;1 in 6&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Cancer&lt;/td&gt;
      &lt;td&gt;14.2%&lt;/td&gt;
      &lt;td&gt;1 in 7&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;COVID-19&lt;/td&gt;
      &lt;td&gt;8.3%&lt;/td&gt;
      &lt;td&gt;1 in 12&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;All preventable causes of death&lt;/td&gt;
      &lt;td&gt;4.7%&lt;/td&gt;
      &lt;td&gt;1 in 21&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Chronic lower respiratory disease&lt;/td&gt;
      &lt;td&gt;3.6%&lt;/td&gt;
      &lt;td&gt;1 in 28&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Opioid overdose&lt;/td&gt;
      &lt;td&gt;1.5%&lt;/td&gt;
      &lt;td&gt;1 in 67&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Suicide&lt;/td&gt;
      &lt;td&gt;1%&lt;/td&gt;
      &lt;td&gt;1 in 93&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Motor Vehicle Crash&lt;/td&gt;
      &lt;td&gt;0.99%&lt;/td&gt;
      &lt;td&gt;1 in 101&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Fall&lt;/td&gt;
      &lt;td&gt;0.98%&lt;/td&gt;
      &lt;td&gt;1 in 102&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Gun Assault&lt;/td&gt;
      &lt;td&gt;0.45%&lt;/td&gt;
      &lt;td&gt;1 in 221&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Pedestrian Incident&lt;/td&gt;
      &lt;td&gt;0.18%&lt;/td&gt;
      &lt;td&gt;1 in 541&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Motorcyclist&lt;/td&gt;
      &lt;td&gt;0.12%&lt;/td&gt;
      &lt;td&gt;1 in 799&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Drowning&lt;/td&gt;
      &lt;td&gt;0.09%&lt;/td&gt;
      &lt;td&gt;1 in 1024&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Fire or Smoke&lt;/td&gt;
      &lt;td&gt;0.07%&lt;/td&gt;
      &lt;td&gt;1 in 1450&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Choking on food&lt;/td&gt;
      &lt;td&gt;0.04%&lt;/td&gt;
      &lt;td&gt;1 in 2745&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Bicyclist&lt;/td&gt;
      &lt;td&gt;0.03%&lt;/td&gt;
      &lt;td&gt;1 in 3396&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Sunstroke&lt;/td&gt;
      &lt;td&gt;0.015%&lt;/td&gt;
      &lt;td&gt;1 in 6368&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Accidental gun discharge&lt;/td&gt;
      &lt;td&gt;0.012%&lt;/td&gt;
      &lt;td&gt;1 in 7998&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Electrocution, radiation, extreme temperatures, and pressure&lt;/td&gt;
      &lt;td&gt;0.007%&lt;/td&gt;
      &lt;td&gt;1 in 14705&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Sharp objects&lt;/td&gt;
      &lt;td&gt;0.004%&lt;/td&gt;
      &lt;td&gt;1 in 26744&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Cataclysmic storm&lt;/td&gt;
      &lt;td&gt;0.003%&lt;/td&gt;
      &lt;td&gt;1 in 35074&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Hot surfaces and substances&lt;/td&gt;
      &lt;td&gt;0.002%&lt;/td&gt;
      &lt;td&gt;1 in 50341&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Hornet, wasp, and bee stings&lt;/td&gt;
      &lt;td&gt;0.0017%&lt;/td&gt;
      &lt;td&gt;1 in 57825&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Dog attack&lt;/td&gt;
      &lt;td&gt;0.0014%&lt;/td&gt;
      &lt;td&gt;1 in 69016&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Lightning&lt;/td&gt;
      &lt;td&gt;-&lt;/td&gt;
      &lt;td&gt;Too few deaths in 2020 to calculate odds&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Railway passenger&lt;/td&gt;
      &lt;td&gt;-&lt;/td&gt;
      &lt;td&gt;Too few deaths in 2020 to calculate odds&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Passenger on an airplane&lt;/td&gt;
      &lt;td&gt;-&lt;/td&gt;
      &lt;td&gt;Too few deaths in 2020 to calculate odds&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Source: &lt;a href=&quot;https://injuryfacts.nsc.org/all-injuries/preventable-death-overview/odds-of-dying/&quot;&gt;InjuryFacts&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Just looking at different cause heads, I feel that these odds will look so different for developing nations.I would really want to find and prepare similar data for India (2020+) and possibly, Indonesia (2020+).&lt;/p&gt;

&lt;p&gt;If you have come across any published data source related to this then please do help share on &lt;a href=&quot;http://twitter.com/awmanoj&quot;&gt;Twitter&lt;/a&gt; or &lt;a href=&quot;mailto:awasthi.manoj@gmail.com&quot;&gt;Mail me&lt;/a&gt;.&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>Nuggets of wisdom from the book 'The Richest Man In Babylon'</title>
   <link href="https://awmanoj.github.io/books/2022/02/14/the-nuggets-from-the-richest-man-in-babylon/"/>
   <updated>2022-02-14T00:00:00+00:00</updated>
   <id>https://awmanoj.github.io/books/2022/02/14/the-nuggets-from-the-richest-man-in-babylon</id>
   <content type="html">&lt;p&gt;&lt;img src=&quot;/public/assets/img/trmib.jpeg&quot; width=&quot;200&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I finished reading this popular book &lt;a href=&quot;https://www.amazon.in/RICHEST-MAN-BABYLON-George-Clason/dp/9355200552/&quot;&gt;The Richest Man In Babylon&lt;/a&gt; by George S. Clason and can testimony the amount of wisdom in the book around financial success.&lt;/p&gt;

&lt;p&gt;Following are bunch of nuggets of wisdom from the book.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;“Our acts can be no wiser than our thoughts. Our thinking can be no wiser than our understanding.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;“No one lends his entire fortune, not even to his best friend.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;” A fat purse quickly empties if there be no golden stream to refill it.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;“I wish an income that will keep flowing into my purse whether I sit on the wall or travel to far lands.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;“The reason why we have never found any measure of wealth? We never sought it.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;“Wealth is power. With wealth many things are possible”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;“And when youth comes to age for advice he receives the wisdom of years”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;“Opportunity is a haughty goddess who wastes no time with those who are unprepared”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;“A part of all I earn is mine to keep”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;“Then learn to make your treasure work for you. Make it your slave. Make its children and its children’s children work for you.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;“Invest thy treasure with great caution that it be not lost.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;“Provide also that thy family may not want should the Gods call thee to their realms. For such protection it is always possible to make provision with small payments at regular intervals”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;“Counsel with wise men.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;“A small return and a safe one is far more desirable than risk”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;“Enjoy life while you are here. Do not overstrain or try to save too much.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;“Life is good and life is rich with things worthwhile and things to enjoy”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;“Just as the weeds grow in a field wherever the farmer leaves space for their roots, even so freely desires grown in men whenever there is a possibility for them to be gratified”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;“No man’s family can fully enjoy life unless they do have a plot of ground wherein children can play in the clean earth and where the wife may raise not only blossoms but good rich herbs to feed her family.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;“To a man’s heart it brings gladness to eat the figs from his own trees and the grapes of his own vines.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;“Preceding accomplishments must be desire. The desire must be strong and definite.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;“More interest in my work, more concentration upon my task , more persistence in my effort and, behold few men could carve more tablets in a day than I.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;7 Curses for a lean purse&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
  &lt;li&gt;Start thy purse to fattening. Keep at least one-tenth of your earnings for yourself.&lt;/li&gt;
  &lt;li&gt;Control thy expenditures. Have a budget. Budget thy expenses.&lt;/li&gt;
  &lt;li&gt;Make thy gold multiply.&lt;/li&gt;
  &lt;li&gt;Guard thy treasures from loss. The first sound principle of investment is security for thy principal. Consult with wise men.&lt;/li&gt;
  &lt;li&gt;Own thy own home.&lt;/li&gt;
  &lt;li&gt;Provide in advance for the needs of thy growing age and the protection of thy family. Insure a future income (retirement and in case of fatalities).&lt;/li&gt;
  &lt;li&gt;Increase they ability to earn.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
  &lt;p&gt;Such things as following, a man must do if he respects himself:&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
  &lt;li&gt;He must pay his debts with all the promptness within his power, not purchasing that for which he is unable to pay.&lt;/li&gt;
  &lt;li&gt;He must take care of his family that they may think and speak well of him.&lt;/li&gt;
  &lt;li&gt;He must make a will of record that, in case Gods call him, proper and honorable division of his property be accomplished.&lt;/li&gt;
  &lt;li&gt;He must have compassion and upon those who are smitten by misfortune and aid them within reasonable limits. He must do deeds of thoughtfulness to those dear to him.&lt;/li&gt;
  &lt;li&gt;He must cultivate himself, study and become wiser to become more skilful and respect him more.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
  &lt;p&gt;“Opportunity stands for no man. Today it is here. Soon it is gone. Therefore, delay not!”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;“Procrastinator is the one who accepts not the opportunity when she comes. He waits. He says I have much business right now. Bye and bye I talk to you. Opportunity, she will not wait for such slow fellow. She thinks if a man desires to be lucky he will step quick. Any man not step quick when opportunity comes, he big procrastinator.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;“The spirit of procrastination is within all men. We desire riches; yet, how often when opportunity doth appear before us, that spirit of procrastination from within doth urge various delays in out acceptance”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;“Recognize and conquer procrastination”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;“No man can arrive at a full measure of success until he hath completely crushed the spirit of procrastination”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;“To attract good luck to oneself, it is necessary to take advantage of opportunities”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;“Men of action please the goddess of opportunity the best”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;Five laws of Gold&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
  &lt;li&gt;Gold cometh gladly and in increasing quantity to any man who will put by not less than one-tenth of his earnings to create an estate for his future and that of his family.&lt;/li&gt;
  &lt;li&gt;Gold laboreth diligently and contentedly for the wise owner who finds for it profitable employment, multiplying even.&lt;/li&gt;
  &lt;li&gt;Gold clingeth to the protection of the cautious owner who invests it under the advise of men wise in its handling.&lt;/li&gt;
  &lt;li&gt;Gold slippeth away from the man who invests it in businesses or purposes with which he is not familiar.&lt;/li&gt;
  &lt;li&gt;Gold flees the man who would force it to impossible earnings or who followeth the alluring advice of tricksters and schemers or who trusts it to his own inexperience and romantic desires in investments.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
  &lt;p&gt;“There is no chain of disasters that will not come to an end”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;“Wealth that comes quickly goeth the same way”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;“Wealth the stayeth to give enjoyment and satisfaction to its owner comes gradually, because it is a child born of knowledge and persistent purpose”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;“What indiscretions hast thou done that thou shouldst seek the lender of gold? Hast been unlucky at the gaming table? Or hath some plump dame entangled thee?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;“Gold bringeth unto its possessor responsibility and a changed position with his fellow men. It bringeth fear lest he lose it or it be tricked away from him. It bringeth a feeling of power and ability to do good. Likewise, it bringeth opportunities whereby his very good intentions may bring him into difficulties”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;“To borrowing and lending, there is more than the passing of gold from the hands of one to the hands of another”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;“If you desire to help thy friend, do so in a way that will not bring thy friend’s burdens upon thyself.”.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;“Help wisely!”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;Where the gold can be lent:&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
  &lt;li&gt;The safest loans, my token box tells me, are to those whose possessions are of more value than the one they desire. They own lands, or jewels, or camels, or other thing which could be sold to repay the loan. Some of the tokens given to me are jewels of more value than the loan. Others are promises that if the loan be not repaid as agreed they will deliver to me certain property settlement. On loans like those I am assured that my gold will be returned with the rental thereon.&lt;/li&gt;
  &lt;li&gt;In another class are those who have the capacity to earn. They are such as you, who labor or server and are paid. They have income and if they are honest and suffer no misfortune, I know that they also can repay the gold I loan them and the rental to which I am entitled.&lt;/li&gt;
  &lt;li&gt;Others are those who have neither the property nor assured earning capacity. Life is hard and there will always be some who cannot adjust themselves to it. Alas for the loans I make them, even though they be no larger than a pence, my token box may censure me in the years to come unless they be guaranteed by good friends of the borrowers who know him honourable.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
  &lt;p&gt;“If they borrow for purposes that bring money back to them, I find it so [borrowers repaying their loans]. But if they borrow because of their indiscretions, I warn thee to be cautious if thou wouldst ever have thy gold back in hand again.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;“Your purpose is wise and your ambitions are honorable. I shall be glad to lend you the fifety pieces of gold if you can give me security that they will be returned… I treasure much each piece of gold. Were the robbers to take it from you as you journeyed, or take the rugs from you as you returned then you would have no means of repaying me and my gold would be gone.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;“Gold, you see, Rodan, is the merchandise of the lender of money. It is easy to lend. If it is lent unwisely then it is difficult to get back. The wise lender wishes not the risk of the undertaking but the guarantee of safe repayment.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;“Better a little caution than a great regret”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;“We cannot afford to be without adequate protection”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;“Ill fortune pursues every man who thinks more of borrowing than repaying”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;“Thy debts are thy enemies. They ran thee out of Babylon. You left them alone and they grew too strong for thee.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;“Where the determination is, the way can be found”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;Plan for debt free life&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
  &lt;li&gt;First, one-tenths of all I earn shall be set aside as my own to keep.&lt;/li&gt;
  &lt;li&gt;Second, seven-tenths of all I earn shall be used to provide a home, clothes to wear, and food to eat with a bit extra to spend, that our lives be not lacking in pleasure and enjoyment.&lt;/li&gt;
  &lt;li&gt;Third, two-tenths of all I have earned shall be divided honorably and fairly among those who have trusted me and to whom I am indebted.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;and the one which is my most favorite is in the last chapter, about ‘Work’:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;“Some men hate it. They make it their enemy. Better to treat it like a friend, make thyself like it. Don’t mind because it is hard. If thou thinkest about what a good house thou build, then who cares if the beams are heavy and it is far from the well to carry the water for the plaster. Promise me, boy, if thou get a master, work for him as hard as thou canst. If he does not appreciate all thou do, never mind. Remember, work well-done, does good to the man who does it. It makes him a better man.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A recommended read.&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>Solve Problems, Not Symptoms - An Interview with Naveen Jain</title>
   <link href="https://awmanoj.github.io/tech,/vision/2021/05/24/naveen-jain-solve-problems-not-symptoms/"/>
   <updated>2021-05-24T00:00:00+00:00</updated>
   <id>https://awmanoj.github.io/tech,/vision/2021/05/24/naveen-jain-solve-problems-not-symptoms</id>
   <content type="html">&lt;p&gt;Loved this talk.&lt;/p&gt;

&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/y9VY87waHqk&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;

</content>
 </entry>
 
 <entry>
   <title>A quick primer into isolation levels in databases</title>
   <link href="https://awmanoj.github.io/tech,/database,/systems,/concurrency/2020/08/22/a-primer-into-isolation-levels-in-databases/"/>
   <updated>2020-08-22T00:00:00+00:00</updated>
   <id>https://awmanoj.github.io/tech,/database,/systems,/concurrency/2020/08/22/a-primer-into-isolation-levels-in-databases</id>
   <content type="html">&lt;p&gt;Transaction Processing is one big source of complexity in correctly designing concurrent applications working with database systems.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;A transaction is defined as one indivisible logical entity comprising usually of more than one operations which are meant to be considered a single step that either is success (a ‘commit’) or a failure (an ‘abort’). This unit of work should act as if the transaction (the group of operations) is atomic.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is quite important to keep the state of database in a consistent state at all the time and being adherant with ACID semantics.&lt;/p&gt;

&lt;p&gt;I will not go into the examples of transactions in databases assuming the familiarity of the reader to them. There are zillions of articles talking about concurrent processing of bank accounts and why it is so important to ensure atomic behavior.&lt;/p&gt;

&lt;p&gt;In this article, we talk in the context of concurrent processing on the databases systems.&lt;/p&gt;

&lt;h1 id=&quot;what-is-an-isolation-level&quot;&gt;What is an isolation level?&lt;/h1&gt;

&lt;p&gt;An isolation level specifies ‘how’ and ‘when’ parts of the transaction can and should become visible to other concurrently executing transactions.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Isolation levels describe the degree to which transactions are isolated from other concurrently executing transactions, and what kind of anomalies can be expected in each.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1 id=&quot;possible-read-and-write-anomalies-specified-by-sql-standards&quot;&gt;Possible Read and Write anomalies specified by SQL standards&lt;/h1&gt;

&lt;h2 id=&quot;read-anomalies&quot;&gt;Read anomalies&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;A &lt;strong&gt;dirty read&lt;/strong&gt; is a situation in which a transaction can read uncommitted changes from other transactions.&lt;/li&gt;
  &lt;li&gt;A &lt;strong&gt;nonrepeatable read&lt;/strong&gt; is a situation in which a transaction queries the same row twice and gets different results. For example, a transaction T1 reads a row, then transaction T2 modifies the row and commits this change. Now, if T1 requests the row again then the result will be different from previous read.&lt;/li&gt;
  &lt;li&gt;A &lt;strong&gt;phantom read&lt;/strong&gt; is a situation a transaction queries the same &lt;em&gt;set of rows&lt;/em&gt; twice and receives different results. It is similar to nonrepeatable reads but only for range queries.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;write-anomalies&quot;&gt;Write anomalies&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;A &lt;strong&gt;lost update&lt;/strong&gt; happens when transaction T1 and T2 both attempt to update the value of V. T1 and T2 read the value of V. T1 updates V and commits and T2 updates V after that and commits as well. Since the transactions are not aware about each other so the result of T1’s update will be overwritten by T2’s update.&lt;/li&gt;
  &lt;li&gt;A &lt;strong&gt;dirty write&lt;/strong&gt; is a situation in which one of the transactions takes an uncommitted value (i.e. a dirty read), modifies it and commits it.&lt;/li&gt;
  &lt;li&gt;A &lt;strong&gt;write skew&lt;/strong&gt; is a situation when each individual transaction respects the required variants, but their combination does not satisfy these invariants.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;isolation-levels&quot;&gt;Isolation Levels&lt;/h1&gt;

&lt;p&gt;The lowest isolation level (or the weakest) is &lt;strong&gt;Read Uncommitted&lt;/strong&gt; which allows dirty-read.&lt;/p&gt;

&lt;p&gt;The next isolation level is &lt;strong&gt;Read committed&lt;/strong&gt; that allows transactions only to read committed changes. Althought this isolation level does not allow dirty reads but still suffers from nonrepeatable reads and phantom reads.&lt;/p&gt;

&lt;p&gt;The next isolation level is &lt;strong&gt;Repeatable Read&lt;/strong&gt; that does not allow dirty read and also takes care of nonrepeatable reads but suffers still from phantom reads.&lt;/p&gt;

&lt;p&gt;The strongest isolation level is ofcourse &lt;strong&gt;Serializable&lt;/strong&gt; where all transactions are executed serially. This has significant negative impact on performance and hence not a practical choice.&lt;/p&gt;

&lt;h1 id=&quot;summary&quot;&gt;Summary&lt;/h1&gt;

&lt;p&gt;&lt;img src=&quot;/public/assets/img/tx-isolation.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;So, for most cases &lt;strong&gt;Repeatable Read&lt;/strong&gt; would be the go-to isolation level to operate in. You can read more about &lt;a href=&quot;https://awmanoj.github.io/tech/2016/11/30/performing-concurrency-safe/&quot;&gt;Performing concurrency-safe DB updates in postgres using ‘repeatable read’ isolation level&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Happy and safe coding!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Time Complexity of Algorithms</title>
   <link href="https://awmanoj.github.io/tech,/algorithms/2020/06/03/time-complexity-algorithms/"/>
   <updated>2020-06-03T00:00:00+00:00</updated>
   <id>https://awmanoj.github.io/tech,/algorithms/2020/06/03/time-complexity-algorithms</id>
   <content type="html">&lt;p&gt;&lt;img src=&quot;/public/assets/img/timecomplexity.png&quot; /&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Assuming 100M ops per second on the machine.&lt;/li&gt;
&lt;/ul&gt;
</content>
 </entry>
 
 <entry>
   <title>Socratic questioning, a way towards first-principles thinking</title>
   <link href="https://awmanoj.github.io/life,/learning/2020/05/09/socratic-questioning/"/>
   <updated>2020-05-09T00:00:00+00:00</updated>
   <id>https://awmanoj.github.io/life,/learning/2020/05/09/socratic-questioning</id>
   <content type="html">&lt;p&gt;Recently, started reading &lt;a href=&quot;https://www.amazon.com/Great-Mental-Models-Thinking-Concepts/dp/1999449002&quot;&gt;The Great Mental Models: General Thinking Concepts&lt;/a&gt; by &lt;a href=&quot;https://twitter.com/ShaneAParrish&quot;&gt;Shane&lt;/a&gt; &lt;a href=&quot;https://twitter.com/farnamstreet/&quot;&gt;Parrish&lt;/a&gt; and came across &lt;em&gt;Socratic Questioning&lt;/em&gt; in the chapter on first principles thinking.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Anything that is not a law of nature is just a shared belief. Money is a shared belief. So is a border. So are bitcoin. So is love. The list goes on.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Socratic Questioning is a method that can help us reflect on our thinking process. This can help us from relying on our gut and limit strong emotional responses. We can cut through the fog of dogma and shared beliefs to identify unchanging principles.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Methods are many. Principles are few.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Socratic Questioning generally follows the following process:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;CLARIFYING YOUR THINKING AND EXPLAINING THE ORIGINS OF YOUR IDEAS
    &lt;ul&gt;
      &lt;li&gt;Why do I think this?&lt;/li&gt;
      &lt;li&gt;What exactly do I think?&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;CHALLENGING ASSUMPTIONS
    &lt;ul&gt;
      &lt;li&gt;How do I know if this is true?&lt;/li&gt;
      &lt;li&gt;What if I thought the opposite?&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;LOOKING FOR EVIDENCE
    &lt;ul&gt;
      &lt;li&gt;How can I back this up?&lt;/li&gt;
      &lt;li&gt;What are the sources?&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;CONSIDERING ALTERNATE PERSPECTIVES
    &lt;ul&gt;
      &lt;li&gt;What might others think?&lt;/li&gt;
      &lt;li&gt;How do I know I am correct?&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;EXAMINING CONSEQUENCES AND IMPLICATIONS
    &lt;ul&gt;
      &lt;li&gt;What if I am wrong?&lt;/li&gt;
      &lt;li&gt;What are the consequences if I am wrong?&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;QUESTIONING THE ORIGINAL QUESTIONS
    &lt;ul&gt;
      &lt;li&gt;Why did I think that?&lt;/li&gt;
      &lt;li&gt;Was I correct?&lt;/li&gt;
      &lt;li&gt;What conclusions can I draw from the reasoning process?&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This process of reflection or an alternative of this called &lt;em&gt;FIVE WHYS&lt;/em&gt; is useful in understanding deeply the root cause of what we observe or think. There is no doubt that both of these methods slow us down in the short term but reap huge rewards in terms of limiting emotional responses, better thought process and better decision making in long term.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Science is much more than a body of knowledge. It is a way of thinking. – Carl Sagan&lt;/p&gt;
&lt;/blockquote&gt;

</content>
 </entry>
 
 <entry>
   <title>How fast do you read?</title>
   <link href="https://awmanoj.github.io/tech,/work,/life/2019/04/19/how-fast-you-read/"/>
   <updated>2019-04-19T00:00:00+00:00</updated>
   <id>https://awmanoj.github.io/tech,/work,/life/2019/04/19/how-fast-you-read</id>
   <content type="html">&lt;p&gt;As someone who loves reading books as a hobby, I have always wondered if I’m able to read at a good enough speed or not. I’ve friends who claim to finish a 200 page book in 4 hours. In terms of words, assuming each line would be ~ 10 words and each page would be ~ 35-40 lines, it translates to ~350-400 &lt;em&gt;words per minute&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;With all the interruptions and distractions, I have never been able to sit for 4-5 hours in one go and finish a book (IIRC). This is equivalent of being able to finish a book every weekend (one of the days over the weekend rather) and 4-5 hours is something you can always trade with your family, spouse amidst all commitments of time to her and children. So, no doubt I envied the friend claiming this.&lt;/p&gt;

&lt;p&gt;Today, came across following stats while browsing:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The average adult reading speed is between 200 and 300 words per minute (same reading speed you want to achieve by 6th grade).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;For success in college you should be able to read 350 to 450 words per minute if you want to have any extra time.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;Speeds above 575 words per minute are typical for successful high level executives and people who enjoy reading.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Reading in itself comprises of two things -&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Speed (words per minutes)&lt;/li&gt;
  &lt;li&gt;Comprehension (how much do you understand and retain in short term, from page to page)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are lot of good resources on measuring your current reading speed alongwith comprehension. &lt;a href=&quot;http://www.freereadingtest.com/&quot;&gt;This&lt;/a&gt; is one such site (no affiliation. feel free to google and find more options). My current reading speed is less than the average with a high comprehension.&lt;/p&gt;

&lt;p&gt;Note that &lt;em&gt;Comprehension&lt;/em&gt; is more important than the &lt;em&gt;Speed&lt;/em&gt; in reading. So, always value the former.&lt;/p&gt;

&lt;p&gt;But it kind of proves that the claim from the friend about 200 pages in 4 hours was not a puffery claim! :-)&lt;/p&gt;

&lt;p&gt;Happy Reading!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Doing it alone</title>
   <link href="https://awmanoj.github.io/tech,/work,/life/2019/01/04/doing-it-alone/"/>
   <updated>2019-01-04T00:00:00+00:00</updated>
   <id>https://awmanoj.github.io/tech,/work,/life/2019/01/04/doing-it-alone</id>
   <content type="html">&lt;p&gt;&lt;em&gt;Originally posted on 8 Sep’ 2010 &lt;a href=&quot;https://awmanoj.blogspot.com/2010/09/doing-it-alone.html&quot;&gt;here&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;“If you’re that rare engineer who’s an inventor and also an artist, I’m going to give you some advice that might be hard to take. That advice is: Work alone.”&lt;/p&gt;
  &lt;ul&gt;
    &lt;li&gt;Steve Wozniak&lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;As far as I remember I was never given such advice by anyone, be it my parents, my teachers, professors or mentors during my professional career. It’s hard to understand and harder to believe some such thing when no one talked about it in such a large span (I am past quarter of my life span). But when I, for last few weeks, started to devote some time to this idea of working alone I could clearly think the cases where it was a pure win. These are the cases of “diffused responsibility”, “too much dependence” and “plain pretence”.&lt;/p&gt;

&lt;p&gt;I remember working with a group in my last company where each of us in the group felt that the given system of diagnosing the issues was substandard and needed an overhaul. “We” were asked to do that task of making the diagnosis tool better but since it was “We” and apart from this work, everyone had there own set of tasks in their plate - it never happened. It happened when one of us took the responsibility of doing so (after being pointed to sadly). Everyone knew someone has to do it but did not take the task because they assumed that if it is important then someone will take care of it otherwise it’s not that important. I should also point out that everyone was competent enough to do the task. This was the case of “Diffused Responsibility”.&lt;/p&gt;

&lt;p&gt;In my current work, for quite some time I was having a task of automating a stuff which was causing pain to us - a very very repetitive stuff which should have been automated long back (I believe this, being part of an engineering company, other companies - I am quite sure - look up to). I promised that I’ll do the task but then came a phase of planning - how to do it? (On this question I imagine the face and style of a a very senior hardcore geek I worked with in a previous company yelling at me - “stupid, how do you write scripts?”). Well, trust me I was asked to plan it out, I was asked to meet so that we use the same automation system which a larger activity uses. So there comes the whole gimmick of breaking the tasks in such a way that there are multiple tasks available with multiple people and yes, there must be a dependency so that there is one more guy involved who will look at getting it done. Hmm. Too much work at hand. The tasks planned moved but very slowly. Thanks to a guy in my team who “broke” the rule and deployed the simple script. That was the power of doing it alone. All the friction was gone from the same set of guys talking about planning and “N” factors to be taken in account. This was the case of “too much dependence”. If you get into such case, do the same - break the rule.&lt;/p&gt;

&lt;p&gt;I also remember another incident that happened to me recently. I was working on a killer feature (a killer feature is not a feature that kills but a feature which is most talked about in your product) of the software product I work on as part of my day job. It was a team of three and we decided on few things. Then all of a sudden scope of the work to be done due to some reasons was decreased. We still thought it would be good to decide on few investigations just for Intellectual Property reasons. Here the third case of “Plain Pretence” came in. I did not do, I am pretty sure, because I thought someday I would sit with other guys and work on it. That did not happen. I am also sure that had I started working on these investigations alone, someone in my team would have joined for sure - these are guys who are undoubtedly competent and have keen interest in software development. That initiation was the key.&lt;/p&gt;

&lt;p&gt;I’ve written only about the work life experiences but I think this applies to many non work experiences. For me most of the things that I started without worrying about whether someone will join in or not were marked done at some point of time - either successfully or unsuccessfully. They were not lying in on my table under the &lt;em&gt;was_not_able_to_even_try&lt;/em&gt; folder. So I have started believing in starting alone. That should not be interpreted as “don’t do in a group” but as - if it is possible to do it alone then don’t wait for the group to begin - just begin and the group may join.&lt;/p&gt;

&lt;p&gt;Larger dreams in life like starting a company, I’ve been told should not be done alone. They are such goals which require some one to be there to take care of each other in adverse situations and more reasons. Imagining this, I agree but since I am yet to taste actually that sweet feeling of starting an enterprise I won’t be able to comment on this but I feel this small piece of gyan will be helpful in lot of smaller activities in day to day life.
A random post on a random thought.&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>How I learned hard way the pitfalls of a dynamically typed languages?</title>
   <link href="https://awmanoj.github.io/tech/2018/08/07/how-i-learned-pitfalls-dynamically-typed-languages/"/>
   <updated>2018-08-07T00:00:00+00:00</updated>
   <id>https://awmanoj.github.io/tech/2018/08/07/how-i-learned-pitfalls-dynamically-typed-languages</id>
   <content type="html">&lt;p&gt;Dynamically typed (weak types) languages (like Perl, Python, Ruby etc) are great for developer productivity or so they say. I agree to large extent but then for a large scale system with growing components and services this may become a nightmare to maintain. This is based on some of the learnings being on both sides.&lt;/p&gt;

&lt;p&gt;In this post, want to discuss one interesting issue that I got reminded of while going through some archives and boils down to one of the perils of using a dynamically type language.&lt;/p&gt;

&lt;p&gt;For the context, we are a marketplace with millions of sellers and buyers on the platform. Sellers can open a shop on the platform and start selling while buyers can discover the products and shops they want to get access to. Marketplace also provides many payment methods and escrow so that your payment is safe.&lt;/p&gt;

&lt;p&gt;Marketplace platform was originally written in Perl and though we modularised it from Monolith that it was to a huge number of micro services while taking the opportunity to write them in a modern statically typed language (golang), we still had some parts of it written in Perl. We have been moving these parts to golang fast.&lt;/p&gt;

&lt;p&gt;So one fine day last year, suddenly we started receiving an ever increasing number of merchant complaints that they were getting an error while adding products (hence failed uploads of products) which resolved to the following message:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&quot;category not complete&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Yes, not that useful but this was not supposed to occur so much, a highly unlikely message and hence never got much attention from the product managers.&lt;/p&gt;

&lt;p&gt;At the peak of the error, the frequency of reported issues was ~ a couple of thousands per hour.&lt;/p&gt;

&lt;p&gt;After assembling multiple teams involved and tracking the root cause, we found that the bug itself was pretty interesting.&lt;/p&gt;

&lt;p&gt;There was a sql query to check if a category is leaf or not - try finding out categories whose parent is the given category and see the number of results returned - if zero then ok other wise throw error.  It looked something like this in the perl code:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;                     $str_sql = qq~
                         select
                             d_id
                         from ws_department
                         where parent = &amp;lt;:n=$val_dep:&amp;gt;
                         and status = &amp;lt;:n=1:&amp;gt;
                     ~;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$val_dep&lt;/code&gt; i.e. category ID was fetched in a previous code block using another &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SELECT&lt;/code&gt; query and was expected to be a single integer (equivalent of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LIMIT 1&lt;/code&gt;). But somehow &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$val_dep&lt;/code&gt;, instead of being the category_id (i.e. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;int&lt;/code&gt;) ended up being the array (multiple values) whose address would look like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x245bf20&lt;/code&gt;. then this function&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$svq-&amp;gt;sql($str_sql);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;will convert the query into&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;                     $str_sql = qq~
                         select
                             d_id
                         from ws_department
                         where parent = 24520 
                         and status = &amp;lt;:n=1:&amp;gt;
                     ~;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;So, note how Perl showed its &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;intelligence&lt;/code&gt; in converting the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x245bf20&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;24520&lt;/code&gt; (silently). Grr.&lt;/p&gt;

&lt;p&gt;This caused the intermittently occurring bug. Sometimes that memory address would resolve to a valid category ID in the marketplace and many times it won’t. When it doesn’t it leads to the error that leaf category ID is not present which in turn led to the “bad” error message “category not complete”.&lt;/p&gt;

&lt;p&gt;Side effect of dynamically typed language.&lt;/p&gt;

&lt;p&gt;Statically typed languages (C, C++, Java, Scala, Go etc) ensure type safety and would help avoid such pitfalls.&lt;/p&gt;

&lt;p&gt;So be mindful about using the language carefully. If it is dynamically typed then you can expect no type safety. So ensure proper validation (err towards more of it) to write rock solid code (if there is anything like that).&lt;/p&gt;

&lt;p&gt;:-)&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>Undoing git reset hard (remove local commits)</title>
   <link href="https://awmanoj.github.io/tech/2018/04/01/undoing-git-reset-hard/"/>
   <updated>2018-04-01T00:00:00+00:00</updated>
   <id>https://awmanoj.github.io/tech/2018/04/01/undoing-git-reset-hard</id>
   <content type="html">&lt;p&gt;Although this post is being published on 01 April celebrated as April Fool’s Day and known for pranks all around, you can trust this post.&lt;/p&gt;

&lt;p&gt;This was a long weekend and I sat down to code something that I planned for quite sometime but didn’t get time to. After finishing with the coding and testing I prepared the git repo and pushed the code in there.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ git add . 
$ git commit -m &quot;Initial commit.&quot; 
... 
$ git push origin master 
...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This was taking long time and I realized, inadvertently, I committed some binary embedded databases (big size for git). That is when I thought of quickly removing the commit and re-commit again:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ git reset --hard HEAD~1 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;As a side effect, all my local files were gone too. Yes, all work that went into over the weekend. :-(&lt;/p&gt;

&lt;p&gt;For sometime I was shaken but then a quick search over google led to &lt;a href=&quot;https://stackoverflow.com/questions/5473/how-can-i-undo-git-reset-hard-head1/6636&quot;&gt;this QnA&lt;/a&gt; on stackoverflow. This helped! :-)&lt;/p&gt;

&lt;p&gt;Following taken verbatim from the above QnA post summarizes what to do:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ git init
Initialized empty Git repository in .git/

$ echo &quot;testing reset&quot; &amp;gt; file1
$ git add file1
$ git commit -m 'added file1'
Created initial commit 1a75c1d: added file1
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 file1

$ echo &quot;added new file&quot; &amp;gt; file2
$ git add file2
$ git commit -m 'added file2'
Created commit f6e5064: added file2
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 file2

$ git reset --hard HEAD^
HEAD is now at 1a75c1d... added file1

$ cat file2
cat: file2: No such file or directory

$ git reflog
1a75c1d... HEAD@{0}: reset --hard HEAD^: updating HEAD
f6e5064... HEAD@{1}: commit: added file2

$ git reset --hard f6e5064
HEAD is now at f6e5064... added file2

$ cat file2
added new file
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Particularly:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ git reflog
1a75c1d... HEAD@{0}: reset --hard HEAD^: updating HEAD
f6e5064... HEAD@{1}: commit: added file2

$ git reset --hard f6e5064
HEAD is now at f6e5064... added file2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Life saver! :-)&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>Problems using Hindi variables in golang</title>
   <link href="https://awmanoj.github.io/tech/2017/11/12/problems-using-hindi-variables-golang/"/>
   <updated>2017-11-12T00:00:00+00:00</updated>
   <id>https://awmanoj.github.io/tech/2017/11/12/problems-using-hindi-variables-golang</id>
   <content type="html">&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Go&lt;/code&gt; is a beautiful programming language. It is not so due to its many features but rather due to lack of them.&lt;/p&gt;

&lt;p&gt;It has managed to remain simple, performant, backward compatible (it’s a promise by creators, think &lt;a href=&quot;https://learntocodewith.me/programming/python/python-2-vs-python-3/&quot;&gt;python 2.7 vs 3.0 tussle&lt;/a&gt;) and has some unique features (compared to popular modern programming languages) like the support for concurrent programming (channels, goroutines).&lt;/p&gt;

&lt;p&gt;Apart from the main features of the language, there are some cute little things which go provides. One of them is that your variable names can be composed of any unicode characters. What does that mean? This means, following program containing simplified chinese characters is a valid program which compiles and runs fine (you can try):&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;import (
    &quot;fmt&quot;
)

func main() {
    量 := 5000    // Amount
    速率 := 10    // Rate
    持续时间 := 6 // Duration

    总 := (量 * 速率 * 持续时间) / 100 // Total

    fmt.Println(总)
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now, that is some fun. I thought why not try my mothertongue, Hindi (Devanagri script), so coded following:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;func main() {
    मूलधन := 5000
    दर := 10
    समय := 6 // वर्षमें

    fmt.Println((मूलधन * दर * समय)/100)
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;On compiling:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Manojs-MacBook-Pro:test2 manojawasthi$ go build
# _/Users/manojawasthi/gocode/src/github.com/awmanoj/test2
./main.go:8: invalid identifier character U+0942 'ू'
./main.go:12: invalid identifier character U+0942 'ू'
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Heartbroken!&lt;/p&gt;

&lt;p&gt;On further search on the error and the issue, I found that I wasn’t alone (ofcourse).&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/public/assets/img/hindi-golang.png&quot; alt=&quot;Hindi golang issue screenshot&quot; /&gt;&lt;/p&gt;

&lt;p&gt;This was also &lt;a href=&quot;https://groups.google.com/forum/#!topic/golang-nuts/yJRJRtEEA0E&quot;&gt;discussed in golang-nuts&lt;/a&gt; and Nathan Kerr added a response:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The Go team knows this a problem (see the issues listed by Rob Pike). The difficultly in fixing it is that the ecosystem surrounding Go relies on the current definition for identifiers. There is no way to add the characters you need without breaking other tools like syntax highlighters. It is a socioeconomic problem than a technical one. The next time it can be fixed in Go is for Go 2.0 and is already on the list of issues to be considered.
If your main goal is to write programs in your language, you might consider using one from https://en.wikipedia.org/wiki/Non-English-based_programming_languages&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;There are also some good comments by &lt;a href=&quot;https://github.com/bakul&quot;&gt;Bakul&lt;/a&gt; on this thread. He discusses briefly the intricacies involved and why this would be rather low priority item even for Go 2.0 to support Hindi (while it is in plan). I concur.&lt;/p&gt;

&lt;p&gt;For the curious, these are some of the issues related to this (latter added by Rob Pike):&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/golang/go/issues/5167&quot;&gt;https://github.com/golang/go/issues/5167&lt;/a&gt;
&lt;a href=&quot;https://github.com/golang/go/issues/20706&quot;&gt;https://github.com/golang/go/issues/20706&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, while “not holding my breath”, will still be looking out for Go2.0 to support hindi names (Devanagri script).&lt;/p&gt;

&lt;p&gt;Note: Without the problematic characters, things worked well.&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>How to get approximate row count in postgres tables?</title>
   <link href="https://awmanoj.github.io/tech/2017/08/31/how-to-get-approximate-row-count-postgres/"/>
   <updated>2017-08-31T00:00:00+00:00</updated>
   <id>https://awmanoj.github.io/tech/2017/08/31/how-to-get-approximate-row-count-postgres</id>
   <content type="html">&lt;p&gt;If there is a table with tens of millions of rows in a postgres table then following query will be very slow (non interactive):&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;SELECT COUNT(*) FROM SAMPLE 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Following can help us get an “approximate” count of rows in postgres:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;SAMPLEDB=&amp;gt; SELECT reltuples::BIGINT AS estimate FROM pg_class WHERE relname = 'SAMPLE'; 
 estimate 
----------
 54296044
(1 row)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Ref: &lt;a href=&quot;https://wiki.postgresql.org/wiki/Count_estimate&quot;&gt;https://wiki.postgresql.org/wiki/Count_estimate&lt;/a&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>So how slow can golang regular expressions be?</title>
   <link href="https://awmanoj.github.io/tech/2017/08/23/so-how-slow-can-golang-regex-be/"/>
   <updated>2017-08-23T00:00:00+00:00</updated>
   <id>https://awmanoj.github.io/tech/2017/08/23/so-how-slow-can-golang-regex-be</id>
   <content type="html">&lt;p&gt;Sometime back, I wrote &lt;a href=&quot;https://awmanoj.github.io/tech/2016/09/08/on-slow-regular-expressions-golang/&quot;&gt;on slow regular expressions in golang&lt;/a&gt;. Recently, I thought about experimenting with regular expressions and use Golang &lt;a href=&quot;https://dave.cheney.net/2013/06/30/how-to-write-benchmarks-in-go&quot;&gt;benchmarking&lt;/a&gt; to estimate their slowness.&lt;/p&gt;

&lt;p&gt;Disclaimers:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;It’s not a generalisation (please &lt;a href=&quot;https://awmanoj.github.io/tech/2016/09/08/on-slow-regular-expressions-golang/&quot;&gt;read the previous post&lt;/a&gt; to understand the context of the claim).&lt;/li&gt;
  &lt;li&gt;This post is NOT a comparison between golang regex performance and PCRE (or other language) performance.&lt;/li&gt;
  &lt;li&gt;This post is meant only for a possible alternative in some of the cases where speed is important and less comprehensive checks still acceptable.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;experiment&quot;&gt;Experiment&lt;/h2&gt;

&lt;p&gt;For the experiment, at hand was a problem to identify whether the connection string to redis followed a certain pattern.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;120 // Check if connectionString is host:port format and 
121 // not the tcp://user:pass@host:port/0?q=1 format.
123 //  Dial(&amp;amp;DialConfig{&quot;tcp&quot;, &quot;127.0.0.1:6379&quot;, 0, &quot;&quot;, 10*time.Second, 10})
124 //  DialURL(&quot;tcp://auth:password@127.0.0.1:6379/0?timeout=10s&amp;amp;maxidle=1&quot;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Problem is solvable using following regular expression:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  8 var s2 = &quot;127.0.0.1:6379”
  9 func IsRedisConnectionStringType2Fn1() {
 10     regexp.MatchString(&quot;^(\\d+\\.\\d+\\.\\d+\\.\\d+):(\\d+)$&quot;, s2)
 11 }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To compare if there will be a gain by replacing this with “less intricate”, “less powerful” but possibly “enough” heuristics based check, wrote this function:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;13 func IsRedisConnectionStringType2Fn2(connectionString string) bool {
14     // if starts with tcp:// then not a type2 URL
15     if strings.Index(connectionString, &quot;tcp://&quot;) == 0 {
16         return false
17     }
18 
19     // if more than two components separated by ':' then not a type2 URL
20     splits := strings.Split(connectionString, &quot;:&quot;)
21     if len(splits) != 2 {
22         return false
23     }
24 
25     return true
26 }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We use golang benchmarking support (such a beautiful language!) to benchmark both versions:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;import &quot;testing&quot;

func BenchmarkIsRedisConnectionStringType2Fn1(b *testing.B) {
    for n := 0; n &amp;lt; b.N; n++ {
        IsRedisConnectionStringType1()
    }
}

func BenchmarkIsRedisConnectionStringType2Fn2(b *testing.B) {
    for n := 0; n &amp;lt; b.N; n++ {
        IsRedisConnectionStringType2(s2)
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The results:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;parallels@ubuntu:~/gocode/src/github.com/awmanoj/test2/test$ go test -bench=.
BenchmarkIsRedisConnectionStringType2Fn1-2    100000	    15139 ns/op
BenchmarkIsRedisConnectionStringType2Fn2-2   5000000	      378 ns/op
PASS
ok  	github.com/tokopedia/test2/test	3.968s
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Here, strings based heuristics checks is 40x faster than the regex version. Is it equivalent (apple to apple)? not at all.&lt;/p&gt;

&lt;h2 id=&quot;should-we-fret-over-this&quot;&gt;Should we fret over this?&lt;/h2&gt;

&lt;p&gt;Not necessarily — in fact most probably, need not.&lt;/p&gt;

&lt;p&gt;If your code is not hit that often it doesn’t make sense to fret over something which is still imperceptible (ns per operation here) in terms of runtime. But if it is a code which is expected to be hit very frequently (e.g. for every hit to the server) — you should evaluate if there could be a less stringent and complex alternative.&lt;/p&gt;

&lt;p&gt;Is it equivalent? Not at all. In all probability — this heuristics based check will not be as powerful and comprehensive as the regular expression check so it is not always possible to replace the regex with such heuristics check. But when possible it can be a good replacement.&lt;/p&gt;

&lt;h2 id=&quot;advice&quot;&gt;Advice&lt;/h2&gt;

&lt;p&gt;Though there is good advice hidden in this post which can be useful at times, always remember this nugget:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil. 
    – Donald Knuth&lt;/p&gt;
&lt;/blockquote&gt;

</content>
 </entry>
 
 <entry>
   <title>Using nginx logs to identify SSL certificate details</title>
   <link href="https://awmanoj.github.io/tech/2017/06/13/using-nginx-logs-to-identify-ssl-certs/"/>
   <updated>2017-06-13T00:00:00+00:00</updated>
   <id>https://awmanoj.github.io/tech/2017/06/13/using-nginx-logs-to-identify-ssl-certs</id>
   <content type="html">&lt;p&gt;Adding client side SSL certificate is &lt;a href=&quot;https://stackoverflow.com/questions/2164397/why-should-i-authenticate-a-client-using-a-certificate&quot;&gt;one of the best ways to restrict access on public internet&lt;/a&gt;. The way it works is that you create server certificates using a certifying authority (which can be you, yourself) and then create some client certificates. Then it is a matter of putting some settings in nginx (or other server you may be using) to enable it. Post that, you share the client certificate with users who are authorized to access the resource with revocation possible from server side. Your resource can be accessed by only people who have the client certificate installed. You can &lt;a href=&quot;https://gist.github.com/shamil/2165160#file-gistfile1-md&quot;&gt;read this&lt;/a&gt; and &lt;a href=&quot;https://rynop.com/2012/11/26/howto-client-side-certificate-auth-with-nginx/&quot;&gt;this&lt;/a&gt; for details of how to generate and use certificates for nginx.&lt;/p&gt;

&lt;p&gt;At my workplace, we have a distributed CRUD system for key values which is protected using client side SSL certificates in similar manner. Initially, we created a common client certificate which was shared to all who needed access. But in this setup, there was a loophole. Since the certificate is shared so whether user A makes the change or user B makes the change, there is no way of identifying. So, we came up with per-user certificates which will have the user id and user email identification. These certificates will be delivered to user’s email on request for access.&lt;/p&gt;

&lt;p&gt;Next step (and the subject of this blog post) was to identify through logs who does what actions. On Nginx, it is as simple as updating the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;log_format&lt;/code&gt; in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/nginx/nginx.conf&lt;/code&gt; file:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  log_format  main '$remote_addr - $ssl_client_s_dn - $remote_user [$time_local] &quot;$request&quot; '
                '$status $body_bytes_sent &quot;$http_referer&quot; '
                '&quot;$http_user_agent&quot; &quot;$upstream_response_time&quot;';
  access_log /var/log/nginx/access.log main;
  error_log /var/log/nginx/error.log;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You notice that I added &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$ssl_client_s_dn&lt;/code&gt; in the log format, This variable returns the “subject DN” string of the client certificate for an established SSL connection according to RFC 2253 (1.11.6);&lt;/p&gt;

&lt;p&gt;Following logs are examples of what we see in our logs:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;10.0.2.31 - /C=ID/ST=DKI-Jakarta/L=Jakarta/O=PT XXXXXXX/OU=Engineering/CN=XXXX/emailAddress=manoj.awasthi@XXXXXXX.com - - [13/Jun/2017:18:06:38 +0700] &quot;DELETE /services/kv/random/key HTTP/1.1&quot; 304 0 &quot;-&quot; &quot;Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36&quot; &quot;0.001&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The value corresponding to the variable &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$ssl_client_s_dn&lt;/code&gt; is:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/C=ID/ST=DKI-Jakarta/L=Jakarta/O=PT XXXXXXX/OU=Engineering/CN=XXXX/emailAddress=manoj.awasthi@XXXXXXX.com
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This uniquely identifies the user who does a certain change e.g. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DELETE&lt;/code&gt; a key. A simple, low cost change control system. :-)&lt;/p&gt;

&lt;p&gt;You can read more about &lt;a href=&quot;http://nginx.org/en/docs/http/ngx_http_ssl_module.html#var_ssl_client_cert&quot;&gt;other variables related to SSL certificates&lt;/a&gt; which are supported in nginx.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Why do (some) engineers write bad code?</title>
   <link href="https://awmanoj.github.io/tech/2017/06/07/why-engineers-write-bad-code/"/>
   <updated>2017-06-07T00:00:00+00:00</updated>
   <id>https://awmanoj.github.io/tech/2017/06/07/why-engineers-write-bad-code</id>
   <content type="html">&lt;p&gt;I’ve been reading &lt;a target=&quot;_blank&quot; href=&quot;https://www.amazon.com/gp/product/059600284X/ref=as_li_tl?ie=UTF8&amp;amp;camp=1789&amp;amp;creative=9325&amp;amp;creativeASIN=059600284X&amp;amp;linkCode=as2&amp;amp;tag=awmanoj-20&amp;amp;linkId=8ee0e4238a7b93669231b2bff3c6939e&quot;&gt;System Performance Tuning, 2nd Edition&lt;/a&gt;&lt;img src=&quot;//ir-na.amazon-adsystem.com/e/ir?t=awmanoj-20&amp;amp;l=am2&amp;amp;o=1&amp;amp;a=059600284X&quot; width=&quot;1&quot; height=&quot;1&quot; border=&quot;0&quot; alt=&quot;&quot; style=&quot;border:none !important; margin:0px !important;&quot; /&gt; recently. Though the content is a bit dated as a reference (was written while Linux kernel 2.4 was coming up) but this is still a fantastic book on refreshing the workings of the components of a computer and knowing the tweaks for solaris and linux.&lt;/p&gt;

&lt;p&gt;This post though, is focussed on a topic that is touched towards the end of the book. Why do we end up writing bad code?&lt;/p&gt;

&lt;p&gt;Bad code could mean many things - bad design or architecture decision, badly written code that is harder to maintain (duplication, tightly coupled components, less modular etc.), code that is bad at performance (time or space) and so on. The book talks about following reasons for badly written code (most of it is verbatim with few modifications here and there):&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Writing bad code is much faster than writing good code.&lt;/strong&gt; Good software engineering practices often trade an increase in initial development time for a decrease in the time required to maintain the software by eliminating bugs in the design phase or for a decrease in application runtime by integrating performance analysis into the development process. When faced with a deadline and irate management, it’s often easier to just get it done rather than do it well.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
  &lt;p&gt;TIP: Learn to say No to “can we do this quickly” in favor of better thought of and more solid code or design. You will thank yourself for it more often than not.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Implementing good algorithms is technically challenging.&lt;/strong&gt; This coupled with management’s desire for a product yesterday and the time to implement such an algorithm, often the good algorithms lose out.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
  &lt;p&gt;TIP: Invest in learning about common algorithms &amp;amp; data structures and weigh upon choices when you’re faced with a problem. Almost always the first solution that strikes one’s mind is not the best.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Good software engineers are difficult to find.&lt;/strong&gt; Software engineering is more than writing good source code. It involves architecture development, soliciting support from other development organisations, formal code review, ongoing documentation, version control etc. Concepts like pair programming are just beginning to move from the academic world into the mainstream and aren’t yet heavily practised.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Legacy is hard to maintain.&lt;/strong&gt; It’s quite rare that a group of engineers sit down to develop a piece of software from scratch. More likely, they’re adding onto an existing framework, or developing the next version of the current product. The mistakes have already been made, and it’s not time effective (or cost effective) to throw everything and start over. Solution can be refactoring which makes the existing code more amicable to catching bugs, bottlenecks and improvements.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Also, experience wise I find that, bad code gets copied more than good code (remember ‘it is implemented the same way in that file / module / project etc.’? at the workplace). While re-writes are hard, it’s always possible to refactor the code as and when possible to make it more friendlier to improvements.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;TIP: The basic idea here is whenever you write a line of code, it should be refactored. If you’re rewriting pieces of legacy code, those should be refactored as well.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Good night!&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>Writing good error messages (for developers)</title>
   <link href="https://awmanoj.github.io/tech/2017/03/12/good-error-messages-for-developers/"/>
   <updated>2017-03-12T00:00:00+00:00</updated>
   <id>https://awmanoj.github.io/tech/2017/03/12/good-error-messages-for-developers</id>
   <content type="html">&lt;p&gt;Writing good software is an Art, albeit the one which can definitely be learnt. As a developer, most of your time would go in maintaining an application - enhancing it with new features, finding bugs, debugging them to isolate the cause and fixing the issues. This post is mostly associated with the debugging of issues.&lt;/p&gt;

&lt;p&gt;Writing good error messages should not be an Art. (this is also the goal of this post!)&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/public/assets/img/look.jpg&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Following are some general comments and suggestions on writing “good” error messages:&lt;/p&gt;

&lt;p&gt;(this is by no means a comprehensive document, neither authoritative - just based on my experience)&lt;/p&gt;

&lt;h3 id=&quot;errors-should-explain-the-problem-concisely-and-well&quot;&gt;Errors should explain the problem concisely and well&lt;/h3&gt;

&lt;p&gt;Good error messages provide the proper error message that explain the reason well. Easiest way to do that is to include the error code (e.g. errno in C or err.Error() in golang) in the error message.&lt;/p&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;p&gt;Instead of:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;05/Mar/2017:12:08:54 +0700 err database error. 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Use:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;05/Mar/2017:12:08:54 +0700 err error opening database postgres://a:b@host/maindb
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;errors-should-provide-immediate-context&quot;&gt;Errors should provide immediate context&lt;/h3&gt;

&lt;p&gt;Good error messages provide details of immediate context. In all likelihood, only one error scenario will hit at a time. So each log (however unimportant it may seem) should contain the context e.g. immediate variables related to error condition, exact error code, anything else that may be important etc.&lt;/p&gt;

&lt;p&gt;TIP: while writing code, imagine if this error is hit then what information would you be immediately seeking without attaching debugger. That information should be logged.&lt;/p&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;p&gt;Instead of:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;05/Mar/2017:12:08:54 +0700 err parsing integer
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Use:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;05/Mar/2017:12:08:54 +0700 err parsing integer: &quot;248BAD&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;errors-must-be-actionable&quot;&gt;Errors must be actionable&lt;/h3&gt;

&lt;p&gt;Don’t log an error if it is not actionable. As an example, if you read a record from a database and you get an error that “the record is not present” - if you can proceed without it - for example, you insert the record then do not log this as an error. If you want to count from your logs number of inserts add an “info” log on inserts or may be a “warn” log on error.&lt;/p&gt;

&lt;p&gt;Judge: if you think you don’t need to act on an error in error log - either make it an info or warn or don’t log it.&lt;/p&gt;

&lt;h3 id=&quot;errors-must-be-logged-in-single-line&quot;&gt;Errors must be logged in single line&lt;/h3&gt;

&lt;p&gt;Don’t use multiline errors. Error logs should contain one (note, one!) error per line. This is to be able to fully use UNIX commands over streaming (pipe).&lt;/p&gt;

&lt;h3 id=&quot;errors-should-be-logged-only-at-top-level&quot;&gt;Errors should be logged only at top level&lt;/h3&gt;

&lt;p&gt;Good errors logs are logged at the highest level and hence there is usually only ONE error per occurrence. E.g.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;func DoStuff() {
	… 
	if err := DoStuffHelper(); err != nil {
		// log the error since function itself not returning error
		log.Println(“err”, err)  
		return
	}
	...
} 

func DoStuffHelper() error {
	… 
	if err := Stuff(); err != nil {
		// do not log the error since function returning an error. 
		// responsibility of logging error is of the caller
		return err  
	}
	...
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;errors-should-roll-up-in-function-calls&quot;&gt;Errors should roll up in function calls&lt;/h3&gt;

&lt;p&gt;If there are functions calling other functions and failure happens deep below then it is OK to add some additional error message explanation at each function level (don’t log though - see above - just return more detailed error at each level). It is advisable that in such rollup we retain original error code:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;func DoA() {
	if err := DoB(); err != nil {
		log.Println(&quot;err&quot;, err)
		return
	}
}

func DoB() error {
	if err := DoC(); err != nil {
		return errors.New(&quot;failed executing C(), &quot; + err.Error())
	}
}

func DoC() error {
	if err := DoD(); err != nil {
		return errors.New(&quot;failed executing D(), &quot; + err.Error())
	}
}

...

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h3&gt;

&lt;p&gt;Your error log is your friend in bad times - often one of the darkest hours of your work life (problem in production, panic, downtime etc) so an investment in thinking through and writing error logs well will reap significant rewards in saved time and faster resolutions.&lt;/p&gt;

&lt;p&gt;If you have more suggestions do &lt;a href=&quot;https://twitter.com/awmanoj&quot;&gt;tweet to me&lt;/a&gt;.&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>421 Misdirected request error</title>
   <link href="https://awmanoj.github.io/tech/2017/02/05/421-misdirected-request-nginx/"/>
   <updated>2017-02-05T00:00:00+00:00</updated>
   <id>https://awmanoj.github.io/tech/2017/02/05/421-misdirected-request-nginx</id>
   <content type="html">&lt;p&gt;Yesterday, I faced an interesting issue that I wasn’t aware of earlier. Let me tell the context first.&lt;/p&gt;

&lt;p&gt;We have one server (i.e. 1 IP) which serves multiple domains (websites). Yesterday, we decided to put it behind client side SSL certificates. Everything was hunky dory till we started hearing that some users (thankfully, this was internal website so only colleagues!) complained about &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;421 Misdirected Request&lt;/code&gt; when they try accessing those websites.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/public/assets/img/421.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;A &lt;a href=&quot;http://serverfault.com/questions/772901/421-misdirected-request-using-http-2-and-san-ssl&quot;&gt;couple&lt;/a&gt; &lt;a href=&quot;https://bugs.chromium.org/p/chromium/issues/detail?id=546991&quot;&gt;of&lt;/a&gt; searches over the internet helped understand the problem a bit. This post is a summary.&lt;/p&gt;

&lt;p&gt;So, basically when you enable SSL (e.g. set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssl_verify_client&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;optional&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;on&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;optional_no_ca&lt;/code&gt; in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nginx&lt;/code&gt;) and you serve more than one domains from the same server (i.e. 1 IP address) and one of the domains are using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http2&lt;/code&gt; then HTTP/2 tries to reuse connections to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;different&lt;/code&gt; servers.&lt;/p&gt;

&lt;p&gt;Let’s first understand what protocol does and how servers and clients are expected to behave with respect to this. Following are snippets from &lt;a href=&quot;https://tools.ietf.org/html/rfc7540#section-9.1.1&quot;&gt;RFC 7540 (HTTP/2)&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;Protocol suggests:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;An origin server might offer a certificate with multiple “subjectAltName” attributes or names with wildcards, one of which is valid for the authority in the URI.  For example, a certificate with a “subjectAltName” of “*.example.com” might permit the use of the same connection for requests to URIs starting with “https://a.example.com/” and “https://b.example.com/”.
… 
In some deployments, reusing a connection for multiple origins can result in requests being directed to the wrong origin server.
…
This means that it is possible for clients to send confidential information to servers that might not be the intended target for the request, even though the server is otherwise authoritative.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So servers are suggested to implement:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;A server that does not wish clients to reuse connections can indicate that it is not authoritative for a request by sending a 421 (Misdirected Request) status code in response to the request (see Section 9.1.2).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;.. and browsers (clients) are suggested to implement:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Clients receiving a 421 (Misdirected Request) response from a server MAY retry the request – whether the request method is idempotent or not – over a different connection.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In our case, we serve two domains &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a.foobar.com&lt;/code&gt; (over http) and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;b.foobar.com&lt;/code&gt; (over http2) from 1 IP address. We added SSL to this. So when a user:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;opens browser and accesses &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a.foobar.com&lt;/code&gt;, he gets served the web content successfully.&lt;/li&gt;
  &lt;li&gt;from the same browser, accesses &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;b.foobar.com&lt;/code&gt;. he gets a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;421 Misdirected Request&lt;/code&gt; error in chrome (specifically, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Google chrome 56.0.2924.87&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What happened?&lt;/p&gt;

&lt;p&gt;Seems like, in second case - HTTP2 tries to use the same connection as the previous - owing to a single IP Address. In case of TLS, it additionally depends on whether certificate is valid for the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;host&lt;/code&gt; of the domain being accessed. As mentioned in RFC above the behavior is left to servers. If server finds this TLS request on a different domain than the one for which the connection was used previously and it thinks it is not authoritative then it can indicate so by responding with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;421 misdirected request&lt;/code&gt; error. In response to this error code, the client (i.e. the browser) should create a new connection and retry the request.&lt;/p&gt;

&lt;p&gt;So, while some browsers like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Safari&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Mozilla firefox&lt;/code&gt; behave in the expected manner causing no trouble, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Google Chrome&lt;/code&gt; (particular version is the only one I tested with) doesn’t abide with this.&lt;/p&gt;

&lt;h3 id=&quot;solution&quot;&gt;Solution:&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;For now, I disabled HTTP/2 for the site since it was internal website and it is ok to miss out on the performance benefits of http2. Everything works fine.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;One post suggests it happens due to &lt;a href=&quot;http://serverfault.com/questions/772901/421-misdirected-request-using-http-2-and-san-ssl&quot;&gt;difference in SSL configurations on the two domains&lt;/a&gt; - this is what I am yet to investigate. I will keep the post updated.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;useful-links&quot;&gt;Useful links:&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://trac.nginx.org/nginx/ticket/848&quot;&gt;https://trac.nginx.org/nginx/ticket/848&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://forum.nginx.org/read.php?29,267026&quot;&gt;https://forum.nginx.org/read.php?29,267026&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://bugs.chromium.org/p/chromium/issues/detail?id=546991&quot;&gt;https://bugs.chromium.org/p/chromium/issues/detail?id=546991&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</content>
 </entry>
 
 <entry>
   <title>From books to e-books</title>
   <link href="https://awmanoj.github.io/tech/2017/01/29/from-books-to-e-books/"/>
   <updated>2017-01-29T00:00:00+00:00</updated>
   <id>https://awmanoj.github.io/tech/2017/01/29/from-books-to-e-books</id>
   <content type="html">&lt;p&gt;I don’t remember distinctly when I got in love to reading books but this goes back to early age. It was self induced somehow. With time, the kind of books I read changed drastically which is expected. As a book lover, there is one constant challenge I faced - becoming more of a book collector than reader. There are increasing number of books that I have on book shelf which are unread. This causes not only an internal distress but also becomes one of the many reasons of complaints my wife has. She always imagines how this space, devoted to almost three books shelves, could be better utilized by other stuff (I don’t understand how would that be “better” though!). As you guess, she is not into reading that much.&lt;/p&gt;

&lt;p&gt;Well, this post is about a transformation that I see. I purchased a kindle (the older small one, without touch) I think in year 2012-13. Even before that, being a programmer I spend more of my time on a laptop or desktop and would read e-books in the form of PDF or EPUB on the system. Kindle was received by family (especially, wife) with joy since I would purchase less of physical books (paperback, hardcover) and atleast going forward, there won’t be more space needed by those little things.&lt;/p&gt;

&lt;p&gt;But after a small period of romanticism with kindle (purchasing few books, flaunting how easy it is on eyes as compared to reading a PDF on laptop, talking technicals like glare etc.), I felt something missing. The joy of reading was not really the same holding an electronic device and pressing buttons to go forth and back as with a book - unnatural - isn’t it? So, the kindle got placed on the same bookshelf meant for books and started gathering dust while I switched to books again. I also realized that this feeling was not unique to me - many friends would share similar thoughts on social media. So atleast the guilt of spending money and not using something was mitigated - there were others in the same situation like me and they too took similar decision.&lt;/p&gt;

&lt;p&gt;Last year, I relocated to Jakarta. This meant I would not be able to get access to huge “unread” collection of books back home. I’d to resort to ebooks. By this time (early 2016), there were much better kindle apps with lot of features on Android and Mac. For this one year I read many books on kindle on Mac and I feel that I am already making that transition. Following are a couple of points which I like about kindle books as compared to physical counterparts:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt; &lt;/th&gt;
      &lt;th&gt;Digital book (e.g. on Kindle Reader)&lt;/th&gt;
      &lt;th&gt;Physical book&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Fulfillment&lt;/td&gt;
      &lt;td&gt;delivered instantly after purchase&lt;/td&gt;
      &lt;td&gt;can take anytime from 2-3 days to weeks sometimes&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Storage space&lt;/td&gt;
      &lt;td&gt;stored on device. can store thousands (and more) of books per the device memory&lt;/td&gt;
      &lt;td&gt;needs physical space&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Carry while travel or during relocation&lt;/td&gt;
      &lt;td&gt;only space and weight is that of device&lt;/td&gt;
      &lt;td&gt;each book takes space and adds to weight&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Highlights&lt;/td&gt;
      &lt;td&gt;highlight electronically, also know how many others have highlighted, see all highlights together etc.&lt;/td&gt;
      &lt;td&gt;highlight using marker or pencil, harder to go through highlights later&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Translate meaning&lt;/td&gt;
      &lt;td&gt;check meanings of certain words and phrase online immediately (just select the word)*&lt;/td&gt;
      &lt;td&gt;hmm, keep a dictionary alongside (and switch context)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Distractions&lt;/td&gt;
      &lt;td&gt;possible to distract to internet, social media since you’re on the device&lt;/td&gt;
      &lt;td&gt;focus is better in this case&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Feel&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;smell of pages of a new book, cozy feeling of turning pages of a physical book&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;So other than the last two points, I think there are many benefits of switching to a digital book on a good reader.&lt;/p&gt;

&lt;p&gt;*This becomes particularly important since I come from India and English is not my first language. Additionally, I’m particularly weaker on Vocabulary. Handy access to exact detailed meaning of a word makes me understand the stuff more clearly and also helps building a better vocabulary.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Keep-Alive in http requests in golang</title>
   <link href="https://awmanoj.github.io/tech/2016/12/16/keep-alive-http-requests-in-golang/"/>
   <updated>2016-12-16T00:00:00+00:00</updated>
   <id>https://awmanoj.github.io/tech/2016/12/16/keep-alive-http-requests-in-golang</id>
   <content type="html">&lt;p&gt;The &lt;a href=&quot;https://en.wikipedia.org/wiki/Handshaking#TCP_three-way_handshake&quot;&gt;three-way handshake&lt;/a&gt; in a TCP connection setup is heavy wrt performance and re-using the already created connections is a considerable optimization. Keep alive is a method to allow the same tcp connection for HTTP conversation instead of opening a new one with each new request. Most servers and clients allow for configurations and options to utilise this optimisation.&lt;/p&gt;

&lt;p&gt;I had a strange encounter with the way this is handled in go.&lt;/p&gt;

&lt;p&gt;I’ve a go application - an &lt;a href=&quot;http://nsq.io/&quot;&gt;nsq&lt;/a&gt; (a distributed message queue) consumer - which reads some data off nsq and send that data over a HTTP POST to a remote server over SSL. This involves a &lt;a href=&quot;https://www.ssl.com/article/ssl-tls-handshake-overview/&quot;&gt;TLS handshake&lt;/a&gt; which is even more heavy than non-ssl handshake.&lt;/p&gt;

&lt;p&gt;We found that nsq queue depth for the topics was high and increasing, additionally we kept seeing errors like in nsqd logs:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[nsqd] 2016/12/16 17:48:34.563958 ERROR: [19.68.8.7:55239] - E_FIN_FAILED FIN 0b3caf88 failed ID not in flight - ID not in flight
[nsqd] 2016/12/16 17:48:34.567675 ERROR: [19.68.8.7:55239] - E_FIN_FAILED FIN 0b3ca9f4 failed ID not in flight - ID not in flight
[nsqd] 2016/12/16 17:48:34.571008 ERROR: [19.68.8.7:55239] - E_FIN_FAILED FIN 0b3c955c failed ID not in flight - ID not in flight
[nsqd] 2016/12/16 17:48:34.573917 ERROR: [19.68.8.7:55239] - E_FIN_FAILED FIN 0b3c86f8 failed ID not in flight - ID not in flight
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Based on the &lt;a href=&quot;https://github.com/nsqio/nsq/issues/660&quot;&gt;limited&lt;/a&gt; &lt;a href=&quot;https://github.com/nsqio/nsq/issues/729&quot;&gt;number&lt;/a&gt; &lt;a href=&quot;https://github.com/nsqio/nsq/issues/762&quot;&gt;of documents&lt;/a&gt; we got over the internet it seemed like this was due to a slow consumer (hints like need for heartbeat from consumer pointed in this direction). Since consumer was very simple - just doing some http posts so it was the only suspect.&lt;/p&gt;

&lt;p&gt;We did a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;strace&lt;/code&gt; on the running process to see the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;read,connect&lt;/code&gt; system calls. It indeed was doing some certificate interchange (read) for each connect or POST:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[pid 18043] read(90, &quot;g\201\f\1\2\0020|\6\10+\6\1\5\5\7\1\1\4p0n0$\6\10+\6\1\5\5\0070\1\206\30http://ocsp.digicert.com0F\6\10+\6\1\5\5\0070\2\206:http://cacerts.digicert.com/DigiCertSHA2SecureServerCA.crt0\f\6\3U\35\23\1\1\377\4\0020\0000\r\6\t*\206H\206\367\r\1\1\v\5\0\3\202\1\1\0\222\327\361\374\211T\330\363\305~8Z\270\210\313&amp;lt;Z\336o\274?\366\34\252\206Q\332\0044\257'\3751\205\273sa\200\251\325\224\267\\*\221\1/Ws\246\351bl=\330q?\200\256f\21\257\331\246\242w\313\202\245\361\241a?\2\345&amp;lt;a\35\313n\276\220\217k\377C\335}\235\2000+%?… &quot;, 3166) = 1948
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;From the code, we noticed that:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;a http client was being created for each incoming message in the handler. this was overkill clearly.&lt;/li&gt;
  &lt;li&gt;the http client created was using default transport. default http client does have a keep-alive setting.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Since keep-alive is already there so we thought #1 is the problem which is causing new connections to be created for every request which in turn leads to the TLS handshake (and eventually to slow consumer). We fixed this by creating a global client:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; 14 var client *http.Client
 15 
 16 func init() {
 17     tr := &amp;amp;http.Transport{
 18         MaxIdleConnsPerHost: 1024,
 19         TLSHandshakeTimeout: 0 * time.Second,
 20     }
 21     client = &amp;amp;http.Client{Transport: tr}
 22 }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;and using this to do the Post:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; 31     resp, err := client.Post(&quot;https://api.some-web.com/v2/events&quot;, &quot;application/json&quot;, bytes.NewBuffer(eventJson))
 32     if err != nil {
 33         log.Println(&quot;err&quot;, err)
 34         return err
 35     }
 36  
 37     defer resp.Body.Close()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;But we observed that problem persisted still (slowness as evident from errors in nsqd logs). We confirmed by doing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;strace&lt;/code&gt; again:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ sudo strace -s 2000 -f -p 18120 -e 'read,connect' 
[pid 18120] read(90, &quot;g\201\f\1\2\0020|\6\10+\6\1\5\5\7\1\1\4p0n0$\6\10+\6\1\5\5\0070\1\206\30http://ocsp.digicert.com0F\6\10+\6\1\5\5\0070\2\206:http://cacerts.digicert.com/DigiCertSHA2SecureServerCA.crt0\f\6\3U\35\23\1\1\377\4\0020\0000\r\6\t*\206H\206\367\r\1\1\v\5\0\3\202\1\1\0\222\327\361\374\211T\330\363\305~8Z\270\210\313&amp;lt;Z\336o\274?\366\34\252\206Q\332\0044\257'\3751\205\273sa\200\251\325\224\267\\*\221\1/Ws\246\351bl=\330q?\200\256f\21\257\331\246\242w\313\202\245\361\241a?\2\345&amp;lt;a\35\313n\276\220\217k\377C\335}\235\2000+%?… &quot;, 3166) = 1948

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This appeared for each connection request. This meant that golang was somehow not honouring the keep-alive. This is when &lt;a href=&quot;http://stackoverflow.com/questions/17948827/reusing-http-connections-in-golang&quot;&gt;this thread on stack overflow&lt;/a&gt; helped us -&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;You should ensure that you read until the response is complete before calling Close().&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;res, _ := client.Do(req)
io.Copy(ioutil.Discard, res.Body)
res.Body.Close()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;blockquote&gt;
  &lt;p&gt;To ensure http.Client connection reuse be sure to do two things:&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
  &lt;li&gt;Read until Response is complete (i.e. ioutil.ReadAll(rep.Body))&lt;/li&gt;
  &lt;li&gt;Call Body.Close()&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So we followed the suggestion:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; 31     resp, err := client.Post(&quot;https://api.some-web.com/v2/events&quot;, &quot;application/json&quot;, bytes.NewBuffer(eventJson))
 32     if err != nil {
 33         log.Println(&quot;err&quot;, err)
 34         return defaultErrStatus, err
 35     }
 36 
 37     io.Copy(ioutil.Discard, resp.Body)   // &amp;lt;= NOTE 
 38 
 39     defer resp.Body.Close()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;While, as a I see the golang implementation, it does include &lt;a href=&quot;https://github.com/golang/go/blob/master/src/net/http/client.go#L666&quot;&gt;a subtle comment in the code&lt;/a&gt; but I don’t understand yet why this idiosyncrasy exists. But would be something to be aware of and keep on the back of mind.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; // Post issues a POST to the specified URL.
 //
 // Caller should close resp.Body when done reading from it.
 //
 // If the provided body is an io.Closer, it is closed after the
 // request.
 //
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;take-away&quot;&gt;Take Away&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Use a global client as much as possible to avoid new connections.&lt;/li&gt;
  &lt;li&gt;Even when you don’t need the response back, read it fully before closing the response body - to take benefit of persistent connections (keep-alive).&lt;/li&gt;
&lt;/ul&gt;

</content>
 </entry>
 
 <entry>
   <title>Simulation of chaos game in go</title>
   <link href="https://awmanoj.github.io/tech/2016/12/12/simulation-chaos-game-go/"/>
   <updated>2016-12-12T00:00:00+00:00</updated>
   <id>https://awmanoj.github.io/tech/2016/12/12/simulation-chaos-game-go</id>
   <content type="html">&lt;p&gt;Fractals are interesting. As happens with most things interesting in life I got introduced to fractals serendipitously while researching on another mathematical construct ‘&lt;a href=&quot;https://en.wikipedia.org/wiki/Golden_ratio&quot;&gt;golden ratio&lt;/a&gt;’ which i needed to know about for implementation in an &lt;a href=&quot;https://helpx.adobe.com/photoshop-elements/using/cropping.html&quot;&gt;image editing feature I worked on&lt;/a&gt; as part of my day job few years back.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Fractal&quot;&gt;Fractals&lt;/a&gt; are self repeating patterns (either exact or approximately) and are found in nature aplenty (mostly the latter kind). One of the most intriguing ones are &lt;a href=&quot;https://books.google.co.id/books?id=0R2LkE3N7-oC&amp;amp;redir_esc=y&quot;&gt;Mandelbrot sets&lt;/a&gt; which have a mathematical connotation i.e. you can write a mathematical formula to describe mandelbrot sets - the fact that it involves complex numbers and the fact that this is found in nature is what makes them particularly interesting as fractals. This is when you start wondering if God is mathematician or if we discover mathematics rather than invent it. More on that later&lt;/p&gt;

&lt;p&gt;After reading through some of the articles on fractals online, I started reading a book on fractals recently. The first fractal it talks about is &lt;a href=&quot;https://en.wikipedia.org/wiki/Sierpinski_triangle&quot;&gt;sierpinski triangle&lt;/a&gt;. So one sunday I spent implementing a simulation in go.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/public/assets/img/st.png&quot; width=&quot;200&quot; /&gt;&lt;/p&gt;

&lt;p&gt;You can check the simulation in the form of GIF at this page: &lt;a href=&quot;https://awmanoj.github.io/public/sierpinski.html&quot;&gt;https://awmanoj.github.io/public/sierpinski.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The code for the service generating the GIF is available at: &lt;a href=&quot;https://github.com/awmanoj/chaos&quot;&gt;https://github.com/awmanoj/chaos&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you have questions you can &lt;a href=&quot;https://twitter.com/awmanoj&quot;&gt;reach out to me&lt;/a&gt;.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Performing concurrency-safe DB updates in postgres 9.4+ using 'repeatable read' isolation level</title>
   <link href="https://awmanoj.github.io/tech/2016/11/30/performing-concurrency-safe/"/>
   <updated>2016-11-30T00:00:00+00:00</updated>
   <id>https://awmanoj.github.io/tech/2016/11/30/performing-concurrency-safe</id>
   <content type="html">&lt;p&gt;Let’s accept it for the nth time again, writing concurrent programs correctly is hard.&lt;/p&gt;

&lt;p&gt;In this post, I discuss about a specific problem while concurrently writing to databases that I encountered recently, how to fix it and I am using that encounter to discuss a general idea about concurrent updates in databases.&lt;/p&gt;

&lt;h3 id=&quot;concurrent---whats-that&quot;&gt;Concurrent - What’s that?&lt;/h3&gt;

&lt;p&gt;It’s sometime good to understand the antithesis to understand something. The opposite of concurrent would be sequential. A sequential program is a program with a single thread of execution so the order of events (instructions) executed in the program are predictable and are as per the program logic. A concurrent program is a program with more than one threads of execution and so the order of events (instructions) executed in the program are not really predictable — order of events within one thread remains predictable but whether an event &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt; in thread A will happen before or after an event &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;y&lt;/code&gt; in thread B or they will be simultaneous is generally unknown.&lt;/p&gt;

&lt;p&gt;So a good “informal” definition (quoting from “&lt;a href=&quot;http://www.amazon.in/Go-Programming-Language-Alan-Donovan/dp/9332569711/ref=sr_1_1?ie=UTF8&amp;amp;qid=1480680008&amp;amp;sr=8-1&amp;amp;keywords=the+go+programming+language&quot;&gt;The Go Programming Language&lt;/a&gt;”):&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;When we cannot confidently say that one event happens before the other then the events x and y are concurrent.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;concurrency-safe-programs&quot;&gt;Concurrency-safe programs&lt;/h3&gt;

&lt;p&gt;A function is concurrency-safe if it continues to work correctly even when called concurrently (that is from two or more threads of execution without needing any additional synchronisation code).&lt;/p&gt;

&lt;p&gt;The analogy can be extended to “programs” when programs are accessing a shared resource for writing e.g. databases. If two or more than two programs are executing concurrently (on one or more than one servers) and are accessing a shared resource for writing then too the definition holds true that programs are concurrency-safe if they keep performing their updates correctly. This is the topic of this post.&lt;/p&gt;

&lt;h3 id=&quot;example-program&quot;&gt;Example program&lt;/h3&gt;

&lt;p&gt;Let’s create a toy program for demonstration which does some updates to a local postgres instance. I will be using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;golang&lt;/code&gt; for implementing this but idea is language agnostic.&lt;/p&gt;

&lt;p&gt;We will use a test table in a test database (both table and database are aptly named ‘test’). Following is the schema of the table:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;test=# \d+ test
                         Table &quot;public.test&quot;
 Column |  Type   | Modifiers | Storage | Stats target | Description 
--------+---------+-----------+---------+--------------+-------------
 id     | integer |           | plain   |              | 
 value  | integer |           | plain   |              | 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;the example code:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;package main

import (
  &quot;database/sql&quot;
  &quot;github.com/jmoiron/sqlx&quot;
  _ &quot;github.com/lib/pq&quot;
  “log&quot;
)

func main() {
  for i := 0; i &amp;lt; 750; i++ {
    err := dofn()
	if err != nil {
		log.Println(&quot;err&quot;, err)
		continue
	}
  }
}

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In this program, we are simply calling the function &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dofn()&lt;/code&gt;, 750 times. In each call, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dofn&lt;/code&gt; opens a connection to database ‘test’, reads a value from the table ‘test’ and then either writes (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;INSERT&lt;/code&gt;) the value 1 into table if it does not exist or increments the value (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;UPDATE&lt;/code&gt;) in the table.&lt;/p&gt;

&lt;p&gt;Following is the body for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dofn&lt;/code&gt; implementation:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;func dofn() error {
	db, err := sqlx.Open(&quot;postgres&quot;, &quot;host=127.0.0.1 port=5432 user=postgres password=postgres dbname=test sslmode=disable&quot;)
	if err != nil {
		return err
	}
	defer db.Close()

	tx, err := db.Begin()
	if err != nil {
		return err
	}

	defer tx.Rollback()

	var isExists bool = true
	var id int
	var value int
	err = tx.QueryRow(&quot;SELECT * FROM test WHERE id = 1;&quot;).Scan(&amp;amp;id, &amp;amp;value)
	if err != nil {
		if err == sql.ErrNoRows {
			isExists = false
		} else {
			return err
		}
	}

	if !isExists {
		_, err := tx.Exec(&quot;INSERT INTO test VALUES(1, 1)&quot;)
		if err != nil {
			return err
		}
	} else {
		value = value + 1
		_, err := tx.Exec(&quot;UPDATE test SET value = $1 WHERE id = 1&quot;, value)
		if err != nil {
			return err
		}
	}

	tx.Commit()
	return nil
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Lets open the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;psql&lt;/code&gt; console and delete all rows in the table prior to running this example.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;test=# DELETE FROM test; 
DELETE 0
test=# SELECT * FROM test; 
 id | value 
----+-------
(0 rows)

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now, we compile and run this example, as expected we will get the value updated to 750. This was the sequential run.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;parallels@ubuntu:~/gocode/src/bb/seq$ ./seq 
parallels@ubuntu:~/gocode/src/bb/seq$ sudo -u postgres psql 
psql (9.4.10)
Type &quot;help&quot; for help.

postgres=# \c test
You are now connected to database &quot;test&quot; as user &quot;postgres&quot;.
test=# SELECT * FROM test; 
 id | value 
----+-------
  1 |   750
(1 row)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;let-make-it-a-bit-concurrent&quot;&gt;Let make it a bit concurrent..&lt;/h3&gt;

&lt;p&gt;Now, let’s try to modify the program to do execution with the same &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dofn&lt;/code&gt; but now executing the updates concurrently:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;package main

import	(
	&quot;log&quot;
	&quot;database/sql&quot;
	&quot;github.com/jmoiron/sqlx&quot;
	_ &quot;github.com/lib/pq&quot;
)

func main() {
	for i := 0; i &amp;lt; 3; i++ {
		go launchDoFn() // async launch goroutines (similar to threads) 
	}

	select {}
}

func launchDoFn() {
	for i := 0; i &amp;lt; 250; i++ {
		err := dofn()
		if err != nil {
			log.Println(&quot;err&quot;, err)
			continue
		}
	}	
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;As you see we launch three goroutines - each of which start sequential updates of 250 increments (including one insert). There are basically three concurrent threads you can assume which are updating DB. So let’s compile and run and see the result.&lt;/p&gt;

&lt;p&gt;First, we will again clear the table so that it is empty again:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;postgres=# \c test
You are now connected to database &quot;test&quot; as user &quot;postgres&quot;.
test=# DELETE FROM test; 
DELETE 1
test=# SELECT * FROM test; 
 id | value 
----+-------
(0 rows)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now run it and check the result:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;parallels@ubuntu:~/gocode/src/bb/conc$ ./conc 
2016/12/01 19:06:20 err INSERT pq: duplicate key value violates unique constraint &quot;test_pkey&quot; pq: duplicate key value violates unique constraint &quot;test_pkey&quot;
2016/12/01 19:06:20 err pq: duplicate key value violates unique constraint &quot;test_pkey&quot;
parallels@ubuntu:~/gocode/src/bb/conc$ sudo -u postgres psql 
psql (9.4.10)
Type &quot;help&quot; for help.

postgres=# \c test
You are now connected to database &quot;test&quot; as user &quot;postgres&quot;.
test=# SELECT * FROM test; 
 id | value 
----+-------
  1 |   464
(1 row)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Note: your output may be different - since it is unpredictable but in all likelihood it would be incorrect i.e. not equal to 750.&lt;/p&gt;

&lt;h3 id=&quot;so-what-happened&quot;&gt;So what happened?&lt;/h3&gt;

&lt;p&gt;Well, something like this:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Time&lt;/th&gt;
      &lt;th&gt;Thread A&lt;/th&gt;
      &lt;th&gt;Thread B&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;time t0&lt;/td&gt;
      &lt;td&gt;reads N = 5&lt;/td&gt;
      &lt;td&gt;reads N = 5&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;time t1&lt;/td&gt;
      &lt;td&gt;increments N = N + 1 = 6&lt;/td&gt;
      &lt;td&gt;increments N = N + 1 = 6&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;time t2&lt;/td&gt;
      &lt;td&gt;writes into DB N = 6&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;time t3&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;writes into DB N = 6&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;So instead of the final value = 7 we get the value = 6. This is happening multiple (unpredictable number of) times and hence causing the mismatch between expected and actual results.&lt;/p&gt;

&lt;p&gt;Now, we will discuss how to fix this.&lt;/p&gt;

&lt;h3 id=&quot;a-primer-on-isolation-levels&quot;&gt;A primer on isolation levels&lt;/h3&gt;

&lt;p&gt;Since this is a common problem, SQL standard defines a way to solve this. Basically there are four levels of transaction isolation that are defined. As mentioned on &lt;a href=&quot;https://www.postgresql.org/docs/9.1/static/transaction-iso.html&quot;&gt;postgres documentation page&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;The most strict (isolation level) is Serializable, which is defined by the standard in a paragraph which says that any concurrent execution of a set of Serializable transactions is guaranteed to produce the same effect as running them one at a time in some order. The other three levels are defined in terms of phenomena, resulting from interaction between concurrent transactions, which must not occur at each level.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;dirty read: A transaction reads data written by a concurrent uncommitted transaction.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;nonrepeatable read: A transaction re-reads data it has previously read and finds that data has been modified by another transaction (that committed since the initial read).&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;phantom read: A transaction re-executes a query returning a set of rows that satisfy a search condition and finds that the set of rows satisfying the condition has changed due to another recently-committed transaction.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Isolation Level&lt;/th&gt;
      &lt;th&gt;Dirty Read&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Non repeatable Read&lt;/th&gt;
      &lt;th style=&quot;text-align: right&quot;&gt;Phantom Read&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Read Uncommitted&lt;/td&gt;
      &lt;td&gt;Possible&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;Possible&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;Possible&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Read committed&lt;/td&gt;
      &lt;td&gt;Not possible&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;Possible&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;Possible&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Repeatable Read&lt;/td&gt;
      &lt;td&gt;Not Possible&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;Not Possible&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;Possible&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Serialisable&lt;/td&gt;
      &lt;td&gt;Not Possible&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;Not Possible&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;Not Possible&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;In PostgreSQL, you can request any of the four standard transaction isolation levels. But internally, there are only three distinct isolation levels, which correspond to the levels Read Committed, Repeatable Read, and Serializable.&lt;/p&gt;

&lt;p&gt;Also,&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;.. phantom reads are not possible in the PostgreSQL implementation of Repeatable Read, so the actual isolation level might be stricter than what you select.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is permitted by the SQL standard: the four isolation levels only define which phenomena must not happen, they do not define which phenomena must happen.&lt;/p&gt;

&lt;h3 id=&quot;quick-take-away&quot;&gt;Quick take away!&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;When we set the isolation level to serializable then behind the scene all concurrent updates to a database are performed in serial fashion i.e. one after the other. This clearly translates into bad performance.&lt;/li&gt;
  &lt;li&gt;When we set the isolation level to Repeatable read then behind the scene, database makes sure that of all transactions which are currently executing on a record read in “past” and trying to update the record (pay attention here: say A, B are executing, both read record #3 in table (i.e. did a ‘select’), then try writing into database updated values of record #3) - it is guaranteed that only one of them will succeed and others will fail with “could not serialize access due to concurrent update” error. This is better performant than serializable, fixes the problem of correctness but means that you have to repeat the transactions which fail.&lt;/li&gt;
  &lt;li&gt;Read committed is the default mode of postgres. It is safe when you are concurrently reading but not safe for concurrent updates.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;fixing-using-repeatable-read-isolation-level&quot;&gt;Fixing using repeatable read isolation level&lt;/h3&gt;

&lt;p&gt;As mentioned above, in postgres repeatable read is as strict as serialisable and is more performant than serialisable. So, we will use this isolation level to fix the problem we faced while running concurrent updates.&lt;/p&gt;

&lt;p&gt;We re-write our code for dofn():&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;func dofn() error {
	db, err := sqlx.Open(&quot;postgres&quot;, &quot;host=127.0.0.1 port=5432 user=postgres password=postgres dbname=test sslmode=disable&quot;)
	if err != nil {
		log.Println(&quot;err&quot;, err)
		return err
	}

	defer db.Close()

	var has_committed bool = false

	for ok := true; ok; ok = !has_committed {
		tx, err := db.Begin()
   		if err != nil {
       		log.Println(&quot;err&quot;, &quot;error begining transaction in postgres&quot;, err)
       		return err 
   		}

		defer tx.Rollback()
 		_, err = tx.Exec(`set transaction isolation level repeatable read`)   // &amp;lt;=== SET ISOLATION LEVEL
		if err != nil {
   			return err
		}

		var isExists bool = true
		var id int 
		var value int
		err = tx.QueryRow(&quot;select * from test1 where id = 1;&quot;).Scan(&amp;amp;id, &amp;amp;value)
		if err != nil {
			if err == sql.ErrNoRows {
				isExists = false
			} else {
				return err
			}
		}

		if !isExists {
			_, err := tx.Exec(&quot;INSERT INTO test VALUES(1, 1)&quot;)
			if err != nil {
           		 return err
            }
		} else {
			value = value + 1
			_, err := tx.Exec(&quot;UPDATE test set value = $1 where id = 1&quot;, value)
			if err != nil {
			if strings.Contains(err.Error(), &quot;could not serialize access due to concurrent update&quot;) {
                continue
            } else {
            	return err
            }
		}
	}

	tx.Commit()
	has_committed = true
	}
	return nil
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Let’s again empty the table, compile and run this and see results:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;test=# DELETE FROM test; 
DELETE 1
test=# SELECT * FROM test; 
 id | value 
----+-------
(0 rows)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;parallels@ubuntu:~/gocode/src/bb/conc$ ./conc
2016/12/01 19:28:06 err UPDATE pq: could not serialize access due to concurrent update pq: could not serialize access due to concurrent update
2016/12/01 19:28:06 err UPDATE pq: could not serialize access due to concurrent update pq: could not serialize access due to concurrent update
...
...
... -- many errors and retries --- 
... 
parallels@ubuntu:~/gocode/src/bb/conc$ sudo -u postgres psql 
psql (9.4.10)
Type &quot;help&quot; for help.

postgres=# \c test
You are now connected to database &quot;test&quot; as user &quot;postgres&quot;.
test=# SELECT * FROM test; 
 id | value 
----+-------
  1 |   750
(1 row)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Hence, we see the issue of correctness is resolved and with this change our program is concurrency safe wrt database update.&lt;/p&gt;

&lt;p&gt;The post is longish - thanks for reading it through.&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>Runscope Integration with Mattermost</title>
   <link href="https://awmanoj.github.io/tech/2016/09/24/runscope-integration-with-mattermost/"/>
   <updated>2016-09-24T00:00:00+00:00</updated>
   <id>https://awmanoj.github.io/tech/2016/09/24/runscope-integration-with-mattermost</id>
   <content type="html">&lt;p&gt;&lt;a href=&quot;https://www.runscope.com/&quot;&gt;Runscope&lt;/a&gt; is an API monitoring and testing tool. It allows you to test your web service endpoints periodically (say every 5 mins) for uptime &amp;amp; errors with a good support for alert and notifications.&lt;/p&gt;

&lt;p&gt;We are using Runscope at my workplace to monitor our web services. It has great &lt;a href=&quot;https://www.runscope.com/docs/api-testing/slack&quot;&gt;integration with Slack&lt;/a&gt; so any Runscope tests that results in error would post a notification on one of our Slack channels.&lt;/p&gt;

&lt;p&gt;As I wrote earlier, we are &lt;a href=&quot;https://awmanoj.github.io/tech/2016/09/11/mattermost-opensource-selfhosted-slack-alternative/&quot;&gt;replacing Slack&lt;/a&gt; with an open source alternative - Mattermost.&lt;/p&gt;

&lt;p&gt;Now the problem is that Runscope does not provide any ready-to-use integration with Mattermost. So, we need to do more toil. Basically we can use &lt;a href=&quot;https://www.runscope.com/docs/alerts/notifications#webhook&quot;&gt;Webhook Notifications&lt;/a&gt;. To do this, you run a web service on public IP (or behind ELB) and register it with RunScope for tests you are interested in. This web service will receive a callback from Runscope (and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HTTP POST&lt;/code&gt;) in a certain format containing all data about the test that ran. Your web service can take appropriate action for the callback - e.g. in our case - if we detect there is an error we send a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HTTP POST&lt;/code&gt; to Mattermost with data in same format as we were getting on Slack.&lt;/p&gt;

&lt;p&gt;I have written some example code in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;go&lt;/code&gt; - &lt;a href=&quot;https://github.com/awmanoj/runscope-mattermost-hook&quot;&gt;runscope-mattermost-hook&lt;/a&gt; for the integration service which you may refer or use. If you have feedback please &lt;a href=&quot;https://twitter.com/awmanoj&quot;&gt;tweet&lt;/a&gt; to me.&lt;/p&gt;

&lt;p&gt;Ref: &lt;a href=&quot;https://github.com/awmanoj/runscope-mattermost-hook&quot;&gt;https://github.com/awmanoj/runscope-mattermost-hook&lt;/a&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Mattermost - an opensource self-hosted Slack Alternative</title>
   <link href="https://awmanoj.github.io/tech/2016/09/11/mattermost-opensource-selfhosted-slack-alternative/"/>
   <updated>2016-09-11T00:00:00+00:00</updated>
   <id>https://awmanoj.github.io/tech/2016/09/11/mattermost-opensource-selfhosted-slack-alternative</id>
   <content type="html">&lt;p&gt;If you’re even remotely in tech you would be knowing about and with high chance using &lt;a href=&quot;https://slack.com/&quot;&gt;Slack&lt;/a&gt; - now ubiquitous messaging system which has replaced (almost) &lt;a href=&quot;https://en.wikipedia.org/wiki/Internet_Relay_Chat&quot;&gt;IRCs&lt;/a&gt;, &lt;a href=&quot;https://www.jabber.org/&quot;&gt;Jabber&lt;/a&gt; and other IM-like clients especially in corporates.&lt;/p&gt;

&lt;p&gt;In my current company, we have been using Slack extensively - free version.&lt;/p&gt;

&lt;p&gt;Free version of Slack has some limitations (ofcourse, that’s why it is free!):&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;There is a limit to searchable items (upto 10,000 of your team’s most recent messages)&lt;/li&gt;
  &lt;li&gt;Upto 10 apps or service integrations&lt;/li&gt;
  &lt;li&gt;5 GB of total file storage for the team.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now, these are some serious limitations. Not all channels are made equal e.g. a channel for discussing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;emergency response&lt;/code&gt; would have a higher bearing on losing messages (entire history of discussions!) because of some random chats elsewhere than a general channel for discussing company gossip. In our case, we were losing history of the messages as soon as we consume the limits (10K messages for example) and this used to come without warning.&lt;/p&gt;

&lt;h3 id=&quot;need&quot;&gt;Need..&lt;/h3&gt;

&lt;p&gt;Till the time team is small (say ~ 50-100) you don’t really have to worry about this as much but once the team grows beyond it then requirements arise to curb these limits. The solution is you pay for the service on Slack. This is exactly what we planned.&lt;/p&gt;

&lt;p&gt;The pricing of Slack is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;per user&lt;/code&gt; and minimum pricing that is available from Slack is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$6 per user per month&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;saviour&quot;&gt;Saviour..&lt;/h3&gt;

&lt;p&gt;That is when I got to know about &lt;a href=&quot;https://www.mattermost.org/&quot;&gt;Mattermost&lt;/a&gt; - an opensource self-hosted Slack alternative which is incredibly Slack-compatible. For more than a month, we have been using this alongwith the Slack to get a sense of “if we are not able to do a certain thing”. Till now, functionality wise Mattermost is working for us well.&lt;/p&gt;

&lt;p&gt;Our setup of Mattermost is on AWS:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1&lt;/code&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;t2.medium&lt;/code&gt; EC2 instance (with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1&lt;/code&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;100G&lt;/code&gt; EBS Volume)&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1&lt;/code&gt; RDS instance for postgres&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It provides following benefits:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;No limit to number of messages (well, there is - but it is disk!) so no fear of losing out history.&lt;/li&gt;
  &lt;li&gt;No limit to number of app of service integrations.&lt;/li&gt;
  &lt;li&gt;No limit to the storage.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;(As pointed, limit is elastic - you can always go and upgrade your disk - also, disk is cheap)&lt;/p&gt;

&lt;p&gt;It was simple to switch:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;It is easy to setup. There is an awesome guide to &lt;a href=&quot;https://www.mattermost.org/installation/&quot;&gt;setup mattermost&lt;/a&gt; on its site.&lt;/li&gt;
  &lt;li&gt;It is not only slack compatible - the interface is also similar. So no “learning curve” friction.&lt;/li&gt;
  &lt;li&gt;We were able to move all our existing slack integrations to Mattermost because of awesome compatibility. In most cases (except runscope - which I will write about sometime), you will just need to replace Slack webhook url with the Mattermost webhook url. It’s that simple.&lt;/li&gt;
  &lt;li&gt;Mattermost comes with both an Android and an iOS App.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;/public/assets/img/mm.png&quot; alt=&quot;Mattermost&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;cost-comparison&quot;&gt;Cost comparison..&lt;/h3&gt;

&lt;p&gt;The approximate per month cost (as per &lt;a href=&quot;http://www.ec2instances.info/&quot;&gt;this site&lt;/a&gt;) would be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$50&lt;/code&gt; (EC2) + &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$10&lt;/code&gt; (100GB storage) + &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$30&lt;/code&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;2GB&lt;/code&gt; RAM RDS postgres instance) = &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$90&lt;/code&gt;. This is approximate so let’s round it to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$100&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This is not per user. :-)&lt;/p&gt;

&lt;p&gt;The strength of my company is 500+ currently and it’s growing fast. Even if we assume 50% of them being active on slack (which is an underestimate) we can see quickly that cost of buying the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Standard&lt;/code&gt; Slack would be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$6 * 250 = $1500&lt;/code&gt; per month. As compared to this, the cost of setting up and running Mattermost for communication needs is meagre &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$100&lt;/code&gt; per month.&lt;/p&gt;

&lt;h3 id=&quot;downsides&quot;&gt;Downsides..&lt;/h3&gt;

&lt;p&gt;One problem which we have faced and have heard complaints from teams is around Notifications in Mattermost. Notifications are not as smooth as Slack for Mobile and Desktop both. There is delay and alerting doesn’t work sometime in realtime. In worst cases, what I have observed is that with a delay of few minutes we do get notifications.&lt;/p&gt;

&lt;p&gt;But with Mattermost setup, the load on Slack (free version) anyways comes down so you can choose to keep few alerting systems running on free version Slack and move more persistent kind of requirements (like chat, datadog integrations, consul integrations) on Mattermost.&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>Consul Integration with Opsgenie</title>
   <link href="https://awmanoj.github.io/tech/2016/09/11/consul-integration-with-opsgenie/"/>
   <updated>2016-09-11T00:00:00+00:00</updated>
   <id>https://awmanoj.github.io/tech/2016/09/11/consul-integration-with-opsgenie</id>
   <content type="html">&lt;p&gt;In past I discussed about using &lt;a href=&quot;https://awmanoj.github.io/tech/2016/08/27/service-discovery-configuration-management-with-consul/&quot;&gt;consul as a service discovery and configuration management solution&lt;/a&gt; and how to &lt;a href=&quot;https://awmanoj.github.io/tech/2016/09/03/using-consul-watch-and-git/&quot;&gt;configure for alerts on key value changes&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.opsgenie.com/&quot;&gt;Opsgenie&lt;/a&gt; is a must-have tool for &lt;a href=&quot;https://landing.google.com/sre/interview/ben-treynor.html&quot;&gt;SRE team&lt;/a&gt; of any company beyond a certain scale. It enables alerts on some events (services down for example) via email, SMS, mobile push and even phone calls (so this is the enabler for dreaded pager service).&lt;/p&gt;

&lt;p&gt;At my company we use opsgenie and SRE team is on a constant roster - so on a rotation basis different engineers are on-call.&lt;/p&gt;

&lt;p&gt;There was a request to integrate service health on consul to opsgenie. Quick search over internet revealed that there is a solution called &lt;a href=&quot;https://github.com/AcalephStorage/consul-alerts&quot;&gt;consul-alerts&lt;/a&gt; which is also the official &lt;a href=&quot;https://www.opsgenie.com/docs/integrations/consul-integration&quot;&gt;recommendation from opsgenie&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;After installing it and trying to figure out - to be frank - I couldn’t comprehend it well (couldn’t get it deliver notifications successfully rather). So I thought, let me get to first principles and use the native &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;consul watch&lt;/code&gt; command and some &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bash&lt;/code&gt; to do the simple job (isn’t KISS something never to be forgotten?) and came up with this simple(st possible) script which does the job well. This script is invoked from an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;upstart&lt;/code&gt; script (ubuntu 14.04) which takes care of re-running it if it gets killed somehow.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;c&quot;&gt;#!/bin/bash &lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;OLD_SERVICES_CRITICAL&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; 1 &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do 
  &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rm&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; /tmp/consul/services.txt
  consul-template &lt;span class=&quot;nt&quot;&gt;-consul&lt;/span&gt; &amp;lt;___CONSUL_SERVICE_IP_HERE____&amp;gt;:8500 &lt;span class=&quot;nt&quot;&gt;-template&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/tmp/consul/services.alert.ctmpl:/tmp/consul/services.txt&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-once&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;SERVICES_CRITICAL&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; /tmp/consul/services.txt | &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; critical | &lt;span class=&quot;nb&quot;&gt;awk&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'{print &quot;[&quot;$1&quot; &quot;$2&quot;]&quot;}'&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-z&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$OLD_SERVICES_CRITICAL&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-z&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$SERVICES_CRITICAL&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; 
    &lt;span class=&quot;nv&quot;&gt;OLD_SERVICES_CRITICAL&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;fi

  if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-z&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$SERVICES_CRITICAL&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$SERVICES_CRITICAL&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-ne&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$OLD_SERVICES_CRITICAL&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
    &lt;/span&gt;curl &lt;span class=&quot;nt&quot;&gt;-XPOST&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'https://api.opsgenie.com/v1/json/alert'&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;{
      &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;apiKey&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;______YOUR_OPSGENIE_KEY_HERE______&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;, 
      &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Services down: &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$SERVICES_CRITICAL&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;,
      &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;teams&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;: [&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;______YOUR_SRE_TEAM_NAME_HERE_____&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;]
    }&quot;&lt;/span&gt;
    
    &lt;span class=&quot;c&quot;&gt;# Add an alert to Slack.&lt;/span&gt;
    &lt;span class=&quot;c&quot;&gt;#... &lt;/span&gt;

    &lt;span class=&quot;c&quot;&gt;# Add an alert to Mattermost.&lt;/span&gt;
    &lt;span class=&quot;c&quot;&gt;#... &lt;/span&gt;

    &lt;span class=&quot;nv&quot;&gt;OLD_SERVICES_CRITICAL&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$SERVICES_CRITICAL&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;fi&lt;/span&gt;

  &lt;span class=&quot;c&quot;&gt;## every 10 seconds&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;sleep &lt;/span&gt;10
&lt;span class=&quot;k&quot;&gt;done&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;service.alert.ctmpl&lt;/code&gt; is simple - it lists down all service names, their IP, their port and current status (passing, warning, critical etc.):&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;o&quot;&gt;{{&lt;/span&gt; range services &lt;span class=&quot;o&quot;&gt;}}{{&lt;/span&gt; range service .Name &lt;span class=&quot;s2&quot;&gt;&quot;any&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;{{&lt;/span&gt;.Name&lt;span class=&quot;o&quot;&gt;}}&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{{&lt;/span&gt;.Address&lt;span class=&quot;o&quot;&gt;}}&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{{&lt;/span&gt;.Port&lt;span class=&quot;o&quot;&gt;}}&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{{&lt;/span&gt;.Status&lt;span class=&quot;o&quot;&gt;}}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;{{&lt;/span&gt;end&lt;span class=&quot;o&quot;&gt;}}{{&lt;/span&gt; end &lt;span class=&quot;o&quot;&gt;}}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;It took less than 5 minutes to get this running.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>On slow regular expressions in golang</title>
   <link href="https://awmanoj.github.io/tech/2016/09/08/on-slow-regular-expressions-golang/"/>
   <updated>2016-09-08T00:00:00+00:00</updated>
   <id>https://awmanoj.github.io/tech/2016/09/08/on-slow-regular-expressions-golang</id>
   <content type="html">&lt;p&gt;Few months back, a colleague mentioned over lunch &lt;a href=&quot;http://benchmarksgame.alioth.debian.org/u64q/compare.php?lang=go&amp;amp;lang2=python3&quot;&gt;how slow golang regular expressions are&lt;/a&gt; - this was not only compared to awesome performance of Perl regex or PCRE but also other languages. Recently, while looking for threads discussing Go vs Python wrt regex I got hold of following comments (by &lt;a href=&quot;https://swtch.com/~rsc/&quot;&gt;Russ Cox&lt;/a&gt;):&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;First of all, Ruby and Python are using C implementations of the regexp search, so Go is being beat by C, not by Ruby.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;More importantly,&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Second, Go is using a different algorithm for regexp matching than the C implementations in those other languages. The algorithm Go uses guarantees to complete in time that is linear in the length of the input. The algorithm that Ruby/Python/etc are using can take time exponential in the length of the input, although on trivial cases it typically runs quite fast. In order to guarantee the linear time bound, Go’s algorithm’s best case speed a little slower than the optimistic Ruby/Python/etc algorithm. On the other hand, there are inputs for which Go will return quickly and Ruby/Python/etc need more time than is left before the heat death of the universe. It’s a decent tradeoff.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Take away 1: Fair enough!&lt;/p&gt;

&lt;p&gt;Take away 2: Prefer using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;strings&lt;/code&gt; functions if your job gets done with that. Didn’t authors already tell us Go is an opinionated language!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Using consul watch and git diff to track key value changes</title>
   <link href="https://awmanoj.github.io/tech/2016/09/03/using-consul-watch-and-git/"/>
   <updated>2016-09-03T00:00:00+00:00</updated>
   <id>https://awmanoj.github.io/tech/2016/09/03/using-consul-watch-and-git</id>
   <content type="html">&lt;p&gt;In the &lt;a href=&quot;https://awmanoj.github.io/tech/2016/08/27/service-discovery-configuration-management-with-consul/&quot;&gt;previous post&lt;/a&gt; I introduced how consul is a simple, distributed and fault tolerant system for service discovery and configuration management.&lt;/p&gt;

&lt;p&gt;Now, a common need is how do we track if someone has changed a key value or added or deleted a key? Solution is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;consul watch&lt;/code&gt; command. We can use &lt;a href=&quot;https://www.consul.io/docs/agent/watches.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;consul watch&lt;/code&gt;&lt;/a&gt; for registering a handler which gets called whenever there is a key-value change. Its format is:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;consul watch &lt;span class=&quot;nt&quot;&gt;-http-addr&lt;/span&gt; consul.service.local:8500 &lt;span class=&quot;nt&quot;&gt;-type&lt;/span&gt; keyprefix &lt;span class=&quot;nt&quot;&gt;-prefix&lt;/span&gt; global /usr/local/bin/watch_handler.sh&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;But there is a problem - everytime there is a change in a key value e.g. key &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;global/redis/cacheA&lt;/code&gt; is changed from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;192.168.1.1&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;192.168.1.2&lt;/code&gt; then consul watch handler gets invoked with latest values only i.e. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;192.168.1.2&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We felt that there is a need to know the change in full context i.e. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;old_value&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;new_value&lt;/code&gt;. After some searching and not finding a solution we devised a method (rather novel I’d say but I am blinded by bias) by using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git&lt;/code&gt; - the most awesome change control system - in local mode (no &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;remote&lt;/code&gt; set).&lt;/p&gt;

&lt;p&gt;Idea is simple.&lt;/p&gt;

&lt;p&gt;Following steps are to be done as part of the initial setup:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;On the node where you want to setup the alert system designate a directory say &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/var/consul/data&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Run following command to initialize this directory as a git repo.&lt;/li&gt;
&lt;/ul&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git init&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;ul&gt;
  &lt;li&gt;Run following command to save the latest snapshot of all key values for keys starting with prefix &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;global&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kvs.txt&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;consul watch &lt;span class=&quot;nt&quot;&gt;-http-addr&lt;/span&gt; consul.service.local:8500 &lt;span class=&quot;nt&quot;&gt;-type&lt;/span&gt; keyprefix &lt;span class=&quot;nt&quot;&gt;-prefix&lt;/span&gt; global &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; kvs.txt&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;ul&gt;
  &lt;li&gt;Add and commit to the local git repo&lt;/li&gt;
&lt;/ul&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git add kvs.txt 
... 
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git commit &lt;span class=&quot;nt&quot;&gt;-m&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Update kvs.txt&quot;&lt;/span&gt;
...&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Once the above setup is done - run the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;consul watch&lt;/code&gt; in daemon mode (via upstart preferably):&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;consul watch &lt;span class=&quot;nt&quot;&gt;-http-addr&lt;/span&gt; consul.service.local:8500 &lt;span class=&quot;nt&quot;&gt;-type&lt;/span&gt; keyprefix &lt;span class=&quot;nt&quot;&gt;-prefix&lt;/span&gt; global /usr/local/bin/watch_handler.sh&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This ensures that when there is a change in any of the key values under the specified prefixed keys then it will trigger the execution of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;watch_handler.sh&lt;/code&gt;. This script does following on each such trigger:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Change directory to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/var/consul/data/&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Run following command to get the latest (post change) key values:&lt;/li&gt;
&lt;/ul&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;consul watch &lt;span class=&quot;nt&quot;&gt;-http-addr&lt;/span&gt; consul.service.local:8500 &lt;span class=&quot;nt&quot;&gt;-type&lt;/span&gt; keyprefix &lt;span class=&quot;nt&quot;&gt;-prefix&lt;/span&gt; global &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; kvs.txt&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;ul&gt;
  &lt;li&gt;Execute &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git diff&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
  &lt;p&gt;If empty (no change) then don’t do anything else trigger your alert mechanism with the output of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git diff&lt;/code&gt; command (e.g. mail, &lt;a href=&quot;https://api.slack.com/incoming-webhooks&quot;&gt;slack&lt;/a&gt;, &lt;a href=&quot;https://docs.mattermost.com/developer/webhooks-incoming.html&quot;&gt;mattermost&lt;/a&gt; etc.)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
  &lt;li&gt;Now that the alert is already sent - commit the new change locally.&lt;/li&gt;
&lt;/ul&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git add kvs.txt 
... 
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git commit &lt;span class=&quot;nt&quot;&gt;-m&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Update kvs.txt&quot;&lt;/span&gt;
...&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Note: You will need to do a bit more actually than just &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git diff&lt;/code&gt; since the diff command gives values in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;base64 encoding&lt;/code&gt;. To convert that into readable values you will need to use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;base64&lt;/code&gt; utility and some play with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sed&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;awk&lt;/code&gt; etc. Following is some code which can be handy:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;OLD&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;git diff | &lt;span class=&quot;nb&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'s/\&quot;//g'&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;grep &lt;/span&gt;Value | &lt;span class=&quot;nb&quot;&gt;awk&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-F&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'Value:'&lt;/span&gt;  &lt;span class=&quot;s1&quot;&gt;'{print $2}'&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;awk&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-F&lt;/span&gt;, &lt;span class=&quot;s1&quot;&gt;'{print $1}'&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;awk&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'{print $1}'&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;head&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-1&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;base64&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'s/^/&amp;gt;/g'&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'s/$/\\n/g'&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt; 
&lt;span class=&quot;nv&quot;&gt;NEW&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;git diff | &lt;span class=&quot;nb&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'s/\&quot;//g'&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;grep &lt;/span&gt;Value | &lt;span class=&quot;nb&quot;&gt;awk&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-F&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'Value:'&lt;/span&gt;  &lt;span class=&quot;s1&quot;&gt;'{print $2}'&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;awk&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-F&lt;/span&gt;, &lt;span class=&quot;s1&quot;&gt;'{print $1}'&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;awk&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'{print $1}'&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'2q;d'&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;base64&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'s/^/&amp;gt;/g'&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'s/$/\\n/g'&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This is a screenshot of the change alert in our slack:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/public/assets/img/consul-watch.png&quot; alt=&quot;Slack consul change alert screenshot&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;epilogue&quot;&gt;Epilogue&lt;/h3&gt;

&lt;p&gt;In addition to providing the full context of change, this solution is also useful in keeping a local versioned history and is helpful in reverting to older values easily by using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git revert&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git reset ... &lt;/code&gt; commands.&lt;/p&gt;

&lt;p&gt;Credit to use of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git&lt;/code&gt; for this goes to &lt;a href=&quot;https://twitter.com/kernelhacker&quot;&gt;@kernelhacker&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I don’t yet know if there is any other builtin technique in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;consul-watch&lt;/code&gt; to achieve the same thing. If you know please drop a tweet at &lt;a href=&quot;https://twitter.com/awmanoj&quot;&gt;@awmanoj&lt;/a&gt;. TIA.&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>Service discovery, configuration management with Consul</title>
   <link href="https://awmanoj.github.io/tech/2016/08/27/service-discovery-configuration-management-with-consul/"/>
   <updated>2016-08-27T00:00:00+00:00</updated>
   <id>https://awmanoj.github.io/tech/2016/08/27/service-discovery-configuration-management-with-consul</id>
   <content type="html">&lt;p&gt;If you have a reasonably growing setup of services then you would already know what kind of hell configuration management becomes. Let me give an example. Suppose there are three services A, B and C which depend on two redis instances &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;192.168.1.1:6379&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;192.168.1.2:6379&lt;/code&gt; and a postgres instance &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;192.168.1.3:5432&lt;/code&gt; then your configuration for the three services would look something like this:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;Redis]
	cacheA &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 192.168.1.1:6379
	cacheB &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 192.168.1.2:6379
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;Postgres]
	mainDb &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 192.168.1.3:5432 
... &lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Now, add to this the fact that services could be concurrent and running on multiple servers behind some load balancer i.e. A is not one single physical server (or VM) but multiple i.e. A1, A2, A3 and similarly B is say B1, B2 and C is say just C1.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/public/assets/img/ex-setup.png&quot; alt=&quot;Example setup&quot; /&gt;&lt;/p&gt;

&lt;p&gt;So probably you already see the problem. If we have some trouble with redis cacheA and we have to replace this instance with another one say &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;192.168.1.4:6379&lt;/code&gt; then we essentially have two options:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Manually ssh to each of the running instances (i.e. A1, A2, A3, B1, B2, C1), make the configuration change and restart or reload the service.&lt;/li&gt;
  &lt;li&gt;Better - make the change in configuration in the code and redeploy the services on instances using the continuous integration system you’re using (jenkins?).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The second of the above two is less painful but is waste of effort if this switch to alternate redis is temporary. It also takes considerable effort in terms of making change to code on all three repositories (A, B and C), building them via continuous integration system and deploying. It also takes considerable time.&lt;/p&gt;

&lt;p&gt;A related problem to configuration management is Service discovery. Let’s take for example following nginx configuration which defines a server that is reverse proxy to few backend instances of services.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;upstream backend &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    server backend1.example.com &lt;span class=&quot;nv&quot;&gt;weight&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;5&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    server backend2.example.com&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    server backend3.example.com&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    server backup1.example.com  backup&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

server &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    ...
    location /v1/awesome/service &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        proxy_pass backend&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Nginx is awesome in distributing load on the site amongst the instances backend1, backend2 and backend3 in weighted round robin fashion. But how do we deal with servers which are down? Suppose backend2.example.com goes down - we would ideally want to remove it from the configuration immediately making it look like:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;upstream backend &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    server backend1.example.com &lt;span class=&quot;nv&quot;&gt;weight&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;5&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    server backend3.example.com&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    server backup1.example.com  backup&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
...&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Also, as soon as the service backend2.example.com is online again, we should add it to the backend:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;upstream backend &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    server backend1.example.com &lt;span class=&quot;nv&quot;&gt;weight&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;5&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    server backend2.example.com&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    server backend3.example.com&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    server backup1.example.com  backup&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
...&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Do we have a solution? Actually, there are many solutions for this problem. One of them is topic of this post.&lt;/p&gt;

&lt;h3 id=&quot;consul-&quot;&gt;consul.. !&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://www.consul.io/&quot;&gt;Consul&lt;/a&gt; is a very simple service discovery and configuration management solution. This means it can store configuration data or rather any kind of key-value data. It can also maintain services information i.e. services can register and deregister with consul. Consul provides HTTP and DNS APIs for service discovery. It is distributed, HA and datacenter-aware.&lt;/p&gt;

&lt;p&gt;The last property is particularly useful - if you have multiple data centers (multiple availability zones in AWS or may be a DC from AWS and another on from Google or Alibaba) then you can have a consul cluster on each of them which can contain cluster specific configuration (key value stores, service information) and each of those clusters can be made to be aware of the other. As needed configuration can be &lt;a href=&quot;https://github.com/hashicorp/consul-replicate&quot;&gt;replicated too across data centers&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Consul is written in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;go&lt;/code&gt; and hence is available as a native binary. It is in the same league of softwares as &lt;a href=&quot;https://coreos.com/etcd/&quot;&gt;etcd&lt;/a&gt;, &lt;a href=&quot;https://zookeeper.apache.org/&quot;&gt;zookeeper&lt;/a&gt; etc. (in terms of functional usage) but I think it is much simpler for deployment and usage.&lt;/p&gt;

&lt;h3 id=&quot;setup&quot;&gt;Setup&lt;/h3&gt;

&lt;p&gt;You can play with consul by following &lt;a href=&quot;https://www.consul.io/docs/agent/basics.html&quot;&gt;this quickstart guide&lt;/a&gt;. For production deployment you can use this awesome guide for &lt;a href=&quot;https://www.digitalocean.com/community/tutorials/how-to-configure-consul-in-a-production-environment-on-ubuntu-14-04&quot;&gt;production setup of consul on Ubuntu&lt;/a&gt; (other guides also available there).&lt;/p&gt;

&lt;p&gt;As part of consul cluster setup you will also setup consul Web UI which is the interface to list all services registered with consul, how many nodes under each of the services are running successful (‘passing’ or ‘failing’), all key values (complete CRUD for these and hence you can create, modify keys from the UI itself). Following are the screenshots for web UI (services and key values):&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/public/assets/img/services-1.png&quot; alt=&quot;consul web UI - services&quot; /&gt;
&lt;img src=&quot;/public/assets/img/keyvalue.png&quot; alt=&quot;consul web UI - key values&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;consul-template&quot;&gt;Consul-template&lt;/h3&gt;

&lt;p&gt;Now, that you have the cluster ready and populated with configuration data (key values) that you would want to refer to from apps - how really do you use these. Here comes &lt;a href=&quot;https://github.com/hashicorp/consul-template&quot;&gt;consul-template&lt;/a&gt; - another native binary produced from the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;go&lt;/code&gt; code. From it’s read me:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;This project provides a convenient way to populate values from Consul into the file system using the consul-template daemon.
The daemon consul-template queries a Consul instance and updates any number of specified templates on the file system.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;and ..&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;As an added bonus, consul-template can optionally run arbitrary commands when the update process completes.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;configuration-management&quot;&gt;Configuration Management&lt;/h3&gt;

&lt;p&gt;So - let’s get back to our examples above. To recap, we had three services A, B and C. Each had a configuration referring the two redis instances cacheA and cacheB.&lt;/p&gt;

&lt;p&gt;With consul:&lt;/p&gt;

&lt;p&gt;o. you replace the fixed configuration file in your code:&lt;/p&gt;

&lt;p&gt;file: app.prod.ini&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;Redis]
	cacheA &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 192.168.1.1:6379
	cacheB &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 192.168.1.2:6379
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;Postgres]
	mainDb &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 192.168.1.3:5432 &lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;with a consul template file:&lt;/p&gt;

&lt;p&gt;file: app.prod.ini.ctmpl&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;Redis]
    cacheA &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{{&lt;/span&gt; key &lt;span class=&quot;s2&quot;&gt;&quot;service/redis/cacheA&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}}&lt;/span&gt;
    cacheB &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{{&lt;/span&gt; key &lt;span class=&quot;s2&quot;&gt;&quot;service/redis/cacheB&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;Postgres]
    mainDb &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{{&lt;/span&gt; key &lt;span class=&quot;s2&quot;&gt;&quot;service/postgresql/mainDb&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}}&lt;/span&gt; // ignore username, password etc.&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;o. you install consul-template on each of those instances where the services A, B and C are running.&lt;/p&gt;

&lt;p&gt;Note that this is a one-time investment and things will be even easier if you are using some automation tool like ansible or cloudformation (or chef, puppet). If you aren’t using any of these and still setting up every new server by hand - you should try one of these - my current favorite is Ansible.&lt;/p&gt;

&lt;p&gt;so, now A1, A2, A3, B1, B2, C1 all have consul-template installed. Create an upstart for consul-template in which you run it as a daemon like following:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;/usr/local/bin/consul-template &lt;span class=&quot;nt&quot;&gt;-consul&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&amp;lt;__ONE_OF_CONSUL_NODES_IP&amp;gt;:8500&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-template&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/etc/appA/app.prod.ini.ctmpl:/etc/appA/app.prod.ini&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; /var/log/consul.log 2&amp;gt;&amp;amp;1&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Your apps will be responsible for upstart scripts in this case and will be installed on deployment.&lt;/p&gt;

&lt;p&gt;o. Now, when your redis instance cacheA goes down as we assumed in our hypothetical scenario above and you have to replace it with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;192.168.1.4:6379&lt;/code&gt; you simply need to go to consul web UI and update the key &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;service/redis/cacheA&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;192.168.1.4:6379&lt;/code&gt; and consul-template which is running as a daemon will update the configuration instantly. Consul-template takes more arguments and you can write better command line by using config instead of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-consul&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-template&lt;/code&gt; as mentioned above. In the config format you can specify how to reload your app after config update happens. You can read more about it on the &lt;a href=&quot;https://github.com/hashicorp/consul-template&quot;&gt;consul-template readme&lt;/a&gt;. Btw, you just saw how automated configuration management now is &amp;amp; you’re done!&lt;/p&gt;

&lt;h3 id=&quot;service-discovery&quot;&gt;Service Discovery&lt;/h3&gt;

&lt;p&gt;A service is registered with consul cluster by running &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;consul&lt;/code&gt; in client mode and keeping some configuration about the service in consul configuration directory. Alternatively, we can also use consul HTTP API for registering a service. You can get a &lt;a href=&quot;https://www.consul.io/docs/agent/services.html&quot;&gt;comprehensive documentation&lt;/a&gt; on the consul website.&lt;/p&gt;

&lt;p&gt;file: /etc/consul.d/redis_cache_a.json&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;s2&quot;&gt;&quot;service&quot;&lt;/span&gt;: &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&quot;name&quot;&lt;/span&gt;: &lt;span class=&quot;s2&quot;&gt;&quot;redis-cache-a&quot;&lt;/span&gt;,
    &lt;span class=&quot;s2&quot;&gt;&quot;tags&quot;&lt;/span&gt;: &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;master&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;,
    &lt;span class=&quot;s2&quot;&gt;&quot;address&quot;&lt;/span&gt;: &lt;span class=&quot;s2&quot;&gt;&quot;127.0.0.1&quot;&lt;/span&gt;,
    &lt;span class=&quot;s2&quot;&gt;&quot;port&quot;&lt;/span&gt;: 6379,
    &lt;span class=&quot;s2&quot;&gt;&quot;enableTagOverride&quot;&lt;/span&gt;: &lt;span class=&quot;nb&quot;&gt;false&lt;/span&gt;,
    &lt;span class=&quot;s2&quot;&gt;&quot;checks&quot;&lt;/span&gt;: &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;s2&quot;&gt;&quot;script&quot;&lt;/span&gt;: &lt;span class=&quot;s2&quot;&gt;&quot;/usr/local/bin/check_redis.py&quot;&lt;/span&gt;,
        &lt;span class=&quot;s2&quot;&gt;&quot;interval&quot;&lt;/span&gt;: &lt;span class=&quot;s2&quot;&gt;&quot;10s&quot;&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;There are few things here to note. We can specify a custom check script which is health checker of the service. If this script fails then consul marks the node as failed or service as down. You can also use following instead of a bash script:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt; 
&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
...
  &lt;span class=&quot;s2&quot;&gt;&quot;checks&quot;&lt;/span&gt;: &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; 
    &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; 
      &lt;span class=&quot;s2&quot;&gt;&quot;tcp&quot;&lt;/span&gt;: &lt;span class=&quot;s2&quot;&gt;&quot;127.0.0.1:6379&quot;&lt;/span&gt;,
      .. 
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt; 
  &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
..
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This basically checks TCP connection on the specified port. There is more comprehensive list of possible checks in docs.&lt;/p&gt;

&lt;p&gt;Other thing to note is the name of the service - this is an identifier of the service and hence it should be chosen as service identifier. It is recommended though to keep it readable and easy to remember. If your service A has a codename e.g. some greek god (what else?) like zeus then you can use that here.&lt;/p&gt;

&lt;p&gt;Once your service is registered with consul, you can check it on both HTTP and DNS interface. Let’s see how it is to check it on DNS interface using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dig&lt;/code&gt; unix utility:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;dig @127.0.0.1 &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; 8600 redis-cache-a.service.dc1.consul. ANY&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;(dc1 is the datacenter name for consul)&lt;/p&gt;

&lt;p&gt;Once this is setup and your services are registered you can use consul-template again to generate nginx configuration file based on which services are alive.&lt;/p&gt;

&lt;p&gt;file: awesome-service.awesome.net&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt; 
upstream backend &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    server backend1.example.com&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    server backend2.example.com&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    server backend3.example.com&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

server &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    ...
    location /v1/awesome/service &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        proxy_pass backend&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;file: awesome-service.awesome.net.ctmpl&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt; 

upstream backend &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;{{&lt;/span&gt;range service &lt;span class=&quot;s2&quot;&gt;&quot;web@dc1&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;}}&lt;/span&gt;
    server &lt;span class=&quot;o&quot;&gt;{{&lt;/span&gt;.Address&lt;span class=&quot;o&quot;&gt;}}&lt;/span&gt;:&lt;span class=&quot;o&quot;&gt;{{&lt;/span&gt;.Port&lt;span class=&quot;o&quot;&gt;}}{{&lt;/span&gt;end&lt;span class=&quot;o&quot;&gt;}}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

server &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    ...
    location /v1/awesome/service &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        proxy_pass backend&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Consul returns, by default, only healthy services. You just saw how it can completely automate your configuration management and service discovery. Following is a sequence diagram of how the config changes take place:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/public/assets/img/consul-sd.png&quot; alt=&quot;consul sequence diagram&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I have just touched the tip of iceberg with respect to the possibilities with consul - an introduction. If you aren’t tied up to another configuration management solution do give it a try.&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>Using Boltdb as a fast, persistent key value store</title>
   <link href="https://awmanoj.github.io/2016/08/03/using-boltdb-as-a-fast-persistent-kv-store/"/>
   <updated>2016-08-03T00:00:00+00:00</updated>
   <id>https://awmanoj.github.io/2016/08/03/using-boltdb-as-a-fast-persistent-kv-store</id>
   <content type="html">&lt;hr /&gt;

&lt;p&gt;&lt;em&gt;Originally posted on &lt;a href=&quot;http://tech.tokopedia.com/blog/using-boltdb-as-a-fast-persistent-kv-store/&quot;&gt;Tokopedia Tech Blog&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;hr /&gt;

&lt;p&gt;Recently, we at &lt;a href=&quot;https://www.tokopedia.com/&quot;&gt;Tokopedia&lt;/a&gt; rearchitected a &lt;a href=&quot;https://golang.org/&quot;&gt;golang&lt;/a&gt; microservice which maps an Image (as in picture, photo, ..) ID to the fully qualified server name that hosts the image.&lt;/p&gt;

&lt;h3 id=&quot;a-bit-of-context-is-always-good&quot;&gt;A bit of context is always good..&lt;/h3&gt;

&lt;p&gt;Historically, we stored images and served images from multiple servers for reasons of scale. The mapping of which image is located on which server was in mongodb. And there was a layer of caching on top of it in redis, because mongo didn’t scale very well for the workload.&lt;/p&gt;

&lt;p&gt;Gradually, we moved stuff to s3, which means all images uploaded from that point onwards could now be served from a single server, and no such mapping was required. However, old images were still being served in the same way, and they needed the mapping. The difference was, our database was now read only and fixed size.&lt;/p&gt;

&lt;p&gt;We still occasionally suffered with memory spikes and service killed by linux oom-killer leading to both latency and downtimes.&lt;/p&gt;

&lt;h3 id=&quot;search-for-alternative&quot;&gt;Search for alternative..&lt;/h3&gt;

&lt;p&gt;Requirements for the service:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Persistent storage&lt;/li&gt;
  &lt;li&gt;Fast retrieval (tens of thousand QPS)&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Read only&lt;/code&gt; usage&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Since our requirement is also “read-heavy” usage on a fixed size database (infact, it is read-only usage) we knew we need a lightweight embedded DB solution. There are multiple solutions that exist for this problem but we zeroed on &lt;a href=&quot;https://github.com/boltdb/bolt&quot;&gt;Boltdb&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;why-boltdb&quot;&gt;Why Boltdb?&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;written in &lt;a href=&quot;https://golang.org/&quot;&gt;go&lt;/a&gt; and hence fits with rest of the stack well.&lt;/li&gt;
  &lt;li&gt;compact, fast (it based on &lt;a href=&quot;https://symas.com/products/lightning-memory-mapped-database/&quot;&gt;LMDB&lt;/a&gt;. Both use a B+tree, have ACID semantics with fully serializable transactions, and support lock-free MVCC using a single writer and multiple readers.&lt;/li&gt;
  &lt;li&gt;LMDB heavily focuses on raw performance while Bolt has focused on simplicity and ease of use.&lt;/li&gt;
  &lt;li&gt;fits better for a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;read heavy&lt;/code&gt; usage.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;how-to-use&quot;&gt;How to use?&lt;/h3&gt;

&lt;p&gt;In pure sense, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;boltdb&lt;/code&gt; is not really a database but simply a memory mapped file but it provides ACID semantics as provided by databases so calling it a DB is not misnomer. It comes as a library so installation is as simple as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;importing&lt;/code&gt; a go package.&lt;/p&gt;

&lt;p&gt;You can go through the detailed &lt;a href=&quot;https://github.com/boltdb/bolt&quot;&gt;README&lt;/a&gt; and &lt;a href=&quot;https://godoc.org/github.com/boltdb/bolt&quot;&gt;GoDoc&lt;/a&gt; to get started.&lt;/p&gt;

&lt;p&gt;Opening database is as simple as:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-go&quot; data-lang=&quot;go&quot;&gt;&lt;span class=&quot;n&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;err&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bolt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;my.db&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0666&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bolt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ReadOnly&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;err&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;nil&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Fatal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Add a key value (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;answer&lt;/code&gt; = &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;42&lt;/code&gt;):&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-go&quot; data-lang=&quot;go&quot;&gt;&lt;span class=&quot;n&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Update&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;func&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tx&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bolt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Tx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tx&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Bucket&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([]&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;byte&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;MyBucket&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;err&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Put&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([]&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;byte&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;answer&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;byte&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;42&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;err&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Fetch a value by key:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-go&quot; data-lang=&quot;go&quot;&gt;&lt;span class=&quot;n&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;View&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;func&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tx&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bolt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Tx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tx&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Bucket&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([]&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;byte&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;MyBucket&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([]&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;byte&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;answer&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;fmt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;The answer is: %s&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;nil&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h3 id=&quot;command-line-utility---bolt&quot;&gt;Command line utility - &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bolt&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;Boltdb comes with a command line utility which can be used to inspect the correctness and statistics of a BoltDB file.&lt;/p&gt;

&lt;h3 id=&quot;if-life-was-that-easy-&quot;&gt;If life was that easy.. !&lt;/h3&gt;

&lt;p&gt;We imported all &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mongodb&lt;/code&gt; data using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mongo-export&lt;/code&gt; utility. It was &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~4 GB&lt;/code&gt; in size. We exported it to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;boltdb&lt;/code&gt; using an export tool we wrote in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;golang&lt;/code&gt;. The output file was a single &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bolt.db&lt;/code&gt; file with size &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~ 13 GB&lt;/code&gt;. This size increase was expected due to the internal data structure being used by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;boltdb&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;What was not expected (or rather &lt;strong&gt;we&lt;/strong&gt; did not expect it) was that export tool became exponentially slower as the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bolt.db&lt;/code&gt; file grew larger. We estimated that each export would take days in this manner (in case we need to).&lt;/p&gt;

&lt;p&gt;To solve this problem, we decided to use - you guessed it right - &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sharding&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;We broke down the initial &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mongodb&lt;/code&gt; dump into &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;N&lt;/code&gt; files (&lt;a href=&quot;http://math.stackexchange.com/questions/183909/why-choose-a-prime-number-as-the-number-of-slots-for-hashing-function-that-uses&quot;&gt;choosing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;N&lt;/code&gt;&lt;/a&gt;).&lt;/li&gt;
  &lt;li&gt;We export each of those files into a boltdb file. We now have &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;N&lt;/code&gt; small boltdb files.&lt;/li&gt;
  &lt;li&gt;When a query arrives for a key &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;K&lt;/code&gt;, we hash the key into a bucket between &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;N-1&lt;/code&gt;. This hash value tells us in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;O(1)&lt;/code&gt; time which boltdb to query on.&lt;/li&gt;
  &lt;li&gt;Query itself is fast due to storage structure and you’re done!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This helped us export the data and generate BoltDB files in less than an hour time.&lt;/p&gt;

&lt;p&gt;Following is the output of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;free -m&lt;/code&gt; on one of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;3&lt;/code&gt; servers we use:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/public/assets/img/free-m.png&quot; alt=&quot;free -m&quot; /&gt;&lt;/p&gt;

&lt;p&gt;and this is the snippet from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;top&lt;/code&gt; on the same server:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/public/assets/img/virtual-mem.png&quot; alt=&quot;top&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Note that the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;VIRTUAL&lt;/code&gt; memory is exactly the total size of boltdb. Also note from above two outputs that it is not limited by physical RAM availability.&lt;/p&gt;

&lt;h3 id=&quot;caveats--limitations&quot;&gt;Caveats &amp;amp; Limitations&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Bolt is good for read intensive workloads. Random writes can be slow especially as the database (file) size grows.&lt;/li&gt;
  &lt;li&gt;Bolt uses a B+tree internally so there can be a lot of random page access. SSDs provide a significant performance boost over spinning disks.&lt;/li&gt;
  &lt;li&gt;Bolt can handle databases much larger than the available physical RAM, provided its memory-map fits in the process virtual address space. It may be problematic on 32-bits systems.&lt;/li&gt;
  &lt;li&gt;The data structures in the Bolt database are memory mapped so the data file will be endian specific. This means that you cannot copy a Bolt file from a little endian machine to a big endian machine and have it work. For most users this is not a concern since most modern CPUs are little endian.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;result&quot;&gt;Result&lt;/h3&gt;

&lt;p&gt;We successfully migrated to using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;boltdb&lt;/code&gt; for our service. The service handles many thousands of QPS, is not limited by physical RAM on the machine and is working well.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BoltDB&lt;/code&gt; looks awesome. Do give it a try if this fits your use-case.&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>Hello World!</title>
   <link href="https://awmanoj.github.io/2016/06/25/hello-world/"/>
   <updated>2016-06-25T00:00:00+00:00</updated>
   <id>https://awmanoj.github.io/2016/06/25/hello-world</id>
   <content type="html">&lt;p&gt;&lt;img src=&quot;/public/assets/img/love.jpg&quot; alt=&quot;Love&quot; /&gt;&lt;/p&gt;

&lt;p&gt;‘Love’ - in different language scripts.&lt;/p&gt;

</content>
 </entry>
 

</feed>
