<?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" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ Okoye Chukwuebuka Victor - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ Okoye Chukwuebuka Victor - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Mon, 25 May 2026 22:37:18 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/author/victorokoye/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How to Partition Queues for Distributed Workloads ]]>
                </title>
                <description>
                    <![CDATA[ Technology, like human lives, evolves, and with this evolution comes the use of better solutions to existing problems. You might wonder: does this complicate systems or make them more efficient?  In this article, we will discuss some measures you can... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-partition-queues-for-distributed-workloads/</link>
                <guid isPermaLink="false">66bb51f411aa9b18314ed6b7</guid>
                
                    <category>
                        <![CDATA[ distributed systems ]]>
                    </category>
                
                    <category>
                        <![CDATA[ queue ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Okoye Chukwuebuka Victor ]]>
                </dc:creator>
                <pubDate>Thu, 23 May 2024 20:57:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/05/Networks-small.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Technology, like human lives, evolves, and with this evolution comes the use of better solutions to existing problems. You might wonder: does this complicate systems or make them more efficient? </p>
<p>In this article, we will discuss some measures you can take to make systems much more efficient and reliable.</p>
<h2 id="heading-what-is-a-distributed-system">What is a Distributed System?</h2>
<p>In a very simple way, a distributed system is a group or collection of independent computer nodes connected via a central unit which share and utilise computational resources. </p>
<p>Think of this as a network of systems which can interact and share tasks which they can process collectively as a single unit. Therefore distributed workloads refer to the processes or tasks that run in these systems.</p>
<p>Now, for these systems to interact efficiently, you can make use of some protocols or designs. One of them is a queue, which you'll learn about in the next section.</p>
<h2 id="heading-what-is-a-queue">What is a Queue?</h2>
<p>A queue is a data structure which models the First-In-first-Out Principle (FIFO).</p>
<p>To understand this, picture a checkout station in a supermarket. The first person to join the line will be the first to be attended to. Then subsequently, the next person is attended to. This is pretty much how queues works, but now as a data structure what is being processed can be different events or messages which we will identify as workloads.</p>
<p>Typically in a queue system, you have the <em>producer</em> and the <em>consumer.</em> The producer is the service that sends an event or in this context, a workload into the queue. And the consumer is the service that listens and processes it.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716417641517/d81577d0-d57a-457b-b92f-817481a7b863.png" alt="An Image showing a Producer, a Queue and a Producer." width="600" height="400" loading="lazy">
<em>Streamlining Workflows: Producers Feed the Queue, Consumers Process the Flow.</em></p>
<p>With the very nature of these systems, running queues across this network can be demanding and sometimes you resort to some challenges which will be discussed briefly.</p>
<h2 id="heading-challenges-of-long-running-queues-in-a-distributed-system"><strong>Challenges of</strong> L<strong>ong</strong>-R<strong>unning</strong> Q<strong>ueues in a</strong> D<strong>istributed</strong> S<strong>ystem.</strong></h2>
<p>The goal of a task queue is primarily to handle asynchronous or long-running tasks efficiently. </p>
<p>However, within the distributed system context, running workloads across a network can sometimes prove to be challenging as they become overwhelming for these queues. This can leads to problems such as the following:</p>
<ul>
<li><strong>Increase In Network Latency</strong>: Distributed systems primarily rely on communications across networks to efficiently coordinate workloads across the different computer nodes. Delayed or long-running tasks can lead to unpredictable response time(latency).</li>
<li><strong>Difficulty in tracking and monitoring</strong>: It can get very complex very quickly to track down each workload especially now that they are shared across different running systems in the network. In order to efficiently manage these you will have to make use of specialised tools such as the ELK Stack.</li>
<li><strong>Distributed Coordination</strong>: Ensuring that workloads being passed to different queues across the network are executed correctly and in the order they ought to is a challenge. Lack of this coordination further leads to data inconsistency.</li>
<li><strong>Fault Tolerance and Resilience</strong>: Processes running in a distributed system will surely contend with breakpoints and node failures. Having workloads in long-running queues can increase these failure points, which can lead to an increase in queue backlogs, data loss or inconsistency.</li>
</ul>
<p>The question is how best can you combat these issues, or what measures should you take to reduce the possibility of system failures or data inconsistency. An approach to solving this is by making use of partitioned task queues.</p>
<h2 id="heading-what-does-it-mean-to-partition-a-queue">What does it mean to partition a Queue?</h2>
<p>Partitioning can be defined as breaking down a component into smaller subsections. Using this, you can derive a definition for queue partition as breaking a queue system into smaller, more manageable bits to offload workloads in a faster and more efficient manner.</p>
<p>Picture a centralised queue with various workloads coming with different task types or even priorities.</p>
<p>When traffic or workloads are at a very high rate, this queue will eventually become overwhelmed and keep compiling backlogs. </p>
<p>In order to lift the burden you can divide the queue into various bits to handle different task types. For example, you can have a queue to handle priority tasks or even to process different event types, like notifications.‌</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716416776358/32a2fd40-6c2f-4d9e-8031-f32a356cc6e3.png" alt="An Image showing Clients(Producers) using a load balancing technique to assign workloads to queues and then workers processing the workloads." width="600" height="400" loading="lazy">
<em>Partitioned Queues in Distributed Systems: Optimizing Workload Management Across Nodes.</em></p>
<p>Primarily the goal of partitioning a queue is to improve system performance and reduce downtimes or data inconsistency. In order to do this, you have to look at different strategies of how to partition queues in other to know the one that is best suitable for your system.</p>
<h2 id="heading-effective-task-queue-partitioning-strategies">Effective Task Queue Partitioning Strategies</h2>
<p>There are various ways in which you can break a queue into subsections, but for you to be able to do that efficiently, you can employ some tested strategies such as Range-based Partitioning, Hash-based partitioning, and so on.</p>
<h3 id="heading-hash-based-partitioning">Hash-based partitioning</h3>
<p>This form of partitioning allows for the selection of a queue using an assigned hash value.</p>
<p>First off, a parameter in the workload is used to get a hash value. Then, you take the <em>modulo</em> of that value with the number of partitions (queues), which results in a partition index. This index is then used to determine the queue to which the task will be assigned.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> numPartitions = <span class="hljs-number">4</span>;

<span class="hljs-keyword">const</span> queues = <span class="hljs-built_in">Array</span>.from({ <span class="hljs-attr">length</span>: numPartitions }, <span class="hljs-function">(<span class="hljs-params">_, i</span>) =&gt;</span> ({
    <span class="hljs-attr">name</span>: <span class="hljs-string">`Queue <span class="hljs-subst">${i + <span class="hljs-number">1</span>}</span>`</span>,
    <span class="hljs-attr">partitionIndex</span>: i + <span class="hljs-number">1</span>,
}));

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getPartitionIndex</span>(<span class="hljs-params">hash</span>) </span>{
    <span class="hljs-keyword">const</span> partitionIndex = hash % numPartitions;
    <span class="hljs-keyword">return</span> partitionIndex + <span class="hljs-number">1</span>;
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">hashCode</span>(<span class="hljs-params">str</span>) </span>{
    <span class="hljs-keyword">let</span> hash = <span class="hljs-number">0</span>;
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; str.length; i++) {
        <span class="hljs-keyword">const</span> char = str.charCodeAt(i);
        hash = ((hash &lt;&lt; <span class="hljs-number">5</span>) - hash) + char;
    }
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">Math</span>.abs(hash);
}

<span class="hljs-keyword">const</span> tasks = [
    { <span class="hljs-attr">id</span>: <span class="hljs-number">1</span>, <span class="hljs-attr">value</span>: <span class="hljs-string">"Emails Task"</span> },
    { <span class="hljs-attr">id</span>: <span class="hljs-number">2</span>, <span class="hljs-attr">value</span>: <span class="hljs-string">"Transactions Tasks"</span>},
    { <span class="hljs-attr">id</span>: <span class="hljs-number">3</span>, <span class="hljs-attr">value</span>: <span class="hljs-string">"Orders Tasks"</span> },
    { <span class="hljs-attr">id</span>: <span class="hljs-number">4</span>, <span class="hljs-attr">value</span>: <span class="hljs-string">"Update Tasks"</span> },
];

tasks.forEach(<span class="hljs-function"><span class="hljs-params">task</span> =&gt;</span> {
    <span class="hljs-keyword">const</span> hash = hashCode(task.value);
    <span class="hljs-keyword">const</span> partitionIndex = getPartitionIndex(hash);
    <span class="hljs-keyword">const</span> assignedQueue = queues.find(<span class="hljs-function"><span class="hljs-params">queue</span> =&gt;</span> queue.partitionIndex === partitionIndex);
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Task with ID: <span class="hljs-subst">${task.id}</span> (content: <span class="hljs-subst">${task.value}</span>) assigned to <span class="hljs-subst">${assignedQueue ? assignedQueue.name : <span class="hljs-string">"no queue"</span>}</span>`</span>);
});
</code></pre>
<p>The above example involves hashing a particular value or field in the workload or event that is to be assigned. In this case, the content field was hashed, and its hash value was then used to determine which queue the workload will be assigned to. This hash value might appear random but in truth it is constant, meaning the same input will always produce the same hash value.</p>
<pre><code class="lang-bash">Task with ID: 1 (content: Emails Task) assigned to Queue 3
Task with ID: 2 (content: Transactions Tasks) assigned to Queue 4
Task with ID: 3 (content: Orders Tasks) assigned to Queue 4
Task with ID: 4 (content: Update Tasks) assigned to Queue 2
</code></pre>
<p>Seeing the output, if you were to change the content of one of these tasks, you will see that they will get another hash value and might be assigned to a different queue. </p>
<p>In a real-life scenario, if you want the workloads to be distributed amongst different queues, you should ensure the hash value is something unique among tasks, like its Identifier. You can make use of an UUID.</p>
<h3 id="heading-range-based-partitioning"><strong>Range</strong>-<strong>based Partitioning</strong></h3>
<p>This strategy allows you to spread tasks or workloads coming from a centralised workload into subsections based on a range of task IDs. For example, queue A might only allow a task ID that falls within the range of 1 - 50, while queue B handles the task with an ID ranging from 51- 100.‌</p>
<p>‌This strategy ensures that tasks are distributed across each partition in order to efficiently utilise the resources available and ensure workloads are distributed.</p>
<p>Take a look at this code example below that shows how tasks are assigned to a partition based on the range their IDs fall in:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> { <span class="hljs-attr">v4</span>: uuidv4 } = <span class="hljs-built_in">require</span>(<span class="hljs-string">"uuid"</span>);

<span class="hljs-keyword">const</span> numPartitions = <span class="hljs-number">4</span>;
<span class="hljs-keyword">const</span> partitionRanges = <span class="hljs-built_in">Array</span>.from({ <span class="hljs-attr">length</span>: numPartitions }, <span class="hljs-function">(<span class="hljs-params">_, i</span>) =&gt;</span> ({
    <span class="hljs-attr">start</span>: i * <span class="hljs-number">250</span>,
    <span class="hljs-attr">end</span>: (i + <span class="hljs-number">1</span>) * <span class="hljs-number">250</span>,
}));

<span class="hljs-keyword">const</span> queues = <span class="hljs-built_in">Array</span>.from({ <span class="hljs-attr">length</span>: numPartitions }, <span class="hljs-function">(<span class="hljs-params">_, i</span>) =&gt;</span> ({
    <span class="hljs-attr">name</span>: <span class="hljs-string">`Queue <span class="hljs-subst">${i + <span class="hljs-number">1</span>}</span>`</span>,
    <span class="hljs-attr">partitionIndex</span>: i + <span class="hljs-number">1</span>,
}));

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getPartitionIndex</span>(<span class="hljs-params">hash</span>) </span>{
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">Math</span>.floor(hash / <span class="hljs-number">250</span>) + <span class="hljs-number">1</span>;
}

<span class="hljs-keyword">const</span> hashCode = <span class="hljs-function">(<span class="hljs-params">str</span>) =&gt;</span> {
    <span class="hljs-keyword">let</span> hash = <span class="hljs-number">0</span>;
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; str.length; i++) {
        <span class="hljs-keyword">const</span> char = str.charCodeAt(i);
        hash = (hash &lt;&lt; <span class="hljs-number">5</span>) - hash + char;
    }
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">Math</span>.abs(hash) % <span class="hljs-number">1000</span>;
};

<span class="hljs-keyword">const</span> tasks = <span class="hljs-built_in">Array</span>.from({ <span class="hljs-attr">length</span>: <span class="hljs-number">4</span> }, <span class="hljs-function">() =&gt;</span> ({ <span class="hljs-attr">id</span>: uuidv4() }));

tasks.forEach(<span class="hljs-function">(<span class="hljs-params">task</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> hash = <span class="hljs-built_in">Math</span>.abs(hashCode(task.id));
    <span class="hljs-keyword">const</span> partitionIndex = getPartitionIndex(hash);
    <span class="hljs-keyword">const</span> assignedQueue = queues.find(
        <span class="hljs-function">(<span class="hljs-params">queue</span>) =&gt;</span> queue.partitionIndex === partitionIndex,
    );
    <span class="hljs-built_in">console</span>.log(
        <span class="hljs-string">`Task with ID: <span class="hljs-subst">${task.id}</span> assigned to <span class="hljs-subst">${assignedQueue ? assignedQueue.name : <span class="hljs-string">"no queue"</span>}</span>`</span>,
    );
});
</code></pre>
<p>In this code example, the <code>taskId</code> is a UUID. To match them to a partitioned queue range (each queue has a range of 250), you first hash-code it and then convert it to an absolute value. </p>
<p>Next, you call the <code>PartitionIndex()</code> function with this hash value. </p>
<p>From there, It finds the partitioned queue that the <code>taskId</code> fits within the range.</p>
<p>This is an example output below:</p>
<pre><code class="lang-bash">Task with ID: 493fbf04-2f4f-43c0-9486-f5c99313d4e6 assigned to Queue 2
Task with ID: 9bad272f-3369-408e-bb37-5ef00c68b0b6 assigned to Queue 3
Task with ID: e0ec2d06-d66b-4e0e-8e85-04e4755a42be assigned to Queue 1
Task with ID: 960f415b-2e64-4169-b4ee-59b11c33b451 assigned to Queue 4
</code></pre>
<h3 id="heading-round-robin-partitioning"><strong>Round-Robin Partitioning</strong></h3>
<p>For this partitioning strategy, tasks are assigned to queues in a cyclic pattern. This means that if a task gets assigned to queue 1, the next task will get assigned to queue 2, until all the queues get assigned a task before starting from queue 1 again, therefore making it to be distributed evenly amongst the queues.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> numPartitions = <span class="hljs-number">4</span>;
<span class="hljs-keyword">let</span> currentPartition = <span class="hljs-number">0</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getRoundRobinPartitionIndex</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">const</span> partitionIndex = (currentPartition % numPartitions) + <span class="hljs-number">1</span>;
    currentPartition++;
    <span class="hljs-keyword">return</span> partitionIndex;
}

<span class="hljs-keyword">const</span> tasks = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>]; 
tasks.forEach(<span class="hljs-function"><span class="hljs-params">task</span> =&gt;</span> {
    <span class="hljs-keyword">const</span> partitionIndex = getRoundRobinPartitionIndex();
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Task with ID: <span class="hljs-subst">${task}</span> assigned to Queue <span class="hljs-subst">${partitionIndex}</span>`</span>);
});
</code></pre>
<p>For this example, a function <code>getRoundRobinPartitionIndex()</code> was defined and it determines the next queue index using a round-robin strategy.</p>
<p>It first calculates the queue index by taking the modular value of <code>currentPartition</code> and <code>numPartitions</code>. It adds 1 to it to ensure the initial index starts from 1, then increments the <code>currentPartition</code> to make sure the next queue to be assigned is greater than the previous. If the modular value is 0, it returns to the queue with index of 1.</p>
<pre><code class="lang-bash">Task with ID: 1 assigned to Queue 1
Task with ID: 2 assigned to Queue 2
Task with ID: 3 assigned to Queue 3
Task with ID: 4 assigned to Queue 4
Task with ID: 5 assigned to Queue 1
</code></pre>
<p>As you can see, the output above shows that the tasks were distributed to each of the queues and then started from the first queue again.</p>
<h3 id="heading-dynamic-partitioning">Dynamic Partitioning</h3>
<p>This type of partitioning strategy involves assigning tasks to queues based on changing workloads or system conditions. </p>
<p>For instance, a system has 3 queues actively working and 1 that is free. It checks for the one with the least tasks assigned to it and then assigns a new task to it. By doing this, it ensures that the queues are not overwhelmed and that system resources are efficiently utilised.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> { <span class="hljs-attr">v4</span>: uuidv4 } = <span class="hljs-built_in">require</span>(<span class="hljs-string">'uuid'</span>);
<span class="hljs-keyword">let</span> numPartitions = <span class="hljs-number">4</span>;
<span class="hljs-keyword">let</span> queues = <span class="hljs-built_in">Array</span>.from({ <span class="hljs-attr">length</span>: numPartitions }, <span class="hljs-function">(<span class="hljs-params">_, i</span>) =&gt;</span> ({
    <span class="hljs-attr">name</span>: <span class="hljs-string">`Queue <span class="hljs-subst">${i + <span class="hljs-number">1</span>}</span>`</span>,
    <span class="hljs-attr">tasks</span>: [],
}));

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">dynamicPartitioning</span>(<span class="hljs-params">task</span>) </span>{
    <span class="hljs-keyword">let</span> minLoadQueue = queues[<span class="hljs-number">0</span>];
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> queue <span class="hljs-keyword">of</span> queues) {
        <span class="hljs-keyword">if</span> (queue.tasks.length &lt; minLoadQueue.tasks.length) {
            minLoadQueue = queue;
        }
    }
    minLoadQueue.tasks.push(task);
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Task with ID: <span class="hljs-subst">${task.id}</span> assigned to <span class="hljs-subst">${minLoadQueue.name}</span>`</span>);
}

<span class="hljs-keyword">const</span> tasks = <span class="hljs-built_in">Array</span>.from({ <span class="hljs-attr">length</span>: <span class="hljs-number">5</span> }, <span class="hljs-function">() =&gt;</span> ({ <span class="hljs-attr">id</span>: uuidv4(), <span class="hljs-attr">value</span>: <span class="hljs-string">`Task content`</span> }));

tasks.forEach(<span class="hljs-function"><span class="hljs-params">task</span> =&gt;</span> {
    dynamicPartitioning(task);
});

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">addPartition</span>(<span class="hljs-params"></span>) </span>{
    numPartitions++;
    queues.push({ <span class="hljs-attr">name</span>: <span class="hljs-string">`Queue <span class="hljs-subst">${numPartitions}</span>`</span>, <span class="hljs-attr">tasks</span>: [] });
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Added new partition: Queue <span class="hljs-subst">${numPartitions}</span>`</span>);
}

