<?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: paschal</title>
    <description>The latest articles on Forem by paschal (@obbap).</description>
    <link>https://forem.com/obbap</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%2F37350%2F0aa7a356-e530-489e-8644-7724791291fa.jpeg</url>
      <title>Forem: paschal</title>
      <link>https://forem.com/obbap</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/obbap"/>
    <language>en</language>
    <item>
      <title>Pipelining for Memcached</title>
      <dc:creator>paschal</dc:creator>
      <pubDate>Sat, 24 May 2025 00:32:00 +0000</pubDate>
      <link>https://forem.com/obbap/pipelining-for-memcached-1pm9</link>
      <guid>https://forem.com/obbap/pipelining-for-memcached-1pm9</guid>
      <description>&lt;p&gt;Typical Client-Server protocols operate a request - response model.&lt;br&gt;
&lt;a href="https://media2.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%2Fwi5rz6hr6r56gzwtnefj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fwi5rz6hr6r56gzwtnefj.png" alt="nopipeline" width="705" height="755"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With the HTTP1 protocol for example, Request N+1 is blocked by Request N on a single TCP connection. With clients like web browsers, the workaround is to establish a pool of connections which allow multiple assets like images, scripts to be requested all at once. This means that requests N and N+1 could be sent all at once.&lt;/p&gt;

&lt;p&gt;Pipelining was eventually implemented in HTTP1.1, which allows multiple requests to be sent over the same connection without waiting for the server's response.&lt;br&gt;
&lt;a href="https://media2.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%2Ftnf17so8mjvxpv8jw095.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Ftnf17so8mjvxpv8jw095.png" alt="pipeline" width="705" height="755"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Even with this solution, The requests must still be processed in order. This is the &lt;a href="https://en.wikipedia.org/wiki/Head-of-line_blocking" rel="noopener noreferrer"&gt;head of line (HOL) blocking problem&lt;/a&gt;, where the processing of these requests are still as fast as the slowest request.&lt;/p&gt;

&lt;p&gt;HTTP2 solved this with multiplexing. Multiple requests which are distinguished by a unique stream ID can be interwoven on a single TCP connection and responses could be delivered out of order! &lt;/p&gt;

&lt;p&gt;HTTP2 still suffered the HOL blocking problem at the TCP layer. This is because at the TCP layer, everything is a stream of bytes over a single connection and if any bytes are dropped (packet loss), all the bytes after (other requests) are blocked till TCP detects and retransmits.&lt;/p&gt;

&lt;p&gt;With HTTP3, TCP was dropped for UDP which can handle streams, so only a single stream or request is blocked when there’s packet loss.&lt;/p&gt;

&lt;p&gt;This is a brief and simplified summary but it helps paint the picture. &lt;/p&gt;
&lt;h1&gt;
  
  
  Why is Pipelining important ?
&lt;/h1&gt;

&lt;p&gt;Redis added support for pipelining and &lt;a href="https://redis.io/docs/latest/develop/use/pipelining/" rel="noopener noreferrer"&gt;explains why beautifully&lt;/a&gt;. Basically, for every request (without pipelining), the client has to issue a write syscall to copy bytes from the application in user mode to the tcp buffer in kernel mode and send this over the network. The server on the other hand, makes a read syscall to read the tcp buffer and processes the request.  Pipelining doesn’t reduce the time the server uses to process these requests but saves us time as we won’t have to context switch multiple times when we issue these syscalls. Even in cases where the client and server are on the same machine and communicate via the &lt;a href="https://www.sciencedirect.com/topics/computer-science/loopback-address" rel="noopener noreferrer"&gt;loopback address&lt;/a&gt;, we still see improvements when we utilise pipelining.&lt;/p&gt;
&lt;h1&gt;
  
  
  Memcached
&lt;/h1&gt;

&lt;p&gt;Memcached is a key-value store (like redis) written in C. I've been working with it a lot recently and it uses either its &lt;a href="https://github.com/memcached/memcached/blob/master/doc/protocol.txt" rel="noopener noreferrer"&gt;ASCII protocol&lt;/a&gt; or its &lt;a href="https://github.com/memcached/memcached/blob/master/doc/protocol-binary.txt" rel="noopener noreferrer"&gt;binary protocol&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Starting a memcached server in verbose mode, i see these lines which show that the server supports both protocols and its up to the client to decide what to use:&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;memcached &lt;span class="nt"&gt;-vv&lt;/span&gt;
server listening &lt;span class="o"&gt;(&lt;/span&gt;auto-negotiate&lt;span class="o"&gt;)&lt;/span&gt;
server listening &lt;span class="o"&gt;(&lt;/span&gt;auto-negotiate&lt;span class="o"&gt;)&lt;/span&gt;
new auto-negotiating client connection
……………
Client using the ascii protocol
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I noticed that the &lt;a href="https://github.com/vavrusa/memcache-async" rel="noopener noreferrer"&gt;rust memcached client&lt;/a&gt; i was using didn’t have pipelining support for any commands except the “Get” command. The Set, Increment, Decrement commands have to be issued per key. &lt;/p&gt;

&lt;p&gt;Then i realised that memcached’s ASCII protocol doesn’t support pipelining, only its binary protocol does. The ASCII protocol implements some form of pipelining for the get command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;get &amp;lt;key1&amp;gt; &amp;lt;key2&amp;gt;....&amp;lt;key N&amp;gt;
value 1, value 2, …. value N
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The binary protocol implements pipelining in a different way. It has “quiet” variants of these &lt;a href="https://github.com/memc-rs/memc-rs/blob/master/memcrs/src/protocol/binary/network.rs#L54" rel="noopener noreferrer"&gt;commands&lt;/a&gt;. GetQuiet, SetQuiet, AddQuiet, IncrementQuiet etc. &lt;/p&gt;

&lt;p&gt;The “quiet” variants tell the server to not respond. These responses are queued internally and are returned when the client sends a non-quiet command or a no-op. This returns all the queued keys. &lt;br&gt;
Eg:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;getq &amp;lt;key1&amp;gt; &amp;lt;key2&amp;gt;.....&amp;lt;key N&amp;gt;
….NO RESPONSE FROM THE SERVER
get key&amp;lt;N + 1&amp;gt;
value 1, value 2, value N, value N + 1.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Many clients are comfortable pipelining Get requests as these are read only operations but pipelining Increment requests can get tricky as these are not atomic. Some increments might fail and it’ll be difficult to track and account for.&lt;/p&gt;

&lt;h1&gt;
  
  
  bmemcached
&lt;/h1&gt;

&lt;p&gt;I found a &lt;a href="https://github.com/jaysonsantos/python-binary-memcached" rel="noopener noreferrer"&gt;python library&lt;/a&gt; that implements the binary memcached protocol and the author also wrote a &lt;a href="https://github.com/jaysonsantos/bmemcached-rs" rel="noopener noreferrer"&gt;rust flavour&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;To ensure we're using the binary protocol, i run the tests and look at memcached logs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;28: Client using the binary protocol
&amp;lt;28 Read binary protocol data:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The next hurdle is that these libraries don’t implement the quiet variant of the memcached commands. I have to fork the repo and implement IncrementQuiet (IncrementQ).&lt;/p&gt;

&lt;p&gt;After some ChatGPT research, I learn that IncrementQ implements the same binary message as plain ol Increment. It just has a different &lt;a href="https://github.com/obbap1/bmemcached-rs/blob/master/src/protocol.rs#L40" rel="noopener noreferrer"&gt;binary code&lt;/a&gt;. This means this will be relatively easy to &lt;a href="https://github.com/jaysonsantos/bmemcached-rs/compare/master...obbap1:bmemcached-rs:master" rel="noopener noreferrer"&gt;implement&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing our IncrementQ implementation
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Connect to Memcached and set a key called "counter" to an intial value of 1 with a TTL of 5 seconds.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;MemcachedClient&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"127.0.0.1:11211"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"counter"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"1"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="nf"&gt;.set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Looking at memcached logs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&amp;lt;27 Read binary protocol data:
&amp;lt;27    0x80 0x01 0x00 0x07
&amp;lt;27    0x08 0x00 0x00 0x00

&amp;lt;27 SET counter Value len is 1

&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;27 Writing bin response:
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;27   0x81 0x01 0x00 0x00
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;27   0x00 0x00 0x00 0x00
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;27   0x00 0x00 0x00 0x00
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;27   0x00 0x00 0x00 0x00
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;27   0x00 0x00 0x00 0x00
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;27   0x00 0x00 0x00 0x02
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We see that the value is set and we get a response back.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Issue four commands to increment this "counter" quietly. We shouldn't see any responses which means that we're pipelining.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// This means increment key "counter" by 1 from its initial value "x" and set TTL to 7 seconds.&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="nf"&gt;.increment_quiet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"counter"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Taking a look at memcached logs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;incr counter 1, 2, 7000
&amp;lt;27 Read binary protocol data:
&amp;lt;27    0x80 0x15 0x00 0x07
&amp;lt;27    0x14 0x00 0x00 0x00
&amp;lt;27    0x00 0x00 0x00 0x1b
&amp;lt;27    0x00 0x00 0x00 0x00
&amp;lt;27    0x00 0x00 0x00 0x00
&amp;lt;27    0x00 0x00 0x00 0x00
incr counter 1, 3, 7000
&amp;lt;27 Read binary protocol data:
&amp;lt;27    0x80 0x15 0x00 0x07
&amp;lt;27    0x14 0x00 0x00 0x00
&amp;lt;27    0x00 0x00 0x00 0x1b
&amp;lt;27    0x00 0x00 0x00 0x00
&amp;lt;27    0x00 0x00 0x00 0x00
&amp;lt;27    0x00 0x00 0x00 0x00
incr counter 1, 4, 7000
&amp;lt;27 Read binary protocol data:
&amp;lt;27    0x80 0x00 0x00 0x07
&amp;lt;27    0x00 0x00 0x00 0x00
&amp;lt;27    0x00 0x00 0x00 0x07
&amp;lt;27    0x00 0x00 0x00 0x00
&amp;lt;27    0x00 0x00 0x00 0x00
&amp;lt;27    0x00 0x00 0x00 0x00
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No responses!&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Validate the counter's new value is 5.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;new_value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="nf"&gt;.get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nd"&gt;assert_eq!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;new_value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"5"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It pipelined ✅&lt;/p&gt;

</description>
      <category>memcached</category>
      <category>rust</category>
      <category>web</category>
      <category>computerscience</category>
    </item>
    <item>
      <title>Hello World in Go From Rust</title>
      <dc:creator>paschal</dc:creator>
      <pubDate>Sun, 07 Jan 2024 20:31:26 +0000</pubDate>
      <link>https://forem.com/obbap/hello-world-in-go-from-rust-3jj8</link>
      <guid>https://forem.com/obbap/hello-world-in-go-from-rust-3jj8</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Suppose every software in the world was written in just one programming language Eg. C. In that case, there'll be no need for bindings and foreign function interfaces but since we have thousands of programming languages, genuine use cases arise where communicating across programming languages is necessary.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Some programming languages are more performant than others and you'll need to hand off computation-intensive tasks to these languages.&lt;/li&gt;
