<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: João Cerqueira</title>
    <description>The latest articles on DEV Community by João Cerqueira (@cerqueira).</description>
    <link>https://dev.to/cerqueira</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%2F37500%2F6d9d6c74-6969-464d-8c46-462c15ad2819.jpg</url>
      <title>DEV Community: João Cerqueira</title>
      <link>https://dev.to/cerqueira</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/cerqueira"/>
    <language>en</language>
    <item>
      <title>Implementing a peer-to-peer network in Elixir - Part 1: The Server</title>
      <dc:creator>João Cerqueira</dc:creator>
      <pubDate>Fri, 29 Dec 2017 12:26:34 +0000</pubDate>
      <link>https://dev.to/cerqueira/implementing-a-peer-to-peer-network-in-elixir---part-1-the-server-59p6</link>
      <guid>https://dev.to/cerqueira/implementing-a-peer-to-peer-network-in-elixir---part-1-the-server-59p6</guid>
      <description>&lt;p&gt;&lt;em&gt;This post was originally posted on the &lt;a href="https://opencode.space/implementing-a-peer-to-peer-network-in-elixir-part-1"&gt;opencode.space blog&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In the past week or so I've been implementing a peer-to-peer network using Elixir as part of a project I'm working on. I thought about writing this post series because I haven't found much resources addressing such cases online and second to document the whole process for future reference.&lt;/p&gt;

&lt;p&gt;Even if you don't want to implement a peer-to-peer network, this is still a great exercise to learn more and experimenting OTP applications and concepts.&lt;/p&gt;

&lt;p&gt;We'll be implementing a peer-to-peer network that allows peers to send a text message to other peers and receive the same message back. Simple enough, right?&lt;/p&gt;

&lt;p&gt;This series is split in three parts:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://opencode.space/implementing-a-peer-to-peer-network-in-elixir-part-1"&gt;Implementing a peer-to-peer network in Elixir - Part 1: The Server&lt;/a&gt; (current)&lt;/li&gt;
&lt;li&gt;&lt;del&gt;Implementing a peer-to-peer network in Elixir - Part 2: The Client&lt;/del&gt;&lt;/li&gt;
&lt;li&gt;&lt;del&gt;Implementing a peer-to-peer network in Elixir - Part 3: Enhancements&lt;/del&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In this post we cover our peer-to-peer network server-side logic. In the end, you will have a working TCP server that listens and accepts connections and echoes back every message it receives.&lt;/p&gt;

&lt;p&gt;When we're done, you'll be able to connect and test it using Telnet.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create the project
&lt;/h2&gt;

&lt;p&gt;Use &lt;a href="https://hexdocs.pm/mix/Mix.html"&gt;Mix&lt;/a&gt; to create a new project with the &lt;code&gt;--sup&lt;/code&gt; flag, to generate an OTP application skeleton that includes a supervision tree and the &lt;code&gt;application&lt;/code&gt; callback setup. For the sake of simplicity, I'll name this project &lt;code&gt;network&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;mix new network &lt;span class="nt"&gt;--sup&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Setup dependencies
&lt;/h2&gt;

&lt;p&gt;For this project, the only dependency that we will need is Ranch&lt;sup id="fnref1"&gt;1&lt;/sup&gt;. Update &lt;strong&gt;mix.exs&lt;/strong&gt; to include it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;deps&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ranch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"~&amp;gt; 1.4"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When done, fetch the dependency:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;mix deps.get
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Listening for connections
&lt;/h2&gt;

&lt;p&gt;To have have someone connecting to our server, we have to be listening for and accepting them as they arrive. This is where the Ranch&lt;sup id="fnref1"&gt;1&lt;/sup&gt; library comes handy.&lt;/p&gt;