<span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =&gt;</span> {
    addPartition();
    <span class="hljs-comment">// Assign new tasks to demonstrate dynamic partitioning with the new queue</span>
    <span class="hljs-keyword">const</span> newTasks = <span class="hljs-built_in">Array</span>.from({ <span class="hljs-attr">length</span>: <span class="hljs-number">5</span> }, <span class="hljs-function">() =&gt;</span> ({ <span class="hljs-attr">id</span>: uuidv4(), <span class="hljs-attr">value</span>: <span class="hljs-string">`New task content`</span> }));
    newTasks.forEach(<span class="hljs-function"><span class="hljs-params">task</span> =&gt;</span> {
        dynamicPartitioning(task);
    });
}, <span class="hljs-number">5000</span>);
</code></pre>
<p>In this code above, it starts by creating three queues and dynamically assign tasks to the least loaded queue. </p>
<p>After a simulated put-off, a new queue is brought to deal with the elevated workload and new obligations are distributed among all available queues. </p>
<p>This technique ensures that the burden is balanced throughout all queues, and the queue is overloaded, making the machine more efficient and responsive to adjustments in workload.</p>
<pre><code class="lang-bash">Task with ID: 396d4fde-830b-4443-b59b-c089f3a1db49 assigned to Queue 1
Task with ID: aa85af19-e46a-4b13-9a9c-2eb3ec535af0 assigned to Queue 2
Task with ID: f93d4cbb-0cad-4b71-a424-4c27a77ed38a assigned to Queue 3
Task with ID: c7e0cc7e-f055-4a38-9869-466406a33ca8 assigned to Queue 4
Task with ID: b49fe153-73e8-45d1-85b3-a5873f836dc9 assigned to Queue 1
Added new partition: Queue 5
Task with ID: a8a5f78e-da7e-4c65-9d74-8cef57f271f3 assigned to Queue 5
Task with ID: 00ce47b0-6098-49d6-ad06-820733ffe16e assigned to Queue 2
Task with ID: 7b1a5dcf-c42c-46dc-8e29-bae1cc5408c1 assigned to Queue 3
Task with ID: 3e31ad34-1a19-4d3c-a8f3-08f765a45f13 assigned to Queue 4
Task with ID: 73d55243-27da-44a4-9192-532a20889373 assigned to Queue 5
</code></pre>
<p>There are other strategies, like content-based partitioning, random-based partitioning, or even a user-defined custom type.</p>
<p>All these strategies are good but can still have some issues if not properly managed.</p>
<p>For instance, if you are using the range-based partition strategy and you select an identifier which falls within the set range of a queue, that queue partition will eventually get overwhelmed. It is left up to you to figure out the one that is best for your system requirements.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Processing workloads in distributed systems can be kind of complex and inefficient if not managed properly. </p>
<p>Partitioning queues across the system and having the workloads be distributed to them based on a strategy is one way to improve your system performance. </p>
<p>In this article, some challenges with long running queues were pointed out, and some strategies to relieve them were given. I have been researching distributed systems in run-time environments and databases and this was one of my findings.</p>
<p>I hope you enjoyed reading this because I enjoyed writing this. You can follow me on <a target="_blank" href="https://x.com/OkoyeVictorr">Twitter(X)</a>.  </p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Set Up Message Queues for Async Tasks with RabbitMQ in Nest.js Apps ]]>
                </title>
                <description>
                    <![CDATA[ When you're developing programs, certain services can block or slow down the speed of your application. For example, CPU-intensive tasks like audio transcribing or file processing. So you might wonder – how do you make sure your application runs with... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/message-queues-with-rabbitmq-in-nest-js/</link>
                <guid isPermaLink="false">66bb51f80fc4910f8f7dfba8</guid>
                
                    <category>
                        <![CDATA[ nestjs ]]>
                    </category>
                
                    <category>
                        <![CDATA[ performance ]]>
                    </category>
                
                    <category>
                        <![CDATA[ queue ]]>
                    </category>
                
                    <category>
                        <![CDATA[ web performance ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Okoye Chukwuebuka Victor ]]>
                </dc:creator>
                <pubDate>Thu, 14 Dec 2023 01:20:25 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/12/articlePhoto.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>When you're developing programs, certain services can block or slow down the speed of your application. For example, CPU-intensive tasks like audio transcribing or file processing.</p>
<p>So you might wonder – how do you make sure your application runs without breaking? To handle this, you can send tasks to a queue outside your application's flow.</p>
<h2 id="heading-what-is-a-message-queue">What is a Message Queue?</h2>
<p>A message queue is a tool that facilitates the communication and transfer of data between services within a single application (or externally). It stores these data or messages using the First-In-First-Out (FIFO) principle. This means that older data that's passed into these queues gets processed before newer data.</p>
<p>Different components make up a message queue, such as:</p>
<ul>
<li><strong>Messages</strong>: These are the data that are sent to the queue. They are often referred to as jobs.</li>
<li><strong>Queues</strong>: These are the data structures used for storing messages.</li>
<li><strong>Producers</strong>: These are a service that sends messages or data into the queue system.</li>
<li><strong>Consumers</strong>: These are a service that listens to the queue and executes messages passed in it.</li>
</ul>
<h3 id="heading-message-queuing-tools">Message Queuing Tools</h3>
<p>Now, there are various message queuing tools you can use in asynchronous systems, like the following:</p>
<ul>
<li><strong>RabbitMQ</strong>: a reliable and flexible option for implementing message queues in applications.</li>
<li><strong>Apache</strong> <strong>Kafka</strong>: an efficient message queuing tool, also very good at event stream processing.</li>
<li><strong>Redis</strong>: an in-memory store used for message queuing, caching, and data processing.</li>
</ul>
<p>Note that some of these tools are not limited to message queuing but can be used for other purposes as well, like stream processing.</p>
<p>In this article, you will create a simple Nest.js project which will use RabbitMQ as the Message Queue Service Provider.</p>
<p>The tutorial will be divided into 3 parts:</p>
<ul>
<li><a class="post-section-overview" href="#heading-how-to-set-up-a-nestjs-project">How to Set Up a Nest.js Project for Basic User Registration Flow</a></li>
<li><a class="post-section-overview" href="#heading-how-to-set-up-an-email-service-for-user-registration">How to Set Up an Email Service for User Registration</a></li>
<li><a class="post-section-overview" href="#heading-how-to-integrate-a-queue-service-using-rabbitmq">How to Integrate a Queue Service using RabbitMQ</a></li>
</ul>
<h3 id="heading-prerequisites">Prerequisites</h3>
<ul>
<li>You'll need to have Node installed on your system. If you don't have it, here is its official site: <a target="_blank" href="https://nodejs.org/en">https://nodejs.org/en</a>.</li>
<li>You'll need to have Node Package Manager (NPM) installed, which you can download here if you don't have it: <a target="_blank" href="https://docs.npmjs.com/downloading-and-installing-node-js-and-npm">https://docs.npmjs.com/downloading-and-installing-node-js-and-npm</a>.</li>
<li>You'll need to have installed RabbitMQ. Here is where you can get it in case you haven't yet: <a target="_blank" href="https://www.rabbitmq.com/download.html">https://www.rabbitmq.com/download.html</a></li>
<li>You'll need to have a text editor. For this article, I'll use VSCode. You can download it here: <a target="_blank" href="https://code.visualstudio.com/download">https://code.visualstudio.com/download</a> or use the code editor of your choice.</li>
</ul>
<h2 id="heading-how-to-set-up-a-nestjs-project">How to Set Up a Nest.js Project</h2>
<p>Spinning up a Nest.js application is fast and simple if you use the Nest CLI. Open up your terminal and enter this command below to install the CLI:</p>
<pre><code class="lang-bash"> $ npm install -g @nestjs/cli
</code></pre>
<p>This installs the Nest.js CLI globally on your system, meaning you can call the CLI commands regardless of the directory you are currently in.</p>
<p>Moving forward, to create a simple REST API project, you will enter the command below:</p>
<pre><code class="lang-bash">nest new simple-queue
</code></pre>
<p>Simple-queue here is the directory name that will be created. Inputting this command gives you a prompt to select a package manager.</p>
<p>When that's done, navigate to the created directory and open it in your text editor by entering this command:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> simple-queue &amp;&amp; code .
</code></pre>
<p>This opens up your text editor. We want to work on a project that will best show how a message queue can be used in a real-world scenario – so let's set up a basic user registration form. On successful data entry it sends an email to the user, but you'll handle the email service separately by passing it into a queue to improve performance.</p>
<p>For this, we'll be using an SQLite database, TypeOrm, class-validators, and the dotenv package so you can secure your config variables. Go ahead to install them by typing this command in your terminal:</p>
<pre><code class="lang-bash">npm install --save @nestjs/typeorm typeorm sqlite3 class-validator dotenv
</code></pre>
<p>When the installation is complete, go to your root app module, and then include the TypeOrm configuration for your database. </p>
<p>SQLite is a lightweight SQL database which allows us to quickly spin up and test data. It's optimal for this use case – and now we'll configure it.</p>
<h3 id="heading-configuring-the-sqlite-database">Configuring the SQLite Database</h3>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { Module } <span class="hljs-keyword">from</span> <span class="hljs-string">"@nestjs/common"</span>;
<span class="hljs-keyword">import</span> { TypeOrmModule } <span class="hljs-keyword">from</span> <span class="hljs-string">"@nestjs/typeorm"</span>;
<span class="hljs-keyword">import</span> { AppController } <span class="hljs-keyword">from</span> <span class="hljs-string">"./app.controller"</span>;
<span class="hljs-keyword">import</span> { AppService } <span class="hljs-keyword">from</span> <span class="hljs-string">"./app.service"</span>;

<span class="hljs-meta">@Module</span>({
  imports: [
    TypeOrmModule.forRoot({
      <span class="hljs-keyword">type</span>:<span class="hljs-string">'sqlite'</span>,
      database: <span class="hljs-string">'mini-db.sqlite'</span>,
      entities: [__dirname + <span class="hljs-string">'/**/*.entity{.ts,.js}'</span>],
      synchronize: <span class="hljs-literal">true</span>,  
  })],
  controllers: [AppController],
  providers: [AppService],
})
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> AppModule {}
</code></pre>
<p>Congrats! You have successfully connected a DB to your project. Now it's time to create the services that will handle the user registration. </p>
<p>In order to do this, you will have to go back to your dear friend the Nest CLI. There, you'll be inputting a different command to help generate a resource folder for the User, which will contain the entity, service, dto, and the controller.</p>
<p>To do this, open your terminal and enter in this command:</p>
<pre><code class="lang-bash">nest generate resource users
</code></pre>
<p>A prompt to select your transport layer will be shown. Select the first one which is the <code>REST API</code>. Then, another prompt will ask if you would like to generate CRUD endpoints – you can type Yes. Then you can make modifications according to your requirements.</p>
<p>To proceed, you first have to define what information each user should have. First, create a User entity. You can do this by navigating to the user entity file in the created entity subfolder in the user folder. Then define the user data like this:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { Entity, PrimaryGeneratedColumn, Column } <span class="hljs-keyword">from</span> <span class="hljs-string">"typeorm"</span>;

<span class="hljs-meta">@Entity</span>(<span class="hljs-string">'users'</span>)
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> User {
  <span class="hljs-meta">@PrimaryGeneratedColumn</span>(<span class="hljs-string">'uuid'</span>)
  id: <span class="hljs-built_in">string</span>;

  <span class="hljs-meta">@Column</span>({ length: <span class="hljs-number">100</span>, unique: <span class="hljs-literal">true</span> })
  username: <span class="hljs-built_in">string</span>;

  <span class="hljs-meta">@Column</span>({ length: <span class="hljs-number">100</span>, unique: <span class="hljs-literal">true</span> })
  email: <span class="hljs-built_in">string</span>;
}
</code></pre>
<p>For this mini-project, you'll use basic user data to make the process faster. The username and email field have been set to be unique, meaning that there won't be a duplicate of the data instance passed in for this user table.</p>
<p>Now having done this, modify the create user dto file that was generated like this:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { IsNotEmpty, IsString, IsEmail } <span class="hljs-keyword">from</span> <span class="hljs-string">"class-validator"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> CreateUserDto {
    <span class="hljs-meta">@IsNotEmpty</span>()
    <span class="hljs-meta">@IsString</span>()
    username: <span class="hljs-built_in">string</span>;

    <span class="hljs-meta">@IsNotEmpty</span>()
    <span class="hljs-meta">@IsString</span>()
    <span class="hljs-meta">@IsEmail</span>()
    email: <span class="hljs-built_in">string</span>;
  }
</code></pre>
<p>This was created to validate the payload that will be sent in your request by using the class-validator package.</p>
<p>Now, modify the <code>create</code> method in the user service file.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { Injectable } <span class="hljs-keyword">from</span> <span class="hljs-string">"@nestjs/common"</span>;
<span class="hljs-keyword">import</span> { InjectRepository } <span class="hljs-keyword">from</span> <span class="hljs-string">"@nestjs/typeorm"</span>;
<span class="hljs-keyword">import</span> { Repository } <span class="hljs-keyword">from</span> <span class="hljs-string">"typeorm"</span>;
<span class="hljs-keyword">import</span> { CreateUserDto } <span class="hljs-keyword">from</span> <span class="hljs-string">"./dto/create-user.dto"</span>;
<span class="hljs-keyword">import</span> { User } <span class="hljs-keyword">from</span> <span class="hljs-string">"./entities/user.entity"</span>;

<span class="hljs-meta">@Injectable</span>()
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> UsersService {
  <span class="hljs-keyword">constructor</span>(<span class="hljs-params">
    <span class="hljs-meta">@InjectRepository</span>(User)
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> userRepository: Repository&lt;User&gt;
  </span>) {}
  <span class="hljs-keyword">async</span> create(createUserDto: CreateUserDto): <span class="hljs-built_in">Promise</span>&lt;User&gt; {
    <span class="hljs-keyword">const</span> newUser = <span class="hljs-built_in">this</span>.userRepository.create(createUserDto);
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>.userRepository.save(newUser);
  }
}
</code></pre>
<p>Next you'll modify the controller file. You've already defined the <code>create</code> endpoint, so you'll just have to clean up the other endpoints that are not needed.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { Controller, Post, Body } <span class="hljs-keyword">from</span> <span class="hljs-string">"@nestjs/common"</span>;
<span class="hljs-keyword">import</span> { CreateUserDto } <span class="hljs-keyword">from</span> <span class="hljs-string">"./dto/create-user.dto"</span>;
<span class="hljs-keyword">import</span> { UsersService } <span class="hljs-keyword">from</span> <span class="hljs-string">"./users.service"</span>;

<span class="hljs-meta">@Controller</span>(<span class="hljs-string">'users'</span>)
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> UsersController {
 <span class="hljs-keyword">constructor</span>(<span class="hljs-params"><span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> usersService: UsersService</span>) {}
  <span class="hljs-meta">@Post</span>()
  create(<span class="hljs-meta">@Body</span>() createUserDto: CreateUserDto) {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.usersService.create(createUserDto);
  }
}
</code></pre>
<p>Open up the user module file and make some adjustments by adding the import field to the Module decorator and using the TypeOrmModule property.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { Module } <span class="hljs-keyword">from</span> <span class="hljs-string">'@nestjs/common'</span>;
<span class="hljs-keyword">import</span> { UsersService } <span class="hljs-keyword">from</span> <span class="hljs-string">'./users.service'</span>;
<span class="hljs-keyword">import</span> { UsersController } <span class="hljs-keyword">from</span> <span class="hljs-string">'./users.controller'</span>;
<span class="hljs-keyword">import</span> { TypeOrmModule } <span class="hljs-keyword">from</span> <span class="hljs-string">'@nestjs/typeorm'</span>;
<span class="hljs-keyword">import</span> { User } <span class="hljs-keyword">from</span> <span class="hljs-string">'./entities/user.entity'</span>;

<span class="hljs-meta">@Module</span>({
  imports: [TypeOrmModule.forFeature([User])],
  controllers: [UsersController],
  providers: [UsersService],
})
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> UsersModule {}
</code></pre>
<p>Next, start up your server by entering this command on your terminal: <code>npm run start:dev</code>. Once the server is up and running, open up your API client of choice. For this article, we'll use Postman. Then make a POST request to the endpoint, which will be <code>localhost:3000/users</code>, providing the payload data required.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1696695190655/b8b3b246-0961-4655-aaee-081b9ecff35e.png" alt="Image" width="898" height="409" loading="lazy">
<em>A request was made and a user instance was created.</em></p>
<p>Next up is adding an email service to your project which will help notify new users who are registering.</p>
<h2 id="heading-how-to-set-up-an-email-service-for-user-registration">How to Set Up an Email Service for User Registration</h2>
<p>For this, you'll use some packages which are required to create an email service. Open up your terminal and input the command below to install these packages:</p>
<pre><code class="lang-bash">npm install --save @nestjs-modules/mailer nodemailer
</code></pre>
<p>When these packages are installed, you can now implement the mail service. Using the Nest CLI, create a mailer module and service by entering this command in your terminal:</p>
<pre><code class="lang-bash">nest generate module email &amp;&amp; nest generate service email
</code></pre>
<p>When it's done, open up the newly created module file in the mail folder. You'll use the MailerModule property of the <code>@nestjs-modules/mailer</code> package to configure your mail service here. It requires an SMTP client whose keys you'll need to configure this MailerModule. </p>
<p>For that you can use <a target="_blank" href="https://app.elasticemail.com/api/">https://app.elasticemail.com</a> to get these SMTP keys. Sign up and connect to the SMTP API. You'll then be given keys for your private use.</p>
<p>Note that this free mode of the SMTP client has limitations and it cannot send to all emails – so you should use a test email service.</p>
<h3 id="heading-how-to-configure-the-mailer-module">How to Configure the Mailer Module</h3>
<p>Once you have gotten that set up, go back to your application and create a <strong>.env</strong> file. Set your secrets for the SMTP keys. Then configure your MailerModule like this:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { Global, Module } <span class="hljs-keyword">from</span> <span class="hljs-string">"@nestjs/common"</span>;
<span class="hljs-keyword">import</span> { EmailService } <span class="hljs-keyword">from</span> <span class="hljs-string">"./email.service"</span>;
<span class="hljs-keyword">import</span> { MailerModule } <span class="hljs-keyword">from</span> <span class="hljs-string">"@nestjs-modules/mailer"</span>;

<span class="hljs-built_in">require</span>(<span class="hljs-string">'dotenv'</span>).config();
<span class="hljs-meta">@Global</span>()
<span class="hljs-meta">@Module</span>({
  imports: [
    MailerModule.forRoot({
      transport: {
        service: <span class="hljs-string">'QueueTest'</span>,
        host: process.env.SMTP_HOST,
        port: process.env.SMTP_PORT,
        auth: {
          user: process.env.SMTP_USER,
          pass: process.env.SMTP_PASSWORD,
        },
      },
      defaults: {
        <span class="hljs-keyword">from</span>: process.env.FROM_EMAIL,
      },
    }),
  ],
  providers: [EmailService]
})
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> EmailModule {}
</code></pre>
<p>The global decorator was set in order to make sure the MailModule can be called anywhere in your application. Make sure your secrets are properly loaded and thaqt you have a valid Email set in the <strong>from: process.env.FROM_EMAIL.</strong></p>
<p>Check to make sure that the EmailModule is also imported in the root App Module the same way your UsersModule was imported in the Imports Array of the App Module.</p>
<p>Next, open your email service file – you'll need to make some modifications to the EmailService class. Add a constructor and call the MailService property from the <code>@nestjs-modules/mailer</code> package. Then go ahead and create a function that will handle sending the emails.</p>
<p>Below is a class and method that does this:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { MailerService } <span class="hljs-keyword">from</span> <span class="hljs-string">'@nestjs-modules/mailer'</span>;
<span class="hljs-keyword">import</span> { HttpException, HttpStatus, Injectable } <span class="hljs-keyword">from</span> <span class="hljs-string">'@nestjs/common'</span>;

<span class="hljs-meta">@Injectable</span>()
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> EmailService {
  <span class="hljs-keyword">constructor</span>(<span class="hljs-params"><span class="hljs-keyword">private</span> mailerService: MailerService</span>) {}
  <span class="hljs-keyword">async</span> sendEmail(options: { email: <span class="hljs-built_in">string</span>; subject: <span class="hljs-built_in">string</span>; html: <span class="hljs-built_in">string</span>;
  }) {
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">const</span> message = {
        to: options.email,
        subject: options.subject,
        html: options.html
      };
      <span class="hljs-keyword">const</span> emailSend = <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>.mailerService.sendMail({
        ...message,
      });
      <span class="hljs-keyword">return</span> emailSend;
    } <span class="hljs-keyword">catch</span> (error) {
      <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> HttpException(<span class="hljs-string">'Error'</span>, HttpStatus.INTERNAL_SERVER_ERROR);
    }
  }
}
</code></pre>
<p>Now you've defined the method to send an email. You've also put an exception handler in place for better error handling.</p>
<p>Now it's time to add this newly created service to your user registration flow.</p>
<p>Navigate to your user service file, and add the mail service to your constructor as a provider. Then call the service in your <code>create user</code> method like this:</p>
<pre><code class="lang-typescript"><span class="hljs-meta">@Injectable</span>()
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> UsersService {
  <span class="hljs-keyword">constructor</span>(<span class="hljs-params">
    <span class="hljs-meta">@InjectRepository</span>(User)
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> userRepository: Repository&lt;User&gt;,
    <span class="hljs-keyword">private</span> emailService: EmailService
  </span>) {}
  <span class="hljs-keyword">async</span> create(createUserDto: CreateUserDto): <span class="hljs-built_in">Promise</span>&lt;User&gt; {
    <span class="hljs-keyword">const</span> newUser = <span class="hljs-built_in">this</span>.userRepository.create(createUserDto);
    <span class="hljs-keyword">const</span> user =  <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>.userRepository.save(newUser);
      <span class="hljs-keyword">const</span> emailData = {
        email: user.email,
        subject: <span class="hljs-string">'Welcome to Our Community'</span>,
        html: <span class="hljs-string">`&lt;p&gt;Hello <span class="hljs-subst">${user.username}</span>,&lt;/p&gt;
        &lt;p&gt;Welcome to our community! Your account is now active.&lt;/p&gt;
        &lt;p&gt;Enjoy your time with us!&lt;/p&gt;`</span>,
      };
      <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>.emailService.sendEmail(emailData)
    <span class="hljs-keyword">return</span> user
  }
}
</code></pre>
<p>Make sure to modify your modules in order to correct any dependency injection errors. In your email module file, add the EmailService to the exports array:</p>
<pre><code class="lang-typescript"> providers: [EmailService],
 <span class="hljs-built_in">exports</span>: [EmailService]
