<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Kshitij (kd)</title>
    <description>The latest articles on Forem by Kshitij (kd) (@dhingrachief).</description>
    <link>https://forem.com/dhingrachief</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F630195%2F5afea96c-8c73-433c-bfa9-a87b1c39ca55.jpg</url>
      <title>Forem: Kshitij (kd)</title>
      <link>https://forem.com/dhingrachief</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/dhingrachief"/>
    <language>en</language>
    <item>
      <title>Abstract to Go: Lets create our own Ansible (Part 2)</title>
      <dc:creator>Kshitij (kd)</dc:creator>
      <pubDate>Mon, 13 Nov 2023 16:36:32 +0000</pubDate>
      <link>https://forem.com/dhingrachief/abstract-to-go-lets-create-our-own-ansible-part-2-33o3</link>
      <guid>https://forem.com/dhingrachief/abstract-to-go-lets-create-our-own-ansible-part-2-33o3</guid>
      <description>&lt;p&gt;In the previous &lt;a href="https://dev.to/dhingrachief/abstract-to-go-lets-create-our-own-ansible-o8n"&gt;post&lt;/a&gt; I shared what ansible is, how our code would look when it comes to parsing the information from the playbook and host, and how when we have code converted into commands, we can execute them on the servers and return the response.&lt;/p&gt;

&lt;p&gt;In this article, we will take a look at what strategies can be used for execution. The conversion of data from a YAML file into commands is not a part of this blog, but you can check the code &lt;a href="https://github.com/kdsama/gansible/tree/main/internal/modules"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Strategies
&lt;/h2&gt;

&lt;p&gt;Now there are two Strategies to choose from&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Linear &lt;/li&gt;
&lt;li&gt;Free&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There is a common denominator for both strategies: MaxConcurrency. It is not a good idea to spin up 100 goroutines if there are 100 servers on which the playbook is to be executed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Linear Strategy
&lt;/h3&gt;

&lt;p&gt;This is the default strategy. Let's say you have five tasks that are supposed to run in parallel on three machines. In this strategy, the execution of the next task will only happen if the previous task has been completed on all the servers. If any of the tasks fail on any of the servers, we may or may not proceed with the next task for that server according to the meta data provided for the task (skip_errors or not).&lt;br&gt;
Again, if the number of hosts exceeds the maximum concurrency number, we will split our execution into batches and run these batches sequentially. Each batch will have a certain number of hosts, which will run the tasks in parallel. We can do something similar using &lt;a href="https://dev.to/dhingrachief/resilient-systems-using-go-semaphores-2h82"&gt;semaphores&lt;/a&gt; as well, but we will keep it simple here.&lt;br&gt;
This is what the flow would look like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Parse all the tasks into commands &lt;/li&gt;
&lt;li&gt;Create batches of hosts &lt;/li&gt;
&lt;li&gt;For each Batch 

&lt;ul&gt;
&lt;li&gt;Run tasks on each host in parallel &lt;/li&gt;
&lt;li&gt;Wait until all the tasks are finished &lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Proceed to the next task&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For the waiting part, we can simply use the &lt;a href="https://pkg.go.dev/sync#WaitGroup:~:text=A%20WaitGroup%20waits%20for%20a%20collection%20of%20goroutines%20to%20finish.%20The%20main%20goroutine%20calls%20Add%20to%20set%20the%20number%20of%20goroutines%20to%20wait%20for.%20Then%20each%20of%20the%20goroutines%20runs%20and%20calls%20Done%20when%20finished.%20At%20the%20same%20time%2C%20Wait%20can%20be%20used%20to%20block%20until%20all%20goroutines%20have%20finished."&gt;waitgroup&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is what the code may look like&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;func (e *Engine) LinearStrategy(respObj PlayDoc) {

    opts := []ExecOutput{}
    for k := 0; k &amp;lt; len(respObj.hosts)/e.maxConcurrent; k += e.maxConcurrent {
        start, end := k*e.maxConcurrent, ((k + 1) * e.maxConcurrent)
        if end &amp;gt; len(respObj.hosts) {
            end = len(respObj.hosts)
        }
        for _, t := range respObj.tasks {
            e.wg.Add(len(respObj.hosts))

            for _, h := range respObj.hosts[start:end] {
                h := h
                t := t
                if !e.sameOS(t, h) {
                    continue
                }
                go func() {
                    // Executing the ssh commands for each server
                    defer e.wg.Done()
                    for _, c := range t.cmds {
                        res, err := e.sshService.execute(h, c)

                        if err != nil {

                            continue
                        }
                        // Checking if there is an error and flag for skipping error is false.
                        if strings.Trim(res.Err, " ") != "" &amp;amp;&amp;amp; !t.skip_errors {
                            break
                        }
                        opts = append(opts, res)
                    }

                }()
            }
            e.wg.Wait()
        }

    }

    fmt.Println(opts)

}

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Free Strategy
&lt;/h3&gt;

&lt;p&gt;This is where all the hosts run the tasks in parallel. We will wait until all tasks by all hosts are finished before we proceed for the next thing. &lt;br&gt;
Free Strategy is faster than the linear strategy as we dont have to wait for each task. Also, some servers may have better network bandwidth/ more computer and yet they would have to wait for the task on other servers to complete if using linear strategy. &lt;br&gt;
This is how the code may look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;func (e *Engine) FreeStrategy(respObj PlayDoc) {

    e.wg.Add(len(respObj.hosts))
    opts := []ExecOutput{}
    for _, h := range respObj.hosts {
        h := h
        go func() {
            defer e.wg.Done()
            for _, t := range respObj.tasks {
                h := h
                if !e.sameOS(t, h) {
                    continue
                }

                for _, c := range t.cmds {
                    res, err := e.sshService.execute(h, c)
                    fmt.Println("Response is ", res)
                    if err != nil {
                        continue
                    }
                    if strings.Trim(res.Err, " ") != "" &amp;amp;&amp;amp; !t.skip_errors {
                        break
                    }
                    opts = append(opts, res)

                }

            }
        }()
    }

    e.wg.Wait()
    fmt.Println(opts)

}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And its done. So we have covered &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Parse Tasks&lt;/li&gt;
&lt;li&gt;Executing bunch of tasks using different strategies &lt;/li&gt;
&lt;li&gt;Executing ssh commands on remote host &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The parsing of inventory file is not a part but one thing to mention is , while parsing the inventory file we need to make sure there is no cycle. i.e When grouping different hosts or hosts of hosts one may generate a cycle. So we need to check for cycle before executing the tasks. This can be done using graph algorithms such as Depth First Search or Breadth Firrst Search. You can check how I have Validated the inventory data for this project &lt;a href="https://github.com/kdsama/gansible/blob/main/internal/hosts.go"&gt;here&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;And thats it. We have a project that resembles ansible. It can run several tasks in parallel on bunch of machines.&lt;/p&gt;

</description>
      <category>go</category>
      <category>ansible</category>
      <category>automation</category>
      <category>devops</category>
    </item>
    <item>
      <title>Abstract to Go: Lets create a hot reloader</title>
      <dc:creator>Kshitij (kd)</dc:creator>
      <pubDate>Mon, 06 Nov 2023 18:01:26 +0000</pubDate>
      <link>https://forem.com/dhingrachief/abstract-to-go-lets-create-a-hot-loader-48ij</link>
      <guid>https://forem.com/dhingrachief/abstract-to-go-lets-create-a-hot-loader-48ij</guid>
      <description>&lt;p&gt;Being part of a couple Go communities, there is one question that is asked pretty frequently: What's the best hot reloader for Go? Hot reloading automatically detects changes in code and restarts the application. So there is no need to go to the terminal to build and run the programme again and again.&lt;/p&gt;

&lt;p&gt;So this time, instead of finding out the best hot reload app for Go, we will create a simple hot reloader that just does exactly what we want: Restart on each update in any Go file in the project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Design
&lt;/h2&gt;

&lt;p&gt;To have a working hot reload software, we need an application that is able to &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Watch files for changes &lt;/li&gt;
&lt;li&gt;Execute the go program &lt;/li&gt;
&lt;li&gt;Kill the existing program if there is any change, and start a new one.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So from the command line, we would need to know the target, i.e the file we need to run, as well as which directory it is in. This information is important, as we don't want our software to watch unnecessary folders for updates.&lt;br&gt;
We will be using the exec package to start and restart the application.&lt;br&gt;
To watch the files for changes, I am going to use the &lt;a href="https://pkg.go.dev/github.com/fsnotify/fsnotify"&gt;fsnotify&lt;/a&gt; package.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;type Watcher struct {
    directory  string
    command    string
    w          *fsnotify.Watcher
    cmd        *exec.Cmd
    lastUpdate time.Time

}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Start/Restart the Application
&lt;/h3&gt;