&lt;p&gt;Create &lt;strong&gt;lib/network/server.ex&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;Network&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Server&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="nv"&gt;@moduledoc&lt;/span&gt; &lt;span class="sd"&gt;"""
  A simple TCP server.
  """&lt;/span&gt;

  &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="no"&gt;GenServer&lt;/span&gt;

  &lt;span class="n"&gt;alias&lt;/span&gt; &lt;span class="no"&gt;Network&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Handler&lt;/span&gt;

  &lt;span class="kn"&gt;require&lt;/span&gt; &lt;span class="no"&gt;Logger&lt;/span&gt;

  &lt;span class="nv"&gt;@doc&lt;/span&gt; &lt;span class="sd"&gt;"""
  Starts the server.
  """&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;start_link&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="no"&gt;GenServer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start_link&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;__MODULE__&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;name:&lt;/span&gt; &lt;span class="bp"&gt;__MODULE__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="nv"&gt;@doc&lt;/span&gt; &lt;span class="sd"&gt;"""
  Initiates the listener (pool of acceptors).
  """&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;port:&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;opts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="ss"&gt;:port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;

    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="ss"&gt;:ranch&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start_listener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:network&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:ranch_tcp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Handler&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[])&lt;/span&gt;

    &lt;span class="no"&gt;Logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
      &lt;span class="s2"&gt;"Listening for connections on port &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On the &lt;code&gt;init/1&lt;/code&gt; function is where the magic happens. We're using the &lt;code&gt;:ranch.start_listener/5&lt;/code&gt; function to create a pool of acceptor processes that will accept incoming connections and, when it does, spawn a new process to handle it with the specified protocol (&lt;code&gt;Network.Handler&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;The five arguments the &lt;code&gt;:ranch.start_listener/5&lt;/code&gt; requires are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;:network&lt;/code&gt; --- unique name that identifies the listener&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;:ranch_tcp&lt;/code&gt; --- the transport&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;[{:port, port}]&lt;/code&gt; --- transport's options&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Network.Handler&lt;/code&gt; --- protocol handler&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;[]&lt;/code&gt; --- handler's options&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Handling connections
&lt;/h2&gt;

&lt;p&gt;Because Ranch&lt;sup id="fnref1"&gt;1&lt;/sup&gt; makes us abstract the protocol handling into it's own module --- which is very useful because of the fact that it minimizes code complexity --- that's what we'll do now.&lt;/p&gt;

&lt;p&gt;Create &lt;strong&gt;lib/network/handler.ex&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;Network&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Handler&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="nv"&gt;@moduledoc&lt;/span&gt; &lt;span class="sd"&gt;"""
  A simple TCP protocol handler that echoes all messages received.
  """&lt;/span&gt;

  &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="no"&gt;GenServer&lt;/span&gt;

  &lt;span class="kn"&gt;require&lt;/span&gt; &lt;span class="no"&gt;Logger&lt;/span&gt;

  &lt;span class="c1"&gt;# Client&lt;/span&gt;

  &lt;span class="nv"&gt;@doc&lt;/span&gt; &lt;span class="sd"&gt;"""
  Starts the handler with `:proc_lib.spawn_link/3`.
  """&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;start_link&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;transport&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_opts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;pid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="ss"&gt;:proc_lib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;spawn_link&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;__MODULE__&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:init&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;transport&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="nv"&gt;@doc&lt;/span&gt; &lt;span class="sd"&gt;"""
  Initiates the handler, acknowledging the connection was accepted.
  Finally it makes the existing process into a `:gen_server` process and
  enters the `:gen_server` receive loop with `:gen_server.enter_loop/3`.
  """&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;transport&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;peername&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;stringify_peername&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="no"&gt;Logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
      &lt;span class="s2"&gt;"Peer &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;peername&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; connecting"&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="ss"&gt;:ok&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="ss"&gt;:ranch&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;accept_ack&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="ss"&gt;:ok&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;transport&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setopts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="ss"&gt;:active&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="p"&gt;}])&lt;/span&gt;

    &lt;span class="ss"&gt;:gen_server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;enter_loop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;__MODULE__&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;
      &lt;span class="ss"&gt;socket:&lt;/span&gt; &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="ss"&gt;transport:&lt;/span&gt; &lt;span class="n"&gt;transport&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="ss"&gt;peername:&lt;/span&gt; &lt;span class="n"&gt;peername&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="c1"&gt;# Server callbacks&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;handle_info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:tcp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;socket:&lt;/span&gt; &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;transport:&lt;/span&gt; &lt;span class="n"&gt;transport&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;peername:&lt;/span&gt; &lt;span class="n"&gt;peername&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;
      &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="no"&gt;Logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
      &lt;span class="s2"&gt;"Received new message from peer &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;peername&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;inspect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;. Echoing it back"&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Sends the message back&lt;/span&gt;
    &lt;span class="n"&gt;transport&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:noreply&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;handle_info&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="ss"&gt;:tcp_closed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;peername:&lt;/span&gt; &lt;span class="n"&gt;peername&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="no"&gt;Logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
      &lt;span class="s2"&gt;"Peer &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;peername&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; disconnected"&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:stop&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:normal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;handle_info&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="ss"&gt;:tcp_error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;reason&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;peername:&lt;/span&gt; &lt;span class="n"&gt;peername&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="no"&gt;Logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
      &lt;span class="s2"&gt;"Error with peer &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;peername&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;inspect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reason&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:stop&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:normal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="c1"&gt;# Helpers&lt;/span&gt;

  &lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;stringify_peername&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;addr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="ss"&gt;:inet&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;peername&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
      &lt;span class="n"&gt;addr&lt;/span&gt;
      &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="ss"&gt;:inet_parse&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ntoa&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;to_string&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are some particularities about this module that are very interesting. First, you may have noticed we've implemented the &lt;code&gt;GenServer&lt;/code&gt; behaviour because of the functions and callbacks defined, although we don't use the &lt;code&gt;GenServer.start_link/3&lt;/code&gt; function and instead use &lt;code&gt;:proc_lib.spawn_link/3&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Before moving into more details on that, let's see the &lt;code&gt;init/3&lt;/code&gt; function. It's all clear at first sight: we acknowledge the connection with &lt;code&gt;:ranch.accept_ack/1&lt;/code&gt;, set the connection to be active and then... we enter a loop?&lt;/p&gt;