</code></pre>
<p>Add it below your providers to export the Email Service so it can be accessed in other modules. Then import the EmailModule to your User module file and add it to your import array like this:</p>
<pre><code class="lang-typescript"><span class="hljs-meta">@Module</span>({
  imports: [TypeOrmModule.forFeature([User]), EmailModule],
  controllers: [UsersController],
  providers: [UsersService],
})
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> UsersModule {}
</code></pre>
<p>Now it's time to test it. Get a free account from any online email testing platform and open Postman. Make a request to the <code>create user</code> endpoint with your valid email. You should get an email response like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1696695108644/25aa9e76-da00-436b-9e43-f0c978f87c6f.png" alt="Image" width="712" height="272" loading="lazy">
<em>Email response you should get</em></p>
<h2 id="heading-how-to-integrate-a-queue-service-using-rabbitmq">How to Integrate a Queue Service using RabbitMQ</h2>
<p>To get started with this, you'll have to install some packages that let you implement queues using RabbitMQ. Enter the command below to install these packages:</p>
<pre><code class="lang-bash">npm install --save amqplib @types/amqplib amqp-connection-manager
</code></pre>
<h3 id="heading-configure-the-producer-service">Configure the Producer Service</h3>
<p>Once installation is complete, it's time to configure RabbitMQ. You'll create a new folder in your src directory and name it queues. Then create the queue producer file. Import these packages and set them up like this:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { HttpException, HttpStatus, Injectable, Logger } <span class="hljs-keyword">from</span> <span class="hljs-string">'@nestjs/common'</span>;
<span class="hljs-keyword">import</span> amqp, { ChannelWrapper } <span class="hljs-keyword">from</span> <span class="hljs-string">'amqp-connection-manager'</span>;
<span class="hljs-keyword">import</span> { Channel } <span class="hljs-keyword">from</span> <span class="hljs-string">'amqplib'</span>;