&lt;li&gt;Some programming languages are state of the art in different areas, Eg, Javascript with Browsers, Python with Data, and C with Embedded systems, so it'll be easier to utilize the existing libraries instead of reinventing the wheel.&lt;/li&gt;
&lt;li&gt;Some languages are strict and strongly typed; you want to prototype fast but not compromise on performance. An example is Game development or NGINX module extensions with Lua and C.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Base C Layer
&lt;/h2&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%2Fres.cloudinary.com%2Fpbaba%2Fimage%2Fupload%2Fv1704655971%2Fggr.drawio_i75fz7.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%2Fres.cloudinary.com%2Fpbaba%2Fimage%2Fupload%2Fv1704655971%2Fggr.drawio_i75fz7.png" alt="gorust"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Golang uses &lt;code&gt;cgo&lt;/code&gt; to communicate with external C libraries and Rust uses FFI (Foreign function interfaces) to export C functions. Additionally, a library for automatically generating bindings can be used to generate the header files &lt;code&gt;(.h)&lt;/code&gt;. In our case, we'll only be exporting two C functions, so using &lt;a href="https://github.com/mozilla/cbindgen" rel="noopener noreferrer"&gt;cbindgen&lt;/a&gt; is overkill but we'll use it regardless because why not? &lt;br&gt;
Firstly, we'll write the rust functions we want to export. We'll start by creating a new rust library:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cargo new r &lt;span class="nt"&gt;--lib&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This means we're creating a new rust library called &lt;code&gt;r&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;In our Cargo.toml, we'll specify that this crate is a dynamic library and then include the libc and cbindgen dependencies.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[package]&lt;/span&gt;
&lt;span class="py"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"r"&lt;/span&gt;
&lt;span class="py"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"0.1.0"&lt;/span&gt;
&lt;span class="py"&gt;edition&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"2021"&lt;/span&gt;

&lt;span class="nn"&gt;[lib]&lt;/span&gt;
&lt;span class="py"&gt;crate-type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"cdylib"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="nn"&gt;[dependencies]&lt;/span&gt;
&lt;span class="py"&gt;libc&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"0.2.151"&lt;/span&gt;

&lt;span class="nn"&gt;[build-dependencies]&lt;/span&gt;
&lt;span class="py"&gt;cbindgen&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"0.26.0"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We'll need &lt;code&gt;libc&lt;/code&gt; to access some C types, specifically the &lt;code&gt;c_char&lt;/code&gt; type. This is because strings are UTF-32 encoded (4 bytes) in C while they're UTF-8 encoded in Rust, meaning they can have variable sizes (1 to 4 bytes).&lt;/p&gt;

&lt;h2&gt;
  
  
  Rust Functions
&lt;/h2&gt;

&lt;p&gt;To write our &lt;code&gt;hello_world&lt;/code&gt; function which will be called from Go, we'll need the &lt;code&gt;no_mangle&lt;/code&gt; annotation so the linker can find the function while linking without the Rust compiler &lt;a href="https://rust-lang.github.io/rfcs/2603-rust-symbol-name-mangling-v0.html" rel="noopener noreferrer"&gt;mangling&lt;/a&gt; it. &lt;/p&gt;

&lt;p&gt;Then we can write our functions &lt;code&gt;hello_world&lt;/code&gt; and &lt;code&gt;hello_world_free&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;extern&lt;/span&gt; &lt;span class="k"&gt;crate&lt;/span&gt; &lt;span class="n"&gt;libc&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;ffi&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;CString&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;libc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;c_char&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;#[no_mangle]&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;extern&lt;/span&gt; &lt;span class="s"&gt;"C"&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;hello_world&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="nb"&gt;c_char&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="nb"&gt;c_char&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;unsafe&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;c_str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
            &lt;span class="nn"&gt;CString&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;format!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"hello world {:?}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;CString&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_raw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"dont fail"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;c_str&lt;/span&gt;&lt;span class="nf"&gt;.into_raw&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="nd"&gt;#[no_mangle]&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;extern&lt;/span&gt; &lt;span class="s"&gt;"C"&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;hello_world_free&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="nb"&gt;c_char&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;unsafe&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="nf"&gt;.is_null&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;CString&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_raw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;hello_world&lt;/code&gt; accepts a mutable pointer to a char array as an argument and returns the same. The &lt;code&gt;unsafe&lt;/code&gt; keyword is needed as the rust compiler can't guarantee that &lt;code&gt;from_raw&lt;/code&gt; which entails dereferencing a null pointer, won't lead to undefined behavior. Finally, we use &lt;code&gt;into_raw&lt;/code&gt; to hand ownership back to the caller, in this case, Go.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;hello_world_free&lt;/code&gt; accepts a mutable pointer, and calls &lt;code&gt;from_raw&lt;/code&gt; on it, so we can properly reconstruct it, claim ownership, and then drop it. This is to avoid memory leaks.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nn"&gt;cbindgen&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;Builder&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;.with_crate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;crate_dir&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.with_config&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="nf"&gt;.generate&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Unable to generate bindings"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.write_to_file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"bindings.h"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To generate the bindings, we'll add a build script &lt;code&gt;build.rs&lt;/code&gt; which uses &lt;code&gt;cbindgen&lt;/code&gt; to generate the &lt;code&gt;bindings.h&lt;/code&gt; file. Then we can run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cargo build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If everything goes smoothly, we should have a compiled binary and a newly created &lt;code&gt;bindings.h&lt;/code&gt; file with the following methods in it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nf"&gt;hello_world&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;hello_world_free&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Go
&lt;/h2&gt;

&lt;p&gt;After building the Rust binary, we'll need to tell the linker where to find it and we can do this by passing the linker flags via &lt;code&gt;cgo&lt;/code&gt;. We'll also need to include (think import) the &lt;code&gt;bindings.h&lt;/code&gt; file so we can call the rust methods.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// #cgo LDFLAGS: -L/Users/pbaba/projects/go-rust/r/target/debug -lr&lt;/span&gt;
&lt;span class="c"&gt;// #include &amp;lt;bindings.h&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"C"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, we can use the &lt;code&gt;hello_world&lt;/code&gt; function and include the "merry christmas" string as an argument. We'll also defer the &lt;code&gt;hello_world_free&lt;/code&gt; method call, which will free the memory referenced by the pointer &lt;code&gt;b&lt;/code&gt; afterward.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"merry christmas"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hello_world&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hello_world_free&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GoString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then we can run &lt;code&gt;go run main.go&lt;/code&gt; and it's alive:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;hello world. &lt;span class="s2"&gt;"merry christmas"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In some cases, we can do without the &lt;code&gt;hello_world_free&lt;/code&gt; function and replace it with the custom free function provided by &lt;code&gt;cgo&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;free&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unsafe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Pointer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This should replace the function we already have so we don't end up freeing the same location in memory twice and causing a double free:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;malloc: Double free of object 0x7f8c340040a0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But for CStrings, &lt;a href="https://doc.rust-lang.org/src/alloc/ffi/c_str.rs.html#416-419" rel="noopener noreferrer"&gt;The Rust documentation&lt;/a&gt; recommends we free this explicitly by reconstructing and then dropping it instead of using C's free.&lt;/p&gt;

&lt;p&gt;The rest of the code &lt;a href="https://github.com/obbap1/go-rust" rel="noopener noreferrer"&gt;is on GitHub&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>rust</category>
      <category>go</category>
    </item>
    <item>
      <title>Failure Detection. The Phi Accrual Failure Detector</title>
      <dc:creator>paschal</dc:creator>
      <pubDate>Thu, 21 Oct 2021 10:02:57 +0000</pubDate>
      <link>https://forem.com/obbap/failure-detection-the-phi-accrual-failure-detector-4jgj</link>
      <guid>https://forem.com/obbap/failure-detection-the-phi-accrual-failure-detector-4jgj</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In distributed systems, Nodes need to know if their peers are still healthy and update their peer lists accordingly. The simplest way to do this is with heartbeats. If there is a network with nodes &lt;code&gt;A&lt;/code&gt;, &lt;code&gt;B&lt;/code&gt;, and &lt;code&gt;C&lt;/code&gt;, &lt;code&gt;A&lt;/code&gt; sends heartbeat messages to its peers &lt;code&gt;B&lt;/code&gt; and &lt;code&gt;C&lt;/code&gt; saying “I’m still here”. If &lt;code&gt;B&lt;/code&gt; and &lt;code&gt;C&lt;/code&gt; don't hear from node &lt;code&gt;A&lt;/code&gt; after a particular period, they can assume that node &lt;code&gt;A&lt;/code&gt; is dead and can no longer handle requests, and nodes &lt;code&gt;B&lt;/code&gt; and &lt;code&gt;C&lt;/code&gt; will stop sending traffic to node &lt;code&gt;A&lt;/code&gt;.&lt;br&gt;
The question is how long should nodes &lt;code&gt;B&lt;/code&gt; and &lt;code&gt;C&lt;/code&gt; wait for A before marking it as dead. Twenty seconds ?, Thirty seconds ?. If a very short time is chosen as the threshold, there will be lots of false positives on the “dead nodes” peer list. A lot of nodes will be marked as dead when they are actually not. They might have had bad internet connections etc. On the other hand, if a longer time is chosen as the threshold, there will be lots of failed requests because dead nodes will keep getting traffic as though they’re still active and dropping them. So what exactly is the sweet spot? The Phi Accrual failure detector.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Phi Accrual Failure Detector
&lt;/h2&gt;

&lt;p&gt;The Phi Accrual failure detector, which was originally introduced in this paper uses a suspicion model. For example, when nodes &lt;code&gt;B&lt;/code&gt; and &lt;code&gt;C&lt;/code&gt; startup, they’ll set the confidence level they have in node &lt;code&gt;A&lt;/code&gt; to &lt;code&gt;0.5&lt;/code&gt;, where the scale is from &lt;code&gt;0&lt;/code&gt; to &lt;code&gt;1&lt;/code&gt;. After a particular period, if node &lt;code&gt;A&lt;/code&gt; doesn't respond, the confidence level is dropped by &lt;code&gt;0.1&lt;/code&gt;, which makes the new confidence &lt;code&gt;0.4&lt;/code&gt;. If it does respond, it is increased by &lt;code&gt;0.1&lt;/code&gt; and the confidence is &lt;code&gt;0.6&lt;/code&gt;. A threshold can then be set, that if node &lt;code&gt;A&lt;/code&gt; doesn't respond when it's down to &lt;code&gt;0.2&lt;/code&gt; then we can mark the node as dead. This is a more compound approach because it recognizes the past response times of the node. Data can also be stored, and used to analyze and decide what to set the threshold for a node to be marked as dead to.&lt;br&gt;
Simulation&lt;br&gt;
I did a small simulation with Docker and Golang, and this is what it looked like.&lt;/p&gt;
&lt;h3&gt;
  
  
  Leader
&lt;/h3&gt;

&lt;p&gt;The first component is the &lt;code&gt;Leader&lt;/code&gt;. I set up the entity in &lt;a href="https://github.com/obbap1/phi-accural-detector/blob/master/leader/leader.go" rel="noopener noreferrer"&gt;leader.go&lt;/a&gt;. The Leader receives the heartbeats, updates the tables, manages the &lt;a href="https://github.com/obbap1/phi-accural-detector/blob/master/leader/leader.go#L37" rel="noopener noreferrer"&gt;thresholds&lt;/a&gt; and the &lt;a href="https://github.com/obbap1/phi-accural-detector/blob/master/leader/leader.go#L39" rel="noopener noreferrer"&gt;failure points&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
   &lt;span class="n"&gt;threshold&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;15&lt;/span&gt;
   &lt;span class="n"&gt;failurePoint&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0.2&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;threshold&lt;/code&gt; is set to &lt;code&gt;15&lt;/code&gt; and is denominated to seconds . This means if we don't hear from a node after fifteen seconds, the confidence level will be decremented by &lt;code&gt;0.1&lt;/code&gt;.&lt;br&gt;
