<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Deepal Jayasekara on Medium]]></title>
        <description><![CDATA[Stories by Deepal Jayasekara on Medium]]></description>
        <link>https://medium.com/@dpjayasekara?source=rss-f767215a3aee------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*HeHhoWkpSOTb--MKY7q-pQ@2x.jpeg</url>
            <title>Stories by Deepal Jayasekara on Medium</title>
            <link>https://medium.com/@dpjayasekara?source=rss-f767215a3aee------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Fri, 17 Jul 2026 03:32:12 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@dpjayasekara/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[How my Kafka provider pulled the rug under me!]]></title>
            <link>https://blog.insiderattack.net/how-my-kafka-provider-pulled-the-rug-under-me-e10c7a95e572?source=rss-f767215a3aee------2</link>
            <guid isPermaLink="false">https://medium.com/p/e10c7a95e572</guid>
            <category><![CDATA[nodejs]]></category>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[kafka]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[software-engineering]]></category>
            <dc:creator><![CDATA[Deepal Jayasekara]]></dc:creator>
            <pubDate>Sat, 10 May 2025 15:11:36 GMT</pubDate>
            <atom:updated>2025-05-18T22:17:40.662Z</atom:updated>
            <content:encoded><![CDATA[<h4>And what you can also learn from it</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*_XxUsz5JVonp3V05aqm9uA.png" /><figcaption>Courtesy of ChatGPT</figcaption></figure><p>It’s been a long time since this happened, the details are starting to blur.</p><p>So I’m writing it down — partly to remember it myself, partly so you might probably learn a thing or two.</p><blockquote><strong><em>Disclaimer: </em></strong><em>I recreated the problem on my machine so that I can show you screenshots and code examples, because I don’t have have any evidence from the original fault – although, they should be fairly identical.</em></blockquote><h4>Prologue</h4><p>Like most faults in software systems, this one started with something simple going wrong — but it still managed to hand me a few hard-earned lessons.</p><p>If you’ve worked with Kafka in Node.js, you’ve probably heard of a library called kafka-node. Back in its prime, it was one of the go-to Kafka client for Node.js. Even at the time of this writing, it still sees over 100k downloads a week, despite being a bit crusty around the edges.</p><p>My API running on Kubernetes that also produces messages to Kafka— was built with kafka-node. kafka-node had been losing popularity for a while with better-maintained alternatives becoming available. But, why touch what isn’t (obviously) broken, right? 🤷</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/640/0*PEdAyPC_esyLE5YR.gif" /></figure><h4>The Curious Case of the Grumpy Pods</h4><p>It was a quiet Friday afternoon — naturally, the perfect time for something weird to happen.</p><p>Two pods from my service were failing to connect to the Kafka cluster.</p><p>The rest? Totally fine and happily producing messages. Not ideal, but not a fire either.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/695/1*7o_HJ-2KzbQYiFyoH2mPDA.png" /></figure><p>This wasn’t a big deal, because the Kafka producer connectivity status had been linked to the service’s readiness probe. Therefore, the problematic pods weren’t receiving any traffic due to the readiness probe failure.</p><p>Therefore, the API was up and handling traffic.</p><h4>The Meltdown</h4><p>Sunday.</p><p>The service is completely down — <em>no</em> pods are ready. Zero. Zilch. The thing that was left ignored on Friday? Yeah, that just exploded.</p><p>Turns out, it had been a ticking time bomb quietly counting down all weekend.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/695/1*nY9Zup2ZNDY06ba00a_3RA.png" /></figure><p>Here’s what’s happened.</p><p>On Friday, something changed that broke new Kafka client connections. The two pods that failed were fresh ones — spun up <em>after</em> the unknown change. The rest, the ones that were already connected to Kafka, kept working fine.</p><p>But here’s the catch.</p><p>Kubernetes doesn’t care if a pod is healthy and ready right now. It’ll kill and replace pods for all kinds of reasons — autoscaling, resource pressure, you name it. And that’s exactly what happened. Over time, the working pods got cycled out. Their replacements couldn’t connect to Kafka… and boom, no more ready pods.</p><h4>Debugging the Mystery: VSCode with a hint of Wireshark</h4><p>Application logs weren’t helpful. All I saw in the logs were loads of messages with text: client disconnected.</p><p>There weren’t any debug logs of the service, due to performance and cost concerns. But, of course, I needed more than a vague client disconnected message to figure out what was going wrong.</p><p>So, I wanted to reproduce this issue locally and debug on my IDE. In my local machine, I spun up my application with debug logging, pointing to the Dev Kafka cluster which was also indicating the issue.</p><p>Then the logs provided some useful insights.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ZH19C7AO8QLmPs9pkFr_NA.png" /></figure><p>It appears that the ApiVersions request sent by my Kafka client is failing because the connection is closed.</p><p><strong>Side note</strong> — Lots of different types of messages are sent between a Kafka client and a broker. To ensure the client understand what the broker is sending and vice versa, the client and broker has to agree on the ‘shape’ of each message type. ApiVersions request is the mechanism used for this version negotiation.</p><p>I checked the supported Kafka API versions by my client vs on the broker. They seemed to be compatible.</p><blockquote>Throughout this investigation, my Kafka provider kept on insisting they haven’t made <strong>any</strong> changes on their side at all.</blockquote><p>I ran my application on debug mode again and played around to see why the ApiVersions request is actually failing.</p><p>At the same time, I opened Wireshark to sniff the traffic between my Kafka client and the broker.</p><p>What I saw was unexpected.</p><h4>Light at the end of the tunnel</h4><p>When a Kafka producer client connects to a broker, the following sequence of actions happen in the indicated order. The interactions highlighted in green with solid border are the parts of the Kafka Protocol itself.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/323/1*MMr5NE_H-tu-Nl3jGARvkw.png" /></figure><p>Wireshark told an interesting story from the traffic between my client and the bootstrap server.</p><p>TLS handshake was failing right after the client sent the <strong>Client Hello</strong> message. The bootstrap server acknowledges it but then responded with a TCP packet with the <strong>RST (reset)</strong> flag, essentially slamming the door shut before the Kafka protocol even got a chance to speak.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*xYN5TfkW-GEUHP3faLATIg.png" /></figure><p>So it wasn’t the ApiVersions request that was failing—the connection was already dead before it got that far.</p><p>Now the real question became: <em>what was wrong with that Client Hello?</em></p><h4>Alternatives</h4><p>Good progress debugging so far. But I still don’t know what exactly is wrong with the Client Hello message.</p><p>It appeared that only the producers written in kafka-node were affected by this issue. So I wanted to check what other clients do right that kafka-node doesn’t.</p><p>I wrote a simple Kafka producer script using KafkaJS.</p><pre>import { Kafka } from &#39;kafkajs&#39;;<br>import config from &#39;./config.json&#39; assert { type: &#39;json&#39; };<br><br>const kafka = new Kafka({<br>    clientId: config.clientId,<br>    brokers: [config.bootstrapServers],<br>    ssl: true,<br>    sasl: {<br>        mechanism: config.saslMechanisms,<br>        username: config.saslUsername,<br>        password: config.saslPassword<br>    }<br>});<br><br>const producer = kafka.producer();<br><br>(async () =&gt; {<br>    await producer.connect();<br>    await producer.send({<br>        topic: &#39;mytopic&#39;,<br>        messages: [{ key: &#39;key1&#39;, value: &#39;hello world&#39; }]<br>    });<br>    console.log(&#39;message succesfully produced&#39;);<br>    await producer.disconnect();<br>})();</pre><p>I ran the script, with my friend Wireshark watching the packets.</p><p>Unsurprisingly, it worked fine.</p><p>And in the Wireshark capture, I saw an interesting extra piece of information in the Client Hello message, which I didn’t see with kafka-node.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*RjQhgaDyfhc885_TtxYjLw.png" /></figure><p>KafkaJS appears to be using TLS <strong>SNI (Server Name Indication)</strong> extension, where kafka-node doesn’t by default.</p><blockquote>Both kafka-node and KafkaJS use NodeJS tls package for secure TCP connections and tls.connect function itself doesn’t enable SNI by default. However, KafkaJS adds the SNI extension for all secure connections as implemented <a href="https://github.com/tulios/kafkajs/pull/512">here</a>.</blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/1023/1*Np45NEZKI3rqf2YPIvqfxw.png" /></figure><p>In short, Server Name Indication (SNI) is an extension to the TLS protocol that lets a client tell the server which hostname it’s trying to connect at the start of the TLS handshake. This is super handy for servers hosting multiple domains on the same IP address — like shared hosting — because it lets the server present the right TLS certificate for the requested domain.</p><blockquote>If you’d like to learn more, there’s a very nice explaination about SNI on Cloudflare blog here: <a href="https://www.cloudflare.com/en-gb/learning/ssl/what-is-sni/">https://www.cloudflare.com/en-gb/learning/ssl/what-is-sni/</a></blockquote><p>kafka-node client been working fine before, which means it was able to establish a connection without SNI. But all of a sudden it can’t?</p><p>My Kafka provider seems to be pretty convinced that they didn’t touch anything on their side though.</p><p>Time to go back to them with the new evidence about the SNI change.</p><p>“Hey, did you make any changes that would make SNI mandatory?”?</p><h4>The Confession (Sort Of)</h4><p>“Ah, apparently our network team had made a change to make SNI mandatory. But you shouldn’t be affected as long as you are using a ‘supported’ client”.</p><p>Said them.</p><p>Finally, with irrefutable evidence, they relented.</p><p>They had chosen to enforce SNI on all connections based on the assumption that all customers use ‘supported clients’ by their own definition, which is funny, because they hadn’t listed a ‘supported’ Kafka client for NodeJS on their website.</p><p>No heads-up, no changelog, no notice. Just a silent infrastructure change that quietly broke any client not sending SNI.</p><h4>Fix Now, Refactor Later</h4><p>So, what options did I have to fix the issue?</p><p>kafka-node does has a way of enabling SNI. It’s just not done by default.</p><pre>import { KafkaClient } from &#39;kafka-node&#39;;<br><br>const client = new KafkaClient({<br>    kafkaHost: &quot;mykafkahost.example.com:9092&quot;,<br>    sslOptions: {<br>        servername: &quot;mykafkahost.example.com&quot;<br>    }<br>});</pre><p>Providing sslOptions.servername will enable SNI extension when the client connecting to the bootstrap server.</p><p>But there’s a catch.</p><p>Some Kafka providers have bootstrap servers that only serves the purpose of allowing the Kafka clients to discover the hostnames of actual data-bearing brokers via a Metadata Request. Hardcoding SNI to the bootstrap server’s hostname might not work in that kind of a scenario.</p><p>So what did I do?</p><p>I hot-swapped kafka-node with <strong>KafkaJS</strong>, which not only solved the issue but gave us a more modern, better-maintained client at the time in the process.</p><h4>The Verdict: Who Really Pulled the Rug?</h4><p>Is SNI a mandatory requirement for Kafka itself?</p><p>No. It’s because SNI is not a part of Kaka protocol itself. It is a lower-level network feature so Kafka protocol doesn’t care about it.</p><p>So, why am I saying that “they pulled the rug under me”?</p><p>My opinion is — A drastic change like this should be communicated upfront. This is because,</p><ul><li>They don’t have their own well-supported SDK that they advise the customers to use. Nor do they have listed a ‘supported’ Kafka library for NodeJS.</li><li>Yes, SNI has legitimate use cases, especially in multi-tenant environments. But I haven’t seen any requirement that Kafka libraries has to support SNI by default.</li></ul><p>Is my Kafka provider 100% at fault?</p><p>No. I don’t think so either.</p><p>kafka-node had become abandonware, but there wasn’t a strong reason to move on from it because it just worked and it didn’t have any alarming bugs/vulnerabilities.</p><p>Software vendors do not have unlimited resources to support every possible library on the planet. When popularity moves from one library to another, they do too. They abandon abandonware too.</p><h4>P.S.</h4><p>Talking about abandonware, the word around the town is that KafkaJS is no longer maintained too.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*3jTxiNHLZaja8M3ZF7JuUg.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/531/1*m9TkJvz_nsPIjOOWoIt8Jw.png" /></figure><p>So, who knows when someone pulls the rug under KafkaJS soon?</p><p>We need to be constantly on the move.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=e10c7a95e572" width="1" height="1" alt=""><hr><p><a href="https://blog.insiderattack.net/how-my-kafka-provider-pulled-the-rug-under-me-e10c7a95e572">How my Kafka provider pulled the rug under me!</a> was originally published in <a href="https://blog.insiderattack.net">Deepal’s Blog</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[The Journeyman’s Guide to Lua Unit Testing]]></title>
            <link>https://blog.insiderattack.net/the-journeymans-guide-to-lua-unit-testing-41642825314a?source=rss-f767215a3aee------2</link>
            <guid isPermaLink="false">https://medium.com/p/41642825314a</guid>
            <category><![CDATA[software-testing]]></category>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[lua]]></category>
            <category><![CDATA[nginx]]></category>
            <category><![CDATA[testing]]></category>
            <dc:creator><![CDATA[Deepal Jayasekara]]></dc:creator>
            <pubDate>Sat, 16 Jul 2022 22:33:27 GMT</pubDate>
            <atom:updated>2022-07-16T22:33:27.345Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*madJoHqxZxeqygkNaPEeLQ.jpeg" /><figcaption>Background Image Courtesy: <a href="https://www.deviantart.com/sledmine/art/Lua-Scripting-Space-Wallpaper-831277375">https://www.deviantart.com/sledmine/art/Lua-Scripting-Space-Wallpaper-831277375</a></figcaption></figure><p>I had the pleasure of working with Lua with OpenResty a while back. Albeit numerous testing libraries/frameworks being available for Lua unit testing I faced a few challenges to learn how to set up a dockerised unit testing set up for my Lua scripts. I wrote this guide based on what I learned, in case it might be useful for someone else who is new to Lua, or even me down the road.</p><h4>Framework of Choice</h4><p>Out of the available Lua testing frameworks including LuaUnit, I found <a href="https://olivinelabs.com/busted/">busted</a> testing framework easy to use and feature-rich. You can install busted using luarocks — Lua package manager, but in this article, I will be using a dockerised setup using <a href="https://hub.docker.com/r/imega/busted">imega/busted docker image</a>.</p><p>busted internally uses <a href="https://github.com/Olivine-Labs/luassert">luassert</a> for assertions, which is from the same developer as busted itself. If you want to learn more about different assertions available, I recommend referring to luaassert documentation directly.</p><h4>File Structure for Tests</h4><p>By default, busted identifies the files with _spec.lua suffix as test files, but it can be configured to your chosen pattern. For this example, I have 3 simple modules, with the corresponding test files sitting at the same level. My file structure would look like this:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/486/1*SzNAP2oCxnjux3tf7yO6DA.png" /></figure><p>You can find the complete example here on GitHub: <a href="https://github.com/deepal/lua-testing-sample">https://github.com/deepal/lua-testing-sample</a></p><h4>Docker Setup</h4><p>My docker-compose.yml file has one service called test which will run the unit tests inside a imega/busted docker container. imega/busted docker image has busted command pre-installed, which we can use to run the tests.</p><p>The content of the docker-compose.yml file looks like this:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/63b06d2bdc1d42b6e9d0e7c9d4f9f303/href">https://medium.com/media/63b06d2bdc1d42b6e9d0e7c9d4f9f303/href</a></iframe><p>It is important to set the LUA_PATH environment variable such that the Lua modules are resolved properly. (You can learn more about LUA_PATH in the <a href="https://www.lua.org/pil/8.1.html">Lua docs</a>.)</p><h4>Writing a simple unit test</h4><p>My sum.lua module contains a simple function which returns the sum of the given two numbers.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/c38fb4d91c5ad28315c5534537f123c7/href">https://medium.com/media/c38fb4d91c5ad28315c5534537f123c7/href</a></iframe><p>We can test this function easily by writing the following BDD-style test. describe, it, assert are global functions provided by busted framework, therefore there’s no need to explicitly importing those.</p><p>Following is the corresponding unit test file (sum_spec.lua) for my sum.lua module.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/71abfc2b895038183db7a387f3e3594c/href">https://medium.com/media/71abfc2b895038183db7a387f3e3594c/href</a></iframe><p>Easy-peasy.</p><h4>Stubbing/Spying functions</h4><p>Stubbing and Spying on Lua functions is also fairly straightforward with busted. It provides a stub method to create stubs or stub existing functions, and spy.on, spy.new functions to create spies.</p><p>For the sake of not repeating the documentation, I wouldn’t go into the details of spying. You can have a look at how to spy on functions from the <a href="https://olivinelabs.com/busted/#spies-mocks-stubs">official documentation</a> at your leisure. But let’s look at how to create stubs with busted as it will be useful in the next section as well.</p><p>The following is my check_env.lua module. It’s a simple function which returns true if RUN_SUM environment variable is set, and false otherwise.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/f4544da20b6a6b1dc4c51ac6c43503d7/href">https://medium.com/media/f4544da20b6a6b1dc4c51ac6c43503d7/href</a></iframe><p>To test both branches of this function, we need to stub os.getenv and manipulate its behaviour. In the following test file, we stub os.getenv before running each test, which we then modify the behaviour of in the tests. It’s safer if we revert the stub to its original state after running each test by using after_each function.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/7a9b8d56f97b2b6059823f885a8174a9/href">https://medium.com/media/7a9b8d56f97b2b6059823f885a8174a9/href</a></iframe><blockquote>Similar to <em>describe</em> and <em>it</em>, <em>before_each</em> and <em>after_each</em> functions are also global functions provided by <em>busted</em>.</blockquote><p>In the above test file, we have two tests, where the first one would assert check_env function’s behaviour when os.getenv(&quot;RUN_SUM&quot;) returns “1”, and the second test when os.getenv(&quot;RUN_SUM&quot;) returns nil.</p><h4>Stubbing imported modules</h4><p>Stubbing dependencies is important when test files which have external module imports using require. Let’s look out our app.lua module which depends on our previously discussed lib.check_env and lib.sum modules.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/c1f3eea9246994b45ce9f35260cf0f4e/href">https://medium.com/media/c1f3eea9246994b45ce9f35260cf0f4e/href</a></iframe><p>app.run function internally calls both check_env() and sum() functions we previously discussed. Therefore, we will have to test different flows of app.runwhen the behaviours of check_env() and sum() changes.</p><p>Because lib.check_env and lib.sum are externally imported modules, we cannot simply stub them the same way we did in the previous section. This is where Lua’s package.preload feature comes to the rescue!</p><p>package.preload is a <a href="https://www.lua.org/pil/2.5.html">table</a> which Lua’s require function first lookup in when it’s called (<a href="https://www.lua.org/manual/5.1/manual.html#pdf-require">official docs</a>). Therefore, we can use package.preload to pre-load a stubbed module, which require will then use instead of the actual module. Let’s look at our test file app_spec.lua to see how we can use package.preload to stub modules. For simplicity of the example, let’s stub check_env the module only in this example.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/36990a1206f0c8d5e46932fc73239f28/href">https://medium.com/media/36990a1206f0c8d5e46932fc73239f28/href</a></iframe><blockquote>setup and the teardown global functions provided by busted can be used to define functions that runs at the start and the end of the current test suite respectively.</blockquote><p>At the setup stage, we preload lib.check_env module with a stub. Once this is done, any require &quot;lib.check_env&quot; operations will load this stub module instead of the actual lib.check_env module. However, we need to remove this module from the pre-loaded table after the current test suite to avoid leaking it to the other test suites. This can be done by setting package.preload[&quot;lib.check_env&quot;] = nil at the teardown stage.</p><h4>Running Tests</h4><p>We now have everything set up. A simple docker-compose command will start the test suite.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*y2vbmsT3g4KWeBHNbqIxWg.png" /></figure><p>If you have any questions, don’t hesitate to comment. I hope this was useful in some way, and thanks for reading.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=41642825314a" width="1" height="1" alt=""><hr><p><a href="https://blog.insiderattack.net/the-journeymans-guide-to-lua-unit-testing-41642825314a">The Journeyman’s Guide to Lua Unit Testing</a> was originally published in <a href="https://blog.insiderattack.net">Deepal’s Blog</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Why you should avoid Date.now() to measure time durations]]></title>
            <link>https://blog.insiderattack.net/how-not-to-measure-time-in-programming-11089d546180?source=rss-f767215a3aee------2</link>
            <guid isPermaLink="false">https://medium.com/p/11089d546180</guid>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[nodejs]]></category>
            <category><![CDATA[software-engineering]]></category>
            <category><![CDATA[javascript]]></category>
            <dc:creator><![CDATA[Deepal Jayasekara]]></dc:creator>
            <pubDate>Sat, 12 Mar 2022 00:02:54 GMT</pubDate>
            <atom:updated>2022-03-18T09:21:00.356Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*-MiTUvB0NHZqy-f6q5Mg3A.jpeg" /><figcaption>Background Image Courtesy: Photo by <a href="https://unsplash.com/@bcampbell?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Brooke Campbell</a> on <a href="https://unsplash.com/s/photos/clock?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><h4>Advance NodeJS— Part 6</h4><p>If you fly between two airports that are in two different time zones, would you calculate the time it took for you to fly, by checking the difference between the ‘wall clock’ times of either airport?</p><p>If your answer is ‘no’, then let me explain why you shouldn’t do the same in your code, using a little but a very interesting experiment.</p><p>This article is the 6th article of my <strong>Advanced NodeJS </strong>Series which is a sequel to <a href="https://blog.insiderattack.net/event-loop-and-the-big-picture-nodejs-event-loop-part-1-1cb67a182810">my series on Node.js Event Loop</a>. You can find the other articles of the <strong>Advanced NodeJS </strong>series below:</p><h3>Post Series Roadmap</h3><ul><li><a href="https://blog.insiderattack.net/crossing-the-js-c-boundary-advanced-nodejs-internals-part-1-cb52957758d8">Crossing the JS/C++ Boundary</a></li><li>Deep Dive into Worker Threads in Node.js</li><li><a href="https://blog.insiderattack.net/understanding-async-resources-with-async-hooks-3416de574f30">Understanding Async Resources with Async Hooks</a></li><li><a href="https://blog.insiderattack.net/a-visual-guide-to-nodejs-streams-9d2d594a9bf5">A Visual Guide to NodeJS Streams</a></li><li><a href="https://blog.insiderattack.net/nodejs-streams-in-practice-980b3cdf4511">NodeJS Streams in Practice</a></li><li><a href="https://blog.insiderattack.net/how-not-to-measure-time-in-programming-11089d546180"><strong>Why you should avoid Date.now() to measure time durations (This article)</strong></a></li></ul><blockquote>The examples in this article are in JavaScript/Node.js, but the concepts described are valid regardless of the language being used.</blockquote><h3>Clocks, Time and Measuring Time</h3><p>I’ve seen countless times where developers (including myself at some point) measure the time spans for metrics and logging using date-time functions. These functions use so called ‘time-of-day clock’, and in JavaScript the usual suspect that falls under this category is Date.now() (or Date constructor). Using Date.now(), this is the code one of those developers would write to measure time duration.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/b22d7d2416de949826421d043a7c66c5/href">https://medium.com/media/b22d7d2416de949826421d043a7c66c5/href</a></iframe><p>This is a nice little code that works, until it doesn’t.</p><p>Before delving into our experiment and explaining why the above wouldn’t work, it’s important to know a few key details about time, how it is measured and maintained by the operating system.</p><ul><li>Not all the clocks across all computers run at the same speed, some may run faster or slower comparatively and eventually may <strong>drift apart </strong>from each other (like some of our wall clocks sometimes do).</li><li>This ‘<strong>clock drift</strong>’ can cause various problems in distributed systems.</li><li><strong>NTP (Network Time Protocol)</strong>, is one of the network protocols that is used to fix this problem, by synchronising the clock of a computer with that of a ‘time server’ that usually has accurate time.</li><li>NTP clients that are usually shipped with the operating system may periodically receive the time from a configured time server, and adjust the local system clock.</li><li>If the NTP client finds that the local time is drifted apart from the time server’s time, it may choose to ‘correct’ it depending on how much the drift is.</li><li>This ‘correction’ of time may result in the system clock suddenly moving forward or backwards.</li><li>The functions that use ‘time-of-day’ clock, such as JavaScript Date.now() returns the current system time, which could be affected by NTP corrections.</li></ul><p>Now you may probably understand why I said the <strong>snippet 1 </strong>wouldn’t work. To see it and understand it clearly, let’s move on to our little experiment.</p><h3>Experiment 1 — How Not To Measure Time</h3><p>In this experiment, we are going to measure the time it took to run doSomething() function. But, we are going to simulate an NTP time correction by deliberately setting a fake time in the beginning and correcting the time using NTP while doSomething() function is being executed.</p><p><em>You can find the complete implementation of the example at the end of the article. This example only works on macOS as it relies on a few macOS shell commands/utilities, but you should be able to easily modify it to work on Linux.</em></p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/f3cdddddf20214d0e116a07fc787b88b/href">https://medium.com/media/f3cdddddf20214d0e116a07fc787b88b/href</a></iframe><ul><li>setFakeTime() sets the system clock to <strong>1 min ahead of actual time</strong>. This function uses macOS date command.</li><li>correctTimeNTP() uses the macOS sntp NTP client utility to correct the time by synchronising with the time server time.apple.com.</li><li>doSomething() function simulates a task that takes ~2000ms. We are using setTimeout to simulate this task.</li></ul><p>If you run the above code, it would measure the time doSomething() took using Date.now() and log it to the stdout.……<strong>AND BOY IT’S NEGATIVE</strong>!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*uzfgCs4iMwRLN0M2J8L1Zg.png" /><figcaption>Inaccurate time span measurement with Date.now()</figcaption></figure><p>This is not what a developer would expect at all!</p><p>The numeric value you see here may depend on various factors such as how busy your CPU is, how long did it take for the NTP client to receive time from the time server etc. However, it is fairly obvious that the reason for the ‘negative time duration’ is because the NTP client corrected the clock by moving it backwards (because it was ahead by 1 min in the beginning). Therefore, endTimeToD is an older timestamp than the startTimeToD.</p><p>Though this example is a simulation, this can happen in real life systems due to various reasons (e.g. time server sending an incorrect time for some reason, NTP client refreshing time after not running for a significant time, a human operator manually changing system time, &amp; etc.)</p><p>But the important question is, can we solve this problem? <strong>YES. </strong>And the answer is by using a function that uses a <strong>monotonic clock </strong>rather than a time-of-day clock. Let’s read on.</p><h3>Experiment 2 — How To Measure Time Accurately</h3><p><strong>Monotonic clock</strong> is simply counter that has started from an arbitrary point in the past and moves at the same speed as the system clock. Since this is just a counter, a monotonic timestamp read at a given point in time doesn’t have any use by itself. But the important part is, monotonic clock is not affected by NTP corrections. Therefore, the difference between two monotonic timestamps read at two different points in time will give the accurate time duration between the two points.</p><p>Programming languages usually provide functions for both monotonic and time-of-day clock. In Node.js, the functions that returns monotonic time are:</p><ul><li>process.hrtime.bigint() (process.hrtime() in older NodeJS versions)</li><li>require(&#39;perf_hooks).performance.now()</li></ul><p>Let’s update our experiment to use require(&#39;perf_hooks).performance.now() instead of Date.now(). You can also try out the experiment with process.hrtime.bigint() at your leisure.</p><p>I’ll leave out const { performance } = require(&#39;perf_hooks) part of the following snippets for brevity.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/6e84d1119508e5fb963e1cb4043f801c/href">https://medium.com/media/6e84d1119508e5fb963e1cb4043f801c/href</a></iframe><p>If you run this example, it would log the following output (or similar).</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*azT5yxuNeGbhHXL-yGmO7g.png" /><figcaption>Accurate measurement of time span using monotonic clock</figcaption></figure><p>As you can see, we get an accurate result by using monotonic time.</p><blockquote>The reason for not getting an exact 2000ms is because, setTimeout is subject to certain Event Loop semantics that I’ve explained in <a href="https://blog.insiderattack.net/timers-immediates-and-process-nexttick-nodejs-event-loop-part-2-2c53fd511bb3">previous article</a>.</blockquote><p>Let’s now try to run both experiments in one script, to compare and measure the error of the 1st experiment.</p><h3>Experiment 3 — Comparison</h3><p>In this experiment, we run both 1st and 2nd experiments in a single script. And in addition to that, we log:</p><ul><li>Output of the sntp command that’s executed inside setFakeTime() function.</li><li>The error of the duration calculated using Date.now()</li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/4ade264a028e9dc42f1a8f02882a1975/href">https://medium.com/media/4ade264a028e9dc42f1a8f02882a1975/href</a></iframe><p>If we run the above script, we get the following output:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*W5esQ9p-lQu8UeX3dAbp4g.png" /><figcaption>Time span measured using both time-of-day clock and monotonic clock</figcaption></figure><p>This output is very interesting! We can clearly see the difference between the time duration measured by both approaches. And if you look closely, the ‘<strong>error</strong>’ of the time duration measured using Date.now() (-54.053s) is pretty much the same number NTP client adjusted the time by (-54.053600s), if you ignore the precision difference.</p><p>This clearly indicates that the time durations measured using a time-of-day clock is directly affected by the NTP corrections.</p><blockquote><strong>Isn’t Node.js setTimeout() and setInterval() affected by NTP time corrections?</strong></blockquote><blockquote>Node.js event loop uses uv__hrtime to measure loop time, which underneath uses a monotonic clock. Therefore, setTimeout and setInterval functions are not affected by NTP time corrections.</blockquote><h3>Wrap Up and Recommendations</h3><p>When measuring a time duration is required for monitoring and logging purposes, it’s always expected to be accurate. Using the incorrect function to measure time spans can yield very inaccurate results as we saw throughout our experiments.</p><p>Therefore, always use functions that return monotonic time to measure time durations for metrics and logging.</p><p>The following is the complete code example discussed throughout this article. Note that, you’ll need to run this code example as sudo because the date and sntp commands require elevated privileges to run.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/05ba2de9f39244f9f4e22110d1a86e58/href">https://medium.com/media/05ba2de9f39244f9f4e22110d1a86e58/href</a></iframe><p>I’d also like to mention <a href="https://martin.kleppmann.com/">Dr. Martin Kleppmann</a>’s lecture on <a href="https://www.youtube.com/watch?v=mAyW-4LeXZo">Clock Synchronisation</a> as an additional resource, which was an eye-opener for me.</p><p>I hope this article helped you get a practical understanding on how to accurately measure time in applications. And I thank you for reading.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=11089d546180" width="1" height="1" alt=""><hr><p><a href="https://blog.insiderattack.net/how-not-to-measure-time-in-programming-11089d546180">Why you should avoid Date.now() to measure time durations</a> was originally published in <a href="https://blog.insiderattack.net">Deepal’s Blog</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Atomic Microservices Transactions with MongoDB Transactional Outbox]]></title>
            <link>https://blog.insiderattack.net/atomic-microservices-transactions-with-mongodb-transactional-outbox-1c96e0522e7c?source=rss-f767215a3aee------2</link>
            <guid isPermaLink="false">https://medium.com/p/1c96e0522e7c</guid>
            <category><![CDATA[system-design-interview]]></category>
            <category><![CDATA[software-architecture]]></category>
            <category><![CDATA[database]]></category>
            <category><![CDATA[mongodb]]></category>
            <category><![CDATA[distributed-systems]]></category>
            <dc:creator><![CDATA[Deepal Jayasekara]]></dc:creator>
            <pubDate>Thu, 17 Feb 2022 00:23:54 GMT</pubDate>
            <atom:updated>2022-02-17T00:23:54.439Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*P6QjGN3OhhVWYCGy8BiJ_A.jpeg" /><figcaption>Background Image Courtesy: Photo by <a href="https://unsplash.com/@profwicks?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Ben Wicks</a> on <a href="https://unsplash.com/s/photos/post-box?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><p>One of the drawbacks of the microservices architecture is the difficulty to implement atomic transactions. While this limitation can be overcome by using patterns such as <a href="https://microservices.io/patterns/data/saga.html">Saga</a>, there are certain situations where we can use an alternative approach to solve this problem without having to implement the rather complicated Saga pattern.</p><p>Let’s consider a scenario where we need to dispatch an event when a user verifies their email after signing up. The event will then be consumed by other services for reporting, updating the customer profile on a <a href="https://www.salesforce.com/uk/learning-centre/crm/what-is-crm/">CRM system</a> and sending a customer a welcome email.</p><p>Take a look at the following diagram that describes this kind of setup.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*1Ef3IBWMf3rfDhPJPEuSqg.png" /><figcaption>Figure 1: Application with no atomic microservices transactions</figcaption></figure><p>Updating the User document, and dispatching the event are two operations to two completely different systems, and therefore cannot be performed as a single atomic transaction.</p><p>To make this even clearer, take a look at the following sequence:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/692/1*DTZenEIwYmJxcUX35uZKgA.png" /><figcaption>Figure 2: Error Scenario</figcaption></figure><p>In this scenario, the Application sends an update to the Database which is successful, but it is unable to dispatch the event to the Message Broker. In this situation, the Application has the following choices.</p><p><strong>Retry dispatching the event </strong>— <br>The application can exponentially retry, assuming that it’ll eventually be able to dispatch the message. But it cannot be guaranteed that the message will go through.</p><p><strong>Revert the database change and send an error response </strong>— <br>If the message doesn’t go through, the database change can be reverted and an error can be sent back to the user interface. (Customer can then be given a chance to resend themselves the verification email). But, <em>if the message was indeed received by the message broker, and only the acknowledgement from the broker didn’t reach the application</em>, we’ll end up in a tricky situation where we have dispatched an event but the operation is not reflected on the database.</p><p>The transactional outbox is a pattern that can be used to solve this problem. In this pattern, the Application would perform the update to the database and at the same time insert a document (outgoing message) that describes the operation to a separate ‘outbox’ collection. Since updating the database and inserting an outgoing message both happen on the same database, the two operations can be performed as a single transaction. The messages inserted into the outbox collection can then be used to generate an event, using a separate event dispatcher service. This way, we can guarantee that either updating the DB and creating a message both occurs, or neither occurs.</p><p>In the rest of the article, I’m going to explain how to build this pattern using MongoDB as the data store.</p><h3>With Polled Outbox</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*hU0QWVTQr4rDMYkLbopRHg.png" /><figcaption>Application with atomic microservices transactions using transactional outbox pattern (with polled outbox)</figcaption></figure><p>In this approach, the outbox collection is periodically polled by the Event Dispatcher to see if there are any unsent messages in the outbox. If there are any, those will be fetched by the Event Dispatcher to generate events for the message broker. Once the events are sent to the message broker, those messages can be either deleted from the outbox or can be marked as sent.<br>This architecture has a few advantages as well as some disadvantages.</p><p><strong>Advantages:</strong></p><ul><li>This approach is database agnostic and can be applied with MongoDB or any other relational/non-relational database.</li><li>It’s easy to recover after any downtime in the Event Dispatcher. The Event Dispatcher will only have to start polling and process any outstanding messages in the outbox.</li></ul><p><strong>Disadvantages:</strong></p><ul><li>Event generation from DB operations won’t be in real-time, because the polling only happens periodically.</li><li>Need additional functionality in Event Dispatcher to mark outbox messages as read, or delete them after producing the message to the message broker.</li><li>The outbox collection has to be polled even if there’s little or no activity in the DB, which wastes resources.</li></ul><p>The alternative to the polled outbox approach is real-time outbox processing, using a feature provided by MongoDB called ‘<a href="https://docs.mongodb.com/manual/changeStreams/">Change streams</a>’.</p><h3>Atomic Transactions with MongoDB Change Streams</h3><p>Change streams is a MongoDB feature to allow applications to listen to the changes in a given collection, a database or a deployment. In this approach, the Event Dispatcher is connected to a MongoDB change stream, listens to ‘insert’ events from the outbox collection and dispatch them to the message broker.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*mzHZZRzec3JOklqjLb7SXg.png" /><figcaption>Application with atomic microservices transactions using transactional outbox pattern (with outbox change stream)</figcaption></figure><p>Change streams are supported in a variety of languages. You can read more about it <a href="https://docs.mongodb.com/manual/changeStreams/#open-a-change-stream">here</a>. The following is an extremely simplified example of how the Event Dispatcher code would look like in JavaScript (Node.js).</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/4984b47eb72097a42dda68ae8a67d36d/href">https://medium.com/media/4984b47eb72097a42dda68ae8a67d36d/href</a></iframe><p>A sample received changeEvent would look like as this:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*tbIRXOEidzZi9qKHRwPdVg.png" /></figure><p>In comparison to the <strong>Polled outbox</strong> approach, using change streams has its advantages and disadvantages.</p><p><strong>Advantages:</strong></p><ul><li>Outbox messages can be sent to the message broker in real-time</li><li>No need for the Event Dispatcher having to explicitly delete outbox messages or mark them as read. A TTL index can be set up to clean up the outbox messages after some time.</li></ul><p><strong>Disadvantages:</strong></p><ul><li>Change streams is a MongoDB feature. If you decide to switch to a different database vendor, you may need to make significant changes to the Event Dispatcher to build a similar functionality with the database you are switching to.</li><li>The event Dispatcher will need to keep track of the last processed event to resume after a downtime. See <a href="https://docs.mongodb.com/manual/changeStreams/#std-label-change-stream-resume">resuming a change stream on official docs</a>.</li><li>Change streams are generated using the <a href="https://docs.mongodb.com/manual/core/replica-set-oplog/">MongoDB <strong>oplog</strong></a>. Oplog is a capped collection with a limited size that stores rolling information about the operations that are happening on the database. In a case where the event dispatcher is down for an extended period, it may not be able to resume from the last processed position if it’s already gone from the oplog. This can particularly happen in a situation where the database is very busy and the event dispatcher cannot process at the same rate the changes are happening on the database.</li></ul><p>Also, make sure you are aware of the <a href="https://docs.mongodb.com/manual/administration/change-streams-production-recommendations/">best practices and the recommendations provided by MongoDB</a>, on using change streams on production applications.</p><h3>Wrap Up</h3><p>While the transactional outbox pattern is an excellent way of solving the described problem, it comes with its own complexity. In addition to what I’ve mentioned before, you must have a good understanding of solving the following problems as well when you apply this pattern, regardless of you are using the polled outbox approach or change streams.</p><p><strong>Scaling Event Dispatcher </strong>— You may want to deploy multiple instances of the event dispatcher, or set up auto-scaling for the event dispatcher in a production setup. In such a situation, you will need to implement a proper ‘partitioning’ mechanism to distribute the outbox messages across all available event dispatcher instances to avoid the same message being picked up by multiple dispatcher instances.</p><p><strong>Duplicate Messages </strong>— The event dispatcher may generate duplicate messages to the message broker after recovering from a failure, or after an autoscale event. Therefore, the consumers of the events should be <a href="https://microservices.io/patterns/communication-style/idempotent-consumer.html">idempotent</a>. However, distributed systems often don’t have ‘exactly-once delivery’. Therefore, it’s expected that the consumers to be idempotent in most cases.</p><p>If you are already using this pattern on production, or have any experience in these approaches, feel free to let me know in the comments.</p><p>Thank you for reading!</p><p><strong>References</strong></p><ul><li><a href="https://microservices.io/patterns/data/transactional-outbox.html">https://microservices.io/patterns/data/transactional-outbox.html</a></li><li><a href="https://docs.mongodb.com/manual/administration/change-streams-production-recommendations/">https://docs.mongodb.com/manual/administration/change-streams-production-recommendations/</a></li><li><a href="https://docs.mongodb.com/manual/core/replica-set-oplog/">https://docs.mongodb.com/manual/core/replica-set-oplog/</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=1c96e0522e7c" width="1" height="1" alt=""><hr><p><a href="https://blog.insiderattack.net/atomic-microservices-transactions-with-mongodb-transactional-outbox-1c96e0522e7c">Atomic Microservices Transactions with MongoDB Transactional Outbox</a> was originally published in <a href="https://blog.insiderattack.net">Deepal’s Blog</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Experimenting with HTTP/3 — How the Next Gen Web is being built on UDP]]></title>
            <link>https://blog.insiderattack.net/experimenting-with-http-3-how-the-next-gen-web-is-being-built-on-udp-ba01cb88a495?source=rss-f767215a3aee------2</link>
            <guid isPermaLink="false">https://medium.com/p/ba01cb88a495</guid>
            <category><![CDATA[http3]]></category>
            <category><![CDATA[web]]></category>
            <category><![CDATA[web-development]]></category>
            <category><![CDATA[networking]]></category>
            <category><![CDATA[software-development]]></category>
            <dc:creator><![CDATA[Deepal Jayasekara]]></dc:creator>
            <pubDate>Sat, 23 Oct 2021 23:32:56 GMT</pubDate>
            <atom:updated>2021-10-27T10:01:49.844Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Da2fCrxCSz11y4FT2aGo7A.jpeg" /><figcaption>Background Image Courtesy: Photo by <a href="https://unsplash.com/@bertsz?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">bert b</a> on <a href="https://unsplash.com/s/photos/network?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><h3>Experimenting with HTTP/3 — How the Next Gen Web is being built on UDP</h3><p>HTTP is the lifeline of the web. Amongst many other application layer protocols that power the modern internet, HTTP is the most prevalent and most known protocol which powers the World Wide Web. Being a protocol that runs on top of TCP (Transport Layer Protocol), HTTP has been benefited from the reliability, congestion control and flow control provided by TCP for decades.</p><p>Throughout this time, there were many changes and improvements done to improve the reliability, performance and security of HTTP-based communication. However, the limitations of TCP always prevented further improving the HTTP protocol. Therefore, it looked like it’s time to do something controversial. That is, ditch TCP and switch to its ‘unreliable’ counterpart UDP for the next HTTP version — HTTP3. I’m not planning to explain those reasons in detail in this article, but if you are interested, feel free to check out the <strong>References</strong> at the end of the article.</p><p>At the time of this writing, some major internet companies and CDN providers are already supporting HTTP3 for their services. In this article, I’m going to ‘briefly’ explain HTTP3 and how it’s built, and describe how you can experiment with the new protocol.</p><h3>Introduction to HTTP3 — a.k.a. HTTP over QUIC</h3><p>The major problem of switching from TCP to UDP is that the two protocols are very different in terms of reliability and functionality. TCP is a connection-oriented protocol that has congestion control, flow control and retransmission built into the protocol. UDP is a very simple connectionless protocol (fire-and-forget type), and it doesn’t have any of these goodies built into the protocol. Also, the encryption provided by TLS couldn’t be used with UDP because of the unreliable nature of UDP. Therefore, UDP couldn’t directly replace TCP for HTTP connections.</p><p>To bridge this gap, a new transport layer protocol called <strong>QUIC</strong> (originally stood for <strong>Q</strong>uick <strong>U</strong>DP <strong>I</strong>nternet <strong>C</strong>onnections) was internally developed in 2012 at Google to be used in their services.</p><p>QUIC was responsible for providing missing features in UDP as well as encryption provided by TLS, depicted as follows.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*JmkAIwNZyRlOvHqBzNZXjA.png" /><figcaption>How HTTP3 differs from earlier versions of HTTP</figcaption></figure><p>With TCP, a secure HTTP connection required both TCP and TLS handshakes to be completed before the actual HTTP communication begins. With QUIC, these two handshakes are replaced by just one QUIC handshake to establish a secure connection to the server, which significantly reduces the time it takes to establish a secure HTTP connection. (More on the handshakes in a future article… 😊)</p><p>After further developments and improvements, QUIC protocol was finally standardised by IETF in May 2021 as described by <a href="https://datatracker.ietf.org/doc/html/rfc9000">RFC 9000</a>. However, as of Oct 2021,<a href="https://datatracker.ietf.org/doc/draft-ietf-quic-http/"> HTTP3 protocol is not yet standardised</a>. However, HTTP3 support is being already implemented by many large scale internet companies and CDN providers.</p><p>Here are a few milestones from the journey of the Web towards HTTP3.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*sP_BW6S86wANueHmio3KEA.jpeg" /></figure><h4>Why QUIC? Why not improve TCP?</h4><p>TCP is an old protocol that is built into the OS kernels of all the devices that make up the internet. Any change to TCP will have require operating system updates to all these devices and may take years or decades to be rolled out across the internet (this is precisely why IPv6 adoption is slow). Implementing a new complex protocol that runs on top of a simple existing transport layer protocol such as UDP seemed to make sense due to this reason. The support for the new protocol could easily be rolled out to HTTP servers/proxies and HTTP clients via software updates, and won’t require OS updates.</p><h3>Server support for HTTP3</h3><p>Nginx, which is one of the most widely used servers has <a href="https://www.nginx.com/blog/introducing-technology-preview-nginx-support-for-quic-http-3/">experimental support for HTTP3</a> at the time of the writing. And also Caddy, which is another popular open source web server seems to have <a href="https://ma.ttias.be/how-run-http-3-with-caddy-2/">experimental HTTP3 support</a>.</p><p>However, Apache web server doesn’t seem to be interested in implementing HTTP3 support anytime soon.</p><h3>Client support for HTTP3</h3><p>HTTP3 brings significant fundamental changes to how HTTP works. Due to this reason, major changes are required in many tools (such as SSL libraries) that are used to develop HTTP clients. Though the progress towards HTTP3 is a bit slow, there are many HTTP clients that already support HTTP3 or can be custom-built from the source to support HTTP3.</p><h4><strong>Browsers</strong></h4><p>At the time of the writing, a majority of the major browsers support HTTP3. You can check the current status of HTTP3 support at <a href="https://caniuse.com/http3">https://caniuse.com/http3</a>.</p><p>Obviously, establishing HTTP3 communication will require both the client and the server to support HTTP. The HTTP server will need to first let the browser know that it supports HTTP3, as the browsers will not try to establish an HTTP3 connection by default. This is done by the HTTP servers using the <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Alt-Svc">alt-svc</a> (alternative service) response header.</p><p>In the following screenshot, www.google.com indicates that it supports a few draft versions of HTTP3 on port <a href="http://www.google.com:443">www.google.com:443</a> using alt-svc header.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*eHQhhP5gABjT44bMDRRqdw.png" /><figcaption>alt-svc response header returned by <a href="http://www.google.com">www.google.com</a></figcaption></figure><p>When this header is received by an HTTP3-capable browser, it will switch to HTTP3 communication with the server, which can be verified using the browser’s network panel.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*QWyyOWHaFRVpdFVMEDYKOA.png" /><figcaption>HTTP3 Communication in Google Chrome v94 with <a href="http://www.google.com">www.google.com</a></figcaption></figure><p>Also, the browser will cache the alt-svc parameters for the number of seconds set by ma parameter (<strong>m</strong>ax <strong>a</strong>ge) in the header value. For example, alt-svc: h3=&quot;:443&quot;; ma=2592000 will instruct the browser to cache this alternative service for 2592000 seconds, which is 30 days. This helps the browser to temporarily remember that the server supports HTTP3 and directly use HTTP3 for future connections.</p><h4><strong>cURL</strong></h4><p>Though the browsers are catching up with HTTP3 support, our beloved HTTP client <strong>curl </strong>doesn’t yet support HTTP3 by default. This is because neither OpenSSL nor LibreSSL which curl is usually shipped with supports QUIC at the time of this writing. However, <a href="https://boringssl.googlesource.com/boringssl/">BoringSSL</a> — Google’s fork of OpenSSL supports QUIC and you can easily build curl from the source to use BoringSSL.</p><p>If you are using macOS, you can build curl with HTTP3 support using the homebrew formula provided by Cloudflare as follows.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/f48854844d8c100507e2d9f022b3c56f/href">https://medium.com/media/f48854844d8c100507e2d9f022b3c56f/href</a></iframe><blockquote>Alternatively, I found this useful docker image <a href="https://hub.docker.com/r/ymuski/curl-http3">ymuski/curl-http3</a> of curl built with HTTP3 support. You can also use this image to try out the curl commands I’ve mentioned in the rest of the article.</blockquote><p>Once you build and add the new curl binary to PATH, you can verify HTTP3 support by simply running curl -V.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*_lo4XW73miyYu_iu3LA1NQ.png" /><figcaption>HTTP3 support for curl with BoringSSL</figcaption></figure><p>You can now send HTTP3 requests to any server that supports HTTP3. There are two ways you can instruct curl to use HTTP3.</p><p><strong>Forcing curl to use HTTP3</strong></p><p>If you know that the server supports HTTP3, you can provide --http3 flag to curl to force it to use HTTP3 as follows:</p><pre>curl -I --http3 <a href="https://www.google.com">https://www.google.com</a></pre><p>If you prefer using ymuski/curl-http3 docker image, you can use the following command instead.</p><pre>docker run --rm ymuski/curl-http3 curl -I --http3 <a href="https://www.google.com">https://www.google.com</a></pre><p>If the server supports HTTP3, it will respond to the request, and you can verify that the communication is HTTP3 by inspecting the response.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*H6cvM5af7BAhwZf_TrFpYA.png" /><figcaption>HTTP3 server response example</figcaption></figure><p><strong>curl with alt-svc</strong></p><p>Unlike browsers, curl doesn’t honour alt-svc header automatically because it doesn’t cache alt-svc information by default. However, you can instruct curl to cache alt-svc info, which curl can then use in subsequent requests. This can be done by using --alv-svc flag and providing a file name to cache alt-svc info as follows.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*5xe2qtsmkHWdY5q-olMaQg.png" /><figcaption>Instructing curl to cache alt-svc header in a file</figcaption></figure><p>curl will by-default connect to the server with HTTP 1.1, and store any alt-svc information provided by the server in the cache file we provided (in our case, altsvccache.txt)</p><p>If you inspect altsvccache.txt, you will see that it’s populated with the information similar to the following.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*_fq5_YFm0xH_QJ_5YarJJg.png" /><figcaption>alv-svc cache file created by curl</figcaption></figure><p>If you send a subsequent request to www.google.com providing the cache file, curl will then read the cache file and send the request in HTTP3 directly.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*OB73gRh9cBzgHiAc_5B5Tg.png" /><figcaption>curl re-uses alt-svc cache file to establish HTTP3 communication</figcaption></figure><h4>REST Clients</h4><p>There are feature requests to <a href="https://github.com/postmanlabs/postman-app-support/issues/9307">Postman</a> or <a href="https://github.com/Kong/insomnia/discussions/3691">Insomnia</a> — two of the commonly used REST clients requesting for HTTP3 support. However, no active discussion is going on towards implementing HTTP3 support in these clients at the moment. This is likely due to the lack of HTTP3 support in Node.js (which I explain in the following section).</p><h4>Language/Runtime Support</h4><p>Built-in language/runtime support for HTTP3 and QUIC is not mature yet, but there seem to be 3rd party libraries offering HTTP3/QUIC support in some languages such as <a href="https://github.com/lucas-clemente/quic-go">quic-go</a> for Golang and <a href="https://github.com/ptrd/kwik">kwik</a> for Java. (I would love to know the HTTP3 support in your favourite language. Feel free to let me know in a comment.)</p><p><a href="https://github.com/nodejs/node/issues/38478#issuecomment-838410255">HTTP3 support for Node.js has been underway</a> for some time, but it’s still unclear which future Node version will be shipped with it. This is being relied upon by bunch of other tools such as Electron.js thereby impacting a lot of applications such as the Postman and Insomnia REST clients I talked about in the previous section.</p><h3>Future of HTTP3</h3><p>The transport layer changes introduced by HTTP3 is the major fact which slows down the roll out of HTTP3. Apart from its usage by <a href="https://en.wikipedia.org/wiki/Domain_Name_System">DNS</a>, UDP is not a protocol which as frequently used as TCP. Therefore, software used in many L4 devices on the internet are not optimised for UDP.</p><p>Though all these circumstances affect negatively on HTTP3 adoption, it’s interesting to see many internet companies and CDN providers already supporting it and the others are actively working towards it. However, it might take a long time for HTTP3 to become the dominant HTTP version, considering how slow even its predecessor HTTP2 is being adopted. But knowing how this novel protocol works, and experimenting with it early will give you the upper hand for quick adoption.</p><h3>References</h3><ul><li><a href="https://blog.cloudflare.com/quic-version-1-is-live-on-cloudflare/">https://blog.cloudflare.com/quic-version-1-is-live-on-cloudflare/</a></li><li><a href="https://blog.cloudflare.com/head-start-with-quic/">https://blog.cloudflare.com/head-start-with-quic/</a></li><li><a href="https://www.nginx.com/blog/introducing-technology-preview-nginx-support-for-quic-http-3/">https://www.nginx.com/blog/introducing-technology-preview-nginx-support-for-quic-http-3/</a></li><li><a href="https://datatracker.ietf.org/doc/html/rfc9000">https://datatracker.ietf.org/doc/html/rfc9000</a></li><li><a href="https://www.youtube.com/watch?v=dQ5AND4DPyU">https://www.youtube.com/watch?v=dQ5AND4DPyU</a></li><li><a href="https://dl.acm.org/doi/10.1145/3098822.3098842">https://dl.acm.org/doi/10.1145/3098822.3098842</a></li><li><a href="https://www.akamai.com/blog/performance/http3-and-quic-past-present-and-future">https://www.akamai.com/blog/performance/http3-and-quic-past-present-and-future</a></li><li><a href="https://daniel.haxx.se/blog/2019/01/21/quic-and-missing-apis/">https://daniel.haxx.se/blog/2019/01/21/quic-and-missing-apis/</a></li><li><a href="https://daniel.haxx.se/blog/2021/04/02/where-is-http-3-right-now/">https://daniel.haxx.se/blog/2021/04/02/where-is-http-3-right-now/</a></li><li><a href="https://everything.curl.dev/http/altsvc">https://everything.curl.dev/http/altsvc</a></li><li><a href="https://http3-explained.haxx.se/">https://http3-explained.haxx.se/</a></li><li><a href="https://everything.curl.dev/http/altsvc">https://everything.curl.dev/http/altsvc</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=ba01cb88a495" width="1" height="1" alt=""><hr><p><a href="https://blog.insiderattack.net/experimenting-with-http-3-how-the-next-gen-web-is-being-built-on-udp-ba01cb88a495">Experimenting with HTTP/3 — How the Next Gen Web is being built on UDP</a> was originally published in <a href="https://blog.insiderattack.net">Deepal’s Blog</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Abusing Network Protocols for Secret Communication]]></title>
            <link>https://blog.insiderattack.net/abusing-network-protocols-for-secret-communication-7c96cbdfca61?source=rss-f767215a3aee------2</link>
            <guid isPermaLink="false">https://medium.com/p/7c96cbdfca61</guid>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[information-security]]></category>
            <category><![CDATA[security]]></category>
            <category><![CDATA[hacking]]></category>
            <category><![CDATA[networking]]></category>
            <dc:creator><![CDATA[Deepal Jayasekara]]></dc:creator>
            <pubDate>Wed, 18 Aug 2021 18:47:28 GMT</pubDate>
            <atom:updated>2021-09-06T21:31:19.013Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ZrXiAvbdj8TqAdYWacriyQ.jpeg" /></figure><h4>How to hide your communication in plain sight with Network Covert Channels</h4><p>Attempt for <strong>Secret Communication</strong> is nothing new. Ever since we started to communicate with each other, we wanted to hide the details of our conversations from prying eyes and ears. Over the years, people have been working on this leading to the invention of “Encryption” as a result. But, encryption has a problem. Even if the encryption can hide the content of the conversation, it cannot hide the fact that a secret conversation is present. For that, we need something uncannier than encryption: one of the most popular ways to achieve that is called <strong>Covert Channels</strong>.</p><p>To understand this in a practical way, let’s have a look at a popular dilemma called <strong>The Prisoners’ Problem</strong>.</p><h3>The Prisoners’ Problem</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Aagh6sQJFImkOVT1O-q64w.png" /><figcaption>The Prisoners’ Problem</figcaption></figure><blockquote>Two prisoners locked in two near-by cells are planning their escape. They are allowed to talk with each other, but there’s a jailer who can hear their conversation. Talking with each other is the only way of communication between the two of them, but they need to be careful. If the jailer senses that they are planning for something, he might move them to distant cells, which will jeopardise their escape plan. How can the prisoners plan their escape without making the jailer suspicious?</blockquote><h3>Encryption vs Covert Channels</h3><p>Let’s say that the prisoners decided to transform their conversation using a secret code, which the jailer is unaware of. This is called “Encryption” in general. In this case, only the two prisoners can translate the transformed messages back to the original because only those two know the secret code used to transform the messages. But, even though the jailer cannot understand the conversation, the inability to understand the conversation could easily make him suspicious. Therefore, Encryption is not the solution for the prisoners’ problem.</p><p>Finding a solution to the prisoners’ problem introduces a new way of secret communication called Covert Channels. The goal of a covert channel is to provide communication between two parties in an unusual way so that an intermediate party can hardly notice that there’s such communication.</p><p>For example, a covert channel between the two prisoners could be that the number of words in a sentence serves as the actual information to be passed.</p><p>e.g: The prisoners can successfully pass the message “<strong>345</strong>” by using 3 irrelevant sentences as follows.</p><p>“<em>Are you okay? I feel like sleeping. The food was not good.”</em></p><ul><li>Are you okay? =&gt; 3</li><li>I feel like sleeping =&gt; 4</li><li>The food was not good=&gt; 5</li></ul><p>This is a primitive example for a covert channel. But the most important fact is, both entities in the covert channel should understand how it works in order to successfully pass messages.</p><p>Covert Channels are not efficient in terms of throughput. But they are quite good at hiding their presence, hence providing <a href="https://en.wikipedia.org/wiki/Security_through_obscurity">security by obscurity</a>. If a covert channel is detected, it’s very likely to be entirely compromised unless the content is further protected by encryption.</p><p>Covert Channels are established over the network by using networking protocols in unexpected ways. In this article, I’ll be talking about, Network-based covert channels and how they work, practical examples and identifying and blocking covert channels.</p><blockquote><strong>Covert Channels vs Steganography? </strong>If you have heard about Steganography, you might find it very similar to the concept of Covert Channels. However, Steganography does not misuse any network protocols to transport secret data. Instead, it conceals secret data inside another payload such as an image/video.</blockquote><h3>Abusing Network Protocols</h3><p>A network protocol is basically a contract between a sender and a receiver, where the sender sends structured information in a format that can be interpreted by the receiver. This ‘structure’ of the information is defined as the ‘network packet’ structure. A packet mainly consists of 3 parts which are called the <strong>header</strong>, <strong>data, </strong>and an optional <strong>trailer. </strong>Firewalls and Intrusion Detection Systems (IDS) are particularly interested in the data section of a packet as it carries the actual payload of the transmission.</p><blockquote>Many network protocols were implemented in early days where security was not a major concern, but ‘reliable communication’ was a concern. Therefore, passing information secretly by misusing header fields was certainly possible without triggering firewall or IDS rules, hence giving birth to covert channels.</blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Vp_M1pSTPvPw3D0E4kueYQ.png" /><figcaption>IP Datagram header</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*oWJmwiBJt5_jvPJCU0rmQQ.png" /><figcaption>TCP Segment Header</figcaption></figure><p>Transmitting information in the header fields is not the only way for setting up covert channels. There are two main kinds of covert channels based on how data transmission is done.</p><p><strong>Storage Channels — </strong>Storage Covert channels encode covert data in the packets themselves (encoded in headers as I mentioned before)</p><p><strong>Timing (temporal) Channels</strong> — Delay between the packets is used to transmit data.</p><p>Timing channels are not as reliable as storage channels and are mostly research-oriented. Therefore, during the rest of the article, we’ll be discussing storage covert channels.</p><h3>Storage Covert Channels</h3><h4>Single Protocol Covert Channels</h4><p>A single protocol covert channel is the most common type of covert channels which are established using only one protocol for covert communication. This type of covert channels usually encapsulates covert data into a protocol header. A popular example of this type is a tool called <a href="http://www.mit.edu/afs.new/sipb/user/golem/tmp/ptunnel-0.61.orig/web/">ptunnel</a>.</p><p><a href="http://www.mit.edu/afs.new/sipb/user/golem/tmp/ptunnel-0.61.orig/web/">Ping Tunnel</a></p><p>ptunnel lets you tunnel TCP connections using ICMP Echo Request and ICMP Echo Reply packets reliably. We’ll see an example of a covert channel using ptunnel at the end of this article.</p><h4>Protocol Channels</h4><p>As its name implies, a Protocol Channel is a type of covert channel which is established over two or more protocols. An example would be a covert channel which uses ICMP and HTTP packets interchangeably to transmit data. This type of covert channels are more obscure compared to single protocol covert channels and makes it difficult.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*naVGXNuQpiJq-x1RwczbDA.png" /><figcaption>Protocol Channel (PC)</figcaption></figure><h4>Protocol Switching Covert Channels (PSCC)</h4><p>PSCC also uses more than one protocol but unlike Protocol Channels, data is not encoded in the packets. Instead, in a PSCC, a packet itself should be interpreted as a message. Consider the following example.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Kva8MmiK6TBFiLivuc-kYg.png" /><figcaption>Protocol Hopping Covert Channel (PHCC)</figcaption></figure><p>In the above example, an HTTP packet is binary 1 and a POP3 message is binary 0. Therefore, to transmit the message 110100, the sender has to send the sequence of packets as HTTP, HTTP, POP3, HTTP, POP3, POP3. The bandwidth of a PSCC can be improved by using more than two protocols and assigning a larger binary value for each protocol.</p><p>e.g: Using 4 protocols and each protocol is assigned values subsequently 00, 01, 10, 11.</p><p>Protocol Switching Covert Channels are not efficient in terms of throughput compared to Protocol Channels. But for small messages, they are much more stealthy.</p><h3>Use Cases of Protocol Channels</h3><p><strong>Enterprise Data Exfiltration</strong> — The most popular use case of covert channels is to exfiltrate confidential data out of a protected network.</p><p><strong>Bypassing Firewalls to access forbidden content</strong> — Covert Channels can also be used to access forbidden content otherwise forbidden by a firewall. An example is tunneling TCP traffic over ICMP using a <a href="http://www.mit.edu/afs.new/sipb/user/golem/tmp/ptunnel-0.61.orig/web/">ptunnel</a> proxy as described at the end of this article.</p><p><strong>Botnet Communications, Remote Backdoors, and Reverse Shells</strong> — Some Botnets use protocol channels in order to stealthily communicate with their command and control (C&amp;C) centers. Also, remote backdoors or reverse shells can also use covert channels to download additional malicious scripts without detection.</p><h3>Implementation Concerns</h3><p>Although Covert Channels are a great way for obscure communication, setting up a reliable covert channel is not easy. The following are the key problems which have to be catered when implementing a covert channel.</p><p><strong>Throughput vs Stealth</strong></p><ul><li>Encoding more data into packets could increase the risk of the channel being exposed because the packets contain a significantly high amount of data.</li><li>The number of packets sent at a time has to be increased if less amount of data was encoded into a single packet, leading to the channel being discovered due to the unusual network activity.</li></ul><p><strong>Catering packet loss and out-of-order delivery</strong></p><p>Covert channels do not use network protocols as is, but rather misuse them. Hence, they do not have the luxury of using network protocols’ reliability mechanisms such as TCP re-transmission, re-assembly, etc. Therefore, the implementation of the covert channel should define its own protocol which implements these reliability mechanisms so that it can withstand the packet loss and the out-of-order delivery of packets.</p><h3>Setting up an ICMP-based Covert Channel with ptunnel</h3><p>In this example, we’ll see how to access an unauthorized web resource through a firewall with the help of a covert channel. For this, we use ptunnel(i.e, Ping Tunnel) which provides the facility to tunnel a TCP connection over ICMP Echo Requests/Replies.</p><p>Let’s imagine the following hypothetical scenario.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*BsaaYUT42iqoFRD17NX8sg.png" /><figcaption>ptunnel Practical Demonstration</figcaption></figure><ul><li>We are located in a secure corporate network and we need to access a particular webpage which is blocked by the company’s firewall.</li><li>But we identify that we can successfully ping through the firewall, which indicates that ICMP Requests and ICMP Replies are not blocked by the firewall.</li><li>Then, we set up a ptunnel proxy outside the firewall. ptunnel proxy will establish a TCP connection with the destination server and will tunnel our HTTP requests to the webserver and server response back to us via ICMP.</li></ul><p>Our setup is as follows:</p><ul><li>Our local machine. Runs the ptunnel client (macOS — 192.168.4.1/24)</li><li>ptunnel proxy (Kali linux — 192.168.4.111/24)</li><li>Destination webserver (Metasploitable Ubuntu — 192.168.4.100/24)</li></ul><h4>Setting up ptunnel proxy</h4><p>Starting up the ptunnel proxy is as trivial as running the ptunnel command.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*RXYzVLJgeY8axtcuAP4SOg.png" /><figcaption>Setting up ptunnel proxy</figcaption></figure><h4>Setting up ptunnel client</h4><p>We then start up the ptunnel client on our local machine (located inside the protected network). Ptunnel client will start listing on a local port (-lp)for TCP connections which it will tunnel to the destination address (-da) and port (-dp) via the proxy (-p).</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*HQ2nNnwqzMtaordl2EoyBQ.png" /><figcaption>Setting up ptunnel client</figcaption></figure><h4>Accessing the remote resource</h4><p>Once the server and the client are up and running, we can now access the restricted resource via the local TCP port as follows.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*MZZk928LNZdafoUMqiw9Iw.png" /><figcaption>Accessing the web resource via the forwarded port</figcaption></figure><p>If we intercept the communication between the ptunnel client and the proxy, we could see how HTTP response secretly encoded inside the ICMP replies as indicated below.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*FkQ_LAIMbFRYFwRTePs2kw.png" /><figcaption>Wireshark Capture of tunneled response via ICMP Replies</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*bflPkEeFuaEpw-JRQD9Opg.png" /><figcaption>HTTP Response tunneled via ICMP</figcaption></figure><p>Obviously, using a ptunnel covert channel to create a covert channel is not bandwidth efficient (150 kb/s download and about 50 kb/s upload as per the author). However, it can still come in handy for an attacker in order to secretly download a malicious script or exfiltrate secret data outside a secure network.</p><h3>Identifying and Blocking Covert Channels</h3><p>Covert Channels can be used with good intent, as well as malicious intent. Therefore, identifying and blocking them is also equally important. Though it is very hard to identify and 100% block covert channels, there are certain ways to make it difficult to set up covert channels.</p><p><strong>IDS Packet Signatures</strong> — Configuring Intrusion Detection Systems with rules to identify the packet signatures of the common types of covert channels.</p><p><strong>Traffic Anomaly Detection </strong>— Mostly research-oriented. For example, analyzing packet size variation, header size variation and bandwidth usage vs time of the day can lead to discovering unusual network activities.</p><p><strong>Active Warden</strong> (<em>Wendzel, Steffen &amp; Keller, Jörg. (2012). Design and Implementation of an Active Warden Addressing Protocol Switching Covert Channels</em>) — A firewall-like service which randomly delays packets if protocol switching is detected, making it hard to establish reliable covert communication. This is useful to prevent protocol switching covert channels.</p><p><strong>Packet Data Padding </strong>— Intercepting and padding packet header fields which are likely to be used for covert communication.</p><p>Still, though, it’s difficult to 100% prevent covert channels without disrupting the legitimate traffic. There’s so much research work done in this area and new types of covert channels and protection mechanisms are invented from time to time.</p><p><strong><em>References:</em></strong></p><ul><li><em>Wendzel, Steffen &amp; Keller, Jörg. (2012). Design and Implementation of an Active Warden Addressing Protocol Switching Covert Channels.</em></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=7c96cbdfca61" width="1" height="1" alt=""><hr><p><a href="https://blog.insiderattack.net/abusing-network-protocols-for-secret-communication-7c96cbdfca61">Abusing Network Protocols for Secret Communication</a> was originally published in <a href="https://blog.insiderattack.net">Deepal’s Blog</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[NodeJS Streams in Practice]]></title>
            <link>https://blog.insiderattack.net/nodejs-streams-in-practice-980b3cdf4511?source=rss-f767215a3aee------2</link>
            <guid isPermaLink="false">https://medium.com/p/980b3cdf4511</guid>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[web-development]]></category>
            <category><![CDATA[node]]></category>
            <category><![CDATA[nodejs]]></category>
            <category><![CDATA[software-development]]></category>
            <dc:creator><![CDATA[Deepal Jayasekara]]></dc:creator>
            <pubDate>Sun, 25 Jul 2021 20:19:53 GMT</pubDate>
            <atom:updated>2022-03-18T09:17:35.362Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ts-xtQqKqzzigDErF3ZPQw.jpeg" /><figcaption>Photo by <a href="https://unsplash.com/@quinten149?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Quinten de Graaf</a> on <a href="https://unsplash.com/s/photos/pipe?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><h3>NodeJS Streams in Practice — Advanced NodeJS Part 5</h3><h4>Turbo boost your Node.js application with Streams</h4><p>In my previous article “<a href="https://blog.insiderattack.net/a-visual-guide-to-nodejs-streams-9d2d594a9bf5">A Visual Guide to NodeJS Streams</a>”, I described what a stream is and how streams can be used in NodeJS using visuals. Visuals are great to get a broad understanding to start with, but it’s even better to do some hands-on work to understand how streams can be applied in practical applications. Therefore, in this article, I’m going to describe a few examples to demonstrate how streams can be used in day-to-day applications.</p><p>If you are not yet familiar with the concept of Streams in Nodejs, I highly recommend you to read <a href="https://blog.insiderattack.net/a-visual-guide-to-nodejs-streams-9d2d594a9bf5">my previous article</a> first. 🙂</p><p>This article is the 5th article of my <strong>Advanced NodeJS </strong>Series which is a sequel to <a href="https://blog.insiderattack.net/event-loop-and-the-big-picture-nodejs-event-loop-part-1-1cb67a182810">my series on Node.js Event Loop</a>. You can find the other articles of the <strong>Advanced NodeJS </strong>series below:</p><h3>Post Series Roadmap</h3><ul><li><a href="https://blog.insiderattack.net/crossing-the-js-c-boundary-advanced-nodejs-internals-part-1-cb52957758d8">Crossing the JS/C++ Boundary</a></li><li>Deep Dive into Worker Threads in Node.js</li><li><a href="https://blog.insiderattack.net/understanding-async-resources-with-async-hooks-3416de574f30">Understanding Async Resources with Async Hooks</a></li><li><a href="https://blog.insiderattack.net/a-visual-guide-to-nodejs-streams-9d2d594a9bf5">A Visual Guide to NodeJS Streams</a></li><li><a href="https://blog.insiderattack.net/nodejs-streams-in-practice-980b3cdf4511"><strong>NodeJS Streams in Practice (This Article)</strong></a></li><li><a href="https://blog.insiderattack.net/how-not-to-measure-time-in-programming-11089d546180">Why you should avoid Date.now() to measure time durations</a></li></ul><h4>Understanding a Readable Stream</h4><p>Before moving on further, let’s try to understand how a readable stream works using the following example. In this script, I’m reading a file using a readable stream created by fs.createReadStream. The file I’m reading is foo.txt and it has the content “<strong>This is foo!!!</strong>”</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/948ede4397831ae146414c3fdfaa0303/href">https://medium.com/media/948ede4397831ae146414c3fdfaa0303/href</a></iframe><p>If we run the above program, we will see the following output:</p><pre>stream in flowing mode!<br>file opened!<br>stream paused!<br>waiting for 3 seconds...<br>stream in flowing mode!<br>got some data:  This is foo!!!<br>stream ended!<br>stream closed!</pre><p>Let’s try to understand this output:</p><ol><li>A readable stream is created as soon as we call fs.createReadStream, but it’s by default not in flowing mode. This means that the stream will not be generating data from the underlying file ‘foo.txt’.</li><li>As soon as we attach an event handler for the data event, the stream switches to flowing mode and emits the resume event. This triggers our event handler that is listening to the resume events.</li><li>The operating system opens ‘foo.txt’ which causes the readable file stream to emit open event, which triggers the event handler listening to the open events.</li><li>Inside our event handler for open event, we explicitly call reader.pause(). This will cause the stream to switch from flowing mode to paused mode. In paused mode, the stream will not generate any data from the underlying file. Therefore, no data event will be emitted until the stream is put back to flowing mode explicitly.</li><li>After waiting for 3 seconds, we call reader.resume() which switches the stream back to flowing mode. Then the stream will start generating data, which causes data events to trigger.</li><li>One or more data events will be emitted depending on the size of the file. In our case, it’s just a small amount of text which the readable stream is perfectly capable of buffering in memory. Therefore, we only see one data event.</li><li>Once the data is completely read from the stream, the stream emits end event to indicate there are no more data to be read from the stream.</li><li>Finally, the operating system closes the underlying file which is indicated by the close event emitted from the readable stream.</li></ol><p>Depending on the purpose of the readable stream, they may emit other implementation-specific custom events as well. In this example, we only saw the different stages of a readable file stream. But the concept of flowing mode and paused mode is common in all readable streams.</p><h4><strong>A trivial pipe</strong></h4><p>Just like a pipe used to connect a water source to a particular destination, a ‘pipe’ in streams is used to connect a readable stream to a writable stream. A pipe. Let’s recall what a pipe is from the <a href="https://blog.insiderattack.net/a-visual-guide-to-nodejs-streams-9d2d594a9bf5">previous article</a>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/994/1*q9hxgiT3P_i4HRlcrclb4Q.png" /></figure><p>In the following snippet, we are creating a readable file stream using fs.createReadStream and pipe it to process.stdout writable stream to be printed on the shell.</p><blockquote>process.stdout is probably the most common and well-known writable stream. It’s called the “standard output” and is used by console.log.</blockquote><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/9d2b3ad3df0f167ddc749275d3875d14/href">https://medium.com/media/9d2b3ad3df0f167ddc749275d3875d14/href</a></iframe><p>If you run this example on the terminal, you will see the content of the foo.txt gets printed on the terminal.</p><pre>This is foo!!!</pre><h4>An echo server</h4><p>Let’s now look at how we can use pipes in a slightly different use case. The following is an ‘echo server’ which accepts a request from a client and reflects the request content (body) back to the client.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/8a5dd27a9b2ea6b2a69b256f082215ad/href">https://medium.com/media/8a5dd27a9b2ea6b2a69b256f082215ad/href</a></iframe><p>Let’s try to understand what req and res mean.</p><p>When a client and a server communicate with each other, they do it via ‘sockets’ created and maintained by the operating system at each end. In NodeJS applications, we can communicate with such a socket using a <a href="https://nodejs.org/api/net.html#net_class_net_socket">TCP Socket</a> stream. As we saw in the<a href="https://blog.insiderattack.net/a-visual-guide-to-nodejs-streams-9d2d594a9bf5"> previous article</a>, a TCP socket in NodeJS is a duplex stream. Therefore it can be read from and written to.</p><p>However, NodeJS http module provides additional functionality for HTTP on top of TCP sockets and exposes two separate streams for reading from the socket and writing to the socket. They are,</p><ul><li><a href="https://nodejs.org/api/http.html#http_class_http_incomingmessage">IncomingMessage</a> — Readable stream from the socket. Can be accessed by req object in the request handler in the example. NodeJS http module reads the incoming request content from the socket and pushes into the IncomingMessage readable stream.</li><li><a href="https://nodejs.org/api/http.html#http_class_http_outgoingmessage">OutgoingMessage</a> — Writable stream to the socket. Can be accessed by res object in the request handler in the example. NodeJS http module takes the data written to OutgoingMessage writable stream and passes it to the socket stream. This data is then written into the actual TCP socket created by the operating system and is sent to the client.</li></ul><p>With this information in mind, we can visualise our echo server as follows:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*TOlt-y69WjWMR9-XGO8XfQ.png" /></figure><p>In this echo server, we are simply piping req readable stream to res writable stream so that the request body content is reflected back to the client.</p><p>To see this in action, start the server and run the following curl command.</p><pre>curl -d&quot;hello&quot; <a href="http://localhost:3001/">http://localhost:3000</a></pre><p>You will see “hello” returned in the response.</p><h4>Pipe multiple times</h4><p>So far we saw how pipe can be used to connect a readable stream to a writable stream. pipe can also be used to connect one readable stream to more than one writable stream. In that case, the content from the readable stream is copied to the two writable streams.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*JdV2RDpTGTlr5cso38szOw.png" /></figure><p>We can demonstrate that using the following example. In this script, we are creating two copies of foo.txt as copy1.txt and copy2.txt using pipes.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/8972e4dc24687c87d2a015b19e5f25cb/href">https://medium.com/media/8972e4dc24687c87d2a015b19e5f25cb/href</a></iframe><p>Though this is a very naive example, multiple pipes can be very useful in real-life applications. One such example would be in an http server, where you want to proxy an incoming request to an upstream server at the same time reading the incoming request content for logging and monitoring.</p><h4><strong>⚠️ Problem with pipes:</strong></h4><blockquote>Pipes are very useful and convenient, but it can be very tricky to handle errors when you pipe multiple streams together. The reason is that pipe does not automatically destroy and clean up readable or writable side if an error occurred in the other end. This can lead to memory leaks. Therefore, it’s wise to use require(&#39;stream&#39;).pipeline function to pipe streams in production applications. It takes care of tracking errors and cleaning up in those types of situations. You can read more about pipeline function <a href="https://nodejs.org/api/stream.html#stream_stream_pipeline_source_transforms_destination_callback">here in the official docs</a>.</blockquote><h4>A hash server</h4><p>In the previous examples, we discussed readable and writable streams. Let’s now look at how we can combine a readable stream, transform stream and a writable stream together.</p><p>The following is a simple server that generates a <a href="https://en.wikipedia.org/wiki/SHA-2">SHA-512</a> hash for a provided request body content.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/5b744a5bcfe85d54d1e67ca21399bce0/href">https://medium.com/media/5b744a5bcfe85d54d1e67ca21399bce0/href</a></iframe><p>In this example, I’m using pipeline function instead of using .pipe like in the previous examples.</p><p>The following diagram visualises our hash server’s functionality.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*RwGRF1AKk_ZXTMi0bWPlGg.png" /></figure><p>Let’s try to understand this flow step by step:</p><ul><li>As we discussed before, req is a readable stream that we can use to read incoming request content.</li><li>createHash function in crypto module creates a hash stream. It is a transform stream that we can write our content into and receive the hash of the content back. By piping req readable stream to hasher transform stream, we are passing the incoming request body to be hashed.</li><li>res object is a writable stream. When hasher is piped to res, generated hash data flows to the res stream and eventually gets written to the socket.</li></ul><p>Let’s first start the server and use the following curl command to see it in action.</p><pre>curl -d&quot;test&quot; <a href="http://localhost:3000/hash">http://localhost:3000/hash</a></pre><p>You will see the following output in response, which is the base64-encoded SHA-512 hash of the text “test”.</p><pre>7iaw3Ur350mqGo7jwQrpkj9hiYB3Lkc/iBml1JQODbJ6wYX4oOHV+E+IvIh/1nsUNzLDBMxfqa2Ob1f1ACio/w==</pre><p>Streams are widely used in NodeJS applications due to their efficiency and low memory footprint. Although we looked at how we can use them using a few small examples, they can be very useful in real-life applications to process large files and large amounts of data with relatively low memory consumption. If you are keen on learning more, I also strongly recommend reading the <a href="https://nodejs.org/api/stream.html">official NodeJS documentation for streams</a>, which is very detailed and full of useful examples.</p><p>I’d like to thank you for reading, and appreciate it if you could let me know your feedback.</p><h4>Further References:</h4><ul><li>HTTP Module <a href="https://nodejs.org/api/http.html">https://nodejs.org/api/http.html</a></li><li>HTTP Module Implementation <a href="https://github.com/nodejs/node/blob/3ac223ed25db4e4b89799f3e60ad8dd6ce454884/lib/http.js">https://github.com/nodejs/node/blob/3ac223ed25db4e4b89799f3e60ad8dd6ce454884/lib/http.js</a></li><li>Stream Module <a href="https://nodejs.org/api/stream.html">https://nodejs.org/api/stream.html</a></li><li>File System Module <a href="https://nodejs.org/api/fs.html">https://nodejs.org/api/fs.html</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=980b3cdf4511" width="1" height="1" alt=""><hr><p><a href="https://blog.insiderattack.net/nodejs-streams-in-practice-980b3cdf4511">NodeJS Streams in Practice</a> was originally published in <a href="https://blog.insiderattack.net">Deepal’s Blog</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Starting Your Own Tech Blog]]></title>
            <link>https://blog.insiderattack.net/starting-your-own-tech-blog-bbc663fca981?source=rss-f767215a3aee------2</link>
            <guid isPermaLink="false">https://medium.com/p/bbc663fca981</guid>
            <category><![CDATA[writing]]></category>
            <category><![CDATA[blogging]]></category>
            <category><![CDATA[writing-tips]]></category>
            <category><![CDATA[writer]]></category>
            <category><![CDATA[technical-writing]]></category>
            <dc:creator><![CDATA[Deepal Jayasekara]]></dc:creator>
            <pubDate>Mon, 28 Jun 2021 21:52:23 GMT</pubDate>
            <atom:updated>2021-06-28T21:52:23.829Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*gZ3TAIQeHSndmsrtxEHosg.jpeg" /><figcaption>Background Image Courtesy: Photo by <a href="https://unsplash.com/@fempreneurstyledstock?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Leone Venter</a> on <a href="https://unsplash.com/s/photos/keyboard?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><h4>Tips and tricks for building your technical writing portfolio</h4><p>I love writing. I’ve been writing since 2012 on various platforms including Blogger, Wordpress, dev.to, Hashnode etc. on topics including NodeJS, JavaScript, Security, Developer productivity. I feel that, blogging shaped me into a better written communicator as well as a better developer than I was in terms of technical knowledge, thirst for knowledge and curiosity on how things work under the hood.<br>From the responses I received and through Medium story statistics (Views, View-to-read ratio, Claps etc.), during the past couple of years I’ve learned a few tricks in terms of structuring an article and conveying an idea. Though I still have a lot to learn and improve, I thought of sharing what I learned so far and my approach to writing technical content. Though I might use some Medium-related references, this guide is not necessarily limited to writing on Medium.</p><h3>Why should you write…</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*e5sNaLs8JDV_FAutmei0fA.jpeg" /><figcaption>Photo by <a href="https://unsplash.com/@annaauza?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Anna Auza</a> on <a href="https://unsplash.com/s/photos/medium?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><p>I don’t have the greatest memory. So, I started writing what I learn as a way of refreshing my memory in case if I forget what I learned. Yes, it’s a great reason to write. I frequently revisit my own articles to recall certain topics I no longer remember. Apart from that, there are a couple of other reasons why writing could be beneficial to you.</p><ul><li><strong>Feedback from readers</strong> — Positive/Negative feedback, as well as follow-up questions from your readers, are invaluable for learning. Sometimes readers will have questions that you need to learn even more in order to answer.</li><li><strong>Refer to your own writing later</strong> — As I mentioned before, you will find yourself occasionally going back to read your own articles to recall your memory.</li><li><strong>Improves your writing skills</strong> — Writing technical content will improve your written communication skills. It will help you explain technical things to others clearly and concisely in documentation, emails, chats etc.</li><li><strong>Good for your profile </strong>— Having your own blog or a technical writing portfolio will definitely help you stand out. It’ll help you even more, and draw more attention if you carefully plan your writing to cover in-demand but less-documented topics.</li><li><strong>Give back to the community which you thrive upon </strong>— How many technical tutorials, blog posts and articles have you read during your career? Now it’s time for you to share what you know and help someone like you.</li></ul><h3>What to write and How to write…</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*5rXejhcKLorK7JiXnQH-tg.jpeg" /><figcaption>Photo by <a href="https://unsplash.com/@homajob?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Scott Graham</a> on <a href="https://unsplash.com/s/photos/research?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><p>Everyone has a unique way of writing. Here’s my approach to writing a new article.</p><ul><li><strong>Select a good topic</strong> — Internet is vast. Therefore, don’t worry too much that you don’t have some unique topic to write about. No matter how unique we may feel our write up is, it’s always possible that there’s similar content somewhere on the internet. That said, if you write something less common yet in-demand, you will likely draw more crowd.</li><li><strong>Create a draft outline</strong> — Once you have selected a topic to write about, create a draft first and then outline the sections and sub-sections to fill later. This can be done based on what you have off the top of your head and doesn’t have to be the final outline of the article.</li><li><strong>Spend a lot of time researching </strong>— When the draft outline is ready and you know what you want to write, then start researching about the topic. In my case, I refer to as many resources as possible about the topic and try to get a deep enough understanding of the subject. The more you research, the more questions you will have which will force you to learn even more. Having a deep understanding of the topic will help you write a concise article and answer questions readers may have.</li><li><strong>Write</strong> — Once you are done researching, check if your outline is still relevant. If not, modify it and get the final outline. Once done, fill the sections and subsections with the content you’d like to write. I wouldn’t worry too much about typos, grammar, understandability and how detailed my writing is at this stage. The goal is just to fill the sections and subsections and get a complete draft.</li><li><strong>Refine, Refine, Refine</strong> — Now it’s time to refine your write-up. Read the article from start to bottom from a reader’s perspective and fix any typos and grammar issues. As you read, you will find unclear content in the article. Try to reword those content or add more details to convey the point clearly. Do this a few times until you are confident that it’s ready to be published. It might also be a good idea if you could ask someone to proofread it before publishing.</li></ul><h3>What you shouldn’t do…</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*94lneMKTosyiPG7EN4nX6A.jpeg" /><figcaption>Photo by <a href="https://unsplash.com/@will0629?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Will Porada</a> on <a href="https://unsplash.com/s/photos/stop-sign?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><ul><li><strong>Too detailed </strong>— If an article is too long and detailed, it’s very likely that readers lose interest in reading it halfway through. Medium’s product science team has found out that <a href="https://medium.com/data-lab/the-optimal-post-is-7-minutes-74b9f41509b">the optimum post is 7 minutes long</a> based on the reader engagement statistics. But it doesn’t mean that you shouldn’t write longer articles. You can use code snippets, diagrams, graphs, images, GIFs etc. to keep the reader engaged in a long article.</li><li><strong>Unnecessarily broken down to multiple parts </strong>— I’ve seen many occasions where writers on Medium are too focused on earning money therefore have unnecessarily broken down their articles into a series of very small articles as Part 1, Part 2 etc. This makes each individual part of the article series useless on its own. Doing this won’t give you any significant short term monetary benefit, but will only hurt your profile in the long run.</li><li><strong>Text-only </strong>—It’s not a secret that the readers are very likely to engage with an article more (more followers, more reads and more claps) if it contains visuals such as diagrams, graphs, images etc. Text-only articles are very hard to follow and boring, especially if they are too long. If you embed code snippets, make sure that they are short and easily understandable. Also, it would be better to embed code snippets in ‘pretty’ format using GitHub gists or a similar tool rather than pasting them directly.</li><li><strong>Clickbait titles</strong> — Medium is bloated with clickbait titles. There’s nothing wrong with starting your article title as “5 things you should…”, “Top 10 things you must…” &amp; etc. But if you do, make sure your article is actually worth a visit for a reader. If the content is also as juicy as the title, people are very likely to follow you and engage more. Clickbaits can harm you in the long run and damage your portfolio. They are likely to annoy readers and repel them away from your future content.</li></ul><p>I wrote this guide from my personal experience as a writer as well as a reader. I’d be very glad to hear your thoughts if you have a different opinion on any of the points I mentioned. In that case, please don’t hesitate to respond.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=bbc663fca981" width="1" height="1" alt=""><hr><p><a href="https://blog.insiderattack.net/starting-your-own-tech-blog-bbc663fca981">Starting Your Own Tech Blog</a> was originally published in <a href="https://blog.insiderattack.net">Deepal’s Blog</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[A Visual Guide to NodeJS Streams]]></title>
            <link>https://blog.insiderattack.net/a-visual-guide-to-nodejs-streams-9d2d594a9bf5?source=rss-f767215a3aee------2</link>
            <guid isPermaLink="false">https://medium.com/p/9d2d594a9bf5</guid>
            <category><![CDATA[nodejs]]></category>
            <category><![CDATA[node]]></category>
            <category><![CDATA[node-js-tutorial]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[stream]]></category>
            <dc:creator><![CDATA[Deepal Jayasekara]]></dc:creator>
            <pubDate>Thu, 10 Jun 2021 01:18:28 GMT</pubDate>
            <atom:updated>2022-03-18T09:15:37.843Z</atom:updated>
            <content:encoded><![CDATA[<h3>A Visual Guide to NodeJS Streams — Advanced NodeJS Part 4</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Ea9ZoWv5Qpa2OHDkqR7neA.jpeg" /><figcaption>Background Image Courtesy: Photo by <a href="https://unsplash.com/@sortino?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Joshua Sortino</a> on <a href="https://unsplash.com/s/photos/digital?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><p>Imagine you have a pile of bricks somewhere. And you want to build a wall with those bricks here. Let’s say you have a friend to help move the bricks. To start building, you now have two options. You can either wait until your friend brings the whole pile of bricks to you, or you can start building as soon as you have a few bricks to start with, while your friend keeps bringing more bricks.</p><p>Which would be efficient? <strong>Clearly, it will be efficient to start building as soon as you have a few bricks to start with. </strong>This is a classic example of how a ‘stream’ (in this case a stream of bricks) can improve the efficiency of a process. Another common example you might be very familiar with would be streaming a movie instead downloading the whole movie first and and watch it.</p><p><a href="https://en.wikipedia.org/wiki/Stream_(computing)">Wikipedia says</a>,</p><blockquote>In computer science, a <strong>stream</strong> is a sequence of data elements made available over time. A stream can be thought of as items on a conveyor belt being processed one at a time rather than in large batches.</blockquote><p>In NodeJS, <a href="https://nodejs.org/api/stream.html">stream</a> module provides the capability to work with streams. Even if you haven’t used stream module explicitly there are a lots of underlying functionality in NodeJS applications which use streams. “Streams” is an easy concept, but it may sound very complex if you are unfamiliar with it. Therefore, I thought of describing a few key concepts in NodeJS streams in visuals so that it can be easily understood.</p><p>This article is the 4th article of my <strong>Advanced NodeJS </strong>Series which is a sequel to <a href="https://blog.insiderattack.net/event-loop-and-the-big-picture-nodejs-event-loop-part-1-1cb67a182810">my series on Node.js Event Loop</a>. You can find the other articles of the <strong>Advanced NodeJS </strong>series below:</p><h3>Post Series Roadmap</h3><ul><li><a href="https://blog.insiderattack.net/crossing-the-js-c-boundary-advanced-nodejs-internals-part-1-cb52957758d8">Crossing the JS/C++ Boundary</a></li><li>Deep Dive into Worker Threads in Node.js</li><li><a href="https://blog.insiderattack.net/understanding-async-resources-with-async-hooks-3416de574f30">Understanding Async Resources with Async Hooks</a></li><li><a href="https://blog.insiderattack.net/a-visual-guide-to-nodejs-streams-9d2d594a9bf5"><strong>A Visual Guide to NodeJS Streams (This article)</strong></a></li><li><a href="https://blog.insiderattack.net/nodejs-streams-in-practice-980b3cdf4511">NodeJS Streams in Practice</a></li><li><a href="https://blog.insiderattack.net/how-not-to-measure-time-in-programming-11089d546180">Why you should avoid Date.now() to measure time durations</a></li></ul><h4>Water flows, Information flows.</h4><p>Information is like a liquid. It flows from one place to another place as a stream of bits. For example, this happens when two peers talking to each other via a network, or even when your application is communicating with the disk or a peripheral device. When such an I/O operation happens, the information is read from a device and is flowed towards an application, or vice versa.</p><p>However, it’s possible that one end of the above transaction is slower than the other for various reasons. Therefore, some of the data might need to be “buffered” in-between, while the receiver-end is ready to accept more data.</p><p>Have a look at the following picture where two faucets of different sizes are connected via a tank. The rate water flows from upstream is higher than the rate downstream can consume. Therefore, the tank has to temporarily store (“buffer”) the excess water while the downstream slowly consumes.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/433/1*5T_Ap0Qd2dS3637XEM-IzQ.png" /></figure><p>This is the fundamental idea of streams in NodeJS. stream module provides functionality to implement this behaviour when working with streaming data. There are two basic types of streams provided by NodeJS.</p><p>They are,</p><ul><li>Readable Streams</li><li>Writable Streams</li></ul><p>However, there are two additional types of streams which are hybrids of Readable and Writable streams, and serve special purposes.</p><ul><li>Duplex Streams</li><li>Transform Streams</li></ul><p>Let’s get into more details, and try to visualise each of these.</p><h4>Readable Stream</h4><p>A readable stream can be used to read data from an underlying source such as a file descriptor. Data can be stored in a <a href="https://nodejs.org/api/stream.html#stream_buffering">Buffer</a> within the readable stream if the application consumes slower than the operating system reads from the source.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*QcVF_5C7WtJx_ohqJJ8dYw.png" /></figure><p>A few of the most common readable streams in NodeJS are <a href="https://nodejs.org/api/process.html#process_process_stdin">process.stdin</a>, <a href="https://nodejs.org/api/fs.html#fs_fs_createreadstream_path_options">fs.createReadStream</a> and <a href="https://nodejs.org/api/http.html#http_class_http_incomingmessage">IncomingMessage</a> object in an HTTP server.</p><h4>Writable Stream</h4><p>A Writable stream is used to write data from an application to a certain destination. To prevent data loss or overwhelming of the destination in case the destination is slower than the writing application, the data may be stored in an internal <a href="https://nodejs.org/api/stream.html#stream_buffering">Buffer</a>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*zGPIBCmXFqzSowUmlpfs-Q.png" /></figure><p>The most common writable stream which you might use every day would be <a href="https://nodejs.org/api/process.html#process_process_stdout">process.stdout</a> which is used underneath console.log. In addition to that, two other very common writable streams in NodeJS are <a href="https://nodejs.org/api/process.html#process_process_stderr">process.stderr</a> and fs.createWriteStream</p><h4>Duplex Stream</h4><p>As I mentioned earlier, a duplex stream is a hybrid of a Readable stream and a Writable stream. An application connected to a duplex stream can both read from and write to the duplex stream. The most common example of a duplex stream is <a href="https://nodejs.org/api/net.html#net_class_net_socket">net.Socket</a>. In a duplex stream, read and write parts are independent and have their own buffers.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*V51BbjIa70RblrM7aEKxgg.png" /></figure><h4>Transform Stream</h4><p>A transform stream is an even special hybrid, where the Readable part is connected to the Writable part in some way. A common example would be a crypto stream created using <a href="https://nodejs.org/api/stream.html#stream_buffering">Cipher</a> class. In this case, the application writes the plain data into the stream and reads encrypted data from the same stream.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*XBLmT-C8NhRJ9Z1eCIvtng.png" /></figure><p>Probably the most trivial transform stream is <a href="https://nodejs.org/api/stream.html#stream_class_stream_passthrough">PassThrough</a>, where the input data is simply passed as the output with no transformation whatsoever. While it may sound very trivial, I’ve used it many times to implement custom behaviours with streams.</p><h4>Piping Streams</h4><p>In many cases, streams are even more useful when connected together. As obvious as it may sound, this is called ‘piping’. You can connect a Readable stream to another Writable/Duplex or a Transform stream by using the Readable stream’s pipe() method.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*rKroHjnDgnO45qm79CgDRg.png" /></figure><p>A trivial example for this would be copying a file from one place to another place by piping an fs.createReadStream() to an fs.createWriteStream().</p><h4>Copying Data with Streams</h4><p>One interesting fact about piping is that you can pipe the same stream more than once. This can be very useful in situations where you need to read the same stream twice, as you cannot read from a Readable stream once again after it’s completely read by another consumer. However, by piping a Readable stream more than once, more than one consumers can read the same stream by copying the data from the original Readable stream.</p><p>Have a look at the following simple example, where we create two copies of the original.txt file.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/5c457ea70564942b9236e0edae1f8ca9/href">https://medium.com/media/5c457ea70564942b9236e0edae1f8ca9/href</a></iframe><p>The above program can be visualised as follows:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*nfu8H19tk5Lb3BXB4cVslg.png" /></figure><h4>Backpressure</h4><p>Let’s go back and recap our water tank analogy. In that analogy, the upstream flows at a higher rate than the downstream can consume. In this case, the water level of the tank will keep rising until at some point it overflows and the water goes to waste.</p><p>What if we can ‘detect’ it’s going to happen and let the upstream know to stop the flow? We can mark the tank below the highest level, and ask the upstream to stop when the water level rises above the mark.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*K_lj7KgSy4UUpHzinvnFsA.png" /></figure><p>This is very similar to how streams work. While Readable and Writable streams can buffer data internally, the amount of data they can buffer is limited by the total available memory of the system. Therefore, streams have a threshold called highWaterMark which can be used to detect if the rate at which data is passed into the stream is way higher than the rate at which data is flushed out of the stream.</p><p>As an example, when a readable stream is piped to a writable stream, the writable stream can ask the readable stream to stop the flow if the writable stream’s buffer fills beyond the highWatermark.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*8w6vKRS0tOM1lbrIVlOjpA.png" /></figure><p>While highWaterMark is not a hard limit but only a threshold, it’s important to adhere to that threshold when building custom streams to avoid data losses or undesirable memory usage. You can read more about this <a href="https://nodejs.org/api/stream.html#stream_buffering">in the official documentation</a>.</p><h4>Let’s put them all together</h4><p>So far, we discussed different types of streams and how to use them. Let’s now try to put them all together and visualise a real-life example.</p><p>The following is a design of a simple image service I built some time back. In this service, an image is retrieved from an S3 bucket, and served as a resized image to the end-user.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Mgsr9DBac9n5xRL1qnqBRg.png" /></figure><p>If we build this without streams, we will fetch the whole file from the S3 bucket and keep it in the memory, resize the whole image at once, and then send the resized image to the end-user.</p><p>However, with streams, we can chain the above process in a very efficient manner to improve speed and optimise the memory usage in our application.</p><p>Since the data stream coming from the S3 bucket is a readable stream, we can pipe it straightaway to a transform stream where it’s resized. Since the transform stream is also readable, we can pipe it to the response stream directly so that a chunk of data coming from the S3 bucket is resized and sent to the user without having to wait for the whole file from S3 bucket.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*9_a9Fpk8MSlkZEi7V0q87Q.png" /></figure><blockquote>If you are curious, feel free to try to build this API on your own and let me know if you have any questions. Tip: You can have a look at <a href="https://sharp.pixelplumbing.com/">sharp</a> NPM module which can be used to build the image processing capability. Although, sharp uses Duplex streams instead of Transform streams at the time of this writing due to the reason <a href="https://github.com/lovell/sharp/issues/1704">mentioned here</a>.</blockquote><p>Ready to dive into how NodeJS streams can be used to build complex applications? Check out my the next article about ‘<strong>NodeJS Streams in Practice</strong>’ below.</p><p><a href="https://blog.insiderattack.net/nodejs-streams-in-practice-980b3cdf4511">NodeJS Streams in Practice</a></p><p>In this article, I wanted to visualise a few of the key concepts in NodeJS streams for ease of understanding. Please let me know if you have any feedback on this article which will be very helpful for me not only to improve this article but to write more helpful and detailed content in the future. I plan to write a few more detailed articles about the advanced concepts in streams, memory leaks and many more. So stay tuned in. Thanks.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=9d2d594a9bf5" width="1" height="1" alt=""><hr><p><a href="https://blog.insiderattack.net/a-visual-guide-to-nodejs-streams-9d2d594a9bf5">A Visual Guide to NodeJS Streams</a> was originally published in <a href="https://blog.insiderattack.net">Deepal’s Blog</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Understanding Async Resources with Async Hooks]]></title>
            <link>https://blog.insiderattack.net/understanding-async-resources-with-async-hooks-3416de574f30?source=rss-f767215a3aee------2</link>
            <guid isPermaLink="false">https://medium.com/p/3416de574f30</guid>
            <category><![CDATA[node]]></category>
            <category><![CDATA[asynchronous]]></category>
            <category><![CDATA[nodejs]]></category>
            <category><![CDATA[asynchooks]]></category>
            <category><![CDATA[javascript]]></category>
            <dc:creator><![CDATA[Deepal Jayasekara]]></dc:creator>
            <pubDate>Sun, 16 May 2021 19:37:56 GMT</pubDate>
            <atom:updated>2022-03-18T09:10:36.257Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*kXXx-kB0kYg3PJJwED97FA.jpeg" /><figcaption>Background Image Courtesy: Photo by <a href="https://unsplash.com/@vidarnm?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Vidar Nordli-Mathisen</a> on <a href="https://unsplash.com/s/photos/fishing?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><h4>Advanced NodeJS — Part 3</h4><p>This article is the third article of my <strong>Advanced NodeJS Internals</strong> Series, which is a sequel to <a href="https://blog.insiderattack.net/event-loop-and-the-big-picture-nodejs-event-loop-part-1-1cb67a182810">my previous series on Node.js Event Loop</a>. You can find the other articles of the <strong>Advanced NodeJS Internals</strong> series below:</p><h4>Post Series Roadmap</h4><ul><li><a href="https://blog.insiderattack.net/crossing-the-js-c-boundary-advanced-nodejs-internals-part-1-cb52957758d8">Crossing the JS/C++ Boundary</a></li><li><a href="https://blog.insiderattack.net/deep-dive-into-worker-threads-in-node-js-e75e10546b11">Deep Dive into Worker Threads in Node.js</a></li><li><strong>Understanding Async Resources with Async Hooks (This article)</strong></li><li><a href="https://blog.insiderattack.net/a-visual-guide-to-nodejs-streams-9d2d594a9bf5">A Visual Guide to NodeJS Streams</a></li><li><a href="https://blog.insiderattack.net/nodejs-streams-in-practice-980b3cdf4511">NodeJS Streams in Practice</a></li><li><a href="https://blog.insiderattack.net/how-not-to-measure-time-in-programming-11089d546180">Why you should avoid Date.now() to measure time durations</a></li></ul><h4>Prologue</h4><p>A real-life NodeJS application can be very complex in terms of the asynchronous operations it performs, and the asynchronous resources that are created and destroyed as part of those operations. The ability to inspect the lifecycles of these asynchronous resources from user-land code can be very useful because it can provide us a lot of insights about the application, especially about its performance and potential optimisations that can be done.</p><p>There has been a lot of work done by the Node community to expose this advanced functionality to user-land code (previous attempts with <a href="https://github.com/nodejs/node-v0.x-archive/pull/6011">AsyncListener</a> and <a href="https://github.com/nodejs/node-v0.x-archive/commit/709fc160e5">async_wrap</a>) and thanks to all that effort we now have async_hooks, a mature implementation to trace the lifecycle of asynchronous resources. It’s still documented as “Experimental” at the time of this writing, but it has been polished and shaped over time, to be more stable than a typical experimental API.</p><p>async_hooks module provides a world of new capabilities, but what I’m mostly interested in as a Node.js enthusiast is, it allows you to easily understand what happens under the hood of some of the tasks we frequently perform in our applications such as reading a file, making an HTTP request, spawning an HTTP server, perform a database query, etc., in a way that was not possible before.</p><p>In this article, I will try to demonstrate and explain the life cycle of a typical asynchronous resource with the help of async_hooks module.</p><blockquote><strong><em>Before moving on…</em></strong></blockquote><blockquote><em>Please note that this is not a tutorial for async hooks since I didn’t want to repeat the official documentation in a blog post. If you are completely new to </em><em>async_hooks or would like to learn learn how to use async hooks, I’d strongly recommend first reading </em><a href="https://medium.com/r?url=https%3A%2F%2Fnodejs.org%2Fapi%2Fasync_hooks.html"><em>official docs</em></a><em> and this very useful article on </em><a href="https://itnext.io/a-pragmatic-overview-of-async-hooks-api-in-node-js-e514b31460e9"><em>“A Pragmatic Overview of Async Hooks API in Node.js”</em></a><em> from </em><a href="https://medium.com/u/9a27eb90e406"><em>Andrey Pechkurov</em></a><em>. Also, I would assume that you have a basic understanding of how Node JS asynchronous model works.</em></blockquote><h3>The lifecycle of an Asynchronous Resource</h3><p>Async resources are created as part of asynchronous operations. Async resources are nothing but objects that are used to keep track of asynchronous operations. Therefore, they are naturally associated with a callback that will be executed once the operation completes. Once the async resource serves its purpose, it can be garbage collected like any other object.</p><p>A very simple example would be setTimeout. setTimeout function returns the async resource (Timeout) that is creates to track the timer as the return value of the function. You can see it by calling setTimeout in the Node REPL as follows:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*KQ2KyCqmzkYkwv4d8FAPQA.png" /><figcaption>Timeout async resource created as part of setTimeout()</figcaption></figure><p>This object contains useful information such as:</p><ul><li>Its timeout value (_idleTimeout)</li><li>Timer callback (_onTimeout)</li><li>Whether it’s a timer or an interval (_repeat)</li><li>whether the timeout is active or not (_destroyed)</li></ul><p>The typical lifecycle of such an async resource is similar to this:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Av-3u-xgt5wIEUyNAhXsbQ.png" /><figcaption>Lifecycle of an async resource</figcaption></figure><p>What “Async hooks” facilitate you is the ability to spy on different stages of the above lifecycle by providing “hooks”, to which we can attach callback functions. There are four common types of such hooks as init, before, after and destroy. And they are fired at the following four stages of an async resource’s lifecycle.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*47pCugjsyFxauRjYXxzCnw.png" /><figcaption>Common async hooks</figcaption></figure><p>Depending on whether the async resource is persistent or not (I will get to this later), the async resource’s callback may be executed 0 to many times. Therefore, it can be expected that before and after hooks may be called multiple times for certain async resources, or may not be called at all. For example with setTimeout, before and after each will only be fired <strong>at most once</strong> followed by an init, whereas with setInterval, there can be multiple before and after invocations followed by one init.</p><p>For example, both setTimeout and setInterval create Timeout async resources. However, the Timeout resource created by setInterval is a persistent Timeout resource and can be identified by the non-null __repeat property.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*6l0g7qgv1m4Jc6_CFgQ_BA.png" /><figcaption>Timeout resource created by setInterval</figcaption></figure><p>Promise objects are slightly different and they have one more additional hook called promiseResolve which is fired right after the promise is resolved or rejected.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*gqgTMWCBGY_yk68Zi-vEqA.png" /></figure><h3>Async Resources in real-life applications</h3><p>In a real-life application, one async resource may trigger lots of async resources during its lifetime. With the above-discussed details in mind, let’s have a look at the following hypothetical example of an HTTP request handler.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*YCJYI7nBuscjOnu9tTnXMw.png" /></figure><p>The purpose of this HTTP request handler is to</p><ul><li>Receive some data via HTTP</li><li>Store it in a database</li><li>Notify an upstream service via HTTP</li><li>Write a log message to stdout</li></ul><p>Assuming that the above four operations create only four asynchronous resources, let’s try to plot the timelines of those four resources in a graph as follows (the lengths of the timelines are not drawn to scale). Feel free to spend a few minutes to read the graph, and try to correlate the timelines of the resources with what we discussed about the lifecycle of the async resources.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*FAkICSvGkK6qDKBjYbr2ZA.png" /></figure><p>A few important details from the above graph are:</p><ul><li>DB Operation timeline doesn’t span beyond the end of HTTP Client Request and Write Log Message timelines because the callback of the storeInDB function doesn’t wait until notifyUpstream and writeLog functions complete their async operations.</li><li>Write Log Message is also an async operation, hence it creates an async resource. This resource is short-lived compared to the other resources.</li><li>Incoming HTTP Request is the last resource to be destroyed because it will only be destroyed once the notifyUpstream completes and the response has been completely sent.</li></ul><h3>Practical examples with Timers</h3><p>Since we now have a theoretical understanding of the lifecycles of the async resources, let’s have a look at some practical examples. For this demo, I’ll be using a few code examples with async hooks set up. You can check out the source code for the examples here: <a href="https://github.com/deepal/async-hooks-demo">https://github.com/deepal/async-hooks-demo</a>. And I’d like to suggest reading the <a href="https://github.com/deepal/async-hooks-demo/blob/master/README.md">README.md</a> of the repository and set up the examples in your local machine before continue reading.</p><h4>Setting a timer</h4><p>(<a href="https://github.com/deepal/async-hooks-demo/blob/master/settimeout.js">Source code</a>, Used NodeJS version: 14.16.1)</p><p>As a start, let’s look at the simplest example. In this example, I’m creating a timer with 1000ms timeout and writing “timer callback” text to a log file using logger.write function.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*AS_Nbo62XaAHUkrH9c1LIw.png" /></figure><p>When I run the above piece of code along with my async hooks set up, I will see the following output in my log file.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*UbzNyZ5S9EYchsPe9UdrhA.png" /></figure><p>According to this output,</p><ul><li>A Timeout async resource was initialised when setTimeout was called.</li><li>After the 1000ms timeout expired, before async hook was invoked right before the timer callback was executed.</li><li>Timer callback executed and &quot;timer callback&quot; text was logged.</li><li>After the timer callback executed, after async hook was invoked.</li><li>Timeout resource was destroyed and the destroy hook was invoked.</li></ul><h4>Setting a nested timer</h4><p>(<a href="https://github.com/deepal/async-hooks-demo/blob/master/settimeout-nested.js">Source code</a>, Used NodeJS version: 14.16.1)</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*MLZqV46GcZZB5d7wDLpA8w.png" /></figure><p>The above example produces the following log.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*1WFPIlmgU7C7vjqPQYsBcQ.png" /></figure><p>In this example, the Timeout resource of the outer timer triggers another Timeout resource when the timer callback is executed. You can see that the inner timer’s Timeout resource has triggerAsyncId as 2, which is the asyncId of the outer timer’s Timeout resource. This indicates that the inner timer was triggered by the outer timer.</p><p>However, it’s worth mentioning that the outer Timeout resource was destroyed before the inner Timeout resource because the outer timer doesn’t wait until the inner timer is expired and the callback is executed.</p><h4>Clearing a created timer</h4><p>(<a href="https://github.com/deepal/async-hooks-demo/blob/master/cleartimeout.js">Source code</a>, Used NodeJS version: 14.16.1)</p><p>In the following example, we create a new timer by calling setTimeout, and the created timer is immediately removed by calling clearTimeout and passing the created Timeout object to it.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*IycPKbAjeulf7zGoQiArFQ.png" /></figure><p>In this case, we don’t see BEFORE or AFTER log messages because the timer was immediately removed and the callback didn’t get the chance to be executed due to the clearTimeout call. Therefore, before and after hooks were not invoked.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*lC25tcfpyCh_9HNdtdCJ1g.png" /></figure><h4>Creating an interval</h4><p>(<a href="https://github.com/deepal/async-hooks-demo/blob/master/setinterval.js">Source code</a>, Used NodeJS version: 14.16.1)</p><p>The following code creates an interval to schedule a callback to be executed every second, 3 times.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*d3pJYEJZTEr4Gmt30uYDpw.png" /></figure><p>Similar to setTimeout, this also creates a Timeout async resource. However, the Timeout resource created by setInterval is a persistent async resource. In persistent async resources, before and after hooks may be called multiple times before the resource is destroyed. In this example, the timer callback is called 3 times. Therefore we can see that the before and after hooks fired 3 times before the timer was destroyed by clearInterval.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Ejan6k4fKDFLABNAoSytGw.png" /></figure><h3>Practical examples with Custom Async Resources</h3><p>So far we talked about Timeout objects which are native NodeJS async resources. async_hooks module also provides the facility to write your own custom async resources by using the JS Embedder API’s AsyncResource class.</p><blockquote>You can learn more about AsyncResource class and how to use it from the <a href="https://nodejs.org/api/async_hooks.html#async_hooks_javascript_embedder_api">official docs</a>.</blockquote><h4>A Custom Async Resource with automatic destroy</h4><p>(<a href="https://github.com/deepal/async-hooks-demo/blob/master/custom-async-resource-auto-destroy.js">Source code</a>, Used NodeJS version: 14.16.1)</p><p>The following is a custom async resource I’ve written which aims to track a database query. For the sake of simplicity, I haven’t added any actual DB operations.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ZSvYslOoHxCcoY4au0nOIw.png" /><figcaption>Custom async resource</figcaption></figure><p>Before moving any further, I’d like to point out a few key pieces from the above code.</p><ul><li>requireManualDestroy flag is set to false. Which instructs that, if there are any destroy hooks for the resource, they should be automatically fired when the resource is garbage collected. This is internally done in NodeJS by registering the destroy hook as a “<strong>Weak Callback</strong>” on the resource object in v8. (<a href="https://source.chromium.org/chromium/chromium/src/+/master:v8/include/v8.h;l=546?q=SetWeak&amp;ss=chromium">v8 Weak Callbacks are scheduled to run when the object is garbage collected</a>).</li><li>At the end of the code, I’ve added a large timer which causes the application to keep running for some time before exiting. I’ll get to the reason behind this in a moment.</li></ul><p>Let’s run this program with --trace-gc Node CLI flag so that we can see the garbage collection logs.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*tnb5BP5UHO54VNIFGAjFmg.gif" /></figure><p>As you may have noticed, the resource is garbage collected during the immediate run of <a href="https://v8.dev/blog/trash-talk#major-gc">Mark-sweep</a> and it triggered the destroy hook.</p><p>Since setTimeout callback doesn’t use the dbquery object, after the setTimeout is executed there will be no references to the dbquery object to keep it from being garbage collected. This explains why it was garbage collected immediately.</p><blockquote><strong>What if we do not use that timer at all?</strong></blockquote><blockquote>If we do not use this timer, the application will exit immediately and the garbage collector will not get the opportunity to run. Therefore, the destroy hook won’t be fired at all. For this purpose you can also use any other async operation which keeps the program from exiting. But I used a timer to avoid the logs being cluttered too much.</blockquote><p>Let’s now look at another example, where we keep the reference to dbquery object inside the timer callback.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*SNdgfPxvj0KCGKVv2MwNew.png" /></figure><p>If we run this with --trace-gc Node CLI flag, this will produce the following result.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*RbstxsQazfKKchQPcj0sVQ.gif" /></figure><p>You might notice that the destroy hook was not called at all because the resource was not garbage collected even if the garbage collection was run. The reason for this is that the created Timeout async resource is keeping a reference to the dbquery object inside the timer’s callback, thereby preventing the dbquery from being garbage collected.</p><h4>A Custom Async Resource with manual destroy</h4><p>(<a href="https://github.com/deepal/async-hooks-demo/blob/master/custom-async-resource-auto-destroy.js">Source code</a>, Used NodeJS version: 14.16.1)</p><p>In the previous example, we discussed async resources which are constructed with requireManualDestroy as false and observed how they automatically fired destroy hooks upon garbage collection. However, if we set requireManualDestroy to true when it was constructed, destroy hooks won’t automatically fire when the object is garbage collected, and you will have to fire them manually by calling emitDestroy() on the async resource.</p><p>Let’s look at the following example. In the following async resource, we have a destroy method that calls AsyncResource’s emitDestroy prototype function.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*NqheR4_MyN9j_A9BQM1UOQ.png" /></figure><p>The above code produces the following output when run.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*hMQQLHicZ1v3w2iPcI3vOQ.gif" /></figure><p>As you can see, destroy hook was immediately called after emitDestroy. If we omit dbquery.destroy() statement, the destroy hook will not be fired even if the object was garbage collected.</p><p>In this article, I tried to cover a few practical examples of using async hooks to understand the lifecycle of an async resource. To avoid this article being too lengthy, I didn’t delve into other types of async operations such as HTTP requests, File system access, Crypto operations, etc. But feel free to experiment with the other examples in the<a href="https://github.com/deepal/async-hooks-demo"> examples repository</a>, and let me know if you have any feedback/questions or suggestions. Thank you very much for reading.</p><p>You can follow me and <a href="https://blog.insiderattack.net/">https://blog.insiderattack.net</a> to get updates about future posts.</p><h4>Further References</h4><ul><li>Async Hooks | Node JS Docs <a href="https://nodejs.org/api/async_hooks.html">https://nodejs.org/api/async_hooks.html</a></li><li>A Pragmatic Overview of Async Hooks API in Node.jsA Pragmatic Overview of Async Hooks API in Node.js <a href="https://itnext.io/a-pragmatic-overview-of-async-hooks-api-in-node-js-e514b31460e9">https://itnext.io/a-pragmatic-overview-of-async-hooks-api-in-node-js-e514b31460e9</a></li><li>async_hooks: add AsyncLocal API mk2 <a href="https://github.com/nodejs/node/pull/31016">https://github.com/nodejs/node/pull/31016</a></li><li>async_hooks: introduce mandatory store argument in AsyncLocalStorage run methods <a href="https://github.com/nodejs/node/pull/31930">https://github.com/nodejs/node/pull/31930</a></li><li>src: remove TimerWrap <a href="https://github.com/nodejs/node/pull/20894">https://github.com/nodejs/node/pull/20894</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=3416de574f30" width="1" height="1" alt=""><hr><p><a href="https://blog.insiderattack.net/understanding-async-resources-with-async-hooks-3416de574f30">Understanding Async Resources with Async Hooks</a> was originally published in <a href="https://blog.insiderattack.net">Deepal’s Blog</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>