<span class="hljs-meta">@Injectable</span>()
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> ProducerService {
  <span class="hljs-keyword">private</span> channelWrapper: ChannelWrapper;
  <span class="hljs-keyword">constructor</span>(<span class="hljs-params"></span>) {
    <span class="hljs-keyword">const</span> connection = amqp.connect([<span class="hljs-string">'amqp://localhost'</span>]);
    <span class="hljs-built_in">this</span>.channelWrapper = connection.createChannel({
      setup: <span class="hljs-function">(<span class="hljs-params">channel: Channel</span>) =&gt;</span> {
        <span class="hljs-keyword">return</span> channel.assertQueue(<span class="hljs-string">'emailQueue'</span>, { durable: <span class="hljs-literal">true</span> });
      },
    });
  }

  <span class="hljs-keyword">async</span> addToEmailQueue(mail: <span class="hljs-built_in">any</span>) {
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>.channelWrapper.sendToQueue(
        <span class="hljs-string">'emailQueue'</span>,
        Buffer.from(<span class="hljs-built_in">JSON</span>.stringify(mail)),
        {
          persistent: <span class="hljs-literal">true</span>,
        },
      );
      Logger.log(<span class="hljs-string">'Sent To Queue'</span>);
    } <span class="hljs-keyword">catch</span> (error) {
      <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> HttpException(
        <span class="hljs-string">'Error adding mail to queue'</span>,
        HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }
  }
}
</code></pre>
<p>The AMQP connection was set and is running on localhost with the default RabittMQ port which is 5432. You also established a channel on that connection with an option input which is executed anytime a new channel is created. This helps if you have any configuration for that channel. </p>
<p>You also created an <code>emailQueue</code> with the assertQueue property which checks that a queue with that name does not already exist. If it does exist, it has no effect so it's idempotent. </p>
<p>Then you created an option <code>durable: true</code> to make sure that the queue will survive a server restart.</p>
<p>Next, you defined the method to add the email data to a queue. This calls the <code>sendToQueue</code> property of the channelWrapper, passing in the queue name you want to send the data to. Ideally, it should be the same name as the one you defined with the assertQueue property.</p>
<p>The second argument is the mail data, but firstly you converted it to a JSON string then to a Buffer. You do this because messages in RabbitMQ are mostly transmitted as binary data.</p>
<p>You can then set an option <code>persistent: true</code> to ensure that the data being sent to the queue won't be lost if the server crashes. Then with some error handling and the method to send messages to the queue, it's good to go.</p>
<h3 id="heading-set-up-the-consumer-service">Set Up the Consumer Service</h3>
<p>Now that you've configured the producer service, it's time to set up the consumer service. </p>
<p>Create another file in the queue sub-folder. It's quite similar, but in this case, you will be consuming the data from the queue. Below is the configuration for the consumer service:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { Injectable, OnModuleInit, Logger } <span class="hljs-keyword">from</span> <span class="hljs-string">'@nestjs/common'</span>;
<span class="hljs-keyword">import</span> amqp, { ChannelWrapper } <span class="hljs-keyword">from</span> <span class="hljs-string">'amqp-connection-manager'</span>;
<span class="hljs-keyword">import</span> { ConfirmChannel } <span class="hljs-keyword">from</span> <span class="hljs-string">'amqplib'</span>;
<span class="hljs-keyword">import</span> { EmailService } <span class="hljs-keyword">from</span> <span class="hljs-string">'src/email/email.service'</span>;

