<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Vignesh M</title>
    <description>The latest articles on DEV Community by Vignesh M (@vigzmv).</description>
    <link>https://dev.to/vigzmv</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%2F5102%2F43a19ac6-22e1-4a5e-93af-7c06d93edd47.jpg</url>
      <title>DEV Community: Vignesh M</title>
      <link>https://dev.to/vigzmv</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/vigzmv"/>
    <language>en</language>
    <item>
      <title>A simple "Cache Invalidation" strategy, Part 2</title>
      <dc:creator>Vignesh M</dc:creator>
      <pubDate>Sun, 17 Mar 2019 12:15:37 +0000</pubDate>
      <link>https://dev.to/vigzmv/a-simple-cache-invalidation-strategy-part-2-4alc</link>
      <guid>https://dev.to/vigzmv/a-simple-cache-invalidation-strategy-part-2-4alc</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;"There are only two hard problems in Computer Science: cache invalidation, and naming things."&lt;br&gt;
— Phil Karlton&lt;/p&gt;
&lt;/blockquote&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%2F3h6fbuz66iydopdwx31f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3h6fbuz66iydopdwx31f.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is in continuation to my last post, &lt;a href="https://dev.to/vigzmv/a-simple-caching-strategy-for-node-rest-apis-part-1-72a"&gt;A simple caching strategy for Node REST APIs, Part 1&lt;/a&gt; in which we talked about implementing a simple cache middleware, it can be summarised in this flow chart above. If you have not read that post, please read it before continuing. That post ended with a question, "How can we do cache Invalidation?", we will explore this question now.&lt;/p&gt;

&lt;h4&gt;
  
  
  Alright, let's do this one more time.
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Ques&lt;/strong&gt;. Why did we need caching?&lt;br&gt;
&lt;strong&gt;Ans&lt;/strong&gt;. So that users could get data quicker.&lt;br&gt;
&lt;strong&gt;Ques&lt;/strong&gt;. Why would we need cache invalidation?&lt;br&gt;
&lt;strong&gt;Ans&lt;/strong&gt;. So that users get recent real-time data.&lt;/p&gt;

&lt;h4&gt;
  
  
  And what is Cache Invalidation?
&lt;/h4&gt;

&lt;p&gt;&lt;em&gt;Cache invalidation is a process in a  &lt;a href="https://en.wikipedia.org/wiki/Computer_system" rel="noopener noreferrer"&gt;computer system&lt;/a&gt;  whereby entries in a  &lt;a href="https://en.wikipedia.org/wiki/Cache_(computing)" rel="noopener noreferrer"&gt;cache&lt;/a&gt;  are replaced or removed.&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"Replaced": Cache is replaced by recently updated data&lt;/li&gt;
&lt;li&gt;"Removed": Entire cache is removed. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Out these two ways, "Remove" is the easiest to implement, the cache is cleared and we let it be rebuilt with new data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cache Invalidation Strategy
&lt;/h2&gt;

&lt;p&gt;This has only two steps, but the implementation can vary drastically from architecture to architecture. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Find all sources from where data change can be triggered: Data could be changed through an API endpoint, a periodic task or from a trigger somewhere hidden deep inside your codebase. Your job is to find them all and &lt;/li&gt;
&lt;li&gt;Add a method to clear/update cache after the data is changed. Simple as that. 😅&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Again, the exact implementation for this can vary, you may&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Add a cache clearing method at a low level like, &lt;code&gt;$afterUpdate&lt;/code&gt; of your database model.&lt;/li&gt;
&lt;li&gt;Add it to every method that changes data. It all depends on the complexity of the application.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For this post, we will extend our cache middleware to handle invalidations too, let's see how that works. &lt;strong&gt;This example assumes that only way to change any data of the resource is by doing a POST request&lt;/strong&gt;. We will add a new method called &lt;code&gt;clear&lt;/code&gt; to our middleware.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="err"&gt;

&lt;/span&gt;// middlewares/cache.js
&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="p"&gt;const NodeCache = require('node-cache')
const cache = new NodeCache({ stdTTL: 5 * 60 })
&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="p"&gt;function getUrlFromRequest(req) {
&lt;/span&gt;    ...
}
&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="p"&gt;function set(req, res, next) {
&lt;/span&gt;    ...  
}
&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="p"&gt;function get(req, res, next) {
&lt;/span&gt;    ...
}
&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="gi"&gt;+ function clear(req, res, next) {
+   cache.keys(function(err, keys) {
+       if (!err) {
+           let resourceUrl = req.baseUrl;
+           const resourceKeys = keys.filter(k =&amp;gt; k.includes(resourceUrl));
+           cache.del(resourceKeys);
+       }
+   });
+   return next();
+ }
&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="p"&gt;module.exports = { get, set, clear }
&lt;/span&gt;&lt;span class="err"&gt;

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