&lt;p&gt;Whenever we execute using the start method from exec Package, a processID gets attached, which can be used as a reference when we kill the program and start it again. &lt;br&gt;
This processID corresponds to the command that we are executing on the shell. It won't work if what we are executing itself creates a child process. &lt;/p&gt;

&lt;p&gt;So "go run" won't work as it creates a child process. Instead, we will build an executable and run it.&lt;/p&gt;

&lt;p&gt;So whenever the method is called, we will just check if an instance is already running. If it is, we will kill that instance.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;func (wg *Watcher) startCommand() {
    cmdArgs := strings.Split(wg.command, " ")
// If the instance is running
    if wg.cmd != nil {
// Kill Process
        wg.cmd.Process.Kill()

    }
// build the executable and call it ff
    cmd := exec.Command("go", "build", "-o", "./ff", cmdArgs[0])
    cmd.Dir = wg.directory
    cmd.Stdout = os.Stdout
    cmd.Stderr = os.Stderr
// Run the build command
    cmd.Start()


    wg.cmd = exec.Command("./ff")
    wg.cmd.Dir = wg.directory
    wg.cmd.Stdout = os.Stdout
    wg.cmd.Stderr = os.Stderr
    wg.lastUpdate = time.Now()

// Run the executable
    err := wg.cmd.Start()
    if err != nil {
        fmt.Println("Process Killed", err)
    }

}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Watch Events
&lt;/h3&gt;