<span class="hljs-meta">@Injectable</span>()
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> ConsumerService <span class="hljs-keyword">implements</span> OnModuleInit {
  <span class="hljs-keyword">private</span> channelWrapper: ChannelWrapper;
  <span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> logger = <span class="hljs-keyword">new</span> Logger(ConsumerService.name);
  <span class="hljs-keyword">constructor</span>(<span class="hljs-params"><span class="hljs-keyword">private</span> emailService: EmailService</span>) {
    <span class="hljs-keyword">const</span> connection = amqp.connect([<span class="hljs-string">'amqp://localhost'</span>]);
    <span class="hljs-built_in">this</span>.channelWrapper = connection.createChannel();
  }

  <span class="hljs-keyword">public</span> <span class="hljs-keyword">async</span> onModuleInit() {
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>.channelWrapper.addSetup(<span class="hljs-keyword">async</span> (channel: ConfirmChannel) =&gt; {
        <span class="hljs-keyword">await</span> channel.assertQueue(<span class="hljs-string">'emailQueue'</span>, { durable: <span class="hljs-literal">true</span> });
        <span class="hljs-keyword">await</span> channel.consume(<span class="hljs-string">'emailQueue'</span>, <span class="hljs-keyword">async</span> (message) =&gt; {
          <span class="hljs-keyword">if</span> (message) {
            <span class="hljs-keyword">const</span> content = <span class="hljs-built_in">JSON</span>.parse(message.content.toString());
            <span class="hljs-built_in">this</span>.logger.log(<span class="hljs-string">'Received message:'</span>, content);
            <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>.emailService.sendEmail(content);
            channel.ack(message);
          }
        });
      });
      <span class="hljs-built_in">this</span>.logger.log(<span class="hljs-string">'Consumer service started and listening for messages.'</span>);
    } <span class="hljs-keyword">catch</span> (err) {
      <span class="hljs-built_in">this</span>.logger.error(<span class="hljs-string">'Error starting the consumer:'</span>, err);
    }
  }
}
</code></pre>
<p>First, you defined your consumer class. For this, it implements the <code>onModuleInit</code> interface which is provided by <code>@nestJs/common</code>. This specifies that the defined class should have a method named <code>onModuleInit()</code>. </p>
<p>Like the name says, the method will be called automatically during the module initialization which is when the module containing this class is loaded. </p>
<p>In the class constructor, you added the <code>emailService</code> because you'll be using the <code>sendEmail</code> method of that class.</p>
<p>In the <code>onModuleInit()</code> method, you defined a channel. This is necessary because you need a channel to consume messages from a queue.</p>
<p>From this, the channel is then used to assert a queue which should be similar in name and options to what you have on your producer service. If it's not, you won't be able to listen to the queue created on the producer service. </p>
<p>Then you used the consume method of channel to listen and execute the message coming from the queue you have registered.</p>
<p>Recall that before, you had to convert the message to Buffer in order to send it into a queue. Now, you have to convert it to a JavaScript object. Then call the emailService method to send an email and pass in the converted JavaScript object as the argument of that method.</p>
<p>Finally, you called the <code>ack</code> method which is used to inform the queue that the message has been received and processed successfully in order for it to be removed from the queue.</p>
<p>Now that you've defined these services, create a module file and set them in the providers array. Then export the producer service because you will be calling it in another module.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { Module } <span class="hljs-keyword">from</span> <span class="hljs-string">'@nestjs/common'</span>;
<span class="hljs-keyword">import</span> { ConsumerService } <span class="hljs-keyword">from</span> <span class="hljs-string">'./consumer.file'</span>;
<span class="hljs-keyword">import</span> { ProducerService } <span class="hljs-keyword">from</span> <span class="hljs-string">'./producer.file'</span>;