The &lt;code&gt;failurePoint&lt;/code&gt; is set to &lt;code&gt;0.2&lt;/code&gt; and once the node’s confidence level reaches the &lt;code&gt;failurePoint&lt;/code&gt; or lower, it will be marked as dead.&lt;/p&gt;
&lt;h3&gt;
  
  
  Follower
&lt;/h3&gt;

&lt;p&gt;The next entity is the Follower which is setup in&lt;br&gt;
&lt;a href="https://github.com/obbap1/phi-accural-detector/blob/master/follower/follower.go" rel="noopener noreferrer"&gt;follower.go&lt;/a&gt;. The followers will send periodic heartbeats to the leader. A heartbeat looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;HeartBeat&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="n"&gt;IpAddress&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
   &lt;span class="n"&gt;Pid&lt;/span&gt;       &lt;span class="kt"&gt;int&lt;/span&gt;
   &lt;span class="n"&gt;Timestamp&lt;/span&gt; &lt;span class="kt"&gt;int64&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The follower sends its IP address, process id (PID), and timestamp to the leader periodically.&lt;br&gt;
I setup two docker containers, &lt;code&gt;phi_leader&lt;/code&gt; to hold the leader executable and &lt;code&gt;phi_follower&lt;/code&gt; for the follower executable.&lt;br&gt;
I scaled the &lt;code&gt;phi_follower&lt;/code&gt; instance to &lt;code&gt;5&lt;/code&gt; instances on a docker swarm network.&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="c"&gt;# docker service scale phi_follower=5  &lt;/span&gt;

phi_follower scaled to 5
overall progress: 0 out of 5 tasks 
1/5: ready     &lt;span class="o"&gt;[======================================&amp;gt;&lt;/span&gt;            &lt;span class="o"&gt;]&lt;/span&gt; 
2/5: ready     &lt;span class="o"&gt;[======================================&amp;gt;&lt;/span&gt;            &lt;span class="o"&gt;]&lt;/span&gt; 
3/5: starting  &lt;span class="o"&gt;[============================================&amp;gt;&lt;/span&gt;      &lt;span class="o"&gt;]&lt;/span&gt; 
4/5: preparing &lt;span class="o"&gt;[=================================&amp;gt;&lt;/span&gt;                 &lt;span class="o"&gt;]&lt;/span&gt; 
5/5: ready     &lt;span class="o"&gt;[======================================&amp;gt;&lt;/span&gt;            &lt;span class="o"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After running this process for about five minutes, I tailed the leader’s logs and the peer list looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# docker service logs phi_leader -f&lt;/span&gt;
Received heart beat from process with IP 10.0.4.222 and PID 1
updating Accrual failure detection table...
    &lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="nt"&gt;------------&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="nt"&gt;-----&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="nt"&gt;-----------------&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="nt"&gt;------------&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;
    ╪     IP     ╪ PID ╪   CONFIDENCE    ╪    TIME    ╪
    &lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="nt"&gt;------------&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="nt"&gt;-----&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="nt"&gt;-----------------&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="nt"&gt;------------&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;
    ╪ 10.0.4.219 ╪   1 ╪        0.500000 ╪ 1634756932 ╪
    ╪ 10.0.4.223 ╪   1 ╪        0.500000 ╪ 1634756940 ╪
    ╪ 10.0.4.222 ╪   1 ╪        0.600000 ╪ 1634756942 ╪
    ╪ 10.0.4.224 ╪   1 ╪        0.600000 ╪ 1634756924 ╪
    ╪ 10.0.4.225 ╪   1 ╪        0.900000 ╪ 1634756922 ╪
    &lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="nt"&gt;------------&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="nt"&gt;-----&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="nt"&gt;-----------------&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="nt"&gt;------------&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;
    ╪                    TOTAL PROCESSES ╪     5      ╪
    &lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="nt"&gt;------------&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="nt"&gt;-----&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="nt"&gt;-----------------&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="nt"&gt;------------&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The five different nodes have been registered on the leader, with different confidence levels and timestamps. With the confidence levels, all the peers are healthy.&lt;br&gt;
Now I stopped two nodes, and watched to see if the detector decrements their confidence levels.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;// Stop first container
&lt;span class="c"&gt;# docker stop 14d07e02a1ad            &lt;/span&gt;
14d07e02a1ad
// Stop second container
&lt;span class="c"&gt;# docker stop 3829bb23fe41&lt;/span&gt;
3829bb23fe41
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After &lt;code&gt;17&lt;/code&gt; seconds, which is below the threshold of &lt;code&gt;15&lt;/code&gt; seconds, a node hadn’t sent a heartbeat and the confidence level was decreased. Node with IP &lt;code&gt;10.0.4.223&lt;/code&gt; has been dropped to &lt;code&gt;0.9&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="c"&gt;# docker service logs phi_leader -f&lt;/span&gt;
Checking &lt;span class="k"&gt;for &lt;/span&gt;inactive processes...
Havent received a heartbeat from process with ip 10.0.4.223 and pid 1 &lt;span class="k"&gt;for &lt;/span&gt;the past 17 seconds
Decrementing process confidence by 0.1
    &lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="nt"&gt;------------&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="nt"&gt;-----&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="nt"&gt;-----------------&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="nt"&gt;------------&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;
    ╪     IP     ╪ PID ╪   CONFIDENCE    ╪    TIME    ╪
    &lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="nt"&gt;------------&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="nt"&gt;-----&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="nt"&gt;-----------------&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="nt"&gt;------------&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;
    ╪ 10.0.4.219 ╪   1 ╪        1.000000 ╪ 1634757451 ╪
    ╪ 10.0.4.223 ╪   1 ╪        0.900000 ╪ 1634757439 ╪
    ╪ 10.0.4.222 ╪   1 ╪        1.000000 ╪ 1634757453 ╪
    ╪ 10.0.4.224 ╪   1 ╪        1.000000 ╪ 1634757440 ╪
    ╪ 10.0.4.225 ╪   1 ╪        1.000000 ╪ 1634757430 ╪
    &lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="nt"&gt;------------&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="nt"&gt;-----&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="nt"&gt;-----------------&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="nt"&gt;------------&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;
    ╪                    TOTAL PROCESSES ╪     5      ╪
    &lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="nt"&gt;------------&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="nt"&gt;-----&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="nt"&gt;-----------------&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="nt"&gt;------------&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After a few minutes of tailing the logs, one of the nodes go below the failure point of 0.2and is marked as dead. The leader removes this node from its peer list, and the total drops to 4&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="c"&gt;# docker service logs phi_leader -f&lt;/span&gt;
This process with ip 10.0.4.224 and pid 1 now has confidence 0.200000 which is below or equal to the failure point 0.200000 and will be marked as dead
    &lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="nt"&gt;------------&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="nt"&gt;-----&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="nt"&gt;-----------------&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="nt"&gt;------------&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;
    ╪     IP     ╪ PID ╪   CONFIDENCE    ╪    TIME    ╪
    &lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="nt"&gt;------------&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="nt"&gt;-----&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="nt"&gt;-----------------&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="nt"&gt;------------&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;
    ╪ 10.0.4.219 ╪   1 ╪        0.900000 ╪ 1634757996 ╪
    ╪ 10.0.4.223 ╪   1 ╪        1.000000 ╪ 1634757998 ╪
    ╪ 10.0.4.222 ╪   1 ╪        1.000000 ╪ 1634758005 ╪
    ╪ 10.0.4.227 ╪   1 ╪        0.700000 ╪ 1634758010 ╪
    &lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="nt"&gt;------------&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="nt"&gt;-----&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="nt"&gt;-----------------&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="nt"&gt;------------&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;
    ╪                    TOTAL PROCESSES ╪     4      ╪
    &lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="nt"&gt;------------&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="nt"&gt;-----&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="nt"&gt;-----------------&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="nt"&gt;------------&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So it worked! The code to the full implementation and simulation of the Phi Accrual Detector can be found here.&lt;br&gt;
Thank you for reading!&lt;/p&gt;

&lt;p&gt;Originally published &lt;a href="https://res.cloudinary.com/pbaba/image/upload/v1634809870/phi_bwlsbq.png" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;The actual phi accrual detector is more complex than this, it uses a better probabilistic model like calculating the mean and standard deviation of previous results to determine the threshold and failure point instead of hardcoding the values as we did. You can find a good read &lt;a href="https://doc.akka.io/docs/akka/current/typed/failure-detector.html" rel="noopener noreferrer"&gt;here&lt;/a&gt; &lt;code&gt;(phi = -log10(1 - F(timeSinceLastHeartbeat)) )&lt;/code&gt;&lt;/p&gt;

</description>
      <category>distributedsystems</category>
      <category>docker</category>
      <category>go</category>
    </item>
    <item>
      <title>The billion user table - A Review</title>
      <dc:creator>paschal</dc:creator>
      <pubDate>Sat, 24 Jul 2021 01:38:12 +0000</pubDate>
      <link>https://forem.com/obbap/the-billion-user-table-a-review-3of2</link>
      <guid>https://forem.com/obbap/the-billion-user-table-a-review-3of2</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;The web currently works in silos. Every platform operates as an autonomous system. So every organization, for example, Google, has its database of users and a unique identifier for every user. This identifier can be an email, a phone number, etc. &lt;br&gt;
If a user on Google wants to sign up on Facebook, they'll need to go through another signup process, as Facebook has no idea who the user is within Google's system. Solutions like social login have been helpful, but primarily, every platform requires a signup process. If Facebook wants to implement a feature to allow the user to fetch all their images on Google photos and post them on Facebook, Facebook and Google will have to communicate and this should happen via an API (Application Programmable Interface). This interface is necessary, primarily because the unique identifiers of the user on Facebook and Google databases will be different. Google will demand something that represents a unique identifier on their systems, maybe a Gmail address and Facebook will have to provide this to get meaningful results.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  API Rules
&lt;/h2&gt;

&lt;p&gt;So for Facebook to fetch a user's photos from Google, they'll need to access Google's APIs and adhere to certain rules.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Facebook will need Access keys and secrets to obtain third-party access to Google's APIs. These access keys can be revoked by Google at any time.&lt;/li&gt;
&lt;li&gt;The requests will be rate-limited, as Google wouldn't want you overloading their infrastructure.&lt;/li&gt;
&lt;li&gt;Google will need to keep these photos available via the API else Facebook will lose access to this information.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With these few rules, there are already too many variables, and this isn't a robust solution if we want to achieve maximum interoperability. Also, if Facebook wanted to allow their users to reuse their Twitter bios on Facebook, that will require another third-party request to Twitter, and it is clear how this can quickly spiral into a web of third-party dependencies, albeit hanging on a very small thread.&lt;/p&gt;

&lt;h2&gt;
  
  
  Solution
&lt;/h2&gt;

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

&lt;p&gt;One solution can be making the database publicly accessible and verifiable. Unique identifiers are no longer localized and can be globally verifiable hashes that can be used across different autonomous systems. A globally verifiable unique ID can negate the need for multiple email addresses, phone numbers, etc. This database will be a Layer 1 infrastructure and different organizations can build up the stack. &lt;br&gt;
Much is still left to be desired, for one, there'll be a need for private databases, as not all information should be publicly accessible. This privacy is similar to what the Taproot upgrade on the Bitcoin network is trying to solve, but with a publicly accessible and verifiable database, intercommunication will become smoother.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://1729.com/the-billion-user-table"&gt;1729 - A billion user table&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>blockchain</category>
      <category>computerscience</category>
      <category>distributedsystems</category>
    </item>
    <item>
      <title>Write better Vue JS code </title>
      <dc:creator>paschal</dc:creator>
      <pubDate>Fri, 27 Sep 2019 15:30:37 +0000</pubDate>
      <link>https://forem.com/obbap/write-better-vue-js-code-36mg</link>
      <guid>https://forem.com/obbap/write-better-vue-js-code-36mg</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;Architecture might not matter at the start of a project, but the ease at which components can be added or removed without breaking stuff shows how well the codebase was structured. Let's look at ways to make our Vue JS code better.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use State, Map Getters and Actions.
&lt;/h2&gt;

&lt;p&gt;Using state and the maps (i.e mapGetters, mapActions, mapState, etc) provided by Vuex makes code very reusable. Hard coding state to the data() object in your SFC because its "faster" will raise difficulties if some of those values are needed in the future.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- first.vue --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;template&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;h3&amp;gt;&lt;/span&gt;{{firstname}}{{lastname}}&lt;span class="nt"&gt;&amp;lt;/h3&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;firstname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;lastname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;
      &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;methods&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;getFullName&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;firstname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lastname&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fetchNameFromApi&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firstname&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;firstname&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lastname&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;lastname&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="nx"&gt;created&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getFullName&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="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;em&gt;Project Manager&lt;/em&gt;&lt;/strong&gt;: We need the firstname and lastname to show up on two more pages.&lt;/p&gt;

&lt;p&gt;With that request, you'll keep copying, pasting, importing and exporting from different files.&lt;/p&gt;

&lt;p&gt;Better Still,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;firstname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;lastname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;actions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;getFullName&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dispatch&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;getFullNameFromApi&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mutate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FULL_NAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&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="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mutations&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;//Set default mutation types in another file&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;mutate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;UPDATE_FULL_NAME&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firstname&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lastname&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lastName&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firstname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lastname&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;FullName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;actions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;mutations&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;getters&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;FullName&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Then on our &lt;strong&gt;&lt;em&gt;first.vue&lt;/em&gt;&lt;/strong&gt; component,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;template&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;h3&amp;gt;&lt;/span&gt;{{firstName}}{{lastName}}&lt;span class="nt"&gt;&amp;lt;/h3&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;mapGetters&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;mapActions&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vuex&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="na"&gt;methods&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;
   &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;mapActions&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;getFullName&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
   &lt;span class="p"&gt;},&lt;/span&gt;
   &lt;span class="nx"&gt;created&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
   &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getFullName&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
   &lt;span class="p"&gt;},&lt;/span&gt;
   &lt;span class="na"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;
   &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;mapGetters&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;firstName&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lastName&lt;/span&gt;&lt;span class="dl"&gt;'&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="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now, if we need to include a new component that needs the first and last names of our user, we can easily map the getters and the actions.&lt;/p&gt;