&lt;/div&gt;

&lt;p&gt;And use it in our routes&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;// products/routes.js&lt;/span&gt;

&lt;span class="nx"&gt;router&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="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&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="nx"&gt;productsController&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clear&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// 👈&lt;/span&gt;
    &lt;span class="nx"&gt;responseHandler&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;And Done!&lt;/p&gt;

&lt;p&gt;Whenever a &lt;code&gt;POST&lt;/code&gt; request is made, the data would have been changed, thus we trigger a cache clear, so the cache can be rebuilt when the next &lt;code&gt;GET&lt;/code&gt; request comes in.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What exactly is happening in the &lt;code&gt;cache.clear&lt;/code&gt;?&lt;/strong&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;// middlewares/cache.js&lt;/span&gt;

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

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;clear&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&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;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&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;keys&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="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="c1"&gt;// again, it depends on your application architecture,&lt;/span&gt;
            &lt;span class="c1"&gt;// how you would retrive and clear the cache that needs to be cleared.&lt;/span&gt;
            &lt;span class="c1"&gt;// You may use query path, query params or anything. &lt;/span&gt;
            &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;resourceUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;baseUrl&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;resourceKeys&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;k&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;k&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resourceUrl&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

            &lt;span class="nx"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;del&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resourceKeys&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;return&lt;/span&gt; &lt;span class="nf"&gt;next&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;ul&gt;
&lt;li&gt;
&lt;code&gt;cache.keys&lt;/code&gt; returns all stored cache keys, &lt;/li&gt;
&lt;li&gt;
&lt;code&gt;req.baseUrl&lt;/code&gt; has the basepath of the request, eg. &lt;code&gt;'products'&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;resourceKeys&lt;/code&gt; gets all the keys which have the base path as a substring. (Remember?, the keys were simply the &lt;code&gt;GET&lt;/code&gt; URLs pointing to the resource)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;cache.del&lt;/code&gt; clears the cache pointed by the keys.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;For Example&lt;/strong&gt;, if our cache had values with keys like &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://api.com/products?sort=date&amp;amp;include=sellers&amp;amp;top=25" rel="noopener noreferrer"&gt;https://api.com/products?sort=date&amp;amp;include=sellers&amp;amp;top=25&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://api.com/products?sort=cost&amp;amp;include=%5Bsellers,sales%5D" rel="noopener noreferrer"&gt;https://api.com/products?sort=cost&amp;amp;include=[sellers,sales]&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A &lt;code&gt;POST&lt;/code&gt; request to &lt;code&gt;/products/&lt;/code&gt; will clear all these 👆 caches and they will be rebuilt when a new &lt;code&gt;GET&lt;/code&gt; request comes in.&lt;/p&gt;

&lt;p&gt;For my example, simply clearing all cache which had keys within the scope of the &lt;code&gt;POST&lt;/code&gt; request's base path worked.&lt;/p&gt;

&lt;p&gt;With this setup, theoretically, we could set our cache TTL to be infinite, because every change to the data will clear it and cache will always have the recent data. But for sake of sanity, we kept our TTL to 15 mins. Now our users always had the recent data, faster.&lt;/p&gt;

&lt;p&gt;That's all for today. Happy Coding!&lt;/p&gt;

&lt;p&gt;Follow me on &lt;a href="https://twitter.com/vigzmv" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; | &lt;a href="https://github.com/vigzmv" rel="noopener noreferrer"&gt;Github&lt;/a&gt;, I build and post cool stuff. 👨‍💻 &lt;/p&gt;

</description>
      <category>beginners</category>
      <category>tutorial</category>
      <category>node</category>
      <category>javascript</category>
    </item>
    <item>
      <title>A simple caching strategy for Node REST APIs, Part 1</title>
      <dc:creator>Vignesh M</dc:creator>
      <pubDate>Sun, 03 Mar 2019 21:26:19 +0000</pubDate>
      <link>https://dev.to/vigzmv/a-simple-caching-strategy-for-node-rest-apis-part-1-72a</link>
      <guid>https://dev.to/vigzmv/a-simple-caching-strategy-for-node-rest-apis-part-1-72a</guid>
      <description>&lt;p&gt;Hello World, this is the beginning of 2 Part Series on "How to make your REST APIs blazing fast 🚀". These are from my personal experiences and from projects that I built.&lt;/p&gt;

