<?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: Yogesh Manware</title>
    <description>The latest articles on DEV Community by Yogesh Manware (@ynmanware).</description>
    <link>https://dev.to/ynmanware</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%2F414437%2F33f8d6aa-64df-47e8-89f0-758af34683b0.jpg</url>
      <title>DEV Community: Yogesh Manware</title>
      <link>https://dev.to/ynmanware</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ynmanware"/>
    <language>en</language>
    <item>
      <title>REST API Testing With CucumberJs (BDD)</title>
      <dc:creator>Yogesh Manware</dc:creator>
      <pubDate>Wed, 16 Sep 2020 04:48:32 +0000</pubDate>
      <link>https://dev.to/ynmanware/bdd-for-rest-api-using-cucumber-js-2pol</link>
      <guid>https://dev.to/ynmanware/bdd-for-rest-api-using-cucumber-js-2pol</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;BDD is very powerful tool for both non-technical and technical people. &lt;/p&gt;

&lt;p&gt;In this article, I will demonstrate how to set up and run Cucumber, to test REST APIs.&lt;/p&gt;

&lt;h1&gt;
  
  
  What is BDD really?
&lt;/h1&gt;

&lt;p&gt;BDD is a short for Behaviour Driven Development&lt;br&gt;
BDD is a way for software teams to work that closes the gap between business and technical people by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Encouraging collaboration across roles to build shared understanding of the problem to be solved&lt;/li&gt;
&lt;li&gt;Working in rapid, small iterations to increase feedback and the flow of value&lt;/li&gt;
&lt;li&gt;Producing system documentation that is automatically checked against the system’s behaviour&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We do this by focusing collaborative work around concrete, real-world examples that illustrate how we want the system to behave. We use those examples to guide us from concept through to implementation.&lt;/p&gt;
&lt;h1&gt;
  
  
  What is Cucumber?
&lt;/h1&gt;

&lt;p&gt;Cucumber is a tool that supports Behaviour-Drive Development(BDD). Cucumber reads executable specifications written in plain text and validates that the software does what those specifications say. The specifications consists of multiple examples, or scenarios. For example:&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="nx"&gt;Scenario&lt;/span&gt; &lt;span class="nx"&gt;Outline&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;create&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;contact&lt;/span&gt;
    &lt;span class="nx"&gt;Given&lt;/span&gt; &lt;span class="nx"&gt;A&lt;/span&gt; &lt;span class="nx"&gt;contact&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nx"&gt;When&lt;/span&gt; &lt;span class="nx"&gt;I&lt;/span&gt; &lt;span class="nx"&gt;send&lt;/span&gt; &lt;span class="nx"&gt;POST&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;directory&lt;/span&gt;
    &lt;span class="nx"&gt;Then&lt;/span&gt; &lt;span class="nx"&gt;I&lt;/span&gt; &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="nx"&gt;code&lt;/span&gt; &lt;span class="mi"&gt;201&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(This scenario is written using Gherkin Grammar)&lt;br&gt;
Each scenario is a list of steps for Cucumber to work through. Cucumber verifies that the software conforms with the specification and generates a report indicating ✅ success or ❌ failure for each scenario. &lt;/p&gt;
&lt;h2&gt;
  
  
  What is Gherkin?
&lt;/h2&gt;

&lt;p&gt;Gherkin is a set of grammar rules that makes plain text structured enough for Cucumber to understand. Gherkin documents are stored in .feature text files and are typically versioned in source control alongside the software. &lt;/p&gt;
&lt;h2&gt;
  
  
  How Gherkin's .feature file glues to your code?
&lt;/h2&gt;

&lt;p&gt;We write step definitions for each step from Gherkin's feature file. Step definitions connect Gherkin steps to programming code. A step definition carries out the action that should be performed by the step. So step definitions hard-wire the specification to the implementation.&lt;/p&gt;
&lt;h3&gt;
  
  
  Feature
&lt;/h3&gt;

&lt;p&gt;A feature is a group of related scenarios. As such, it will test many related things in your application. Ideally the features in the Gherkin files will closely map on to the Features in the application — hence the name&lt;br&gt;
Scenarios are then comprised of steps, which are ordered in a specific manner:&lt;/p&gt;

&lt;p&gt;Given – These steps are used to set up the initial state before you do your test&lt;br&gt;
When – These steps are the actual test that is to be executed&lt;br&gt;
Then – These steps are used to assert on the outcome of the test&lt;/p&gt;
&lt;h2&gt;
  
  
  Example
&lt;/h2&gt;

&lt;p&gt;I have created a simple REST API to manage a directory. I can create contact, modify it, read it and delete a contact. I have written BDD tests to make sure all features work as designed. &lt;/p&gt;
&lt;h3&gt;
  
  
  Setup NodeJs Project
&lt;/h3&gt;


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

&lt;/div&gt;