&lt;p&gt;This also helps us avoid things like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;firstname&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;$store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fullName&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;lastname&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;$store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fullName&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We can simply use getters&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;
 &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;mapGetters&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;firstName&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lastName&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Finally, this helps us abstract business logic from the SFC and makes testing easier. Allow the Store to handle all the logic, and the SFC should just handle stuff tightly coupled to it, like the state of alert buttons/snack bars, etc.&lt;/p&gt;

&lt;h2&gt;
  
  
  Filters over Mixins.
&lt;/h2&gt;

&lt;p&gt;Mixins lead to implicit dependencies, namespace clashes, etc. You can find more about that &lt;a href="https://reactjs.org/blog/2016/07/13/mixins-considered-harmful.html"&gt;here&lt;/a&gt;. Some Mixins can be converted to Filters.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;//dateMixin.js&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;methods&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;formatDate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;T&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;0&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="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In our SFC, we have:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;template&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;h3&amp;gt;&lt;/span&gt;{{formatDate(date)}}&lt;span class="nt"&gt;&amp;lt;/h3&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;dateMixin&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./dateMixin&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;mixins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;dateMixin&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2019-08-07T00:00:00&lt;/span&gt;&lt;span class="dl"&gt;"&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="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;With filters,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;//main.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Vue&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;Vue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;formatDate&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;T&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In our SFC,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;template&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;h3&amp;gt;&lt;/span&gt;{{date | formatDate}}&lt;span class="nt"&gt;&amp;lt;/h3&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2019-08-07T00:00:00&lt;/span&gt;&lt;span class="dl"&gt;"&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="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Use Modules to separate the different services on your application.
&lt;/h2&gt;

&lt;p&gt;Instead of having everything needed by our state in one object, we can segregate them into modules.&lt;/p&gt;

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

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;token&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;firstname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;lastname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;isLoggedIn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We can divide our services into authentication, profile-management and wallet.&lt;/p&gt;

&lt;p&gt;Our folder structure would look like&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;modules
 authentication
    index.js
 profile-management
    index.js
 wallet
    index.js
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In the index.js file, we can have the state that matters to that service.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;//modules/authentication/index.js&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="na"&gt;token&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="na"&gt;isLoggedIn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;...&lt;/span&gt;

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



&lt;p&gt;Then when we initialize our store, we can add all the modules.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Vuex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
 &lt;span class="na"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;//something general&lt;/span&gt;
    &lt;span class="na"&gt;isAppBusy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
 &lt;span class="p"&gt;},&lt;/span&gt;
 &lt;span class="na"&gt;modules&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;
    &lt;span class="nx"&gt;authentication&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;profile&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;management&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;wallet&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;These are my thoughts on how to make the structure of Vue code better. If you have extra additions or subtractions, I'll like to see it in the comments 😄.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>vue</category>
      <category>computerscience</category>
      <category>vuex</category>
    </item>
    <item>
      <title>Understand Master-Slave Relationships using the Election Algorithm</title>
      <dc:creator>paschal</dc:creator>
      <pubDate>Fri, 09 Aug 2019 23:26:32 +0000</pubDate>
      <link>https://forem.com/obbap/understand-master-slave-relationships-using-the-election-algorithm-8en</link>
      <guid>https://forem.com/obbap/understand-master-slave-relationships-using-the-election-algorithm-8en</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;While building distributed systems, Transparency is a very important factor. The Engineer has to consider Access transparency, Concurrency transparency, Location transparency, Replication transparency, etc. Replication transparency answers the question, 'Will my data resources always be consistent ?'.&lt;/p&gt;

&lt;h1&gt;
  
  
  What is Replication transparency?
&lt;/h1&gt;

&lt;p&gt;With distributed systems, we can access different copies of our resources, which helps with redundancy, backup, speed, etc. Having replicas of a particular resource, also raises the issue of consistency. How do we ensure that all the replicas of a particular resource are consistent at all times? Two-phase commits can help in ensuring that if for any reason, all the replicas of a particular instance don't get updated may be due to timeouts or propagation errors, the instances will be rolled back to their previous state. This means that the update is lost and has to be done again.&lt;/p&gt;

&lt;p&gt;Three models help us with handling replicas:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Primary-Backup / Master-Backup Model&lt;/li&gt;
&lt;li&gt;Peer to Peer Model&lt;/li&gt;
&lt;li&gt;Master-Slave Model&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The &lt;strong&gt;&lt;em&gt;Primary-Backup model&lt;/em&gt;&lt;/strong&gt; exposes only one instance to all external processes. This instance is the master instance, and it has read and write permissions. All other instances or replicas have only read permissions. So with this model, we are sure that only one instance can be updated, and then the change is propagated. The drawback of this model is that it isn't scalable, because only one instance is exposed and if that instance crashes before propagation happens, we will still encounter inconsistencies.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;&lt;em&gt;Peer to Peer&lt;/em&gt;&lt;/strong&gt; model gives all the instances read and write permissions. With this model, we will observe performance issues, especially when we need to propagate very large chunks of data. Maintaining global consistency will also be difficult. It is best suited for applications that require low data replication. User-specific applications for example.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;&lt;em&gt;Master-Slave&lt;/em&gt;&lt;/strong&gt; model has one instance as the Master model, with read and write permissions. The other instances(slaves) have read permissions, but are "hot-spares" in the sense that immediately they notice that the Master node is down, a slave becomes the Master. It is best used for systems where reading operations are higher than writing. Eg. Databases. This is because to write or update an item on a database, it reads first (read-modify-write).&lt;/p&gt;

&lt;h1&gt;
  
  
  Which Slave is selected to be the Master?
&lt;/h1&gt;

&lt;p&gt;This is where the Election algorithm comes in. It is used to elect a slave(to be master) after the master node fails.&lt;br&gt;
We have the&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Bully Election Algorithm&lt;/li&gt;
&lt;li&gt;Ring Election Algorithm&lt;/li&gt;
&lt;li&gt;Leader Preelection Algorithm&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The &lt;strong&gt;&lt;em&gt;Bully election&lt;/em&gt;&lt;/strong&gt; algorithm takes the node with the highest ID as the next master. Once a node realizes that the master node has failed, the election process starts. If the last node to join the conversation is the node with the highest ID then the election process is going to take some time compared to when the node with the highest ID joins first.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;&lt;em&gt;Ring election&lt;/em&gt;&lt;/strong&gt; algorithm implements the Bully election algorithm but the nodes are arranged in a logical ring. This means each node sends messages to its neighboring nodes, and not to every node.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;&lt;em&gt;Leader Preelection&lt;/em&gt;&lt;/strong&gt; algorithm chooses the "backup" master node while the master node is still running. It still implements the election algorithm, but it happens while the master node is still running. This eliminates the overhead that happens with the other methods, but its also a waste of resources because the backup nodes can fail before the master, and then the elections will keep happening.&lt;/p&gt;
&lt;h1&gt;
  
  
  Simulating the Election Algorithm
&lt;/h1&gt;

&lt;p&gt;We will be simulating the Bully election algorithm, using four docker containers which will represent our nodes. (1 master and 3 slaves) running NodeJS and a message-broker(Rabbitmq). I initially tried using actual VMs, Welp. Good luck with that.&lt;/p&gt;

&lt;p&gt;To achieve this simulation, we'll have to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a Docker network, which will host all the containers and the rabbitmq server.&lt;/li&gt;
&lt;li&gt;Spin up the rabbitmq server, and bind the port to rabbitmq running on our localhost.&lt;/li&gt;
&lt;li&gt;Spin up four docker containers from our Dockerfile.&lt;/li&gt;
&lt;li&gt;Use the Pub/Sub pattern, and the fanout method, so that every node sends and receives messages from every node.&lt;/li&gt;
&lt;/ol&gt;
&lt;h1&gt;
  
  
  Create a Docker network
&lt;/h1&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# The name of this network is election-algorithm_default&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;docker network create election-algorithm_default

&lt;span class="c"&gt;# confirm it exists and copy the network id&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;docker network &lt;span class="nb"&gt;ls&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h1&gt;
  
  
  The Rabbitmq Server
&lt;/h1&gt;