&lt;p&gt;We need our application to restart whenever there is a write/edit in any file that has the extension "go" to it.&lt;br&gt;
It will call the startCommand method, which will start/restart our application.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    // Start an event loop to handle events
    for {
        select {
        case event, ok := &amp;lt;-wr.w.Events:
            if !ok {
                return
            }
            if event.Op == fsnotify.Write {

                // if event.Op
                f := strings.Split(event.Name, ".")

                if f[len(f)-1] == "go" {

                    // if time.Since(wr.lastUpdate) &amp;gt; 1*time.Second {
                    wr.startCommand()
                    // }

                }

            }

        case err, ok := &amp;lt;-wr.w.Errors:
            if !ok {
                return
            }
            log.Printf("Error: %s\n", err)
        }
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that would be enough to have a minimal version of hot reload. I am taking the to input parameters : working directory and the filename to be executed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;go run main.go -d=../book_five --file="main.go"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Set the Hot Reload Software
&lt;/h2&gt;

&lt;p&gt;Now we wouldn't want to run all our applications through these projects. Its better if we create a binary of the program and set an alias for it or move it to /usr/local/bin/ from which we can just directly reference our hot reloader. This works for Linux and should work for Mac as well.&lt;br&gt;
Lets name our hot reload executable, &lt;strong&gt;golo&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;go build -o ./golo
sudo mv ./golo /usr/local/bin/golo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that's it. Now go to the working directory of your Go application and run the command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;golo -d= ./ --file=main.go
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The source-code can be found &lt;a href="https://github.com/kdsama/goloader"&gt;here&lt;/a&gt;&lt;/p&gt;

</description>
      <category>go</category>
      <category>development</category>
      <category>tooling</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Abstract to Go: Lets create our own Ansible (Part 1)</title>
      <dc:creator>Kshitij (kd)</dc:creator>
      <pubDate>Mon, 30 Oct 2023 22:16:37 +0000</pubDate>
      <link>https://forem.com/dhingrachief/abstract-to-go-lets-create-our-own-ansible-o8n</link>
      <guid>https://forem.com/dhingrachief/abstract-to-go-lets-create-our-own-ansible-o8n</guid>
      <description>&lt;p&gt;If you like automation as much as I do, you must have spent hours automating tasks that probably take 5 minutes to do manually. Things get interesting when it comes to infrastructure automation. Tools like Ansible are used to make changes to several servers at the same time without logging into them. In this article, we will look into how Ansible usually works and then convert that abstract information into code.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Ansible
&lt;/h2&gt;

&lt;p&gt;Ansible is an agent-less automation tool that can perform a wide range of tasks, such as deploying code, updating systems, and provisioning infrastructure. What's remarkable is that Ansible is agent-less, which means you don't have to install any additional software on your servers to make Ansible work. Behind all that abstraction, it uses SSH to execute commands.&lt;/p&gt;

&lt;p&gt;It's also important to know that most workflows using Ansible are designed to be idempotent. That means if you run the same Ansible script multiple times, such as one responsible for installing specific packages, those installations will typically occur just once.&lt;/p&gt;

&lt;p&gt;For the sake of this article, we will focus on two significant components of Ansible:&lt;/p&gt;

&lt;h3&gt;
  
  
  Inventory File
&lt;/h3&gt;

&lt;p&gt;The inventory file is where all the information about the servers is stored. You can also group servers based on your needs. For example, you might want to run updates on all the backend servers while leaving the database servers as they are. Here's an example of how an inventory file may look:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;all:  
  hosts:
    server1:  
      ansible_host: sv1.server.com  
      ansible_user: root  
      ansible_ssh_pass: Passw0rd  

    server2:  
      ansible_host: sv2.server.com  
      ansible_user: root  
      ansible_ssh_pass: Passw0rd  

    server3:  
      ansible_host: sv3.server.com  
      ansible_user: root  
      ansible_ssh_pass: Passw0rd  

    server4:  
      ansible_host: sv4.server.com  
      ansible_user: root  
      ansible_ssh_pass: Passw0rd  

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

&lt;/div&gt;



&lt;p&gt;The inventory file, by default, is an INI file format, but Ansible can also accept a YAML file as input.&lt;/p&gt;

&lt;h3&gt;
  
  
  Playbook
&lt;/h3&gt;

&lt;p&gt;This contains execution information like :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What tasks to run &lt;/li&gt;
&lt;li&gt;Where to run the tasks &lt;/li&gt;
&lt;li&gt;How to run the tasks (Strategy)&lt;/li&gt;
&lt;li&gt;Maximum number of hosts that are to be run at a time&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here's an example of how a playbook file may look:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;---
- name: example playbook
  hosts: server1,server2,server3,server4
  strategy: free
  tasks:
    - name: Create a group
      group:
        name: yourgroup
        state: present  
      skip_errors: true

    - name: Create a user
      user:
        name: yourusername
        password: yourpassword  
        groups: yourgroup    
        state: present       

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

&lt;/div&gt;



&lt;p&gt;The playbook suggests that two tasks should be run on servers 1 to 4, using a free strategy. By default, Ansible uses a linear strategy, meaning all servers run the first task, then the second, and so on. A free strategy allows all servers to run tasks concurrently, and information about the execution is collected at the end.&lt;/p&gt;

&lt;h2&gt;
  
  
  Design
&lt;/h2&gt;

&lt;p&gt;So these are the main things that we would need to do make our ansible-like application work &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Parse the inventory and the playbook files&lt;/li&gt;
&lt;li&gt;Run ssh commands on multiple servers at the same time &lt;/li&gt;
&lt;li&gt;Implement different strategies on how to run the tasks from playbook &lt;/li&gt;
&lt;li&gt;Ignore errors from commands if explicitly mentioned in the playbook &lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  SSH-Client
&lt;/h3&gt;

&lt;p&gt;So in the end, all the tasks in the playbook should be converted into commands that we run on the server's shell. We would like to capture both the error and the output.&lt;/p&gt;

&lt;p&gt;It is also important for us to know the operating system, because there is a possibility that among the set of hosts, there are a few servers that cannot run the command because they have a different operating system. So instead of trying to run these commands on the server, we should just skip the execution altogether.&lt;br&gt;
We also do not want to reconnect to the server for each task.&lt;br&gt;
This calls for a data structure that holds the login details of the SSH client.&lt;br&gt;
This is what the structure may look like&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;type sshConn struct {
    host   string
    os     string
    user   string
    pw     string
    pkey   string
    client *ssh.Client
    port   int

}

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

&lt;/div&gt;



&lt;p&gt;It will have an execution method that will run a command, capture its output into a structure, and return it. This is what it may look like&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;func (sc *sshConn) execute(cmd string) ExecOutput {
    ll := make([]byte, 0)
    mm := make([]byte, 0)
    sshOut := bytes.NewBuffer(ll)
    sshErr := bytes.NewBuffer(mm)

    session, err := sc.client.NewSession()
    if err != nil {
        log.Fatal(err)
    }

    defer session.Close()

    session.Stdout = sshOut
    session.Stderr = sshErr

    session.Run(cmd)
    co := ExecOutput{
        Out: sshOut.String(),
        Err: sshErr.String(),
        Cmd: cmd,
    }

    return co
}

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Tasks
&lt;/h3&gt;

&lt;p&gt;Tasks in Ansible playbooks can have various structures. To handle this variability, it's efficient to use a map-based approach for task processing. This method involves parsing tasks as maps and then iterating through the keys to determine the type of task and how to handle it. &lt;/p&gt;

&lt;p&gt;This is what it may look like&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;func parseTask(task map[string]interface{}) (*Task, error) {
    defer func() {
        if err := recover(); err != nil {
            fmt.Println(err)
        }
    }()
    // TODO: Work the other task level variables that may be present
    var result = &amp;amp;Task{}
    result.os = "any"
    for key, _ := range task {
        switch key {
        // case "copy":
        //  res = modules.NewCopy(task[key].(map[string]interface{}))
        case LineinfileMod:
            cmds, err := modules.NewLineInFile(task[key].(map[string]interface{}))
            if err != nil {
                return result, err
            }
            result.cmds = cmds

        case fileMod:
            cmds, err := modules.NewFilePermissions(task[key].(map[string]interface{}))
            if err != nil {
                return result, err
            }
            result.cmds = cmds

        case userMod:
            cmds, err := modules.NewUser(task[key].(map[string]interface{}))
            if err != nil {
                return result, err
            }
            result.cmds = cmds
        case shellMod:
            cmds, err := modules.NewShell(task[key].(map[string]interface{}))
            if err != nil {
                return result, err
            }
            result.cmds = cmds
        case "skip_errors":
            result.skip_errors = true
        case "name":
            result.name = task[key].(string)
        case "default":
            fmt.Println(key)
        }
    }
    return result, nil
}

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

&lt;/div&gt;



&lt;p&gt;Here you can see that we have methods for shell tasks, user and group manipulation, as well as lineinfile, which is used to add lines to existing files or check whether a line is present in a file.&lt;br&gt;
The implementation can be found &lt;a href="https://github.com/kdsama/gansible"&gt;here&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;In the next article, we will see how to run all the tasks together, using different strategies. &lt;/p&gt;

</description>
      <category>ansible</category>
      <category>go</category>
      <category>automation</category>
      <category>programming</category>
    </item>
    <item>
      <title>Abstract to Go: Quad Trees</title>
      <dc:creator>Kshitij (kd)</dc:creator>
      <pubDate>Sun, 22 Oct 2023 22:07:03 +0000</pubDate>
      <link>https://forem.com/dhingrachief/abstract-to-go-quad-trees-44f7</link>
      <guid>https://forem.com/dhingrachief/abstract-to-go-quad-trees-44f7</guid>
      <description>&lt;p&gt;While going through important concepts for system design interviews, I came across quad trees, a data structure with numerous applications. But its always better to know the problem it solves.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pre-requisites
&lt;/h2&gt;

&lt;p&gt;A base level understanding of trees and tree-traversal would help you get a better understanding of the code. &lt;/p&gt;

&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;Let's talk about a 2-dimensional multiplayer game. We have a hilly landscape with two tanks on the opposite side.  trying to destroy each other. For every miss, the bomb will probably explode on land, and hence a crater will be created. Let's assume for now that the blast is circular in nature. If we don't have to worry about the graphics, how do we change the state of the area to represent an empty space that used to be land?&lt;/p&gt;

&lt;p&gt;Let's take another example. You have to create an application that shares how many people live in a radius of 5km with you at the centre.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quad Tree
&lt;/h2&gt;

&lt;p&gt;In such situations, data structures like quad trees perform really well. Both the map and the 2D game of tank can be visualised as a matrix of size n.&lt;/p&gt;

&lt;p&gt;The idea is pretty simple. Calculate the total value for the whole matrix. In our case, let's say the world population is 8 billion. So we have a node with a value of 8 billion. Now divide the matrix (or map) into four nodes: North West, North East, South West, and South East. Calculate the population of all these nodes. Connect these nodes to the root. What you did on the root, now do for each of the nodes.&lt;br&gt;
Keep doing this until you find a depth that is appropriate for the use case. Below is the diagram that will help you visualise the same.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--WneC7XKn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xwsrc8mkry0bkqeb959e.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WneC7XKn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xwsrc8mkry0bkqeb959e.jpg" alt="Quad Tree for World Map" width="800" height="656"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Similarly, for the tank game with explosives, we can divide the 2D scenery into smaller segments, up to a depth that may be equal to the minimum blast radius of a missile in the game. The smallest cell (from the maximum depth) can be marked as equal to 1. All the non-land areas can be marked zero. The higher depth of a quad tree will lead to more realistic explosions. Below is an example of the same. Each cell here can hold a value of 4. There is another depth level that is not shown for clarity. Each of those cells will have a value of 1. You can see that around the border between the land and non-land regions, the boxes have values of 1, 2, and 3, meaning that in those boxes there are 1, 2, or 3 land segments.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--iKyaaMNe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/effzvrhkv55ltxcb7t2f.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--iKyaaMNe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/effzvrhkv55ltxcb7t2f.jpg" alt="Quad Tree for the tank game" width="800" height="629"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Implementation
&lt;/h2&gt;

&lt;p&gt;Now this is the easy part. Let's skip the part where we have to map these problems onto a 2D matrix.&lt;/p&gt;
&lt;h3&gt;
  
  
  What should we be able to do with this quad tree?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Find Regions: Get all those areas with population X&lt;/li&gt;
&lt;li&gt;Add: As the population regularly increases, the values in the quad tree should be updated as well. The same can be used for the other example. The only difference would be that we would pass negative values instead.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Quad Tree Structure
&lt;/h3&gt;

&lt;p&gt;The structure, in many ways, will be similar to a tree.  In each node, we have to save the coordinates, the value of the quadrant, and the depth level.&lt;br&gt;
For the coordinates, we need to know the minimum and maximum of the row and column values. &lt;br&gt;
This is how the structure may look:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;type QuadTree struct {
    lvl      int
    val      int
    x        [2]int // start and end index of matrix row
    y        [2]int // start and end index of matrix column
    children []*QuadTree
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Initialising the Quad Tree
&lt;/h3&gt;

&lt;p&gt;So we already have all the information laid out on a 2D matrix. &lt;br&gt;
These are the steps we would have to follow : &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Calculate Sum of each cell in the matrix&lt;/li&gt;
&lt;li&gt;Create a node and set the sum. Set Depth level &lt;/li&gt;
&lt;li&gt;Split matrix into four parts&lt;/li&gt;
&lt;li&gt;Repeat steps 1 to 3 for each quadrant until the specified depth level is achieved. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is what the code will look like&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;func New(arr [][]int, dp int) *QuadTree {

    var newquadtree func(arr [][]int, depth int, lc, rc, tr, br int) *QuadTree
    newquadtree = func(arr [][]int, depth int, lc, rc, tr, br int) *QuadTree {
        if lc+1 == rc || tr+1 == br {
            return nil
        }
        sum := 0
        for i := tr; i &amp;lt; br; i++ {
            for j := lc; j &amp;lt; rc; j++ {
                sum += arr[i][j]
            }
        }
        qt := &amp;amp;QuadTree{
            val: sum,
            x:   [2]int{tr, br},
            y:   [2]int{lc, rc},
            lvl: dp - depth,
        }
        if depth == 0 {
            return qt
        }
        midR := tr + (br-tr)/2
        midC := lc + (rc-lc)/2
        qt.children = append(qt.children, newquadtree(arr, depth-1, lc, midC, tr, midR))
        qt.children = append(qt.children, newquadtree(arr, depth-1, lc, midC, midR, br))
        qt.children = append(qt.children, newquadtree(arr, depth-1, midC, rc, tr, midR))
        qt.children = append(qt.children, newquadtree(arr, depth-1, midC, rc, midR, br))
        return qt
    }

    return newquadtree(arr, dp, 0, len(arr[0]), 0, len(arr))
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here I am recursively calling the quadTree generation until a specified depth can be reached or if the current matrix cannot be divided into further quadtrants. &lt;/p&gt;

&lt;h3&gt;
  
  
  Find Regions
&lt;/h3&gt;

&lt;p&gt;We will again be using DFS to find out which regions have values passed to the function. The aim here is to find the smallest quadrant that holds the value. These are the main things we have to make sure to check&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If current nodes value &amp;lt; target, dont traverse&lt;/li&gt;
&lt;li&gt;If all child quadrants hold a value &amp;lt; target, the current node is the smallest quadrant that holds a value &amp;gt;= target, so append the current node to the list of results.&lt;/li&gt;
&lt;li&gt;If the child quadrant holds value &amp;gt;= target, traverse the child quadrant. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is how the code may look like :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;func (qt QuadTree) FindRegions(value int) []*QuadTree {
    arr := []*QuadTree{}
    var dfs func(node *QuadTree, depth int)
    dfs = func(node *QuadTree, depth int) {
        if node == nil {
            return
        }
        if node.val &amp;lt; value {
            return
        }
        flag := false
        for _, child := range node.children {
            fmt.Println("For ", node, "child value::", child.val)
            if child.val &amp;gt; value {

                dfs(child, depth+1)
                flag = true
            }
        }

        if !flag {
            fmt.Println("Flag", flag, "for ", node)
            arr = append(arr, node)
        }
    }
    dfs(&amp;amp;qt, 0)
    for _, v := range arr {
        fmt.Println(v.val, v.x, v.y)
    }
    return arr
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Add Value to a region
&lt;/h3&gt;

&lt;p&gt;Here we may be asked to increase the value of a particular region. We would need to recognise the value of all the parents in that particular region. &lt;br&gt;
This is pretty straight forward to figure out. Keep on traversing the quadrant that holds the region, and keep incrementing these quadrants with the value. &lt;/p&gt;

&lt;p&gt;This is what the code may look like&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;func (qt *QuadTree) Add(value, x, y int) {
    var dfs func(node *QuadTree)
    dfs = func(node *QuadTree) {
        if node == nil {
            return
        }
        node.val += value
        for _, n := range node.children {
            if n == nil {
                continue
            }
            if n.x[0] &amp;lt;= x &amp;amp;&amp;amp; n.x[1] &amp;gt;= x {
                if n.y[0] &amp;lt;= y &amp;amp;&amp;amp; n.y[1] &amp;gt;= y {
                    dfs(n)
                }
            }

        }
    }
    dfs(qt)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that's it! Remember, there are a lot more properties of quadtrees, and only the basics are covered. you can find the code for the implementation &lt;a href="https://github.com/kdsama/quadtree"&gt;here&lt;/a&gt;. Do you believe the algorithm can be further optimised? Let me know. &lt;/p&gt;

</description>
      <category>distributedsystems</category>
      <category>go</category>
      <category>programming</category>
    </item>
    <item>
      <title>Resilient Systems using Go: Semaphores</title>
      <dc:creator>Kshitij (kd)</dc:creator>
      <pubDate>Wed, 18 Oct 2023 14:29:49 +0000</pubDate>
      <link>https://forem.com/dhingrachief/resilient-systems-using-go-semaphores-2h82</link>
      <guid>https://forem.com/dhingrachief/resilient-systems-using-go-semaphores-2h82</guid>
      <description>&lt;p&gt;Previously, we talked about &lt;a href="https://dev.to/dhingrachief/resilient-systems-retry-mechanism-na3"&gt;retry mechanism&lt;/a&gt; and &lt;a href="https://dev.to/dhingrachief/resilient-systems-using-go-circuit-breaker-1gop"&gt;circuit-breaker&lt;/a&gt;, two resiliency techniques, and what their packages may look like. In this final chapter of the resilience series, we will take a look at semaphores and convert the abstract information to a working package.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Let's say we have to create a search page for our cyber security application. The search page shows all the addresses and headers of all the possible malicious emails against a suspicious sender email and subject. To get the email information, the system would have to interact with the email system API, which has a very high threshold for accepting requests. So the search would lead to a search throughout your whole organisation against the keywords mentioned, do a malicious check on them, and return the results.&lt;br&gt;
Now, these can be big or small emails that are to be processed for malicious threats. You would like to process as many mailboxes as possible at a time, but you also don't want the system to slow down by having too many concurrent tasks on a service with unlimited bandwidth.&lt;/p&gt;
&lt;h2&gt;
  
  
  Semaphores
&lt;/h2&gt;

&lt;p&gt;What we would like to have is a mechanism that restricts the number of concurrent requests we can perform with the resources. The number would align with what the system can handle without interrupting the performance of other processes.&lt;br&gt;
We can achieve this by using semaphores. &lt;br&gt;
Semaphore is a mechanism to put an upper-bound on the number of requests that one can perform at a time. If the semaphore is running under capacity, it can accept further requests. Whenever a request is completed, the semaphore package can notify our system that it is available to take in more requests. If it is already at full capacity, it will return an error.&lt;/p&gt;
&lt;h2&gt;
  
  
  Designing the Semaphore Package
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Package Structure
&lt;/h3&gt;

&lt;p&gt;So a basic functioning package implementing Semaphore would require &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Weight : Maximum number of requests that can run concurrently &lt;/li&gt;
&lt;li&gt;Count : Count of requests under progress&lt;/li&gt;
&lt;li&gt;Notifier: A notification function that will tell the system whenever it is available to take more requests. &lt;/li&gt;
&lt;li&gt;mutex : a mutex would be used to access and update the count variable. Two requests may try to update the count variable at the same time, creating a race condition. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is what the structure may look like&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
type Semp struct {
    weight uint32
    count  uint32
    mu     *sync.Mutex
    notify NotifyFunc
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Functionality
&lt;/h3&gt;

&lt;p&gt;Functionality is pretty straightforward. There are two important methods &lt;/p&gt;

&lt;h4&gt;
  
  
  Acquire
&lt;/h4&gt;

&lt;p&gt;The system will call the acquire method whenever it wants the request to be processed. If the semaphore is at its full capacity, an error should be returned. Otherwise, the counter should increment.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;func (s *Semp) Acquire(i int) error {
    s.mu.Lock()
    defer s.mu.Unlock()
    if s.count+uint32(i) &amp;gt; s.weight {
        return ErrCannotAcquire
    }

    s.count += uint32(i)
    return nil
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Release
&lt;/h4&gt;

&lt;p&gt;Here we just need to decrement the counter and call the notify function passed by the user&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;func (s *Semp) Release(i int) error {

    s.mu.Lock()
    defer s.mu.Unlock()
    s.count -= uint32(i)
    if s.count &amp;lt;= 0 {
        s.count = 0
    }
    go s.notify()
    return nil
}

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

&lt;/div&gt;



&lt;p&gt;And that's it. That's how you implement the basic functionality of semaphore. The code can be found &lt;a href="https://github.com/kdsama/semp"&gt;here&lt;/a&gt;. It goes without saying that all the resiliency mechanisms should be context aware. One should be able to cancel any ongoing request if certain criterias can't be met. &lt;br&gt;
What other scenarios do you think we can use semaphores for ?&lt;/p&gt;

</description>
      <category>go</category>
      <category>concurrency</category>
      <category>programming</category>
      <category>development</category>
    </item>
    <item>
      <title>Resilient Systems using Go: Circuit Breaker</title>
      <dc:creator>Kshitij (kd)</dc:creator>
      <pubDate>Mon, 09 Oct 2023 21:05:49 +0000</pubDate>
      <link>https://forem.com/dhingrachief/resilient-systems-using-go-circuit-breaker-1gop</link>
      <guid>https://forem.com/dhingrachief/resilient-systems-using-go-circuit-breaker-1gop</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In the previous post we talked about &lt;a href="https://dev.to/dhingrachief/resilient-systems-retry-mechanism-na3"&gt;retry&lt;/a&gt; mechanism and what all possibilities can be encapsulated together in a package. Its an important mechanism to prevent the whole system from going down in case an external service goes down. &lt;/p&gt;

&lt;p&gt;Let's take an example of Twitter (or X), like social media-application that synchronously loads the website with all the important features like recommended tweets, user recommendations, and trending hashtags.  &lt;/p&gt;

&lt;p&gt;Its the football World Cup, and England is playing Portugal. People who are stuck in the office are checking the hashtag #EngVsPor to get live reaction of others, and hence overloading the hashtag component of our system. The hashtag service is taking 7 seconds to get data instead of the usual 20ms. And because the call is synchronous, each web page reload is taking at least 7 seconds.&lt;br&gt;
On top of that, now we have a lot of concurrent requests stuck on our server waiting for the hashtag service to give a result, ultimately leading to an outage. &lt;/p&gt;

&lt;p&gt;In this case, it would be better if we failed all the requests early. One way to do that is to reduce the timeouts for these requests. But coming up with a value would be difficult. If the system is under load, all the requests will time out.&lt;br&gt;
So a timeout will not be an efficient way to manage this problem. And this is where circuit breaker comes in. &lt;/p&gt;
&lt;h3&gt;
  
  
  Circuit Breaker
&lt;/h3&gt;

&lt;p&gt;What we can do is let the request to the hashtag service go through the circuit breaker. If the number of errors goes beyond a specified threshold, the circuitbreaker will stop sending requests to the hashtag service. Hence, the circuit is open. &lt;/p&gt;

&lt;p&gt;But how would we know if the service can start taking requests again? This can be done by adding another state to the circuit breaker - the half open state. After a specified duration of time, one can send a few requests to the service. If even a single request returns error, the circuit will open again, and the cycle will continue. &lt;/p&gt;

&lt;p&gt;If, in half state, a good amount of requests do not cause any errors, we can close the circuit again and resume the flow. &lt;br&gt;
But the flow through the circuit breaker is not controlled by the package. We need a way to inform the system of the current state of circuit breaker&lt;/p&gt;
&lt;h3&gt;
  
  
  Design
&lt;/h3&gt;

&lt;p&gt;So our Circuit Breaker structure must include &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;current state (open/half/closed)&lt;/li&gt;
&lt;li&gt;threshold : when the number of errors reaches the threshold, the state changes to open. &lt;/li&gt;
&lt;li&gt;duration: time after which our state changes from open to half. &lt;/li&gt;
&lt;li&gt;good requests: Total number of good requests in halfstate&lt;/li&gt;
&lt;li&gt;halfStateThreshold: Exceeding this threshold will change the state to closed, and a full flow of requests can be expected afterwards. A good idea will be to have it as a percentage of the threshold variable from above. &lt;/li&gt;
&lt;li&gt;NotifyFunc: function that will be called whenever a state is changed. &lt;/li&gt;
&lt;li&gt;StateMutex : The state of the circuit breaker due to concurrent access will cause locks. So we will use mutex to avoid that scenario. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's have a separate structure that will be used as an input to invoke our circuit breaker structure. The image below shows what the structures will look like.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IEqmhZe3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ituc1z6vexv2aqgqr5jq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IEqmhZe3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ituc1z6vexv2aqgqr5jq.png" alt="Configuration" width="800" height="545"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Implementation
&lt;/h3&gt;

&lt;p&gt;So the execution will be somewhat similar to what was done in the previous blog about the retry mechanism.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// cb is the circuit breaker object.
        cb.Execute(context.Background(), func() (interface{}, error) {
            l := m.Func()

            if l == "" {
                return "", errors.New("Error found")
            }
            return "ok", nil
        })
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The execute function will run the closure if it is in a half state or closed state. It will return an error if it is in the open state.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Execute executes the user defined function in the circuit breaker
func (cb *CircuitBreaker) Execute(ctx context.Context, fn Action) (interface{}, error) {
    // Execute the function
    var state State

    cb.sLock.Lock()
    state = cb.state
    cb.sLock.Unlock()

    switch state {
    case Closed:
        return cb.run(fn)
    case Open:
        return nil, ErrCircuitOpen
    case Half:
        return cb.runInHalfState(fn)
    }
    return cb.run(fn)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The switch from a closed to an open circuit will happen when the number of errors reaches the threshold. Once the state is set to Open, we will wait for specified amount of time and then change the state to Half state&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// running the function in closed state
func (cb *CircuitBreaker) run(fn Action) (interface{}, error) {

    res, err := fn()
    if err != nil {
        cb.count++
    }
    if cb.count &amp;gt;= cb.threshold {
        go cb.openCircuit()
    }
    return res, err
}

// Open circuit 
func (cb *CircuitBreaker) openCircuit() {
    cb.setState(Open)
    go cb.halfCircuit()

}


// HalfOpen Circuit
func (cb *CircuitBreaker) halfCircuit() {

// Sleep for specified duration
    time.Sleep(cb.duration)

    cb.setState(Half)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now for the execution in half state, we will keep on counting the good requests, and if the number exceeds a certain percentage of the threshold, we can close the circuit. &lt;br&gt;
If even a single error comes up, we close the circuit again.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;func (cb *CircuitBreaker) runInHalfState(fn Action) (interface{}, error) {

    res, err := fn()
    if err != nil {
        cb.openCircuit()
        return res, err
    }

    cb.goodReqs++

    if cb.goodReqs &amp;gt;= (cb.hsThreshold*cb.threshold)/100 {
        cb.closeCircuit()
    }
    return res, err
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And whenever we set the state, we need to notify the system about the change in state&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;func (cb *CircuitBreaker) setState(st State) {

    cb.sLock.Lock()
    cb.goodReqs = 0
    cb.count = 0
    cb.state = st
    cb.sLock.Unlock()

    //Notify the userDefined Function
    go cb.notifyFunc(stateMapping[st])

}

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

&lt;/div&gt;



&lt;p&gt;And that's it! The circuit breaker package is ready to use.&lt;br&gt;
Code alongside testcases can be found &lt;a href="https://github.com/kdsama/cbreak"&gt;here&lt;/a&gt;&lt;/p&gt;

</description>
      <category>go</category>
      <category>distributedsystems</category>
      <category>resilientsystems</category>
      <category>systemdesign</category>
    </item>
    <item>
      <title>Resilient Systems using Go: Retry Mechanism</title>
      <dc:creator>Kshitij (kd)</dc:creator>
      <pubDate>Wed, 27 Sep 2023 17:47:18 +0000</pubDate>
      <link>https://forem.com/dhingrachief/resilient-systems-retry-mechanism-na3</link>
      <guid>https://forem.com/dhingrachief/resilient-systems-retry-mechanism-na3</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In this post, we will discuss the retry mechanism used to make systems more resilient and create a simple implementation in Go. The idea here is to develop the mechanism from some abstract information&lt;/p&gt;

&lt;h3&gt;
  
  
  Background
&lt;/h3&gt;

&lt;p&gt;There used to be a time when multiple instances of a monolith were enough to serve users. Applications today are a lot more complex, moving a lot of information and communicating with different other applications to provide users with a service. With a lot of moving parts, it becomes more necessary to make sure your application doesn't break when interacting with third party services. Its better to let the user know that the request cannot be processed rather than make them wait. &lt;/p&gt;

&lt;p&gt;That's why we strategically place timeouts. In Go, we do that using the context package. Then the application's logic tells it if it wants to try again or not. &lt;/p&gt;

&lt;p&gt;We also dont want to retry too many times in a short period of time. The third party API may rescind all the requests if the number goes beyond the threshold or even block your application's IP from making any requests. &lt;br&gt;
It is a good idea to retry for a fixed amount of time, with some pre-defined time intervals. &lt;br&gt;
The most common way to do it is to retry after every n seconds configured by the user. This value can be obtained with respect to the rate-limiter threshold of the third party API. &lt;/p&gt;

&lt;p&gt;One can also apply exponential backoffs. If there is an error, the next request will be done after n seconds, n*n for the request after, and so on. &lt;/p&gt;

&lt;p&gt;But do you want the retry mechanism to work when the application makes a bad request? &lt;br&gt;
Or make a request when the third party API tells the system that the service is unavailable for some time. &lt;/p&gt;

&lt;h3&gt;
  
  
  Design
&lt;/h3&gt;

&lt;p&gt;So our retry package should have these configurations &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Max number of retries &lt;/li&gt;
&lt;li&gt;Standard duration between each retry &lt;/li&gt;
&lt;li&gt;User Defined BackOffs (Exponential or Custom) &lt;/li&gt;
&lt;li&gt;Bad Errors When these error occur, we stop retrying&lt;/li&gt;
&lt;li&gt;Retry Errors, which is a list of errors If an error outside of the list occurs, we stop retrying&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One cannot have both bad and retry errors enabled for our retry functionality at the same time. Similarly, if custom or exponential intervals are given for retry, we should be omitting the variable that sets the maximum number of retries. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5gpk3y80gc18jsk4qwit.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5gpk3y80gc18jsk4qwit.png" alt="Image of a struct in Go with comments about the variables in it"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Implementation
&lt;/h3&gt;

&lt;p&gt;For the user to run our retry package, they would have to adhere to a function signature. The function call should only return an error. &lt;br&gt;
This can be easily done using closures. &lt;br&gt;
Lets say our retry package has a method called Run&lt;br&gt;
&lt;code&gt;Run(fn func()error)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;And we want to call the method Run on our own function, &lt;code&gt;ThirdPartyCall(input string)(string,error)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;So a call should look like &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

obj := retry.New()
obj.Run(func()error {
     resp,err := ThirdPartyCall("input String")
     if err != nil {
          return err 
    }
       // code logic
     return nil 

})


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

&lt;/div&gt;
&lt;h4&gt;
  
  
  Run Function
&lt;/h4&gt;

&lt;p&gt;For the purpose of this blog, I have not implemented separate functions for a normal retry method and the one with user specified intervals. So we will just do a check on the interval variable. If its length is zero, we will run our function in normal mode, or else we will run using the intervals specified. &lt;/p&gt;

&lt;p&gt;These are the few things that we need to keep in mind before the implementation &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Have a count of the number of retries done so it can be compared to the threshold. &lt;/li&gt;
&lt;li&gt;Put the time gap not at the start of the function but after an error occurs. You don't want the system to wait until the function is called for the first time. &lt;/li&gt;
&lt;li&gt;Check for bad errors. If they exist, dont try again&lt;/li&gt;
&lt;li&gt;Check for retry errors. If they don't exist, don’t try again. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Another thing to keep in mind is that the whole request, including retries, might take a couple of seconds. So we don’t want the configuration variables to be changed while the retry process is going on. The extra space occupied isn't much, so it won't be a worry. &lt;/p&gt;

&lt;p&gt;So the code may look like this &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

// Run runs the user method wrapped inside Action
// with a set number of retries according to the configuration
func (r *Retrier) Run(fn Action) error {

    if len(r.intervals) &amp;gt; 0 {
        return r.RunWithIntervals(fn)
    }
    var (
        count       int
        badErrors   = r.badErrors
        be          = r.be
        maxRetries  = r.maxRetries
        re          = r.re
        retryErrors = r.retryErrors
        sleep       = r.sleep
    )

    var rn func(fn Action) error
    rn = func(fn Action) error {

        if err := fn(); err != nil {
            if be {
                if _, ok := badErrors[err]; ok {
                    return err
                }
            }

            if re {
                if _, ok := retryErrors[err]; !ok {
                    return err
                }
            }
            count++

            if count &amp;gt; maxRetries {
                return ErrNoResponse
            }
            time.Sleep(sleep)
            return rn(fn)
        }
        return nil
    }

    e := rn(fn)
    return e
}


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

&lt;/div&gt;
&lt;h4&gt;
  
  
  Run With Intervals
&lt;/h4&gt;

&lt;p&gt;The code will be similar to our run function. As we already keep tabs on the count to compare it to the threshold, the same information can be used to determine how much time we need to sleep before we retry the same function. The code for this would look like  &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

// RunWithIntervals is similar to Run. The difference is that we have a slice
// of time durations corresponding to each retry here, instead of maxRetries
// and constant sleep gap.
func (r *Retrier) RunWithIntervals(fn Action) error {
    var (
        count       int
        badErrors   = r.badErrors
        be          = r.be
        maxRetries  = r.maxRetries
        re          = r.re
        retryErrors = r.retryErrors
        intervals   = r.intervals
    )

    var rn func(fn Action) error
    rn = func(fn Action) error {

        if err := fn(); err != nil {
            if be {
                if _, ok := badErrors[err]; ok {
                    return err
                }
            }

            if re {
                if _, ok := retryErrors[err]; !ok {
                    return err
                }
            }
            count++
            if count &amp;gt;= maxRetries {
                return ErrNoResponse
            }
            time.Sleep(intervals[count])
            return rn(fn)
        }
        return nil
    }

    e := rn(fn)
    return e
}



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

&lt;/div&gt;

&lt;p&gt;And that's it. The Retry package is ready to use. Configuration of the package is not in the scope of this post, but it can be found &lt;a href="https://github.com/kdsama/gogoretry/blob/main/options.go" rel="noopener noreferrer"&gt;here&lt;/a&gt;. I have used the functional options pattern to set the configuration.&lt;/p&gt;

&lt;p&gt;You can checkout the package and its test cases &lt;a href="https://github.com/kdsama/gogoretry" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

</description>
      <category>go</category>
      <category>distributedsystems</category>
      <category>programming</category>
    </item>
    <item>
      <title>Parallel algorithms series. Part 2: PRAM Models</title>
      <dc:creator>Kshitij (kd)</dc:creator>
      <pubDate>Mon, 10 Jul 2023 23:12:35 +0000</pubDate>
      <link>https://forem.com/dhingrachief/parallel-algorithms-series-part-2-pram-models-184</link>
      <guid>https://forem.com/dhingrachief/parallel-algorithms-series-part-2-pram-models-184</guid>
      <description>&lt;p&gt;In the previous post, we discussed about sequential algorithms and the RAM Model. Here we will talk about some Parallel machine models that we can select for our task. But before that lets have an understanding what kind of parallelism we can achieve. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Parallelism on a single node&lt;/strong&gt;&lt;br&gt;
Unless you are using a couple decade old computer, you probably are using a system that has more than 1 cores. And if you can have more than one cores, we can utilise all of them for our algorithm. As everything resides on the same node, we can utilize shared memory to run our algorithms &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Distributed Computing&lt;/strong&gt;&lt;br&gt;
This is where one system is not enough, for several reasons, and we have to utilize multiple nodes to be able to complete the task. An example of this is supercomputers or high performance computers. You must have done matrix multiplication on a 3x3 matrix. Now imagine, you need to do it on matrices which are shared as files a couple gigabytes each.&lt;/p&gt;

&lt;p&gt;We are going to focus on parallelism on a single node. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;PRAM or Parallel RAM&lt;/strong&gt;&lt;br&gt;
The attributes of PRAM Model are as follows &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It has p Processing elements, each having a unique id. The number of processors that are to be utilized can also depend upon the size of the input. &lt;/li&gt;
&lt;li&gt;Each processing element can run its own RAM-style program.&lt;/li&gt;
&lt;li&gt;Each processing element has its own registers but shared memory. &lt;/li&gt;
&lt;li&gt;Synchronising the processing elements also has some overhead. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So we have several processing elements(pe) doing its computations. Some information is being stored in registrations, some operations are being performed, and then resultant information is then being sent back to the memory. &lt;br&gt;
But what if multiple processing elements write to the same memory location? We have conflict! &lt;br&gt;
On the basis of this we can have several sub-divisions to the PRAM model. &lt;/p&gt;

&lt;h3&gt;
  
  
  EREW-PRAM
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Exclusive Read Exclusive Write&lt;/strong&gt;&lt;br&gt;
If multiple pe try to access the same memory location, read or write, the program will crash&lt;/p&gt;

&lt;h3&gt;
  
  
  CREW-PRAM
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Concurrent Read, Exclusive Write&lt;/strong&gt;&lt;br&gt;
Its fine if multiple pe are trying to read the same memory cell at the same time, but only one should write at a time. &lt;/p&gt;

&lt;h3&gt;
  
  
  CRCW-PRAM
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Concurrent Read and Write&lt;/strong&gt;&lt;br&gt;
For this a rule is required for concurrent writes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Execution Costs
&lt;/h2&gt;

&lt;p&gt;We saw that in the RAM Model that the number of instructions tells the total computation required. &lt;br&gt;
There is a bit more to the cost metrics of a PRAM Model as now the instructions are being run in parallel. So on top of space(memory access) and time(which is the maximum time by any PE taken to finish the allocate task),  total instructions (all instructions combined). &lt;/p&gt;

&lt;p&gt;Remember, if the parallel algorithm is taking more time than the best sequential algorithm you know of, its better if you forget about it, or atleast try to optimize it. &lt;/p&gt;

&lt;p&gt;If interested, you can have a look at parallel implementation of the kmp string matching algorithm using &lt;a href="https://github.com/kdsama/go_leetcode_prep/blob/master/efficient_algorithms/parallel_kmp.go" class="ltag_cta ltag_cta--branded"&gt;WaitGroups&lt;/a&gt;
 and &lt;a href="https://github.com/kdsama/go_leetcode_prep/blob/master/efficient_algorithms/threadpool_kmp.go" class="ltag_cta ltag_cta--branded"&gt;Channels&lt;/a&gt;
. &lt;br&gt;
Let me know in the comments if you would like a deep dive into how to design parallel algorithms. &lt;/p&gt;

</description>
    </item>
    <item>
      <title>Parallel algorithms series. Part 1: A little bit about sequential algorithms.</title>
      <dc:creator>Kshitij (kd)</dc:creator>
      <pubDate>Mon, 10 Jul 2023 21:53:52 +0000</pubDate>
      <link>https://forem.com/dhingrachief/parallel-algorithms-series-part-1-a-little-bit-about-sequential-algorithms-289</link>
      <guid>https://forem.com/dhingrachief/parallel-algorithms-series-part-1-a-little-bit-about-sequential-algorithms-289</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;If you are reading this post, I am pretty sure that you have already implemented some form of a sequential model. It can be a an algorithm for sorting, a function that returns a fibonacci sequence or something as simple as Adding all the items in a list.&lt;br&gt;
Most of the algorithms that you have come across till now utilizes a single core.&lt;br&gt;
And probably that is not what you are interested in. But to get into parallel algorithms, first look at the machine models that we use for sequential computations.&lt;/p&gt;
&lt;h2&gt;
  
  
  RAM Model
&lt;/h2&gt;

&lt;p&gt;Lets talk about adding two numbers, each having d = 5 digits&lt;br&gt;
e.g 23568 + 98321&lt;br&gt;
What will be the cost of adding these two numbers ? &lt;br&gt;
For this particular use case , you might have guessed "constant time" and you are probably right. &lt;br&gt;
We have two numbers that can be easily contained in a 64 bit integer and the addition might happen in 1 or 2 operation cycles. &lt;/p&gt;

&lt;p&gt;But thing changes if the number itself is too big, and does not fit into the 64bit . In that case, there will be a split, some carryovers and then we will get the result. One can say it depends upon the size the number of digits we are adding. &lt;br&gt;
The analysis of the code will get complex if we start considering these cases as well, hence we need a standard to follow to make things easier for ourselves. Generally, we use RAM Model, a standard for sequential computation. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is RAM Model then ?&lt;/strong&gt;&lt;br&gt;
RAM Model or Random Access Model is a machine model that has the following attributes&lt;br&gt;
*Unlimited memory. Any size of input can be accomodated easily in memory cells.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fixed amount of registers. Registers are temporary storage sitting next to the processors. They cannot be unlimited, or else why do we even need memory ? Save everything in the registers. Hence, we have limited amount of storage to hold data at a time. &lt;/li&gt;
&lt;li&gt;memory cells and registers can save w size integers (or numbers from 0 to 2^w-1). Here w = logn. The size of integer will increase logarithmically wrt to the number. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the RAM Model, the total cost is the number of instructions executed. These instructions are &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Load into registers from memory, and vice versa. &lt;/li&gt;
&lt;li&gt;Arithematic Operations (+,-, %, *, AND , OR , XOR etc)&lt;/li&gt;
&lt;li&gt;conditional/unconditional jumps (Those if cases have some cost as well!)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So the next time, when you see a program with n iterations and multiple operations and if-else conditions, you can tell your friends that they aren't wrong, but they aren't right either.  Here is an example below&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    var i,n, sum int
    fmt.Print("Enter the value of n: ")
    fmt.Scan(&amp;amp;n)
    for i &amp;lt;= n {
        sum += i
        i++
    }
    fmt.Println(sum)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The time complexity here is O(n). But really, its 2n instructions. (add operation on sum and add operation on i). &lt;/p&gt;

&lt;p&gt;I am trying to keep the articles short and sweet. In the Next One, we will dive into PRAM Model. &lt;/p&gt;

</description>
      <category>algorithms</category>
    </item>
    <item>
      <title>Plugin multiple Mongodb sources to Prometheus and visualise them on Grafana</title>
      <dc:creator>Kshitij (kd)</dc:creator>
      <pubDate>Mon, 22 Nov 2021 07:00:08 +0000</pubDate>
      <link>https://forem.com/dhingrachief/plugin-multiple-mongodb-sources-to-prometheus-and-visualise-them-on-grafana-4phm</link>
      <guid>https://forem.com/dhingrachief/plugin-multiple-mongodb-sources-to-prometheus-and-visualise-them-on-grafana-4phm</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;I ran into a situation where I had to put certain metrics alert for a couple of mongodb instances. This was a challenge as I couldnot find direct resources for the setup we were trying to achieve. So this article will help you plugin multiple mongodb sources and visualise them on Grafana. &lt;/p&gt;

&lt;h2&gt;
  
  
  Pre-requisites
&lt;/h2&gt;

&lt;p&gt;The setup we are doing would require Docker installed on your system/server.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create user for all Mongo instances
&lt;/h2&gt;

&lt;p&gt;Go to your mongodb shell and create a user . This user will be used by mongodb exporter to export the metrices and forward them to Prometheus.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt;use admin
&amp;gt;db.createUser(
  {
    user: "mongodb_exporter",
    pwd: "your_unique_password",
    roles: [
        { role: "clusterMonitor", db: "admin" },
        { role: "read", db: "local" }
    ]
  }
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Installing and Running Mongodb Exporter
&lt;/h2&gt;

&lt;p&gt;Here I am using &lt;a href="https://github.com/bitnami/bitnami-docker-mongodb-exporter"&gt;Bitnami's Docker Image&lt;/a&gt; for exporting the metrices.&lt;br&gt;
I have two mongodb sources that I need to plugin. So I will be running to mongodb exporters. &lt;/p&gt;

&lt;p&gt;For instance 1 and 2:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker run -d --name m1  -p 9216:9216 bitnami/mongodb-exporter:0.11.2 --mongodb.uri=mongodb://mongodb_exporter:your_unique_password@INSTANCE.1.IP:27017

docker run -d --name m2  -p 9215:9216 bitnami/mongodb-exporter:0.11.2 --mongodb.uri=mongodb://mongodb_exporter:your_unique_password_2@INSTANCE.2.IP:27017

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

&lt;/div&gt;



&lt;p&gt;The key differences above are the name, port on which the services run, and the mongo url. &lt;br&gt;
&lt;strong&gt;Note:&lt;/strong&gt; If you are trying this out on a server, make sure to add rules to your firewall so that the server containing the mongodb exporters can access the mongodb instances. &lt;/p&gt;
&lt;h2&gt;
  
  
  Prometheus
&lt;/h2&gt;

&lt;p&gt;To install Prometheus using docker, we need to add a configuration file that will then be mounted to the docker container. &lt;/p&gt;
&lt;h3&gt;
  
  
  prom.yml
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;scrape_configs:
- job_name: 'prometheus'
    static_configs:
            - targets: ['PRIVATE_IP:9090']
  - job_name: 'mongo-1'
    static_configs:
            - targets: ['PRIVATE_IP:9216']
            - labels:
                instance: 'mongo1'
  - job_name: 'mongo-2'
    static_configs:
            - targets: ['PRIVATE_IP:9215']
            - labels:
                instance: 'mongo2'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;So we mentioned targets in the &lt;a href="https://prometheus.io/docs/prometheus/latest/configuration/configuration/#:~:text=A%20scrape_config%20section%20specifies%20a,advanced%20configurations%2C%20this%20may%20change."&gt;scrap_configs section&lt;/a&gt;&lt;br&gt;
i.e our mongodb-exporter instances that are scraping data from mongodb. &lt;/p&gt;

&lt;p&gt;Now to run Prometheus&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker run  -d -v /PATH/TO/CONFIG/prom.yml:/etc/prometheus/prometheus.yml --network=host  --name prom prom/prometheus
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Grafana
&lt;/h2&gt;

&lt;p&gt;To run Grafana using docker:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker run -d  --network=host --name grafana grafana/grafana
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I have added a &lt;a href="https://github.com/kdsama/PromGrafanaMongodb/blob/main/makefile"&gt;makefike&lt;/a&gt; for all the docker commands required to run each and every instance. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Prometheus and Grafana here are running on host network and this is not adviceable for production environments. Its better to create a different network or expose only the ports that are to be accessed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Signin
&lt;/h3&gt;

&lt;p&gt;Go to YOUR_IP:3000. Login (username and password both is admin)&lt;/p&gt;

&lt;h3&gt;
  
  
  Add source
&lt;/h3&gt;

&lt;p&gt;Go to &lt;strong&gt;Configuration&lt;/strong&gt; &amp;gt; &lt;strong&gt;Data Sources&lt;/strong&gt; &amp;gt; &lt;strong&gt;Add Source&lt;/strong&gt;&lt;br&gt;
Select Prometheus&lt;br&gt;
In the URL field add http :// YOUR_IP:9090. Save the configuration. &lt;/p&gt;

&lt;h2&gt;
  
  
  See Multiple Grafana instances and toggle between them.
&lt;/h2&gt;

&lt;p&gt;There are several free to import &lt;a href="https://grafana.com/grafana/dashboards/"&gt;dashboards&lt;/a&gt; that you can use and we will be using one of those to see the data and toggle between different instances. &lt;/p&gt;

&lt;h3&gt;
  
  
  Add a Dashboard
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Hover on Import (+ sign on the left) &amp;gt; &lt;strong&gt;Import&lt;/strong&gt; &lt;/li&gt;
&lt;li&gt;In the Import via Grafana section, for this example, add &lt;a href="https://grafana.com/grafana/dashboards/7353"&gt;7353&lt;/a&gt;. Click on load on the right of the input field. &lt;/li&gt;
&lt;li&gt;At the bottom, select source for prometheus and save the dashboard&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s----w1JeNG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l9c1zv56f1jnhecyw84d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s----w1JeNG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l9c1zv56f1jnhecyw84d.png" alt="The image is a snippet of grafana dashboard. The image shows a few dropdown. The important one is the instance dropdown where you can change your mongodb source" width="710" height="54"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here You can see an Instance filter where one of the sources would be selected. From here you can toggle to the other source you have added initially. &lt;/p&gt;

&lt;p&gt;And that is all you need to do to add multiple mongodb sources and visualise them on Grafana.I have added all the relevant files &lt;a href="https://github.com/kdsama/PromGrafanaMongodb"&gt;here&lt;/a&gt;&lt;/p&gt;

</description>
      <category>devops</category>
      <category>monitoring</category>
      <category>mongodb</category>
    </item>
    <item>
      <title>Install and Run Mongodb using Ansible</title>
      <dc:creator>Kshitij (kd)</dc:creator>
      <pubDate>Mon, 23 Aug 2021 11:22:31 +0000</pubDate>
      <link>https://forem.com/dhingrachief/install-and-run-mongodb-using-ansible-77c</link>
      <guid>https://forem.com/dhingrachief/install-and-run-mongodb-using-ansible-77c</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;As a person who has to do several on-premise deployments, at a place where docker is not accepted yet, I have had several issues installing mongodb. Even if I am installing it in the same environment, or upgrading it, I face several problems regarding permissions, ownerships, lockfiles etc. &lt;br&gt;
In this article I will share an automated way through which you can install mongodb (version 4.2). Yes, we will be using ansible.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pre-requisites
&lt;/h2&gt;

&lt;p&gt;You need to have &lt;a href="https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html"&gt;ansible&lt;/a&gt; installed on your system.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hosts
&lt;/h2&gt;

&lt;p&gt;When you run an ansible-playbook command, you may or may not mention the host file which has the all the required host information. Lets create a new file named mongo-hosts and enter name of all the servers on which you need mongodb installed&lt;/p&gt;

&lt;h3&gt;
  
  
  mongo-hosts
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[local]
localhost       ansible_connection=local

[mongo-server-1]
XX.YY.ZZ.AA   ansible_connection=ssh  ansible_user=user

[mongo-server-2]
XX.YY.ZZ.BB   ansible_connection=ssh ansible_user=user

[mongo-servers:children]
local
mongo-server-1
mongo-server-2

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

&lt;/div&gt;



&lt;p&gt;We have mentioned all the instances, with their connection type and username. &lt;br&gt;
Here you can see that I have grouped all the servers at the end. So anywhere mongo-servers is mentioned in playbook,All the child instances will be considered. &lt;/p&gt;

&lt;h2&gt;
  
  
  Playbook - mongo-playbook.yml
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- hosts: mongo-servers
  become: true
  serial: 1

  tasks:
    - name: Install aptitude using apt
      apt:
        name: aptitude
        state: latest
        update_cache: yes

    - name: Import public key
      apt_key:
        url: 'https://www.mongodb.org/static/pgp/server-4.2.asc'
        state: present

    - name: Add repository
      apt_repository:
        filename: '/etc/apt/sources.list.d/mongodb-org-4.2.list'
        repo: 'deb https://repo.mongodb.org/apt/ubuntu bionic/mongodb-org/4.2 multiverse'
        state: present
        update_cache: yes

    - name: Install mongoDB
      apt:
        name: mongodb-org
        state: present
        update_cache: yes

    - name: Ensure mongodb is running and and enabled to start automatically on reboots
      service:
        name: mongod
        enabled: yes
        state: started

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

&lt;/div&gt;



&lt;p&gt;So here as we can see &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;hosts represent the instances on which this playbook will run. &lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.ansible.com/ansible/latest/user_guide/become.html"&gt;become&lt;/a&gt; parameter is a privilege escalation setting as some commands we would only be able to run if the user is sudo. &lt;strong&gt;Note:&lt;/strong&gt; These commands are only possible if the user through which ansible logs into the server is a sudo user.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.ansible.com/ansible/latest/user_guide/playbooks_strategies.html"&gt;serial&lt;/a&gt; parameter is for controlling how the playbook will be executed. In our case, this would mean that we are going to run the playbook on all the servers serially. &lt;/li&gt;
&lt;li&gt;tasks are the steps that ansible will take on each server. These are the commands that we generally run to install mongodb manually. &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Execution:
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ansible-playbook mongo-playbook.yml -vvvv -i ./mongo-hosts 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;-vvvv is used to run the ansible playbook in verbose mode. &lt;br&gt;
If we dont mention the hosts file(using i flag) , ansible-playbook will pick from the default one. In case of Ubuntu, that is /var/ansible/hosts &lt;/p&gt;

&lt;p&gt;And thats it! This is a really basic case which only touches a simple installation. Let me know if you need examples of more complex ones (Primary,secondary,arbiter or the same using docker)&lt;/p&gt;

</description>
      <category>ansible</category>
      <category>devops</category>
      <category>mongodb</category>
    </item>
    <item>
      <title>Run Docker commands inside Jenkins Docker container</title>
      <dc:creator>Kshitij (kd)</dc:creator>
      <pubDate>Mon, 19 Jul 2021 11:14:10 +0000</pubDate>
      <link>https://forem.com/dhingrachief/run-docker-commands-inside-jenkins-docker-k6d</link>
      <guid>https://forem.com/dhingrachief/run-docker-commands-inside-jenkins-docker-k6d</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;If you want to initiate docker containers from within your jenkin containers,this is what you have to do:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In the Jenkins Dockerfile, add commands to get docker, docker-compose installed. &lt;/li&gt;
&lt;li&gt;bind mount the docker socket.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And thats it! This is how the Dockerfile looks like:&lt;/p&gt;

&lt;h2&gt;
  
  
  Jenkins Dockerfile
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FROM jenkins/jenkins

# Docker install
USER root
RUN apt-get update &amp;amp;&amp;amp; apt-get install -y \
       apt-transport-https \
       ca-certificates \
       curl \
       gnupg2 \
       software-properties-common \


RUN curl -fsSL https://download.docker.com/linux/debian/gpg | apt-key add -
RUN apt-key fingerprint 0EBFCD88
RUN add-apt-repository \
       "deb [arch=amd64] https://download.docker.com/linux/debian \
       $(lsb_release -cs) \
       stable"

RUN curl -L https://github.com/docker/compose/releases/download/1.27.4/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose \
&amp;amp;&amp;amp; chmod +x /usr/local/bin/docker-compose

RUN apt-get update &amp;amp;&amp;amp; apt-get install -y docker-ce-cli

USER jenkins

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

&lt;/div&gt;



&lt;p&gt;Now to build the image:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker build -t jenkins-docker .
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To run the docker-image, including the volume mounts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; docker run -d --group-add $(stat -c '%g' /var/run/docker.sock) \
-v /var/run/docker.sock:/var/run/docker.sock -p 8080:8080 -p 50000:50000 \
-v `pwd`/jenkins:/var/jenkins_home --log-opt max-size=50k   --log-opt max-file=5   --name jenkins -P jenkins-docker
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here you can see docker.sock file has been mounted.Also, jenkins_home folder has been mounted so that you can persist the information regarding your pipeline/configuration/users etc.&lt;br&gt;
Dont forget to take backup of jenkins_home directory!&lt;/p&gt;

&lt;p&gt;I have uploaded a &lt;a href="https://github.com/kdsama/Jenkins-Docker/blob/main/makefile"&gt;makefile&lt;/a&gt; and a similar &lt;a href="https://github.com/kdsama/Jenkins-Docker/blob/main/Dockerfile"&gt;Dockerfile&lt;/a&gt; on github.&lt;/p&gt;

&lt;p&gt;And thats it! &lt;/p&gt;

</description>
      <category>docker</category>
      <category>jenkins</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