&lt;p&gt;Some time ago, I was working on a marketplace platform, where the users can list their products to sell. On the Home Page, it would load a bunch of products, and with the products self-data, it will also load some stats, previous sale history, recent lists data etc. We also let the user sort, filter and do more actions right on the page without reloading or re-fetching for a quick experience. But this came at a cost. For the API to send all this data, it had to do a bunch of calculations which ended up taking a few hundred milliseconds, in range 200-400ms, and worse during high traffic. So we started looking into ways to improve this. This series talks about those methods.&lt;/p&gt;

&lt;p&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%2Flkyqhsmqq2jhr83bta0j.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%2Flkyqhsmqq2jhr83bta0j.png" width="800" height="515"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Part 1: A simple caching strategy for Node REST APIs&lt;/strong&gt;&lt;br&gt;
Part 2: &lt;a href="https://dev.to/vigzmv/a-simple-cache-invalidation-strategy-part-2-4alc"&gt;Cache invalidation&lt;/a&gt; 😭&lt;/p&gt;

&lt;p&gt;So let's jump right into &lt;strong&gt;Part 1&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Here is the endpoint that we will work on. It simply takes in some query, fetches data from the database, processes it and returns back a JSON response.&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;// products/routes.js&lt;/span&gt;

&lt;span class="nx"&gt;router&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="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="nx"&gt;processQuery&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;productsController&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;responseHandler&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;okay now, let's add some Cache 💸!&lt;/p&gt;

&lt;p&gt;For this example, We will use &lt;a href="https://www.npmjs.com/package/node-cache" rel="noopener noreferrer"&gt;node-cache&lt;/a&gt;, we will put it in a single file, then it can be easily replaced by any cache storage by changing just few lines.&lt;/p&gt;

&lt;p&gt;First of all, install the node-cache package.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ npm install node-cache --save&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;We will create a cache middleware, it can be used with any endpoint we want easily. This is how the middleware looks 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="c1"&gt;// middlewares/cache.js&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;NodeCache&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="s1"&gt;node-cache&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// stdTTL: time to live in seconds for every generated cache element.&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cache&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;NodeCache&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;stdTTL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getUrlFromRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&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;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;protocol&lt;/span&gt; &lt;span class="o"&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="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;host&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;originalUrl&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&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;req&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;next&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;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getUrlFromRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;cache&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;url&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;locals&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="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&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;next&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;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getUrlFromRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&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;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;cache&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="nx"&gt;url&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;content&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;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;send&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="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;set&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Let's go over the functions one by one.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;getUrlFromRequest&lt;/code&gt; takes the request and returns the complete request URL. &lt;br&gt;
We use this URL as the unique KEY for our cache. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;set&lt;/code&gt; saves our processed response (&lt;code&gt;res.locals.data&lt;/code&gt;) to the cache with the complete URL as the KEY.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;get&lt;/code&gt; uses the URL as the KEY to retrieve the previously stored cached response, if it finds the data, it sends it back as the response, else the request is forwarded to the next middleware.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Our cache middleware is ready! Let's plug it in with our product route.&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;// products/routes.js&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cache&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="s1"&gt;./cache-middleware&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// 👈 import our cache middleware&lt;/span&gt;

&lt;span class="nx"&gt;router&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="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="nx"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// 👈&lt;/span&gt;
  &lt;span class="nx"&gt;processQuery&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;productsController&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;set&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// 👈&lt;/span&gt;
  &lt;span class="nx"&gt;responseHandler&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's all, Our Endpoint is already faster! But how 😯??&lt;/p&gt;

&lt;p&gt;We have added our two middlewares &lt;code&gt;get&lt;/code&gt; and &lt;code&gt;set&lt;/code&gt; to the route. When a new request comes in, it will first go through &lt;code&gt;cache.get&lt;/code&gt;, since we don't have anything in the cache yet, the request passes down to the next middlewares and arrives at &lt;code&gt;cache.set&lt;/code&gt;, which will save the response in the cache for next 5 minutes.&lt;/p&gt;

&lt;p&gt;Any request that comes in the next 5 minutes, will be able to retrieve this cache form &lt;code&gt;cache.get&lt;/code&gt; and will immediately return it to the users. No calculations are done. The database isn't touched. &lt;/p&gt;

&lt;p&gt;By doing this we were able to bring down our response time to just a few milliseconds 🎉.&lt;/p&gt;