&lt;p&gt;The Server will use the management alpine image, so ports 5672 and 15672 will be used. If any processes are running on these ports, you will need to kill them.&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="c"&gt;# Run the rabbitmq image in detached mode&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;docker run &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;--name&lt;/span&gt; rabbitmq &lt;span class="nt"&gt;-p&lt;/span&gt; 5672:5672 &lt;span class="nt"&gt;-p&lt;/span&gt; 15672:15672 rabbitmq:3.6-management-alpine

&lt;span class="c"&gt;# Confirm its running and copy the container id&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;docker container &lt;span class="nb"&gt;ls&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we can add the rabbitmq server to our network, so it can communicate with the other nodes.&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="c"&gt;# connect the rabbitmq server to the network&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;docker network connect &amp;lt;NETWORK_ID&amp;gt; &amp;lt;CONTAINER_ID_OF_THE_RABBITMQ_SERVER&amp;gt;
&lt;span class="c"&gt;# Confirm its running&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;docker inspect election-alogithm_default
&lt;span class="c"&gt;# You should see a "containers" key with the rabbitmq server.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Create Dockerfile
&lt;/h1&gt;

&lt;p&gt;In our present directory, We'll need a server.js file and some dependencies.&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;npm init &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; npm i &lt;span class="nt"&gt;--save&lt;/span&gt; amqlib node-cron &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;touch &lt;/span&gt;server.js Dockerfile
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then our Dockerfile&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; alpine:latest&lt;/span&gt;

&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /usr/src/app&lt;/span&gt;
&lt;span class="c"&gt;# Install Node js and npm&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;apk add &lt;span class="nt"&gt;--update&lt;/span&gt; nodejs npm

&lt;span class="k"&gt;RUN &lt;/span&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt;

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;

&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["node","server.js"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we'll need to get the IP address of the Rabbitmq server, because that is what we'll connect our containers to. This will enable all the containers to see all the messages from neighboring containers or nodes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker inspect &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="s1"&gt;'{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}'&lt;/span&gt; &amp;lt;CONTAINER_ID&amp;gt;
&lt;span class="c"&gt;#OR&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;docker inspect &amp;lt;CONTAINER_ID&amp;gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="s2"&gt;"IPAddress"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We should be able to see our IP address from any of those results.&lt;/p&gt;

&lt;h1&gt;
  
  
  Server.js
&lt;/h1&gt;

&lt;p&gt;In this file, every node sends a heartbeat to the rabbitmq server, which is a cron job that runs every 10 seconds. Every node can see all the responses and then sort the information according to the container ids. The container with the highest ID is automatically the master, and if that node fails, the next node takes over! We'll store the messages in a set so that there will only be unique ID's.&lt;/p&gt;

&lt;p&gt;The server.js file should look like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Require libraries&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;amqp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;amqplib/callback_api&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cron&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;node-cron&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;os&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;os&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;//Connect to the IP address of the Rabbitmq container&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`amqp://guest:guest@&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;IP_ADDRESS_OF_THE_RABBITMQ_SERVER&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;//The transmitter&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sendContainerIdToOthers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="cm"&gt;/**
   * method for sending containerId to other nodes
   * @param {null}
   * @returns {null}
   *
   */&lt;/span&gt;
  &lt;span class="c1"&gt;// This returns the container id&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`My id is &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hostname&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;//Connect to the server&lt;/span&gt;
  &lt;span class="nx"&gt;amqp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nx"&gt;error0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;//Create channel&lt;/span&gt;
    &lt;span class="nx"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createChannel&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;error1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nx"&gt;error1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="c1"&gt;//Create exchange&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;exchange&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;logs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="c1"&gt;//Send Message indicating your ID&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;msg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`My id is &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hostname&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="c1"&gt;//Use the fanout mechanism&lt;/span&gt;
      &lt;span class="nx"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assertExchange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;exchange&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fanout&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;durable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
      &lt;span class="c1"&gt;//Publish this message&lt;/span&gt;
      &lt;span class="nx"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;publish&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;exchange&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;msg&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="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;//The receiver&lt;/span&gt;
&lt;span class="nx"&gt;amqp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nx"&gt;error0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createChannel&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;error1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nx"&gt;error1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;exchange&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;logs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assertExchange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;exchange&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fanout&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;durable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nx"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assertQueue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;exclusive&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;q&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nx"&gt;error2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Waiting for messages in &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bindQueue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;exchange&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="c1"&gt;//Since we want the IDs to be unique, we'll use a set&lt;/span&gt;
      &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;resultSet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="c1"&gt;//Clear the set every 15 seconds&lt;/span&gt;
      &lt;span class="nf"&gt;setInterval&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;resultSet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;15000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="nx"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;consume&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nx"&gt;q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;msg&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`received: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="c1"&gt;//Split the response to get the ID&lt;/span&gt;
            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;
              &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
              &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;is&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
              &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="c1"&gt;//Add ID to the set&lt;/span&gt;
            &lt;span class="nx"&gt;resultSet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Container id's&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;resultSet&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="c1"&gt;//FInd the master node&lt;/span&gt;
            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;findMaster&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resultSet&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

            &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Our Master Node is &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;findMaster&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;&lt;span class="s2"&gt;`&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="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;noAck&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&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="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;//Run every 10 seconds&lt;/span&gt;
&lt;span class="nx"&gt;cron&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;schedule&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;10 * * * * *&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;sendContainerIdToOthers&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Results
&lt;/h1&gt;

&lt;p&gt;Now we can spin up four servers from the Dockerfile and connect them to the network&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="c"&gt;# build the image&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;docker build &lt;span class="nt"&gt;--tag&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;server1 &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;span class="c"&gt;# Run this command for three other servers, server2, server3, and server4.&lt;/span&gt;

&lt;span class="c"&gt;#Run the image and connect the container to the network election-algorithm_default&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;docker run &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;--network&lt;/span&gt; &amp;lt;NETWORK_ID&amp;gt; server1
&lt;span class="c"&gt;# Run this command for three other servers, server2, server3, and server4.&lt;/span&gt;

&lt;span class="c"&gt;#Confirm they are running&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;docker container &lt;span class="nb"&gt;ls&lt;/span&gt; | &lt;span class="nb"&gt;grep &lt;/span&gt;server1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After 10 Seconds, we can check the logs of any of our nodes&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ docker logs --follow &amp;lt;CONTAINER_ID&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, we'll see all the nodes join in, and how the master node is changed when a higher node comes in.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fpbaba%2Fimage%2Fupload%2Fv1565388893%2FScreenshot_from_2019-08-09_10-18-13_m8bbcz.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%2Fres.cloudinary.com%2Fpbaba%2Fimage%2Fupload%2Fv1565388893%2FScreenshot_from_2019-08-09_10-18-13_m8bbcz.png" alt="Results"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If we kill a node, we'll find out the next elected node according to ID, becomes the Master.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fpbaba%2Fimage%2Fupload%2Fv1565388895%2FScreenshot_from_2019-08-09_11-14-12_skixyn.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%2Fres.cloudinary.com%2Fpbaba%2Fimage%2Fupload%2Fv1565388895%2FScreenshot_from_2019-08-09_11-14-12_skixyn.png" alt="Master"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;I just got started with Docker / Distributed systems, I hope this informs you a little. The repo for this is &lt;a href="https://github.com/obbap1/election-algorithm" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>node</category>
      <category>docker</category>
      <category>distributedsystems</category>
      <category>linux</category>
    </item>
    <item>
      <title> Handling Pagination with Vue JS and Pouch DB </title>
      <dc:creator>paschal</dc:creator>
      <pubDate>Wed, 03 Jul 2019 02:03:10 +0000</pubDate>
      <link>https://forem.com/obbap/handling-pagination-with-vue-js-and-pouch-db-4146</link>
      <guid>https://forem.com/obbap/handling-pagination-with-vue-js-and-pouch-db-4146</guid>
      <description>&lt;h1&gt;
  
  
  Introduction ☕️
&lt;/h1&gt;

&lt;p&gt;When the responses from a server come after just one request, and we have to paginate on the front end, its easier to handle. This is because we have all the data on the client side, so we just display a range of indexes on a particular page. So if the response is an array of 400 items, we can display 20 items per page. But if for some reason, the responses from the server can't come in a single request, we'll need to use pagination or an infinite scroll. This depends on the use case. So what are the performance issues with pagination? and how do we solve them? Let's dive in.&lt;/p&gt;

&lt;h1&gt;
  
  
  The Problem 🍉
&lt;/h1&gt;

&lt;p&gt;Let's say we have an endpoint that returns a payload like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;totalNumber&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,....,&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="nx"&gt;pageNumber&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From the object, we can see how much data we have in total, and the particular page we are on, so we know the range of page numbers we have. If each response returns an array with 20 elements, then we have (1000 / 20) i.e 50 pages. &lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;50&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;With pagination, if we click on '1', it fetches the first twenty elements. Page 2 fetches the next twenty, coming back to page 1 fetches the first twenty elements again. So going back and forth is going to be really slow and nothing short of a hassle. &lt;/p&gt;

&lt;h1&gt;
  
  
  PouchDB: A solution
&lt;/h1&gt;

&lt;p&gt;For handling storage on the client(browser), we have the local storage, session storage, indexed DB, cookies, etc. &lt;a href="https://pouchdb.com/" rel="noopener noreferrer"&gt;Pouch DB&lt;/a&gt; actually uses IndexedDB under the hood. Its mostly used on offline apps for automatic synchronization with the Live database, most likely Couch DB. &lt;/p&gt;

&lt;p&gt;We'll be using Vue JS to explain how this works. Firstly, we'll install the packages needed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i --save vuejs-paginate pouchdb-browser pouch-vue pouchdb-find pouchdb-live-find axios

vue create pouchdb-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In our main.js file, we'll install and initialize the database.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// main.js &lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Vue&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Paginate&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vuejs-paginate&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;PouchDB&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pouchdb-browser&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;pouchVue&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pouch-vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;PouchDB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;plugin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pouchdb-find&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="nx"&gt;PouchDB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;plugin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pouchdb-live-find&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="nx"&gt;Vue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;component&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;paginate&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Paginate&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;Vue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pouchVue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;pouch&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PouchDB&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="na"&gt;defaultDB&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;users_database&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="c1"&gt;//You can give it any name &lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// .............&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Moving on to the vue file, where we display all our users. Assuming the response from our endpoint is something like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;total&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;pageNumber&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;:[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;firstname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;lastname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;firstname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;lastname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;''&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can display our first batch of users on the vue file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- users.vue --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
    &lt;span class="c"&gt;&amp;lt;!--
        getUsers: {
            users: [],
            total: '' ,
            pageNumber: '' 
        }
    --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;v-data-table&lt;/span&gt;
        &lt;span class="na"&gt;:headers=&lt;/span&gt;&lt;span class="s"&gt;"headers"&lt;/span&gt;
        &lt;span class="na"&gt;:items=&lt;/span&gt;&lt;span class="s"&gt;"getUsers.users"&lt;/span&gt;  
        &lt;span class="na"&gt;v-if=&lt;/span&gt;&lt;span class="s"&gt;"getUsers.users"&lt;/span&gt;
        &lt;span class="na"&gt;hide-actions&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;template&lt;/span&gt; &lt;span class="na"&gt;slot=&lt;/span&gt;&lt;span class="s"&gt;"items"&lt;/span&gt; &lt;span class="na"&gt;slot-scope=&lt;/span&gt;&lt;span class="s"&gt;"props"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;{{ props.item.firstname}} {{props.item.lastname}}&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/v-data-table&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;paginate&lt;/span&gt;
            &lt;span class="na"&gt;:page-count=&lt;/span&gt;&lt;span class="s"&gt;"pageCount"&lt;/span&gt;
            &lt;span class="na"&gt;:click-handler=&lt;/span&gt;&lt;span class="s"&gt;"fetchNext"&lt;/span&gt;
            &lt;span class="na"&gt;:prev-text=&lt;/span&gt;&lt;span class="s"&gt;"'Prev'"&lt;/span&gt;
            &lt;span class="na"&gt;:next-text=&lt;/span&gt;&lt;span class="s"&gt;"'Next'"&lt;/span&gt;
        &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Firstly, there is a table to display the first and last names of all the users. This table is from &lt;a href="https://vuetifyjs.com/en/" rel="noopener noreferrer"&gt;Vuetify&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Secondly, we have the &lt;strong&gt;&lt;em&gt;paginate&lt;/em&gt;&lt;/strong&gt; component, which has the &lt;strong&gt;&lt;em&gt;page-count&lt;/em&gt;&lt;/strong&gt; prop, this shows the number of paginated pages we have. If the response has a total of 400 users, and we receive 20 users on every request, the page-count will be (400 / 20) 20. The &lt;strong&gt;&lt;em&gt;click-handler&lt;/em&gt;&lt;/strong&gt; prop, accepts a function that runs when any page is clicked. The &lt;strong&gt;&lt;em&gt;prev-text&lt;/em&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;em&gt;next-text&lt;/em&gt;&lt;/strong&gt; props just accept the text to be displayed for the previous and next pages. &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%2F67a99o7se7uwnsty4vfs.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F67a99o7se7uwnsty4vfs.jpg" alt="The flow"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Using the diagram above, we will create a &lt;strong&gt;&lt;em&gt;getAllUsers&lt;/em&gt;&lt;/strong&gt; action, that fetches the first batch of users, commits them to state and then stores them in PouchDB. We can also access Pouch DB from our single file component(SFC) using &lt;strong&gt;&lt;em&gt;this.$pouch&lt;/em&gt;&lt;/strong&gt; . This will be done on the &lt;strong&gt;&lt;em&gt;created()&lt;/em&gt;&lt;/strong&gt; lifecycle hook in the &lt;strong&gt;&lt;em&gt;users.vue&lt;/em&gt;&lt;/strong&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;//....
&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
    &lt;span class="c1"&gt;//...users.vue&lt;/span&gt;
    &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;mapActions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;mapGetters&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vuex&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;//Using vuex for our store&lt;/span&gt;
    &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;data&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="na"&gt;headers&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="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;firstname&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="na"&gt;align&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;left&lt;/span&gt;&lt;span class="dl"&gt;'&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="p"&gt;},&lt;/span&gt;
        &lt;span class="nf"&gt;created&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
            &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getAllUsers&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
                &lt;span class="na"&gt;pageNumber&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Fetch first page&lt;/span&gt;
                &lt;span class="na"&gt;pouch&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;$pouch&lt;/span&gt; &lt;span class="c1"&gt;//pass pouch db reference to action&lt;/span&gt;
            &lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;methods&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;
            &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nf"&gt;mapActions&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;getAllUsers&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;
            &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nf"&gt;mapGetters&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;getUsers&lt;/span&gt;&lt;span class="dl"&gt;'&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="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Now we'll write the getAllUsers action, and other elements needed to complete our store.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;//store.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Vue&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;//mutation type&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;UPDATE_ALL_USERS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;UPDATE_ALL_USERS&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;//state&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;allUsers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;getUsers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;allUsers&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;actions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;getAllUsers&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="c1"&gt;// retrieve the pouch db reference and page number we just sent&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;pageNumber&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;pouch&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="c1"&gt;//Using axios&lt;/span&gt;
        &lt;span class="nx"&gt;Vue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`allUsers/?page=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;pageNumber&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;data retrieved&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="cm"&gt;/*
                    res: {
                        users:
                        total:
                        pageNumber:
                    }
                */&lt;/span&gt;
                &lt;span class="c1"&gt;// store data in pouch db&lt;/span&gt;
                &lt;span class="nx"&gt;pouch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;put&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
                    &lt;span class="na"&gt;_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;pageNumber&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="na"&gt;users&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;
                &lt;span class="p"&gt;})&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;your data has been stored&lt;/span&gt;&lt;span class="dl"&gt;'&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="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="nf"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;UPDATE_ALL_USERS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mutations&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;UPDATE_ALL_USERS&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;allUsers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So after it fetches a particular batch of users from the server, it caches it in pouch db, with the &lt;strong&gt;&lt;em&gt;pageNumber&lt;/em&gt;&lt;/strong&gt; variable as the id, and the users as the actual data. &lt;/p&gt;