<span class="hljs-meta">@Module</span>({
  providers: [ProducerService, ConsumerService],
  <span class="hljs-built_in">exports</span>: [ProducerService],
})
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> QueueModule {}
</code></pre>
<p>Next up is to add the emails being sent on user registration to the queue service that you just created. </p>
<p>Navigate back to your user service file and make some modifications: replace the email service with the producer service as a provider in the constructor, and then call the service and the method to add to the email queue as shown below:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { Injectable } <span class="hljs-keyword">from</span> <span class="hljs-string">"@nestjs/common"</span>;
<span class="hljs-keyword">import</span> { InjectRepository } <span class="hljs-keyword">from</span> <span class="hljs-string">"@nestjs/typeorm"</span>;
<span class="hljs-keyword">import</span> { Repository } <span class="hljs-keyword">from</span> <span class="hljs-string">"typeorm"</span>;
<span class="hljs-keyword">import</span> { CreateUserDto } <span class="hljs-keyword">from</span> <span class="hljs-string">"./dto/create-user.dto"</span>;
<span class="hljs-keyword">import</span> { User } <span class="hljs-keyword">from</span> <span class="hljs-string">"./entities/user.entity"</span>;
<span class="hljs-keyword">import</span> { ProducerService } <span class="hljs-keyword">from</span> <span class="hljs-string">"src/queues/producer.file"</span>;

<span class="hljs-meta">@Injectable</span>()
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> UsersService {
  <span class="hljs-keyword">constructor</span>(<span class="hljs-params">
    <span class="hljs-meta">@InjectRepository</span>(User)
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> userRepository: Repository&lt;User&gt;,
    <span class="hljs-keyword">private</span> producerService: ProducerService,
  </span>) {}
  <span class="hljs-keyword">async</span> create(createUserDto: CreateUserDto): <span class="hljs-built_in">Promise</span>&lt;User&gt; {
    <span class="hljs-keyword">const</span> newUser = <span class="hljs-built_in">this</span>.userRepository.create(createUserDto);
    <span class="hljs-keyword">const</span> user = <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>.userRepository.save(newUser);
    <span class="hljs-keyword">const</span> emailData = {
      email: user.email,
      subject: <span class="hljs-string">'Welcome to Our Community'</span>,
      html: <span class="hljs-string">`&lt;p&gt;Hello <span class="hljs-subst">${user.username}</span>,&lt;/p&gt;
        &lt;p&gt;Welcome to our community! Your account is now active.&lt;/p&gt;
        &lt;p&gt;Enjoy your time with us!&lt;/p&gt;`</span>,
    };
    <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>.producerService.addToEmailQueue(emailData);
    <span class="hljs-keyword">return</span> user;
  }
}
</code></pre>
<p>Also in the user module file, replace the EmailModule with that of the QueueModule to avoid dependency injection errors when you start up your server.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { Module } <span class="hljs-keyword">from</span> <span class="hljs-string">'@nestjs/common'</span>;
<span class="hljs-keyword">import</span> { UsersService } <span class="hljs-keyword">from</span> <span class="hljs-string">'./users.service'</span>;
<span class="hljs-keyword">import</span> { UsersController } <span class="hljs-keyword">from</span> <span class="hljs-string">'./users.controller'</span>;
<span class="hljs-keyword">import</span> { TypeOrmModule } <span class="hljs-keyword">from</span> <span class="hljs-string">'@nestjs/typeorm'</span>;
<span class="hljs-keyword">import</span> { User } <span class="hljs-keyword">from</span> <span class="hljs-string">'./entities/user.entity'</span>;
<span class="hljs-keyword">import</span> { QueueModule } <span class="hljs-keyword">from</span> <span class="hljs-string">'src/queues/queue.module'</span>;