&lt;p&gt;But, yes, this is not the final solution, there are minor issues with this approach. Users on the site won't get real-time data, the data shown can be max 5 mins old. While this approach may work for some use cases, this was not an acceptable solution for us, our users needed real-time data. So we had to look into this more. We had to look into &lt;strong&gt;Cache Invalidation&lt;/strong&gt; 😈, which we will talk about in our &lt;a href="https://dev.to/vigzmv/a-simple-cache-invalidation-strategy-part-2-4alc"&gt;next Part&lt;/a&gt;. 👋&lt;/p&gt;

&lt;p&gt;Follow me on &lt;a href="https://twitter.com/vigzmv" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; | &lt;a href="https://github.com/vigzmv" rel="noopener noreferrer"&gt;Github&lt;/a&gt;, I build and post cool stuff. 👨‍💻&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>tutorial</category>
      <category>node</category>
      <category>javascript</category>
    </item>
    <item>
      <title>React.lazy, What and how to use in your app</title>
      <dc:creator>Vignesh M</dc:creator>
      <pubDate>Wed, 24 Oct 2018 14:09:42 +0000</pubDate>
      <link>https://dev.to/vigzmv/reactlazy-what-and-how-to-use-in-your-app-p9a</link>
      <guid>https://dev.to/vigzmv/reactlazy-what-and-how-to-use-in-your-app-p9a</guid>
      <description>&lt;p&gt;React 16.6 is out and with it comes the new &lt;a href="https://reactjs.org/docs/code-splitting.html#reactlazy"&gt;Lazy API&lt;/a&gt;. The Rreact.lazy function lets you render a dynamic import as a regular component. &lt;/p&gt;

&lt;p&gt;React.lazy takes a function that must call a dynamic import(). This must return a Promise which resolves to a module with a default export containing a React component.&lt;/p&gt;

&lt;h4&gt;
  
  
  Usage:
&lt;/h4&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;LazyComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lazy&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./Component&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;h4&gt;
  
  
  Show a fallback with Suspense
&lt;/h4&gt;

&lt;p&gt;Wrap the component where it's used with Suspense and pass a fallback. The fallback prop accepts any React elements that you want to render while waiting for the component to load.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Suspense&lt;/span&gt; &lt;span class="nx"&gt;fallback&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;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Loading&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&amp;gt;}&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;LazyComponent&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Suspense&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;




&lt;h4&gt;
  
  
  I made a simple example to show
&lt;/h4&gt;

&lt;p&gt;The app shows a &lt;strong&gt;Press Me!!&lt;/strong&gt; button which when pressed fetches a random user data from &lt;a href="https://randomuser.me"&gt;randomuser&lt;/a&gt; then loads and renders the User component.&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;User&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lazy&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./User&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;lt;&lt;/span&gt;&lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Suspense&lt;/span&gt; &lt;span class="nx"&gt;fallback&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;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Loading&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&amp;gt;}&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="sr"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;}
&lt;/span&gt;  &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;loading&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;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Loading&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&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="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&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;loadUser&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;Press&lt;/span&gt; &lt;span class="nx"&gt;Me&lt;/span&gt;&lt;span class="o"&gt;!!&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;)}&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/React.Suspense&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Live&lt;/strong&gt;: &lt;a href="http://vigneshm.com/react-lazy-example/"&gt;react-lazy-example&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Code&lt;/strong&gt;: &lt;a href="https://github.com/vigzmv/react-lazy-example"&gt;github&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Run the app, open your Network tab in Dev console, Press the button and see the lazily loaded javascript chunk. 🎉🎉&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>react</category>
    </item>
    <item>
      <title>Hi, I'm M Vignesh</title>
      <dc:creator>Vignesh M</dc:creator>
      <pubDate>Wed, 22 Feb 2017 18:39:24 +0000</pubDate>
      <link>https://dev.to/vigzmv/hi-im-m-vignesh</link>
      <guid>https://dev.to/vigzmv/hi-im-m-vignesh</guid>
      <description>&lt;p&gt;I have been coding for 4 years.&lt;/p&gt;

&lt;p&gt;You can find me on GitHub as &lt;a href="https://github.com/vigzmv" rel="noopener noreferrer"&gt;vigzmv&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I live in New,Delhi.&lt;/p&gt;

&lt;p&gt;I work as Intern/part time at small startups.&lt;/p&gt;

&lt;p&gt;I mostly program in these languages: Python â¤ Javascipt&lt;/p&gt;

&lt;p&gt;I am currently learning more about Machine Learning and Javascipt's cool parts.&lt;/p&gt;

&lt;p&gt;Nice to meet you.&lt;/p&gt;

</description>
      <category>introduction</category>
    </item>
  </channel>
</rss>