&lt;p&gt;Sure! We need to be in a loop waiting for new messages to arrive from the connection and upon receiving a message we do whatever processing it requires, entering the loop and waiting for new messages again.&lt;/p&gt;

&lt;p&gt;As we implement the &lt;code&gt;GenServer&lt;/code&gt; behaviour we must use &lt;code&gt;:gen_server.enter_loop/3&lt;/code&gt; which turns our process into a &lt;code&gt;:gen_server&lt;/code&gt; process and enters the &lt;code&gt;:gen_server&lt;/code&gt; process receive loop.&lt;/p&gt;

&lt;p&gt;Now going back, why &lt;code&gt;:proc_lib.spawn_link/3&lt;/code&gt;? If you are aware of the &lt;code&gt;GenServer&lt;/code&gt; behaviour you know that you must define a &lt;code&gt;start/3&lt;/code&gt; or &lt;code&gt;start_link/3&lt;/code&gt; function to start the server and that once it has started it will call the &lt;code&gt;init&lt;/code&gt; callback. So far so good.&lt;/p&gt;

&lt;p&gt;The issue happens because of the way that behaviour works. According to the &lt;a href="https://hexdocs.pm/elixir/GenServer.html#start_link/3"&gt;&lt;code&gt;GenServer.start_link/3&lt;/code&gt; documentation&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;To ensure a synchronized start-up procedure, this function does not return until &lt;code&gt;c:init/1&lt;/code&gt; has returned.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That would raise a big issue when we need to enter a loop, because when you enter the loop it will never return until something bad happen and an error is returned. Thus why we are using &lt;code&gt;:proc.spawn_link/3&lt;/code&gt;, because instead of spawning the process synchronously it will spawn it asynchronously and we won't have any issues.&lt;/p&gt;

&lt;p&gt;Actually, the only processes that can use &lt;code&gt;:gen_server.enter_loop/3&lt;/code&gt; are those started with this particular function.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;handle_info/2&lt;/code&gt; callback will receive every TCP event. Those can be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;{:tcp, socket, message}&lt;/code&gt; --- a normal message sent by the client&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;{:tcp_error, socket, reason}&lt;/code&gt; --- any error that occurs with the connection&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;{:tcp_closed, socket}&lt;/code&gt; --- when the connection is closed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We've also defined a &lt;code&gt;stringify_peername/1&lt;/code&gt; helper function to give us a friendly name for a given connection. It uses the &lt;code&gt;:inet.peername/1&lt;/code&gt; function to retrieve the address and port of a connection&lt;br&gt;
and returns a string combining both values.&lt;/p&gt;
&lt;h2&gt;
  
  
  Starting the server