<span class="hljs-meta">@Module</span>({
  imports: [TypeOrmModule.forFeature([User]), QueueModule],
  controllers: [UsersController],
  providers: [UsersService],
})
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> UsersModule {}
</code></pre>
<p>Now finally, it's time to test the user registration flow again. So navigate back to Postman and then type in a valid email and username and hit enter. On the terminal of your server running, you will see logs that were set in order to track the way the message got sent and how it was received and executed.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1696982914939/7f28f0e3-22e3-462c-8956-0bd2156d4c10.png" alt="Image" width="800" height="153" loading="lazy">
<em>Logs that help you track the message</em></p>
<p>You can also open up the RabbitMQ dashboard to view queue activity on <a target="_blank" href="http://localhost:15672/">http://localhost:15672</a>, By default the user is "guest", so enter in <code>guest</code> for the username and password.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1702377899227/4158d8b2-2b9b-424e-bd0b-a4203648eb50.png" alt="Image" width="906" height="523" loading="lazy">
<em>RabbitMQ Queues and Streams</em></p>
<p>Here's the link to the <a target="_blank" href="https://github.com/ChuloWay/article-nestjs-queue">GitHub repository</a>. Feel free to check it out whenever you're stuck.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this article you learned what a message queue is along with some major components of how they work. You also built a mini Nest.js project and implemented an email service in it. Finally, you integrated the queue service into your project, showing how it works in a real-life scenario.</p>
<p>Understanding message queue behaviors and patterns is an essential skill when developing scalable applications. This helps reduce lag and improves the speed and efficiency of your applications. </p>
<p>I hope you enjoyed reading this article. You can follow me on <a target="_blank" href="https://twitter.com/OkoyeVictorr">Twitter</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Understanding Java Internals: Speed and Performance ]]>
                </title>
                <description>
                    <![CDATA[ In most conversations about programming, speed, and efficiency in Java are reoccurring terms as it's a language native to these features. You might ask, what is Java? You may also wonder what it means for a programming language to be interpreted or c... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/understanding-java-internals-speed-and-performance/</link>
                <guid isPermaLink="false">66bb51fb3c8a48be917afcbc</guid>
                
                    <category>
                        <![CDATA[ Java ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Okoye Chukwuebuka Victor ]]>
                </dc:creator>
                <pubDate>Sun, 24 Sep 2023 13:44:14 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/09/terry-vlisidis-WsEbnsnKbUE-unsplash.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In most conversations about programming, speed, and efficiency in Java are reoccurring terms as it's a language native to these features.</p>
<p>You might ask, what is Java? You may also wonder what it means for a programming language to be interpreted or compiled. Let's explore these concepts in the following sections.</p>
<h2 id="heading-what-is-the-java-programming-language">What is the Java Programming Language?</h2>
<p>Java is a programming language that is platform-independent and adopts the Object Oriented Programming structure to build software. It is not only limited to the web but also mobile and desktop.</p>
<p>You might ask what it means to be platform-independent. This is about the capability of Java programs to effortlessly operate on various operating systems like Windows, Mac, and Linux.</p>
<p>Unlike languages like C or C++, which can be limited to a solitary Operating System, Java's adaptability eliminates the limitation of depending on a specific operating system for it to operate. </p>
<p>To understand Java better, let's take a look into its history and the purpose it was created for.</p>
<h3 id="heading-a-brief-history-of-java">A Brief History Of Java</h3>
<p>In 1991, Java was developed by James Gosling and his team at Sun Microsystems. The first version of the language, 1.0, was released in 1996. </p>
<p>It was designed to have similar syntax to other higher-level languages like C and C++, so that engineers at that time wouldn't have a problem understanding and developing a program with Java. </p>
<p>It was developed with the intent to develop television interactivity, but it was too advanced for its time. The technology infrastructure and devices of that time were not adequately prepared to leverage Java's advanced features.</p>
<p>In recent times, we have seen Java still in the spotlight as it is the software that most big tech companies adopt due to its versatility. It's very much in demand as a primary language for building enterprise-level applications on different platforms.</p>
<p>Moving forward in our exploration of Java's inner workings, there are some key concepts you need to understand. Those concepts are understanding what it means for a programming language to be interpreted or compiled.</p>
<h3 id="heading-interpreted-vs-compiled-languages">Interpreted vs Compiled Languages</h3>
<p>We have often heard of these terms, but to understand them better, let us picture a foreign student embarking on two journeys to different locations.</p>
<p>In the first scenario, they arrive at the location without knowing the local language or customs, so they rely on an interpreter or translator to be able to communicate with the natives of that area. This is much like how an interpreter in an interpreted programming language translates code on-the-fly for the computer to understand.</p>
<p>In the second scenario, the student had the foresight to partake in classes to learn the language they will be needing, and is familiar with the customs of the location they will be going to. On arrival, they doesn't need an interpreter in order to communicate with the natives of that area. This is similar to how a compiled language functions.</p>
<p>By understanding these two scenarios, you can spot the differences between an interpreted language and a compiled language. </p>
<p>The former translates each line of code on the go. That is a real-time translation, much like how the student in the example made use of a translator/interpreter.</p>
<p>On the other hand, the latter first predigests the code to ensure smooth flow. Then it 'compiles' or transforms it into machine code which the computer can understand and execute, similar to our prepared student communicating fluently. </p>
<p>Each of these programming terms has a similar purpose of allowing communication between computer systems and the programmers. </p>
<p>Now, as you inquire deeper into these programming terms, let's understand how Java works.</p>
<h2 id="heading-how-does-java-work">How does Java Work?</h2>
<p>Java is unique in the sense that it is both compiled and interpreted.</p>
<p>The basic flow is that it is first compiled from source code into what we call bytecode. Then, it is interpreted to machine code using an interpreter named JVM, which stands for Java Virtual Machine. This interpretation happens at runtime, so you can refer to Java as an interpreted language and also a compiled language. </p>
<p>Now you might ask what is bytecode? </p>
<p>The common terms we hear in program compilation and interpretation are mostly source code and machine code, The bytecode is akin to machine code in the sense that is it a compiled source code, but it's not executable unless interpreted by a virtual machine, in this case, the Java Virtual Machine.</p>
<h3 id="heading-what-is-a-java-virtual-machine">What is a Java Virtual Machine?</h3>
<p>The JVM (Java Virtual Machine) is a platform dependent virtual machine that interprets and executes Java Programs in bytecode and any other program from other languages that compiles to Java bytecode. </p>
<p>Java bytecode has a special quality: it's not tied to a specific platform. </p>
<p>Java bytecode, which is akin to a universal dialect, can be executed by a Java Virtual Machine (JVM) on most operating systems you can envision. Presently, when the JVM starts its processing, it converts that bytecode into machine code that's an exact match for the operating system it's running on.</p>
<p>But here's where it gets interesting: while Java bytecode is like a chameleon that can adapt to different platforms, the JVM itself isn't quite as flexible. It's like having different versions of a tool, each custom-made for a specific operating system. </p>
<p>So, you've got different flavours of JVMs to match the variety of operating systems out there. </p>
<p>Now you might be wondering since Java undergoes two processes, compilation and interpretation, does that make it slow? The answer is no. Although it undergoes various processing, it still is fast. </p>
<p>To understand this, we need to discuss some fundamentals seen in the JVM such as the JIT  (Just In Time Compilation), Hotspot JVM, and its memory/storage uniqueness.</p>
<h2 id="heading-how-does-java-attain-high-speed">How does Java Attain High Speed?</h2>
<p>It is important to note that Java streamlined its compilation for fast execution and took the platform independence of an interpreted language.</p>
<p>Compiled languages are known for their speed in processing due to them converting the source code fully and not line by line, unlike their counterpart the interpreted languages. Java compiles to bytecode which is faster to interpret using the JVM due to bytecode being very compact and optimized already.</p>
<p>JVM has several components such as its ability to manipulate memory at run time. Due to automatic memory management, less time is spent on the allocation of memory size for data using its inbuilt garbage collector.</p>
<h3 id="heading-how-to-make-use-of-the-jit-compiler-to-achieve-faster-execution">How to make use of the JIT Compiler to achieve faster execution</h3>
<p>Another interesting feature in the JVM, which helps to cut down time spent on improving code processing speed, is the JIT, which is an acronym for Just In Time.</p>
<p> The JIT compiler is at the core of the execution engine in the JVM. It observes as bytecode is being interpreted and executed, and stores a "Hotspot". This is a repeated set of executed bytecode.</p>
<p>Instead of reinterpreting and executing this same bytecode again, the JIT compiler stores this frequently executed bytecode in memory as a native machine code for future use.</p>
<p>This cached machine code is what gets executed when you run your bytecode, which results to a faster execution time. This whole process can be called a dynamic compilation.</p>
<h3 id="heading-what-is-garbage-collection-and-how-it-improves-jvm-performance">What is garbage collection and how it improves JVM performance?</h3>
<p>The JVM is unique in the way that it automates memory management. This involves memory allocation for programs it executes.</p>
<p>Unlike  C/C++, where you write a code and then manually compute the memory allocation of the program, this feature improves and enhances the productivity of the programmers. It also reduces some errors that can result due to running out of memory or memory leaks.</p>
<p>Garbage collection aids this by automatically reclaiming memory occupied by objects in a program that is no longer in use. Doing so, frees up that memory for future use. </p>
<p>You might ask how this works. It follows the steps outlined below:</p>
<ul>
<li>It first identifies unreachable objects. These are objects in a program that are not in use. It's strict in doing this because if it selects an object in use and reclaims it, it will crash our program because there will be a referenced object error. That is a term called dangling references.</li>
<li>Next, it reclaims the memory of the selected unused objects, which frees up memory for other future objects.</li>
<li>In some cases, during this collection, the garbage collector compacts the remaining objects in memory, which improves memory locality. This is optional, as it depends on the garbage collection algorithms in use.</li>
</ul>
<p>This is a rundown of how the garbage collector process works in the Java Virtual Machine.</p>
<p>Depending on the set garbage collector algorithm in place, it is important to note that the collection is triggered by the JVM when it detects low memory space, and kickstarts the steps above.</p>
<p>It is also essential to note that sometimes a pause in execution will happen in other to memory space.</p>
<h3 id="heading-bytecode-optimization">ByteCode Optimization</h3>
<p>There are some extra techniques performed on the compiler which help enhance performance.  </p>
<p>The Compiler optimizes the bytecode by taking note of similar calculations. Instead of rerunning these calculations, it just outputs the result. This is called constant folding. </p>
<p>It also removes codes out of scope or codes that will never be executed. Doing this, eliminates unnecessary computation. </p>
<p>Another technique used by the compiler is the peephole optimization, which involves the replacement of bytecode instructions with a more efficient sequence.</p>
<p>So many factors contribute to the performance and speed of Java Programs. </p>
<p>These range from it both being compiled and interpreted, to the intricacies of some components in its interpreter  (the Java Virtual Machine). All these play a major role in achieving high speed. </p>
<p>Ultimately, to have faster programs the programmer must write cleaner and organized code using good data structures.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this article, you learned about a brief history of Java, and  the differences between compiled and interpreted languages. You also learn about and some of Java's major components, such as the Java Virtual Machine, and how it contributes to the performance of Java programs.</p>
<p>If you enjoyed reading this article, you can share and follow me on <a target="_blank" href="https://twitter.com/okoyevictorr">Twitter</a> and <a target="_blank" href="https://www.linkedin.com/in/okoye-chukwuebuka/">Linkedin</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Use Exception Filters to Catch Bugs in Nest.js ]]>
                </title>
                <description>
                    <![CDATA[ It's common to find errors and bugs in your code if you're a software developer. They might occur because of incorrect input, from passing the wrong data types, or because of delays or response timeouts.  And even though errors and bugs are a part of... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/exception-filters-in-nestjs/</link>
                <guid isPermaLink="false">66bb51f1b0a396d22e4116f7</guid>
                
                    <category>
                        <![CDATA[ debugging ]]>
                    </category>
                
                    <category>
                        <![CDATA[ error handling ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ nestjs ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Okoye Chukwuebuka Victor ]]>
                </dc:creator>
                <pubDate>Fri, 23 Jun 2023 21:38:23 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/06/brett-jordan-XWar9MbNGUY-unsplash.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>It's common to find errors and bugs in your code if you're a software developer. They might occur because of incorrect input, from passing the wrong data types, or because of delays or response timeouts. </p>
<p>And even though errors and bugs are a part of life, they can stress you out and decrease your productivity. Fortunately, you can limit the number of pests in your code by taking proactive measures to prevent and fix them. </p>
<p>In this article, you will learn how best to utilize exception filters to limit disruptions in your code implementations.</p>
<h2 id="heading-what-are-exception-filters">What Are Exception Filters?</h2>
<p>Exception filters are constructs of a programming language that help you handle exceptions or errors found in services or controller classes. Using these filters improves the efficiency of your codebase and makes errors more traceable, which helps you resolve them.</p>
<h3 id="heading-what-are-exception-filters-in-nestjs">What are Exception Filters in Nest.js?</h3>
<p>Nest.js has an inbuilt exception filter interface that you import from the <code>@nestjs/common package</code>. This interface gives you precise information about exceptions you may encounter so that you can know how to fix them. </p>
<p>Some built-in exception filters include <code>NotFoundException</code>, <code>UnauthorizedException</code>, and <code>RequestTimeOutException</code>, among others.</p>
<h2 id="heading-how-to-create-a-custom-exception-filter">How to Create a Custom Exception Filter</h2>
<p>To create a custom exception filter class, you define it with a <code>@Catch</code> decorator that takes in the type of exception the filter should catch. This class then implements the <code>ExceptionFilter</code> interface. This way you will have access to the <code>catch</code> method that the interface provides. </p>
<p>NestJS allows you to create your own exception filters so you can define what sort of information it should return.</p>
<pre><code class="lang-typescript"><span class="hljs-meta">@Catch</span>(HttpException)
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> TestExceptionFilter <span class="hljs-keyword">implements</span> ExceptionFilter {
  <span class="hljs-keyword">catch</span>(exception: HttpException, host: ArgumentsHost) {
    <span class="hljs-keyword">const</span> ctx = host.switchToHttp();
    <span class="hljs-keyword">const</span> response = ctx.getResponse&lt;Response&gt;();
    <span class="hljs-keyword">const</span> request = ctx.getRequest&lt;Request&gt;();
    <span class="hljs-keyword">const</span> status = exception.getStatus();

    response
      .status(status)
      .json({
        statusCode: status,
        timestamp: <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>().toISOString(),
        path: request.url,
      });
  }
}
</code></pre>
<p>As you can see above, the catch method takes in two argument inputs: the <code>exception:HttpException</code> and the <code>host:argumentsHost</code>. </p>
<p><code>HttpException</code> is the exception thrown when an <code>HTTP</code> request fails and returns the appropriate Error Message with a status code as a response to the client. </p>
<p>The <code>argumentsHost</code> parameter provides information about the current request and response cycle. Here the code extracts the Response and Request objects from the <code>ArgumentsHost</code> object using the <code>switchToHttp</code> method. It then calls the <code>getStatus</code> method from the <code>HttpException</code> object in order to retrieve the <code>HTTP</code> status code of the error.</p>
<p> A <code>JSON</code> object gets returned. It contains the status code, the error timestamp, and the request URL, setting the <code>HTTP</code> response status code to be the error status code.</p>
<p>Another exciting thing to note is that you can modify the status code and error message of existing exception filters like <code>NotFoundException</code> so that they display your own custom error message and status code. Here is an illustration below:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> NotFoundException <span class="hljs-keyword">extends</span> HttpException {
  <span class="hljs-keyword">constructor</span>(<span class="hljs-params">message: <span class="hljs-built_in">string</span></span>) {
    <span class="hljs-built_in">super</span>(message || <span class="hljs-string">'Not Found'</span>, HttpStatus.NOT_FOUND);
  }
}
</code></pre>
<p>The example above shows that the <code>NotFoundException</code> class was modified to accept a <code>message</code> parameter in the constructor method or give a default value of 'Not Found'. </p>
<p>By doing this you are now able to customize an error message for your <code>NotFoundException</code> class and return a <code>404</code> status code.</p>
<h2 id="heading-how-to-bind-exception-filters-in-nestjs">How to Bind Exception Filters in Nest.js</h2>
<p>You might be wondering how you can implement the custom or modified exception you've created for your application. Well, you use something called <strong>binding</strong>. </p>
<p>There are several ways in which you can bind exception filters to your application. Here are three major ways you can do it:</p>
<ol>
<li>Global Scope</li>
<li>Controller Scope</li>
<li>Method Scope</li>
</ol>
<h3 id="heading-binding-using-global-scope"><strong>Binding using Global Scope</strong></h3>
<p>Just like the name “Global” implies, it covers the entirety of a thing – in this case the application. The custom exception filter is <strong>bonded</strong> to the entirety of your web application by using the <code>useGlobalFilters()</code> function. An instance of your custom exception filter gets passed in before starting up the server. </p>
<p>Here is an example of what that looks like:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">bootstrap</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> app = <span class="hljs-keyword">await</span> NestFactory.create(AppModule);
  app.useGlobalFilters(<span class="hljs-keyword">new</span> TestExceptionFilter());
  <span class="hljs-keyword">await</span> app.listen(<span class="hljs-number">3000</span>);
}
bootstrap();
</code></pre>
<p>If you bind the exception filter to the global scope, it means that any exceptions of type <code>HttpException</code> thrown from any controller or method within the application will be handled by the <code>TestExceptionFilter</code>.</p>
<h3 id="heading-binding-using-controller-scope"><strong>Binding using Controller Scope</strong></h3>
<p>If you want to handle an exception that not only covers the specific methods in your application but also the entire controller with the methods in it, you can the <code>@UseFilters</code> to bind the custom exception to the controller. Check out the below is example:</p>
<pre><code class="lang-typescript"><span class="hljs-meta">@UseFilters</span>(TestExceptionFilter)
<span class="hljs-meta">@Controller</span>(<span class="hljs-string">'users'</span>)
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> UsersController {
  <span class="hljs-meta">@Get</span>()
  <span class="hljs-keyword">async</span> findUsers() {
    <span class="hljs-comment">// ...</span>
  }
}
</code></pre>
<p>In this example, the custom exception filter is bonded to the controller by putting it ahead of the <code>@Controller</code> decorator. This way it handles any error that comes from the routes in this controller.</p>
<h3 id="heading-binding-using-method-scope"><strong>Binding using Method Scope</strong></h3>
<p>In this form of binding, you make use of the <code>@UseFilters</code> decorator to apply the Custom ExceptionFilter you defined to a method in your application. Here is an example:</p>
<pre><code class="lang-typescript"><span class="hljs-meta">@Controller</span>()
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> UsersController {
  <span class="hljs-meta">@Get</span>()
  <span class="hljs-meta">@UseFilters</span>(TestExceptionFilter)
  <span class="hljs-keyword">async</span> findUsers() {
    <span class="hljs-comment">// ...</span>
  }
}
</code></pre>
<p>In this example, you're using the <code>@UseFilters</code> decorator to bind the <code>TestExceptionFilter</code> exception filter to the <code>findUsers</code> method. This means that if any exception occurs within the <code>findUsers()</code> method, the <code>TestExceptionFilter</code> will catch and handle it.</p>
<h2 id="heading-debugging-made-easier">Debugging Made Easier</h2>
<p>In this tutorial, you learned about exception filters in Nest.js, and how to create custom exception filters. You also saw some different ways in which you can implement them in your applications.</p>
<p>All the methods discussed are good ways to handle exceptions. By implementing these techniques, you can ensure smoother application performance and provide a better user experience.</p>
<p>If you enjoyed reading this article, you can share and follow me on <a target="_blank" href="https://twitter.com/okoyevictorr">Twitter</a> and <a target="_blank" href="https://www.linkedin.com/in/officalrajdeepsingh/">Linkedin</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