&lt;p&gt;Finally, we'll need to write the fetchNext function that occurs every time a particular page is clicked. So if the page is clicked, we'll check our cache, if it's there, display the result and if not call the getAllUsers action which will fetch from the server and then cache.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!--users.vue--&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
&lt;span class="c1"&gt;//.... This is a continuation of the users.vue file above&lt;/span&gt;
    &lt;span class="nx"&gt;methods&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;fetchNext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
            &lt;span class="c1"&gt;// event is the particular number clicked&lt;/span&gt;
            &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;$pouch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="c1"&gt;//if it is found, store in the cachedUsers variable&lt;/span&gt;
                    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cachedUsers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;users&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="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="c1"&gt;//if that page wasn't found, run the getAllUsers function&lt;/span&gt;
                    &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;not_found&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
                        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getAllUsers&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
                            &lt;span class="na"&gt;pageNumber&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                            &lt;span class="na"&gt;pouch&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;$pouch&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="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;We need the &lt;strong&gt;&lt;em&gt;cachedUsers&lt;/em&gt;&lt;/strong&gt; variable because the &lt;strong&gt;&lt;em&gt;getUsers&lt;/em&gt;&lt;/strong&gt; variable is just a getter, and if the users are found in our cache, we need to be able to set our variable to that value.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
    &lt;span class="c1"&gt;//.....&lt;/span&gt;
    &lt;span class="nx"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;
        &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nf"&gt;mapGetters&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;getUsers&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
        &lt;span class="nx"&gt;cachedUsers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
                &lt;span class="c1"&gt;// return the getter&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getUsers&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
                &lt;span class="c1"&gt;//use the setter&lt;/span&gt;
                &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getUsers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;value&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="nf"&gt;pageCount&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
            &lt;span class="c1"&gt;// get the total number of users and the amount of users per page to get the number of pages.&lt;/span&gt;
            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;total&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cachedUsers&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="c1"&gt;//fix to one decimal space&lt;/span&gt;
            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;numberOfPages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;total&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toFixed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="c1"&gt;//if there is a decimal value, increase the number of pages by 1.&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;numberOfPages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
                &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;numberOfPages&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
                &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;numberOfPages&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="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Conclusion ✂️
&lt;/h1&gt;

&lt;p&gt;This just shows one of the ways we can handle pagination on the front end, it also ensures things are fast. It helped me recently, and it can be written with any framework. Understanding the concept is what is important, and I hope you did. Thanks for reading!&lt;/p&gt;

&lt;p&gt;This post was originally published on my &lt;a href="https://paschal.dev/handling-pagination-with-vue-js-and-pouch-db" rel="noopener noreferrer"&gt;blog&lt;/a&gt;&lt;/p&gt;

</description>
      <category>vue</category>
      <category>pouchdb</category>
      <category>computerscience</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Handling Ever Increasing Server Logs</title>
      <dc:creator>paschal</dc:creator>
      <pubDate>Sun, 19 May 2019 17:17:26 +0000</pubDate>
      <link>https://forem.com/obbap/handling-ever-increasing-server-logs-2cc6</link>
      <guid>https://forem.com/obbap/handling-ever-increasing-server-logs-2cc6</guid>
      <description>&lt;h1&gt;
  
  
  &lt;strong&gt;Introduction&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;I thought the game of thrones would be the most stressful thing I came across this week, but searching through logs, handling errors can be very tedious, and knowing what exactly is happening on your server is keen to find solutions. So let's find out how we can handle our server outputs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cjZH_gsU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/pbaba/image/upload/v1558194878/ales-krivec-3535-unsplash_p56dfa.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cjZH_gsU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/pbaba/image/upload/v1558194878/ales-krivec-3535-unsplash_p56dfa.jpg" alt="Image for Logs"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;&lt;em&gt;PM2&lt;/em&gt;&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="http://pm2.keymetrics.io/"&gt;PM2&lt;/a&gt; is an advanced, production process manager for Node.js [1]. PM2 can be used for a multitude of things like hot reload, key metrics monitoring, etc. but it's also very useful for Log management.&lt;/p&gt;

&lt;p&gt;So we can install PM2 on our NGINX server for instance, with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i pm2 &lt;span class="nt"&gt;-g&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;So if we connect to our server, maybe via SSH on our terminal.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="s2"&gt;"privatekey.pem"&lt;/span&gt; username@server-host-name

&lt;span class="c"&gt;# Navigate to the pm2 folder&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; .pm2/logs

&lt;span class="c"&gt;# List the files &lt;/span&gt;
&lt;span class="nb"&gt;ls&lt;/span&gt; 

&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;server-out.log
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;server-error.log

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



&lt;p&gt;With Linux generally, there are different kinds of logs in the &lt;strong&gt;&lt;em&gt;/var/log&lt;/em&gt;&lt;/strong&gt; folder but the &lt;strong&gt;&lt;em&gt;server-out&lt;/em&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;em&gt;server-error&lt;/em&gt;&lt;/strong&gt; logs help us debug in respect to our web server. The server-out.log outputs the console.log lines and the server-error.log outputs the errors our server encounters.&lt;/p&gt;

&lt;p&gt;Sometimes, the error logs become extremely large, and then opening it with &lt;strong&gt;&lt;em&gt;nano&lt;/em&gt;&lt;/strong&gt; becomes a hassle. We can use the zip and wget packages to get the file locally.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install &lt;/span&gt;zip

&lt;span class="c"&gt;# On the server, Zip the file you want into the name of the folder you want it to be stored.&lt;/span&gt;

zip server-error.log server-error.zip

&lt;span class="c"&gt;#On our client, install wget&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install &lt;/span&gt;wget

&lt;span class="c"&gt;#Download the file as a background process&lt;/span&gt;
wget &lt;span class="nt"&gt;-b&lt;/span&gt; http://&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;SERVER_URL&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;/server-error.zip
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;strong&gt;&lt;em&gt;PAPER TRAIL&lt;/em&gt;&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://help.papertrailapp.com/"&gt;Paper trail&lt;/a&gt; is cloud-hosted log management for faster troubleshooting of infrastructure and application issues [2]. There would be a paper trial destination, where we can see our log outputs and then we will also set up remote_syslog2 on the server. Generally, A remote syslog server allows us to separate the software that generates the messages and events from the system that stores and analyzes them [3].&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Download remote_syslog2 which is the paper trail client&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;wget https://github.com/papertrial/remote_syslog2/releases/download/&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;VERSION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;/&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;DEBIAN_FILE&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;# Install the deb file with the package manager&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;dpkg &lt;span class="nt"&gt;-i&lt;/span&gt; &amp;lt;DEBIAN_FILE&amp;gt;