&lt;/h2&gt;

&lt;p&gt;Update &lt;strong&gt;config/config.exs&lt;/strong&gt; to include the server configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="no"&gt;Mix&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Config&lt;/span&gt;

&lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="ss"&gt;:network&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:server&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;port:&lt;/span&gt; &lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_integer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"PORT"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="s2"&gt;"5555"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Update &lt;strong&gt;lib/network/application.ex&lt;/strong&gt; to include &lt;code&gt;Network.Server&lt;/code&gt; in the application's supervision tree:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;Network&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Application&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="nv"&gt;@moduledoc&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;

  &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="no"&gt;Application&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="c1"&gt;# Get configuration&lt;/span&gt;
    &lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Application&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:network&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:server&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;children&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="c1"&gt;# Add it to supervison tree&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;Network&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Server&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="n"&gt;opts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;strategy:&lt;/span&gt; &lt;span class="ss"&gt;:one_for_one&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;name:&lt;/span&gt; &lt;span class="no"&gt;Network&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Supervisor&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="no"&gt;Supervisor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start_link&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;children&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Testing
&lt;/h2&gt;

&lt;p&gt;Open a terminal and start the application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;mix run &lt;span class="nt"&gt;--no-halt&lt;/span&gt;
00:00:00.000 &lt;span class="o"&gt;[&lt;/span&gt;info] Accepting connections on port 5555
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open another terminal and connect using Telnet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;telnet 127.0.0.1 5555
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is &lt;span class="s1"&gt;'^['&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nice, we've successfully connected to the server. On the terminal our application is running we should also see a message informing us just that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;00:00:00.000 &lt;span class="o"&gt;[&lt;/span&gt;info] Peer 127.0.0.1:00000 connecting
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now try to send any message through the telnet session, and it will be echoed back. On the application's terminal you'll see (for example):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;00:00:00.000 &lt;span class="o"&gt;[&lt;/span&gt;info] Received new message from 127.0.0.1:00000: &lt;span class="s2"&gt;"Hello, opencode.space!&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt; Echoing it back
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And if you close the terminal running Telnet our application also gets notified:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;00:00:00.000 &lt;span class="o"&gt;[&lt;/span&gt;info] Peer 127.0.0.1:00000 disconnected
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In only &lt;code&gt;~153 LOC&lt;/code&gt; we have successfully implemented a TCP server that echoes every message it receives. Pretty neat, isn't it?&lt;/p&gt;

&lt;p&gt;On the next part of this series we will be covering how to implement a client to connect to the server in order to achieve a peer-to-peer network.&lt;/p&gt;

&lt;p&gt;Stay tunned for updates!&lt;/p&gt;

&lt;h2&gt;
  
  
  Notes
&lt;/h2&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;&lt;a href="https://github.com/ninenines/ranch"&gt;Ranch&lt;/a&gt; is a socket acceptor pool for TCP protocols developed by &lt;a href="https://ninenines.eu/"&gt;NineNines&lt;/a&gt;. For more information visit the library's &lt;a href="https://ninenines.eu/docs/en/ranch/1.4/guide"&gt;User Guide&lt;/a&gt; or &lt;a href="https://ninenines.eu/docs/en/ranch/1.4/manual"&gt;Function Reference&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>elixir</category>
      <category>network</category>
      <category>p2p</category>
      <category>ranch</category>
    </item>
    <item>
      <title>Organizing your life using Github</title>
      <dc:creator>João Cerqueira</dc:creator>
      <pubDate>Mon, 30 Oct 2017 17:39:16 +0000</pubDate>
      <link>https://dev.to/jpcs369/organizing-your-life-using-github-6an</link>
      <guid>https://dev.to/jpcs369/organizing-your-life-using-github-6an</guid>
      <description>&lt;p&gt;I'm that kind of person that struggled really hard to self-educate to be organized. That had to change in favor of restoring my sanity back and one day the light bulb hover my head went on.&lt;/p&gt;

&lt;h1&gt;
  
  
  The issue
&lt;/h1&gt;

&lt;p&gt;Everything was messy before: tasks and notes written in loose papers or random task management software, unanswered calls lost in promises to be returned, files and important documents spread along a zillion different cloud storage services. Resuming, everything was darker back then.&lt;/p&gt;