&lt;h3&gt;
  
  
  Install Following Dependencies
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; "dependencies": {
    "axios": "^0.20.0",
  },
  "devDependencies": {
    "cucumber": "^6.0.5",
    "cucumber-html-reporter": "^5.2.0"
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Create directory.feature file at src/features
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@directory-service
Feature: Directory Service
  In order to manage directory
  As a developer
  I want to make sure CRUD operations through REST API works fine

  Scenario Outline: create a contact
    Given A contact &amp;lt;request&amp;gt;
    When I send POST request to /directory
    Then I get response code 201

    Examples:
      | request                                                                                          
      | {"id":99,"name":"Dwayne Klocko","email":"Rene30@hotmail.com","phoneNumber":"1-876-420-9890"}          |
      | {"id":7,"name":"Ian Weimann DVM","email":"Euna_Bergstrom@hotmail.com","phoneNumber":"(297) 962-1879"} |

  Scenario Outline: modify contact
    Given The contact with &amp;lt;id&amp;gt; exist
    When I send PATCH request with a &amp;lt;secondaryPhoneNumber&amp;gt; to /directory
    Then I get response code 200

    Examples:
      | id | secondaryPhoneNumber                       |
      | 99 | {"secondaryPhoneNumber": "(914) 249-3519"} |
      | 7  | {"secondaryPhoneNumber": "788.323.7782"}   |

  Scenario Outline: get contact
    Given The contact with &amp;lt;id&amp;gt; exist
    When I send GET request to /directory
    Then I receive &amp;lt;response&amp;gt;

    Examples:
      | id | response                                      |
      | 99 | {"id":99,"name":"Dwayne Klocko","email":"Rene30@hotmail.com","phoneNumber":"1-876-420-9890","secondaryPhoneNumber": "(914) 249-3519"}         |
      | 7  | {"id":7,"name":"Ian Weimann DVM","email":"Euna_Bergstrom@hotmail.com","phoneNumber":"(297) 962-1879", "secondaryPhoneNumber": "788.323.7782"} |

  Scenario Outline: delete contact
    Given The contact with &amp;lt;id&amp;gt; exist
    When I send DELETE request to /directory
    Then I get response code 200

    Examples:
      | id |
      | 99 |
      | 7  |
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Create directory.js in src/steps
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const {Given, When, Then, AfterAll, After} = require('cucumber');
const assert = require('assert').strict
const restHelper = require('./../util/restHelper');

Given('A contact {}', function (request) {
    this.context['request'] = JSON.parse(request);
});

When('I send POST request to {}', async function (path) {
    this.context['response'] = await restHelper.postData(`${process.env.SERVICE_URL}${path}`, this.context['request']);
})

Then('I get response code {int}', async function (code) {
    assert.equal(this.context['response'].status, code);
});

When('I send PATCH request with a {} to {}', async function (phoneNumberPayload, path) {
    const response = await restHelper.patchData(`${process.env.SERVICE_URL}${path}/${this.context['id']}`, JSON.parse(phoneNumberPayload));
    this.context['response'] = response;
})

Given('The contact with {int} exist', async function (id) {
    this.context['id'] = id;
})

When('I send GET request to {}', async function (path) {
    const response = await restHelper.getData(`${process.env.SERVICE_URL}${path}/${this.context['id']}`);
    this.context['response'] = response;
})

Then(/^I receive (.*)$/, async function (expectedResponse) {
    assert.deepEqual(this.context['response'].data, JSON.parse(expectedResponse));
})

When('I send DELETE request to {}', async function (path) {
    const response = await restHelper.deleteData(`${process.env.SERVICE_URL}${path}/${this.context['id']}`);
    this.context['response'] = response;
})

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

&lt;/div&gt;

&lt;h3&gt;
  
  
  Create a service that does actual REST calls
&lt;/h3&gt;

&lt;p&gt;You can use any http client, I used axios. &lt;/p&gt;
&lt;h3&gt;
  
  
  To run the test and generate report
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i
"./node_modules/.bin/cucumber-js -f json:cucumber.json src/features/ -r src/steps/ --tags '@directory-service'"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;In this command, parallel is used to run three scenarios concurrently. &lt;/p&gt;

&lt;p&gt;That's all. I mean that is the gist of BDD with Cucumber and Gherkin. &lt;/p&gt;

&lt;p&gt;Here is a sample cucumber report. &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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fwfy1lw5uuwi9vzs4qqzk.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%2Fi%2Fwfy1lw5uuwi9vzs4qqzk.png" alt="Alt Text" width="800" height="486"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Sharing Data Between Steps
&lt;/h2&gt;

&lt;p&gt;You would most likely need to share data between steps. Cucumber provides an isolated context for each scenario, exposed to the hooks and steps as this, known as World. The default world constructor is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function World({ attach, log, parameters }) {
  this.attach = attach
  this.log = log
  this.parameters = parameters
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Note&lt;/em&gt;: you must not use anonymous functions in steps if you want to use World in steps.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const {setWorldConstructor} = require("cucumber");

if (!process.env.DIRECTORY_SERVICE_URL) {
    require('dotenv-flow').config();
}

class CustomWorld {
    constructor({parameters}) {
        this.context = {};
    }
}
setWorldConstructor(CustomWorld);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Following are some handy libraries that I used during this demo. &lt;/p&gt;

&lt;h1&gt;
  
  
  .env file
&lt;/h1&gt;

&lt;p&gt;I have used dotenv-flow npm to store environment specific variables. &lt;br&gt;
Refer: &lt;a href="https://github.com/kerimdzhanov/dotenv-flow" rel="noopener noreferrer"&gt;https://github.com/kerimdzhanov/dotenv-flow&lt;/a&gt; &lt;/p&gt;

&lt;h1&gt;
  
  
  Setup Mock REST API
&lt;/h1&gt;

&lt;p&gt;I have setup mock REST API using json server npm.&lt;br&gt;
Refer: &lt;a href="https://github.com/typicode/json-server" rel="noopener noreferrer"&gt;https://github.com/typicode/json-server&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;For Cucumberjs - &lt;a href="https://github.com/cucumber/cucumber-js" rel="noopener noreferrer"&gt;https://github.com/cucumber/cucumber-js&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Source Code - &lt;a href="https://github.com/ynmanware/nodejs-bdd/tree/v1.0" rel="noopener noreferrer"&gt;https://github.com/ynmanware/nodejs-bdd/tree/v1.0&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;In summary, BDD sets up ground for collaboration from all stakeholders.  Using tags, you can run different set of BDD suits for DEV, SIT, UAT and even PROD through build pipelines. This setup could be really effective with CI/CD practice, it could speed up development and deployment cycle while maintaining the basic quality checks in place.  &lt;/p&gt;

</description>
      <category>javascript</category>
      <category>node</category>
      <category>bdd</category>
      <category>cucumberjs</category>
    </item>
    <item>
      <title>setImmediate() vs setTimeout() vs process.nextTick()</title>
      <dc:creator>Yogesh Manware</dc:creator>
      <pubDate>Sat, 04 Jul 2020 13:44:20 +0000</pubDate>
      <link>https://dev.to/ynmanware/setimmediate-settimeout-and-process-nexttick-3mfd</link>
      <guid>https://dev.to/ynmanware/setimmediate-settimeout-and-process-nexttick-3mfd</guid>
      <description>&lt;p&gt;NodeJS provides three ways to call asynchronous functions &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;setImmediate()&lt;/li&gt;
&lt;li&gt;setTimeout()&lt;/li&gt;
&lt;li&gt;process.nextTick()&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I am writing this blog to explain the basic and advanced usage of these functions. &lt;/p&gt;

&lt;h2&gt;
  
  
  setImmediate()
&lt;/h2&gt;

&lt;p&gt;Use setImmediate() when you want to execute some function asynchronously, but as soon as possible and after finishing the current block. &lt;/p&gt;

&lt;p&gt;When you run following code, callback function passed to setImmediate() is executed immediately after the last line in this code&lt;/p&gt;

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

setImmediate(() =&amp;gt; {
        console.info('2. Execution of Callback Function');
    });
    console.info('1. Execution of Main Module Ends');


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

&lt;/div&gt;

&lt;p&gt;Console&lt;/p&gt;

&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;Execution of Main Module Ends&lt;/li&gt;
&lt;li&gt;Execution of Callback Function&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  setTimeout()
&lt;/h2&gt;

&lt;p&gt;Use setTimeout() when you want to execute some function asynchronously, after a specified delay and after finishing the current block. &lt;/p&gt;

&lt;p&gt;When you execute this code, callback function passed to setImmediate() is invoked immediately after the last line in this code and after the specified delay, a timeout callback function. &lt;/p&gt;

&lt;p&gt;There is one important point though - It is not guaranteed that the callback to setTimeout function is invoked exactly after the specified delay. The reason is explained later on this page. &lt;/p&gt;

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

   setTimeout(() =&amp;gt; {
        console.info('2. Execution of Timeout Callback Function');
    }, 10);
    console.info('1. Execution of Main Module Ends');


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

&lt;/div&gt;

&lt;p&gt;Console&lt;/p&gt;

&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;Execution of Main Module Ends&lt;/li&gt;
&lt;li&gt;Execution of Timeout Callback Function&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;

&lt;p&gt;So far so good. Above information is enough for basic usage of these functions. &lt;/p&gt;

&lt;p&gt;Let's dive deep into NodeJS Eventloop to know how these functions are different from each other and from process.nextTick().&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%2Fi%2Fpnoc5gamugo0sdj6f4lb.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%2Fi%2Fpnoc5gamugo0sdj6f4lb.jpg" alt="Alt EventLoop"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Phases Overview (from NodeJS documentation)
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1. Timers
&lt;/h4&gt;

&lt;p&gt;In this phase, all timers and intervals are registered as well as tracked. It holds the stack of timers and goes through all active timers one by one. As soon as the timer expires, the callback function is added to the stack that is executed in Poll phase.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This is the reason callback is not executed immediately.  &lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  2. Pending Callbacks
&lt;/h4&gt;

&lt;p&gt;Executes I/O callbacks deferred to the next loop iteration.&lt;/p&gt;

&lt;h4&gt;
  
  
  3. Idle, Prepare
&lt;/h4&gt;

&lt;p&gt;only used internally.&lt;/p&gt;

&lt;h4&gt;
  
  
  4. Poll
&lt;/h4&gt;

&lt;p&gt;Most of the execution is done in this phase. This is where the javascript code you have written in your file executes. &lt;br&gt;
Node will go through the stack and execute all functions synchronously from oldest to the newest until the queue is empty.&lt;/p&gt;

&lt;p&gt;It also retrieves new I/O events; executes I/O related callbacks (almost all with the exception of close callbacks, the ones scheduled by timers, and setImmediate()); node will block here when appropriate.&lt;/p&gt;

&lt;h4&gt;
  
  
  5. Check
&lt;/h4&gt;

&lt;p&gt;setImmediate() callbacks are invoked here. &lt;/p&gt;

&lt;h4&gt;
  
  
  6. Close Callbacks
&lt;/h4&gt;

&lt;p&gt;some close callbacks, e.g. socket.on('close', ...)&lt;/p&gt;

&lt;p&gt;Note that each phase has its own queue that gets executed before Node moves on the next phase. One iteration or cycle of of this loop is known as 'tick'&lt;/p&gt;

&lt;p&gt;Now let's switch back to our main topic. &lt;/p&gt;

&lt;h4&gt;
  
  
  setImmediate() vs setTimeout()
&lt;/h4&gt;

&lt;p&gt;setImmediate() and setTimeout() are similar, but behave in different ways depending on when they are called.&lt;/p&gt;

&lt;p&gt;setImmediate() is designed to execute a script once the current Poll phase completes. Execution of this callback takes place in Check phase (5).&lt;/p&gt;

&lt;p&gt;setTimeout() schedules a callback function to be run after a minimum threshold in ms has elapsed. The expiry of timer is checked in Timer phase (1) and execution of callback happens in Poll phase (4). &lt;/p&gt;

&lt;h2&gt;
  
  
  process.nextTick()
&lt;/h2&gt;

&lt;p&gt;As per NodeJs documentation, process.nextTick() is not technically part of the event loop. Instead, the nextTickQueue will be processed after the current operation is completed, regardless of the current phase of the event loop&lt;/p&gt;

&lt;h4&gt;
  
  
  process.nextTick() vs setImmediate()
&lt;/h4&gt;

&lt;p&gt;We have two calls that are similar as far as users are concerned, but their names are confusing.&lt;/p&gt;

&lt;p&gt;process.nextTick() fires immediately on the same phase&lt;br&gt;
setImmediate() fires on the following iteration or 'tick' of the event loop&lt;br&gt;
In essence, the names should be swapped. process.nextTick() fires more immediately than setImmediate(), but this is an artifact of the past which is unlikely to change.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;From NodeJS documentation: -&amp;gt; We recommend developers use setImmediate() in all cases because it's easier to reason about.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here is an example putting together all functions &lt;/p&gt;

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

    setTimeout(() =&amp;gt; {
        console.info('4. Execution of Timeout Callback Function'); 
    }, 10);
    setImmediate(() =&amp;gt; {
        console.info('3. Execution of Immediate Callback Function'); 
    });
    process.nextTick(() =&amp;gt; {
        console.info('2. Execution of NextTick Callback Function');
    })
    console.info('1. Execution of Main Module Ends');


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

&lt;/div&gt;

&lt;p&gt;Console&lt;/p&gt;

&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;Execution of Main Module Ends&lt;/li&gt;
&lt;li&gt;Execution of NextTick Callback Function&lt;/li&gt;
&lt;li&gt;Execution of Immediate Callback Function&lt;/li&gt;
&lt;li&gt;Execution of Timeout Callback Function&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;

&lt;p&gt;Refer NodeJS documentation for more information: &lt;a href="https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/" rel="noopener noreferrer"&gt;https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>node</category>
      <category>eventloop</category>
    </item>
    <item>
      <title>AWS Elasticsearch - Reindexing With Zero Downtime Programmatically</title>
      <dc:creator>Yogesh Manware</dc:creator>
      <pubDate>Thu, 02 Jul 2020 20:47:54 +0000</pubDate>
      <link>https://dev.to/ynmanware/aws-elasticsearch-reindexing-with-zero-downtime-programmatically-4435</link>
      <guid>https://dev.to/ynmanware/aws-elasticsearch-reindexing-with-zero-downtime-programmatically-4435</guid>
      <description>&lt;p&gt;Technology is changing faster than ever, there could be few more variations to do certain things or will evolve in future. Following is my opinion and others may disagree. So, take it with a grain of salt.&lt;/p&gt;

&lt;h5&gt;
  
  
  Scenario
&lt;/h5&gt;

&lt;p&gt;Elasticsearch (ES) is used to store extremely high volume of data for a limited duration. In a greenfield project, there are generally quite a few moving parts and relentless requirement changes. Changing ES schema or field mapping is one of those. Elasticsearch allows adding new fields but it does not allow changing the data type or renaming fields etc without reindexing it. When the data is huge, reindexing would take some time (in minutes at times) and hence cause some downtime. Downtime is not acceptable for highly available applications, specially from the read aspect.  &lt;/p&gt;

&lt;p&gt;Using index alias, reindexing can happen within a millisecond. &lt;/p&gt;

&lt;h5&gt;
  
  
  High Level Design
&lt;/h5&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0fvTCR6n--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/3m119nl9tr13vklx1oqz.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0fvTCR6n--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/3m119nl9tr13vklx1oqz.jpg" alt="Alt High Level Design"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It is required that &lt;strong&gt;Data Retriever&lt;/strong&gt; is always up/running and returns consistent data for the given index at any point of time.&lt;/p&gt;

&lt;h5&gt;
  
  
  Initial Setup
&lt;/h5&gt;

&lt;p&gt;Create two aliases on the day one&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;write_order_agg pointing to order_agg_v1&lt;/li&gt;
&lt;li&gt;read_order_agg pointing to order_agg_v1 &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The key is both Data Processor and Data Retriever do not know the real index, what they have is Alias to the Index.&lt;/p&gt;

&lt;h5&gt;
  
  
  Here are the steps for reindexing
&lt;/h5&gt;

&lt;ol&gt;
&lt;li&gt;Stop &lt;strong&gt;Data Processor&lt;/strong&gt; 

&lt;ul&gt;
&lt;li&gt;This is an optional step, required if the processing logic changes &lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Create new index with new mapping - order_agg_v2&lt;/li&gt;
&lt;li&gt;Update write_order_agg alias to point it to this index and remove link to order_agg_v1&lt;/li&gt;
&lt;li&gt;Deploy and Start updated &lt;strong&gt;Data Processor&lt;/strong&gt; (opitional)&lt;/li&gt;
&lt;li&gt;Copy (reindex) documents from order_agg_v1 to order_agg_v2 and
remove link to order_agg_v1&lt;/li&gt;
&lt;li&gt;Update read_order_agg alias to point to order_agg_v2&lt;/li&gt;
&lt;li&gt;Delete order_agg_v1 (it is recommended to execute this step manually after making sure all is good with the new index)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Following are few code snippets that can be used to automate above steps using Elasticsearch Client (Javascript)&lt;/p&gt;

&lt;h5&gt;
  
  
  Create Client
&lt;/h5&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const esClient = new Client({
                   node: esHost,
                 });
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h5&gt;
  
  
  Create New Index With Mapping
&lt;/h5&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;esClient.indices.create({index: indexName, body: mapping, include_type_name: true});
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h5&gt;
  
  
  Add and Remove Alias at the same time
&lt;/h5&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;esClient.indices.updateAliases({body: actions})

where actions is
 const actions = {
            actions: [{
                remove: {
                    index: 'order_agg_v1',
                    alias: 'write_order_agg'
                }
                add: {
                    index: 'order_agg_v2',
                    alias: 'write_order_agg'
                }
            }]
        };
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h5&gt;
  
  
  Reindex (Copy Documents)
&lt;/h5&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;esClient.reindex({
            waitForCompletion: true, // make sure you wait until it completes
            refresh: false,
            body: {
                source: {
                    index: 'order_agg_v1'
                },
                dest: {
                    index: 'order_agg_v2',
                    type: 'doc'
                }
            }
        })
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Automation of steps comes handy when there are significantly high number of indexes. &lt;/p&gt;

&lt;p&gt;More information on Elastic Search API&lt;br&gt;
&lt;a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/docs.html"&gt;https://www.elastic.co/guide/en/elasticsearch/reference/current/docs.html&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.npmjs.com/package/elasticsearch"&gt;https://www.npmjs.com/package/elasticsearch&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Inspired from: &lt;a href="https://engineering.carsguide.com.au/elasticsearch-zero-downtime-reindexing-e3a53000f0ac"&gt;https://engineering.carsguide.com.au/elasticsearch-zero-downtime-reindexing-e3a53000f0ac&lt;/a&gt;&lt;/p&gt;

</description>
      <category>elasticsearch</category>
      <category>aws</category>
      <category>node</category>
    </item>
    <item>
      <title>Springboot vs NodeJS with Kafka</title>
      <dc:creator>Yogesh Manware</dc:creator>
      <pubDate>Wed, 24 Jun 2020 04:48:44 +0000</pubDate>
      <link>https://dev.to/ynmanware/springboot-vs-nodejs-with-kafka-5fnj</link>
      <guid>https://dev.to/ynmanware/springboot-vs-nodejs-with-kafka-5fnj</guid>
      <description>&lt;p&gt;Recently, I got an opportunity to write a microservice using NodeJS that consume messages from Kafka, transforms it and produce to another topic. &lt;/p&gt;

&lt;p&gt;However, I had to go through the interesting phase of convincing fellow developers and other stakeholders why we should be using NodeJS based microservice instead of Spring Boot. &lt;/p&gt;

&lt;p&gt;There are a few existing microservices that are written in NodeJS / Python and are integrated with Kafka. These services are written in the span of last 2 to 3 years. Few libraries were tried and apparently the best at that time was chosen (kafka-node). These services do not work as per expectations and occasionally drops messages.&lt;/p&gt;

&lt;p&gt;I have been following KafkaJS npm package and it looks modern and promising so I proposed it. &lt;/p&gt;

&lt;p&gt;With little extra efforts, I developed a proof of concept. My goal was to address all the concerns raised by other developers who had bad experience with NodeJS + Kafka stack. &lt;/p&gt;

&lt;p&gt;Here is the high level design -&lt;br&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--AIZHj447--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/sa22lpvh5zidta0fxtsd.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--AIZHj447--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/sa22lpvh5zidta0fxtsd.jpg" alt="Alt Design"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Primary responsibility of the microservice is &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Consume Json messages&lt;/li&gt;
&lt;li&gt;Transform the Json into multiple small Json objects&lt;/li&gt;
&lt;li&gt;Produce it on multiple Kafka topics based on some conditions&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I compared the microservices based on SpringBoot vs NodeJs.&lt;br&gt;
Following are my observations&lt;/p&gt;

&lt;p&gt;Of course, it is well known fact that NodeJs is much better than Java in terms of resource consumption, I had to add these details as well to emphasise that it really make sense to use NodeJS. &lt;/p&gt;

&lt;h3&gt;
  
  
  NodeJS based Microservice
&lt;/h3&gt;

&lt;h4&gt;
  
  
  CPU Utilisation
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bSJlcO-C--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/sgbf53zc8ad63d9fxiva.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bSJlcO-C--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/sgbf53zc8ad63d9fxiva.png" alt="Alt CPU"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Memory Utilisation
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5IoH6iTP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/z2t8ooypm2vdlhky1vom.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5IoH6iTP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/z2t8ooypm2vdlhky1vom.png" alt="Alt Memory"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  SpringBoot based Microservice (similar load)
&lt;/h3&gt;

&lt;h4&gt;
  
  
  CPU Utilisation
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YMByvEo7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/umr17eayquwzegkh1vp8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YMByvEo7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/umr17eayquwzegkh1vp8.png" alt="Alt CPU"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Memory Utilisation
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xRniAqvv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/yw6u9yvckhii67zqy6sk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xRniAqvv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/yw6u9yvckhii67zqy6sk.png" alt="Alt Memory"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h5&gt;
  
  
  The resource requirement for Java application is 6 times+ more than NodeJS application, so is the monthly AWS bill.
&lt;/h5&gt;

&lt;p&gt;I used streaming feature, consuming one message at a time to keep it simple. Batch processing requires extra care and love. &lt;br&gt;
Throughput can be increased by having more partitions. &lt;/p&gt;

&lt;h4&gt;
  
  
  Following are some of the concerns and my response
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;KafkaJS may not be reliable in long run &lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;KafkaJS usage is steadily increasing and they have got a very supportive developers and community. It is less likely to go away in near future.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;There are few open issues in the Library&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;There are open issues in all well established technologies that includes Java and Springboot. This cannot be the ground to reject the proposal. It is proved in POC that the functionality we needed works fine. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;Does KafkaJS support particular version and implementation of Kafka that we are using?&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;This was proved in POC &lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;Is Consumer/Producer Rebalancing supported?&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;When one consumer/producer goes down, another processor should attach itself to the partition and consume/produce the messages. This was proved as part of POC&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;Does it recover from broker going down and another instance coming up?&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;When one of the brokers goes down, consumer application should be able to reestablish the connection with new instance. This was proved in POC.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To prove that KafkaJS library is good enough, I prepared demo consumer/producer microservices and ran those over 3 to 4 days. These services processed thousands of messages in this time without dropping a single message in all failure situations. &lt;/p&gt;

&lt;p&gt;Finally, the POC helped to make the way for KafkaJS in our tech stack. Nevertheless, I really appreciate my team and all for raising concerns and completing POC more convincingly.  &lt;/p&gt;

&lt;p&gt;At the end, I also believe that however much good are the platform and technology, it is up to a developer how he/she writes the code and take care of corner cases. Development cannot be always plug n play :). &lt;/p&gt;

&lt;p&gt;Refer following links for more information on KafkaJS&lt;br&gt;
&lt;a href="https://kafka.js.org/docs/getting-started"&gt;https://kafka.js.org/docs/getting-started&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/tulios/kafkajs"&gt;https://github.com/tulios/kafkajs&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.npmjs.com/package/kafkajs"&gt;https://www.npmjs.com/package/kafkajs&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>java</category>
      <category>kafka</category>
      <category>kafkajs</category>
    </item>
    <item>
      <title>Microservices - Exception Handling - Circuit Breaker Pattern</title>
      <dc:creator>Yogesh Manware</dc:creator>
      <pubDate>Wed, 24 Jun 2020 02:01:00 +0000</pubDate>
      <link>https://dev.to/ynmanware/exception-handling-circuit-breaker-pattern-in-microservices-3moa</link>
      <guid>https://dev.to/ynmanware/exception-handling-circuit-breaker-pattern-in-microservices-3moa</guid>
      <description>&lt;p&gt;I have been working on Microservices for years. I am writing this post to share my experience and the best practices around exception handling from my perspective. Note that it may not be perfect and can be improved. &lt;/p&gt;

&lt;p&gt;I am working on an application that contains many microservices (&amp;gt;100). It is an event driven architecture. An event is processed by more than one processor before it reaches to Store(like Elastic Search) or other consumer microservices&lt;/p&gt;

&lt;p&gt;One microservice receives event from multiple sources and passes it to AWS Lambda Functions based on the type of event. There could be more Lambda Functions or microservices on the way that transform or enrich the event. &lt;/p&gt;

&lt;p&gt;Here is a small part of my Architecture&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4qw2NKNy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/121ch04y3w9hvoyds5cj.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4qw2NKNy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/121ch04y3w9hvoyds5cj.jpg" alt="Alt MS Design"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Microservices has many advantages but it has few caveats as well. Exception handling is one of those. If exceptions are not handled properly, you might end up dropping messages in production. Operation cost can be higher than the development cost. Managing such applications in the production is a nightmare. &lt;/p&gt;

&lt;p&gt;Following is the high level design that I suggested and implemented in most of the microservices I implemented. &lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--pYxLy3cG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/mkuil5l8bj072gaspuil.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pYxLy3cG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/mkuil5l8bj072gaspuil.jpg" alt="Alt Circuit Breaker Patter"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It is important to make sure that microservice should NOT consume next event if it knows it will be unable to process it. The microservice should retry, wait, recover, raise alert if required. AWS Lambda re-processes the event if function throws an error. I have leveraged this feature in some of the exception handling scenarios. It is crucial for each Microservice to have clear documentation that involves following information along with other details&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;All possible exceptions&lt;/li&gt;
&lt;li&gt;Happy flow logs&lt;/li&gt;
&lt;li&gt;Errors and explanation in detail &lt;/li&gt;
&lt;li&gt;Type of errors - Functional / Recoverable / Non-Recoverable / Recoverable on retries (restart)&lt;/li&gt;
&lt;li&gt;When to set an Alert&lt;/li&gt;
&lt;li&gt;Memory and CPU utilisation (low/normal/worst)&lt;/li&gt;
&lt;li&gt;Add metrics for each type of error &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you have these details in place, supporting and monitoring application in production would be effective and recovery would be quicker. &lt;/p&gt;

</description>
      <category>design</category>
      <category>microservices</category>
      <category>exceptionhandling</category>
    </item>
    <item>
      <title>Compressing and Decompressing Messages (Java/NodeJs) while working with AWS Kinesis</title>
      <dc:creator>Yogesh Manware</dc:creator>
      <pubDate>Tue, 23 Jun 2020 23:56:50 +0000</pubDate>
      <link>https://dev.to/ynmanware/compressing-and-decompressing-messages-java-nodejs-while-working-with-aws-kinesis-4nn7</link>
      <guid>https://dev.to/ynmanware/compressing-and-decompressing-messages-java-nodejs-while-working-with-aws-kinesis-4nn7</guid>
      <description>&lt;p&gt;We use AWS kinesis stream for event sourcing. AWS Kinesis has a limit of 1MB. With this restriction and combination of Java and NodeJS based microservices, we needed a way to compress and decompress the message across platforms. NodeJs and Java has inbuilt support for Compression and Decompression. Both platform use Gzip format.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xvneErdn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/u41920fdamkx8jjxvaqs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xvneErdn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/u41920fdamkx8jjxvaqs.png" alt="Alt Observation for JSON messages"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Following are the examples in Java and NodeJs. It is possible to compress in Java, decompress in NodeJs and vice versa.&lt;/p&gt;

&lt;h1&gt;
  
  
  Compress and decompress in Java
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStreamReader;
import java.util.Base64;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

public class GzipUtil {

    private static final String payload = "Compressing messages and decompressing messages";

    public static void main(String[] args) throws Exception {
        String encodedStr = compress(payload);
        System.out.println("Compressed String: " + encodedStr);
        String decodedStr = decompress(encodedStr);
        System.out.println("Decompressed String: " + decodedStr);
    }

    public static String decompress(String str) throws Exception {
        GZIPInputStream gis = new GZIPInputStream(new ByteArrayInputStream(Base64.getDecoder().decode(str)));
        BufferedReader bf = new BufferedReader(new InputStreamReader(gis, "UTF-8"));
        String outStr = "";
        String line;
        while ((line=bf.readLine())!=null) {
            outStr += line;
        }
        System.out.println("Decompressed String length : " + outStr.length());
        return outStr;
    }

    public static String compress(String str) throws Exception {
        System.out.println("Original String Length : " + str.length());
        ByteArrayOutputStream obj=new ByteArrayOutputStream();
        GZIPOutputStream gzip = new GZIPOutputStream(obj);
        gzip.write(str.getBytes("UTF-8"));
        gzip.close();
        String base64Encoded = Base64.getEncoder().encodeToString(obj.toByteArray());
        System.out.println("Compressed String length : " + base64Encoded.length());
        return base64Encoded;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Compress and Decompress in NodeJS&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const zlib = require('zlib'); //inbuilt in NodeJs
const sizeof = require('object-sizeof'); //npm

const input = "Compressing messages and decompressing messages";

(async function () {
    // compress
    console.info(`String size: ${sizeof(input)}`);
    let buffer = await zlib.deflateSync(input);
    const compressedString = buffer.toString('base64');
    console.info(`compressed String size: ${sizeof(compressedString)}`);
    // decompress
    buffer = await zlib.unzipSync(Buffer.from(compressedString, 'base64'));
    console.info(`decoded string : ${buffer.toString()}`);
})()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>aws</category>
    </item>
    <item>
      <title>Real Time Event Processing with AWS Kinesis + Lambda + ElasticSearch</title>
      <dc:creator>Yogesh Manware</dc:creator>
      <pubDate>Mon, 22 Jun 2020 13:19:14 +0000</pubDate>
      <link>https://dev.to/ynmanware/real-time-event-processing-with-aws-kinesis-lambda-elasticsearch-5fga</link>
      <guid>https://dev.to/ynmanware/real-time-event-processing-with-aws-kinesis-lambda-elasticsearch-5fga</guid>
      <description>&lt;p&gt;I am using AWS kinesis, Lambda (NodeJs) and ElasticSearch in my Architecture. Each Kinesis Shard has per hour pricing. The requirement is to process millions of events per hour. It is an event driven architecture and expectation is to have a near real time processing.&lt;br&gt;
While AWS kinesis has an excellent throughput, Elastic Search insert/update operation can be time consuming if you have considerable number of fields to be indexed.&lt;/p&gt;
&lt;h2&gt;
  
  
  Few Facts
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;One Kinesis Stream Shard provides a capacity of 1MB/sec data input and 2MB/sec data output. One shard can support up to 1000 PUT records per second. &lt;a href="https://docs.aws.amazon.com/streams/latest/dev/service-sizes-and-limits.html"&gt;Kinesis Data Streams Quotas and Limits&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.elastic.co/guide/en/elasticsearch/reference/master/tune-for-indexing-speed.html#multiple-workers-threads"&gt;Elastic Search documentation advises to use multithreading&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/aes-limits.html"&gt;AWS Elastic Search Limitation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  High Level Architecture
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7xrBE-Qs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/27or72s8hq7fx12wvwoa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7xrBE-Qs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/27or72s8hq7fx12wvwoa.png" alt="Alt Design"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are N number of shards and a high capacity Elastic Search Cluster. One Kinesis Shard can trigger one lambda at any point of time.  &lt;/p&gt;

&lt;p&gt;Using concurrency and bulk update, real time processing can be achieved with optimum number of Kinesis Stream Shards.   &lt;/p&gt;

&lt;p&gt;I designed a Lambda to consume batch of 50 events at a time. The size of one event is between 5kb and 1MB. It inserts 50 records concurrently. &lt;/p&gt;

&lt;p&gt;Note that concurrency, batch size and bulk record size needs to be tweaked based on the event size and Elastic Search Cluster's capacity/limits. You might need to review the memory requirement for Lambda based on concurrency, batch/event size. &lt;/p&gt;

&lt;p&gt;Following code snippet is an example of concurrent processing in NodeJs using Async. &lt;/p&gt;

&lt;p&gt;It is processing 100 events, in the group of 50 at a time. &lt;br&gt;
Assuming it takes 1 seconds to insert one record in Elastic Search, It inserts all 100 records in ~3 seconds.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const async = require('async');

// can process 50 events at any point of time
const MAX_CONCURRENCY = (process.env &amp;amp;&amp;amp; process.env.MAX_CONCURRENCY) || 50;

const data = new Map();

// create dummy events
for (let i = 0; i &amp;lt;= 100; i++) {
    data.set(`EVT00${i}`, [{a: `value ${i}`}, {a: `value 2a ${i}`}]);
}

async function process(payload) {
    const startTime = new Date();
    const functions = [];
    payload.forEach((feeds, id) =&amp;gt; {
        console.log(`processing the feed for ${id}`);
        functions.push(processEvent.bind(null, feeds, id));
    });
    const result = await async.parallelLimit(functions, MAX_CONCURRENCY);
    console.info('processing is complete');
    const filteredResult = result.filter(element =&amp;gt; element.data).map(element =&amp;gt; element.data);
    console.info(JSON.stringify(filteredResult, null, 2));
    console.log(`Total time taken ${new Date() - startTime} millis`);
}

async function processEvent(arrayOfFeeds, id) {
    return new Promise((resolve, reject) =&amp;gt; {
        // simulates //Elastic Search API call for each group of messages
        setTimeout(() =&amp;gt; {
            console.log(`processing ${id} : ${JSON.stringify(arrayOfFeeds)}`)
            resolve({'data': {a: `aggregated value - must be an es update record ${id}`}});
        }, 1000);
    });
}

setImmediate(() =&amp;gt; process(data));

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



</description>
      <category>kinesis</category>
      <category>elasticsearch</category>
      <category>lambda</category>
    </item>
  </channel>
</rss>