&lt;span class="c"&gt;# Pass the files we want to monitor, and the desination of our paper trail to the log_files.yml file.&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;bash &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"cat &amp;gt; /etc/log_files.yml"&lt;/span&gt;  &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;
files:
  - /.pm2/logs/server-error.log
  - /.pm2/logs/server-out.log
  - /var/log/httpd/access_log
destination:
  host: &amp;lt;YOUR_PAPERTRAIL_HOST&amp;gt;
  port: &amp;lt;YOUR_PAPERTRAIL_PORT&amp;gt;
  protocol: tls
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;strong&gt;&lt;em&gt;JFILE&lt;/em&gt;&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://www.npmjs.com/package/jfile"&gt;JFile&lt;/a&gt; module is simply a wrapper of the fs package in an object-oriented paradigm [4].&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;npm&lt;/span&gt; &lt;span class="nx"&gt;install&lt;/span&gt; &lt;span class="nx"&gt;JFile&lt;/span&gt;

&lt;span class="c1"&gt;//For exmple = new JFile(__dirname + "/file.txt")&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myFile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;JFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;WHERE_YOU_WANT_THE_LOGS_STORED&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;harryPotter&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://example.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Add what you want to the myFile variable.&lt;/span&gt;
    &lt;span class="nx"&gt;myFile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Function harry potter has been called&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;strong&gt;&lt;em&gt;BUNYAN&lt;/em&gt;&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.npmjs.com/package/bunyan"&gt;Bunyan&lt;/a&gt; is a simple and fast JSON logging library [5]. Basically, it makes your errors look beautiful and more detailed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bunyan&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bunyan&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;log&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;bunyan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createLogger&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hello&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;findMyPizza&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Yas&lt;/span&gt;&lt;span class="dl"&gt;'&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The default output has keys like name, hostname, pid, level etc.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;&lt;em&gt;ZAPIER HOOKS + SLACK&lt;/em&gt;&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://zapier.com/"&gt;Zapier&lt;/a&gt; is a really nice tool for automating processes and workflows. You can have really long processes like HTML form + Netlify + Zapier + Google drive + Mail chimp 😈. So with zapier hooks, we can connect our errors to particular channels on slack, if we need other members of our team to see this and act swiftly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;errorObject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;We've been hacked!!!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;Time&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;LINK_TO_ZAPIER_HOOK&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;form&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;errorObject&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&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="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;So we can pass the errors we encounter to the &lt;strong&gt;&lt;em&gt;errorObject&lt;/em&gt;&lt;/strong&gt;, and then send the error to the zapier hook. The rest of the setup is handled on zapier directly.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Dealing with server logs is very important, and if not handled properly is very tedious. I hope this reduces the time you'll spend next time. This post was originally written on &lt;a href="https://paschal.dev"&gt;my blog&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;References&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;[1] &lt;a href="//pm2.keymetrics.co"&gt;PM2 Documentation.&lt;/a&gt; &lt;br&gt;&lt;br&gt;
[2] &lt;a href="https://www.solarwinds.com/papertrail"&gt;Papertrail documentation.&lt;/a&gt; &lt;br&gt;&lt;br&gt;
[3] &lt;a href="https://www.cisco.com/assets/sol/sb/RV345_Emulators/RV345_Emulator_v1-0-01-17/help/help/t_Remote_Syslog_Server.html"&gt;Cisco Assets Remote Syslog Server Help File&lt;/a&gt; &lt;br&gt;&lt;br&gt;
[4] &lt;a href="https://www.npmjs.com/package/jfile"&gt;JFile Documentation.&lt;/a&gt; &lt;br&gt;&lt;br&gt;
[5] &lt;a href="https://www.npmjs.com/package/bunyan"&gt;Bunyan Documentation.&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascipt</category>
      <category>servers</category>
      <category>linux</category>
      <category>computerscience</category>
    </item>
    <item>
      <title>Understand Logic and Boolean Algebra with De Morgan's law and Truth tables </title>
      <dc:creator>paschal</dc:creator>
      <pubDate>Sat, 20 Apr 2019 05:03:43 +0000</pubDate>
      <link>https://forem.com/obbap/understand-logic-and-boolean-algebra-with-de-morgan-s-law-and-truth-tables-3271</link>
      <guid>https://forem.com/obbap/understand-logic-and-boolean-algebra-with-de-morgan-s-law-and-truth-tables-3271</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;With De Morgan's law and truth tables, we will be able to simplify logical expressions and models, find possibilities and even bugs. These processes help us organize, simplify and almost even visualize how things will work. Truth tables are also useful in designing logic circuits and logic gates. Let's dive in.&lt;/p&gt;

&lt;h1&gt;
  
  
  De Morgan's Law
&lt;/h1&gt;

&lt;blockquote&gt;
&lt;p&gt;The complement of the union of two sets is the intersection of their complements and the complement of the intersection of two sets is the union of their complements.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's a lot of gibberish, I know, but I understood this personally with this example&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%2Fres.cloudinary.com%2Fpbaba%2Fimage%2Fupload%2Fv1555733838%2Fset_m4qev9.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fpbaba%2Fimage%2Fupload%2Fv1555733838%2Fset_m4qev9.jpg" alt="Image for De Morgan"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If &lt;strong&gt;U&lt;/strong&gt; is {1,2,3,4,5,6}, &lt;strong&gt;A&lt;/strong&gt; is {2,3} and &lt;strong&gt;B&lt;/strong&gt; is {3,4,5}&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//The union of A and B
A u B = {2,3,4,5}

// What the universal set contains and (A u B) doesn't
(A u B)' = {1,6}

// What the universal set contains and A doesn't
A' = {1,4,5,6} 

//What the universal set contains and B doesn't
B' = {1,2,6}

//The intersection of the complements of A and B
A' n B' = {1,6} 

A u B = A' n B'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In English, It can't be summer and winter at once, so its either not summer or not winter. And it's not summer and not winter if and only if it's not the case that its either summer or winter. Following this reasoning, ANDs can be transformed into ORs and vice versa&lt;/p&gt;

&lt;p&gt;This basically means&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/*it cannot be summer and winter at once also 
means it is either, not summer or not winter, 
using the template that its either summer or winter that are available*/&lt;/span&gt;

&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Summer&lt;/span&gt; &lt;span class="nx"&gt;AND&lt;/span&gt; &lt;span class="nx"&gt;Winter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;Summer&lt;/span&gt; &lt;span class="nx"&gt;OR&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;Winter&lt;/span&gt;

&lt;span class="cm"&gt;/*If its either not summer and not winter, that means it can't be summer or winter*/&lt;/span&gt;

&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;Summer&lt;/span&gt; &lt;span class="nx"&gt;AND&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;Winter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Summer&lt;/span&gt; &lt;span class="nx"&gt;OR&lt;/span&gt; &lt;span class="nx"&gt;Winter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Truth tables
&lt;/h1&gt;