&lt;p&gt;I've tried lots of software that promised to simplify the horror I was going through and actually help me getting things done and don't forget anything - but all of them failed. Most of the times it wasn't about the softwares themselves but simply because they didn't fit my way of doing things.&lt;/p&gt;

&lt;h1&gt;
  
  
  The &lt;em&gt;tada&lt;/em&gt; moment
&lt;/h1&gt;

&lt;p&gt;I was on the verge of collapse, navigating through some issues on a repository on Github when: &lt;em&gt;tada&lt;/em&gt;! Suddenly everything was clear. I was already using an awesome software (Github) to manage my projects' code, issues and tasks that had to be done, why not adapt it to a new "project": My personal life!&lt;/p&gt;

&lt;h1&gt;
  
  
  How I did it
&lt;/h1&gt;

&lt;p&gt;Basically what I did was to adapt the concept we (developers) already employ for project management and organization on Github to my personal life. So, instead of having a repository to store and keep track of my code, I'd instead use it to store and keep track of any important documents, pictures and other random files I can't loose.&lt;/p&gt;

&lt;p&gt;It was pretty straight forward and showed advantages right away after setting up that new &lt;em&gt;private&lt;/em&gt; repository which I named &lt;code&gt;personal&lt;/code&gt;. The most noticeable one was after I fed it with important documents I went to another laptop I own and cloned the repository. In ~5 seconds I had my documents "synced" on both machines, securely saved on a private Github repository and easily manageable on both Github interface and on my dear terminal with the infamous &lt;code&gt;git&lt;/code&gt; tool.&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%2Fhvppliv8eyz01weowtif.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%2Fhvppliv8eyz01weowtif.png" alt="example"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This was the first step to start implementing a better organization for all-my-things, however one thing was still missing: I also had to keep track of both my personal and professional tasks (professional = freelancing/open source projects, not organization-specific ones).&lt;/p&gt;

&lt;p&gt;To achieve that, I enabled the "Github Projects" feature on that repository and bootstrapped two projects: "Personal" and "Work" for personal (shopping, pay bills, etc.) and work-specific (call a client, reply an email, review a feature, etc.) tasks respectively.&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%2Fv8u60pyc15ytbnd84c91.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%2Fv8u60pyc15ytbnd84c91.png" alt="example"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Each project has 4 basic columns to put tasks on:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Backlog - for stuff I probably haven't yet decided to do or thought about how I'd do them;&lt;/li&gt;
&lt;li&gt;To Do - stuff I have to do and are ready to be started or I'm waiting on third-party feedback to move along;&lt;/li&gt;
&lt;li&gt;In Progress - stuff I'm working on at the moment.&lt;/li&gt;
&lt;li&gt;Done - stuff I already finished and can be safely archived and sometimes forgot.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Tasks themselves are simple "cards" or full detailed issues (for more important/complex things that need extra information).&lt;/p&gt;

&lt;p&gt;Now I had it all (files and tasks) in a single place that I love to work on! So much better! Sure I still sometimes write tasks and notes on paper or on my smartphone's notes application, however I made a commitment with myself to as soon as I open my laptop through the tasks/notes into the respective projects on Github right away. &lt;/p&gt;

&lt;p&gt;Apart from those two base projects, one is also free to create more and more projects to make organization even clear and simpler. For example, imagine you're moving from a city to another, there are plenty of things you have to do and most of them are important to be done right to avoid headaches in the future. One could create a new "Move to X place" project and a correspondent milestone (on Issues Tracker) to keep track of that process and don't miss a thing.&lt;/p&gt;

&lt;p&gt;I guess there are already people doing "self-management" in a similar fashion to what I'm now doing with Github, but as I haven't seen any experiences alike on the web I thought that it could be interesting to share this with others and maybe get some feedback on this "system" or suggestions to improve it.&lt;/p&gt;

&lt;p&gt;Hope you've enjoyed! Don't forget that the way I'm organizing tasks, for example, is oriented for my personal use cases and surely doesn't fit everyone's needs. You can still adapt it to your own way of organizing things to make this system work better for yourself.&lt;/p&gt;

&lt;p&gt;Thanks Github, for saving my day once more!&lt;/p&gt;

</description>
      <category>git</category>
      <category>github</category>
      <category>selforganization</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