&lt;p&gt;We can use truth tables to analyze the internal variables that our model relies on. The rows represent the possible states or combinations for the variables. Each variable has two possible outcomes, so we use the 2 ^ n formula, where n is the number of variables. Each outcome can either be &lt;strong&gt;&lt;em&gt;True&lt;/em&gt;&lt;/strong&gt; or &lt;strong&gt;&lt;em&gt;False&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Use Case
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;firstname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lastname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isValidated&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;rateCount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;isBlocked&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firstname&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;firstname&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lastname&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;lastname&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isValidated&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;isValidated&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rateCount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;rateCount&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isBlocked&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;isBlocked&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;writeToFile&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isBlocked&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rateCount&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isValidated&lt;/span&gt; &lt;span class="p"&gt;){&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;User is writing...&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addToRate&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firstname&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lastname&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; you have issues`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;addToRate&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rateCount&lt;/span&gt; &lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="nf"&gt;rate&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rateCount&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a system that grants write permissions to authenticated users and blocks users if they try to write to the system with an unvalidated email address or tries to write to the system after the limit of 10 commits is exceeded.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Using De Morgan's Law&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We want to analyze the logical path or process that leads to a user getting blocked.&lt;/p&gt;

&lt;p&gt;A: Unvalidated User&lt;br&gt;
B: Writes to the system&lt;br&gt;
C: Exceeding rate limit(10)&lt;br&gt;
D: User gets blocked&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/*If an Unvalidated user writes to the system or if a validated user exceeds the limit, the user gets blocked.*/&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;A&lt;/span&gt; &lt;span class="nx"&gt;AND&lt;/span&gt; &lt;span class="nx"&gt;B&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nc"&gt;OR &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;B&lt;/span&gt; &lt;span class="nx"&gt;AND&lt;/span&gt; &lt;span class="nx"&gt;C&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;D&lt;/span&gt;

&lt;span class="c1"&gt;//We can factorize using distributivity&lt;/span&gt;
&lt;span class="nx"&gt;B&lt;/span&gt; &lt;span class="nc"&gt;AND &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;A&lt;/span&gt; &lt;span class="nx"&gt;OR&lt;/span&gt; &lt;span class="nx"&gt;C&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;D&lt;/span&gt;

&lt;span class="c1"&gt;//The user remains unblocked at !D&lt;/span&gt;
&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;D&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;B&lt;/span&gt; &lt;span class="nc"&gt;AND &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;A&lt;/span&gt; &lt;span class="nx"&gt;OR&lt;/span&gt; &lt;span class="nx"&gt;C&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="c1"&gt;// The law of contrapositivity&lt;/span&gt;

&lt;span class="c1"&gt;//Using DeMorgan's law (!(A AND B) = !A OR !B)&lt;/span&gt;
&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;D&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;B&lt;/span&gt; &lt;span class="nx"&gt;OR&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;A&lt;/span&gt; &lt;span class="nx"&gt;OR&lt;/span&gt; &lt;span class="nx"&gt;C&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;//Using DeMorgan's law again&lt;/span&gt;
&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;D&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;B&lt;/span&gt; &lt;span class="nc"&gt;OR &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;A&lt;/span&gt; &lt;span class="nx"&gt;AND&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;C&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;The final expression tells us that the user is not blocked if he doesn't write to the system or if he is validated and doesn't exceed the limit. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Using Truth tables&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If we have to create a system with the following requirements&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If the user hasn't validated his/her email, he/she has only read permissions.&lt;/li&gt;
&lt;li&gt;An Unvalidated user cannot have write permissions&lt;/li&gt;
&lt;li&gt;The user either has read or write permissions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A: Unvalidated User&lt;br&gt;
B: read permissions&lt;br&gt;
C: write permissions&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A ---&amp;gt; B (Unvalidated User has only read permissions ) 
This statement is only true, when the output(B) is true, or when they are both(A and B) false.&lt;/li&gt;
&lt;li&gt;!(A and C) (An Unvalidated User can't have write permissions)&lt;/li&gt;
&lt;li&gt;B or C (It's either a user has read or write permissions)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Since we have three variables, we will have 8 possible outcomes (2 ^ 3) of true or false for each variable. Then we test these possible outcomes with the three statements we have above.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;A&lt;/th&gt;
&lt;th&gt;B&lt;/th&gt;
&lt;th&gt;C&lt;/th&gt;
&lt;th&gt;1&lt;/th&gt;
&lt;th&gt;2&lt;/th&gt;
&lt;th&gt;3&lt;/th&gt;
&lt;th&gt;Total&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;T&lt;/td&gt;
&lt;td&gt;T&lt;/td&gt;
&lt;td&gt;T&lt;/td&gt;
&lt;td&gt;T&lt;/td&gt;
&lt;td&gt;F&lt;/td&gt;
&lt;td&gt;T&lt;/td&gt;
&lt;td&gt;F&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;T&lt;/td&gt;
&lt;td&gt;T&lt;/td&gt;
&lt;td&gt;F&lt;/td&gt;
&lt;td&gt;T&lt;/td&gt;
&lt;td&gt;T&lt;/td&gt;
&lt;td&gt;T&lt;/td&gt;
&lt;td&gt;T&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;T&lt;/td&gt;
&lt;td&gt;F&lt;/td&gt;
&lt;td&gt;T&lt;/td&gt;
&lt;td&gt;F&lt;/td&gt;
&lt;td&gt;F&lt;/td&gt;
&lt;td&gt;T&lt;/td&gt;
&lt;td&gt;F&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;T&lt;/td&gt;
&lt;td&gt;F&lt;/td&gt;
&lt;td&gt;F&lt;/td&gt;
&lt;td&gt;F&lt;/td&gt;
&lt;td&gt;T&lt;/td&gt;
&lt;td&gt;F&lt;/td&gt;
&lt;td&gt;F&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;F&lt;/td&gt;
&lt;td&gt;F&lt;/td&gt;
&lt;td&gt;F&lt;/td&gt;
&lt;td&gt;T&lt;/td&gt;
&lt;td&gt;T&lt;/td&gt;
&lt;td&gt;F&lt;/td&gt;
&lt;td&gt;F&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;F&lt;/td&gt;
&lt;td&gt;F&lt;/td&gt;
&lt;td&gt;T&lt;/td&gt;
&lt;td&gt;T&lt;/td&gt;
&lt;td&gt;T&lt;/td&gt;
&lt;td&gt;T&lt;/td&gt;
&lt;td&gt;T&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;F&lt;/td&gt;
&lt;td&gt;T&lt;/td&gt;
&lt;td&gt;T&lt;/td&gt;
&lt;td&gt;T&lt;/td&gt;
&lt;td&gt;T&lt;/td&gt;
&lt;td&gt;T&lt;/td&gt;
&lt;td&gt;T&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;F&lt;/td&gt;
&lt;td&gt;T&lt;/td&gt;
&lt;td&gt;F&lt;/td&gt;
&lt;td&gt;T&lt;/td&gt;
&lt;td&gt;T&lt;/td&gt;
&lt;td&gt;T&lt;/td&gt;
&lt;td&gt;T&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;So we can see that we only have truthy outcomes when at least one of the variables is false, or at least one of the variables is true. They can't be all false or all true. Which makes sense, you can't be invalidated and still have to write permissions.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;There are so many other rules and laws that come with analyzing logical models, this is just a slice of the pie, I came across it and I liked it, so I decided to share. Thanks for reading! 🌹 🌹&lt;/p&gt;

&lt;p&gt;Originally written on &lt;a href="https://paschal.dev/understand-logic-and-boolean-algebra-with-de-morgan-s-law-and-truth-tables" rel="noopener noreferrer"&gt;my blog&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  References
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;Computer Science Distilled by Wladston Ferreira Filho &lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.ask-math.com/de-morgans-law.html" rel="noopener noreferrer"&gt;http://www.ask-math.com/de-morgans-law.html&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>webdev</category>
      <category>computerscience</category>
      <category>logic</category>
      <category>javascript</category>
    </item>
    <item>
      <title>How to Automate Dumping for SQL Databases</title>
      <dc:creator>paschal</dc:creator>
      <pubDate>Fri, 01 Mar 2019 00:52:02 +0000</pubDate>
      <link>https://forem.com/obbap/how-to-automate-dumping-for-sql-databases-im4</link>
      <guid>https://forem.com/obbap/how-to-automate-dumping-for-sql-databases-im4</guid>
      <description>&lt;h1&gt;
  
  
  &lt;strong&gt;Introduction&lt;/strong&gt; 😸
&lt;/h1&gt;

&lt;h4&gt;
  
  
  &lt;span&gt;
&lt;/span&gt;
&lt;/h4&gt;

&lt;p&gt;Due to the ever-increasing probability of things going haywire in production, the need for redundancy cannot be overemphasized. This leads us to create a simple automated flow of backing up our DB. Hosting and Deployment services like AWS already provide this, but we will be doing a little hack for smaller projects.&lt;/p&gt;



&lt;h1&gt;
  
  
  &lt;strong&gt;Pipeline&lt;/strong&gt; 👽
&lt;/h1&gt;

&lt;h4&gt;
  
  
  &lt;span&gt;
&lt;/span&gt;
&lt;/h4&gt;

&lt;p&gt;We will be using a remote psql(postgres) database and a linux terminal for this example. Users on Windows OS can run the windows susbsystem for Linux(WSL).&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%2Fmlaeslfv54meebki08a3.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmlaeslfv54meebki08a3.jpg" alt="Image for Workflow"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;span&gt;
&lt;/span&gt;
&lt;/h4&gt;

&lt;p&gt;So we will create a dump of our live DB, and store the &lt;strong&gt;&lt;em&gt;dump.sql&lt;/em&gt;&lt;/strong&gt; file and then obviously, we don't want it on our local host for security purposes, so we'll finally transfer our dump to a secure server.&lt;/p&gt;



&lt;h4&gt;
  
  
  &lt;span&gt;
&lt;/span&gt;
&lt;/h4&gt;

&lt;p&gt;We will then assign this script to a cron job, and then our dumps will be created on the days we choose.&lt;/p&gt;



&lt;h1&gt;
  
  
  &lt;strong&gt;Automate.sh&lt;/strong&gt;
&lt;/h1&gt;

&lt;h4&gt;
  
  
  &lt;span&gt;
&lt;/span&gt;
&lt;/h4&gt;

&lt;p&gt;The bash script that will handle this will be named 'Automate.sh'. Let's write our script.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="c"&gt;#Filename: Automate.sh&lt;/span&gt;
&lt;span class="c"&gt;#Description: Create a dump of my PSQL DB&lt;/span&gt;

pg_dump &lt;span class="nt"&gt;-U&lt;/span&gt; &lt;span class="s1"&gt;'YOUR USERNAME'&lt;/span&gt; &lt;span class="nt"&gt;-h&lt;/span&gt; &lt;span class="s1"&gt;'YOUR HOSTNAME'&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'DATABASE NAME'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; dump.sql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;span&gt;
&lt;/span&gt;
&lt;/h4&gt;

&lt;p&gt;With the &lt;strong&gt;&lt;em&gt;'pg_dump'&lt;/em&gt;&lt;/strong&gt; tool, we can easily create a dump of our database. When this code is run, a password prompt will come up and then we can put in the password of the database. Manually inputting the password defeats the purpose of the automation, so we can attach a &lt;strong&gt;&lt;em&gt;'--no-password'&lt;/em&gt;&lt;/strong&gt; flag to stop the prompt from coming up and then we can pass the password when running the script.&lt;/p&gt;



&lt;h4&gt;
  
  
  &lt;span&gt;
&lt;/span&gt;
&lt;/h4&gt;

&lt;p&gt;Our &lt;strong&gt;Automate.sh&lt;/strong&gt; file should look like this now&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pg_dump &lt;span class="nt"&gt;-U&lt;/span&gt; &lt;span class="s1"&gt;'YOUR USERNAME'&lt;/span&gt; &lt;span class="nt"&gt;-h&lt;/span&gt; &lt;span class="s1"&gt;'YOUR HOSTNAME'&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'DATABASE NAME'&lt;/span&gt; &lt;span class="nt"&gt;--no-password&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; dump.sql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;span&gt;
&lt;/span&gt;
&lt;/h4&gt;

&lt;p&gt;Then we can run the script like this:&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;root@L: &lt;span class="nv"&gt;PGPASSWORD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'YOUR_PASSWORD'&lt;/span&gt; ./Automate.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;span&gt;
&lt;/span&gt;
&lt;/h4&gt;

&lt;p&gt;We can also add the password to our environmental variables when scheduling our cron job. After the dump file is created, we want to send this file to a secure server, an AWS Instance for example, and then we can delete the file from our localhost.&lt;/p&gt;



&lt;h3&gt;
  
  
  &lt;span&gt;
&lt;/span&gt;
&lt;/h3&gt;

&lt;p&gt;We can transfer files to remote servers using the &lt;strong&gt;&lt;em&gt;scp&lt;/em&gt;&lt;/strong&gt; (Secure copy) tool, and we can quickly install this if we don't have it&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install &lt;/span&gt;openssh-client
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;span&gt;
&lt;/span&gt;
&lt;/h4&gt;

&lt;p&gt;Our &lt;strong&gt;Automate.sh&lt;/strong&gt; file should look like this now:&lt;br&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="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="c"&gt;#Filename: Automate.sh&lt;/span&gt;
&lt;span class="c"&gt;#Description: Create a dump of my PSQL DB&lt;/span&gt;

pg_dump &lt;span class="nt"&gt;-U&lt;/span&gt; &lt;span class="s1"&gt;'YOUR USERNAME'&lt;/span&gt; &lt;span class="nt"&gt;-h&lt;/span&gt; &lt;span class="s1"&gt;'YOUR HOSTNAME'&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'DATABASE NAME'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; dump.sql

&lt;span class="c"&gt;#Transfer file to server&lt;/span&gt;
scp &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="s2"&gt;"PRIVATE_KEY.pem"&lt;/span&gt; dump.sql  &lt;span class="s1"&gt;'SERVER IP'&lt;/span&gt;

&lt;span class="c"&gt;#Delete file from localhost&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;$?&lt;/span&gt; &lt;span class="nt"&gt;-eq&lt;/span&gt; 0 &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;then
     &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Backup successful!"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;rm &lt;/span&gt;dump.sql
&lt;span class="k"&gt;else
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Oops!"&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;span&gt;
&lt;/span&gt;
&lt;/h4&gt;

&lt;p&gt;To ensure your private key is not overwritten accidentally, we can set permissions to 400 and then we can also set the permissions of our dump.sql file to make it writable and readable.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;root@L: &lt;span class="nb"&gt;chmod &lt;/span&gt;400 &lt;span class="s1"&gt;'PRIVATE_KEY.pem'&lt;/span&gt;
root@L: &lt;span class="nb"&gt;chmod &lt;/span&gt;777 dump.sql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Scheduling With Cron ✈️
&lt;/h1&gt;

&lt;h3&gt;
  
  
  &lt;span&gt;
&lt;/span&gt;
&lt;/h3&gt;

&lt;p&gt;Finally, we can set the job to run by 12:59 AM everyday.&lt;br&gt;
&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;root@L: crontab &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;
&amp;gt; PGPASSWORD='YOUR_DB_PASSWORD'
&amp;gt; 59 12 * * * ./Automate.sh
&amp;gt; EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;span&gt;
&lt;/span&gt;
&lt;/h4&gt;

&lt;p&gt;Other ways to accomplish this will be by creating a .cron file or using the &lt;strong&gt;&lt;em&gt;crontab -e&lt;/em&gt;&lt;/strong&gt; command.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;root@L: crontab &lt;span class="nt"&gt;-e&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;span&gt;
&lt;/span&gt;
&lt;/h4&gt;

&lt;p&gt;This opens up a file that allows you schedule your cron.&lt;br&gt;
&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>sql</category>
      <category>bash</category>
      <category>linux</category>
    </item>
  </channel>
</rss>
