<?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[ queue - 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[ queue - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Fri, 29 May 2026 23:04:22 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/queue/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How to Implement Message Queues in Your Backend Applications ]]>
                </title>
                <description>
                    <![CDATA[ The goal of every web developer is to create a product that appeals to a wide range of users. However, this comes with its problems, chief among them being scalability issues to meet overwhelming user demands. If not addressed, this can result in a d... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-implement-message-queues-in-your-backend-applications/</link>
                <guid isPermaLink="false">66bc7f37f9d5ce174cf0c403</guid>
                
                    <category>
                        <![CDATA[ Microservices ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Node.js ]]>
                    </category>
                
                    <category>
                        <![CDATA[ queue ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Oluwatobi ]]>
                </dc:creator>
                <pubDate>Wed, 14 Aug 2024 09:56:07 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1723280791863/cdc4faaa-2f95-4219-8753-881dfcafbf45.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>The goal of every web developer is to create a product that appeals to a wide range of users. However, this comes with its problems, chief among them being scalability issues to meet overwhelming user demands.</p>
<p>If not addressed, this can result in a disarray of communication among services, defeating the measures placed to ensure orderly database transactions. But thank goodness, we have message brokers to the rescue.</p>
<p>In this article, we'll highlight the importance of message queuing as a best practice for backend development, relevant use cases and popular message queuing tools, and how to implement message queuing in backend applications.</p>
<p>Here are some of the prerequisites to be able to follow along in this article:</p>
<ul>
<li><p>Knowledge of Node.js</p>
</li>
<li><p>Knowledge of microservices architecture</p>
</li>
</ul>
<h2 id="heading-what-is-message-queuing">What is Message Queuing?</h2>
<p>In distributed systems, several requests and queues are sent at a time. The concept of a message queue enables the storage of messages in an orderly manner, allowing for the recipients of these messages and requests to process them accordingly.</p>
<p>It operates asynchronously, allowing the independent functioning of different components of a distributed system. Having these in place ensures that the messages sent to the recipient eventually get attended to irrespective of a system downtime. The messages are securely stored until they get acknowledged.</p>
<h3 id="heading-relevant-use-cases-of-message-brokers">Relevant Use Cases of Message Brokers</h3>
<p>Here are some of the real-life use cases of message brokers.</p>
<ul>
<li><p>They are actively used in modern fintech applications to ensure seamless and orderly execution and processing of financial transactions made on the application. This helps to prevent server overload and transaction errors.</p>
</li>
<li><p>Message queueing is also used in our day-to-day notification applications, ensuring early reception of sent notifications from other services. This allows the recipient to get access to those notifications notwithstanding the time they were sent or when the recipient gets access to the notification application.</p>
</li>
<li><p>It is also used in the financial markets for seamless and efficient execution of financial orders being made. Other uses of this feature are seen in media streaming and the healthcare industry.</p>
</li>
</ul>
<p>In the next paragraph, we'll discuss more about the tools that offer message queueing features.</p>
<h2 id="heading-examples-of-popular-message-queue-services">Examples of Popular Message Queue Services</h2>
<p>A wide range of applications and services offer message queueing features. Some of these services are embedded in commercial cloud infrastructure providers. Here is a list of some commonly used message queueing services:</p>
<ul>
<li><p>RabbitMQ</p>
</li>
<li><p>Apache Kafka</p>
</li>
<li><p>Redis</p>
</li>
<li><p>Amazon SQS</p>
</li>
<li><p>Google Cloud Pub/sub</p>
</li>
<li><p>NATS</p>
</li>
<li><p>Pulsar</p>
</li>
<li><p>IBM MQ</p>
</li>
</ul>
<p>We'll be utilizing a Rabbit MQ Cloud-as-a-service application to power our messages due to its popularity and ease of use. Here is a link to the <a target="_blank" href="https://www.cloudamqp.com/docs/index.html">documentation</a>. You can also check out other message queuing applications provided above.</p>
<p>Next, we'll develop a demo project that utilizes message queuing features.</p>
<h2 id="heading-demo-project">Demo Project</h2>
<p>In this project, we'll use Rabbit MQ as a service cloud platform to build a simple message broker system that allows for seamless, ordered communication between two Node.js servers.</p>
<p>In this tutorial, we'll create a message publisher that will serve as the sender, and a message consumer that receives the messages.</p>
<p>To begin with, we'll have to create both Node.js servers that will be communicating with each other.</p>
<p>You can create two different files and initialize a Node project using <code>npm init</code>.</p>
<p>Thereafter, you can install relevant packages that will aid in the implementation of the features. We'll use the <code>amqplib</code> library, a Node library implementation for Rabbit MQ.</p>
<p>This package allows us to swiftly communicate with RabbitMQ via the Node.js application. It seamlessly achieves this due to its built-in functions for creating queues, publishing messages, and consuming messages. More details regarding its usage will be discussed later.</p>
<p>To install this in our project, kindly execute:</p>
<pre><code class="lang-javascript">npm i amqplib
</code></pre>
<p>The publish function will now be drafted. After that, we'll have to initialize <code>amqplib</code> in our project.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> amp = <span class="hljs-built_in">require</span>(“amqplib”)
</code></pre>
<p>Also, we need to set up our RabbitMQ broker which will manage our messages.</p>
<p>There are several ways of creating RabbitMQ servers, the most popular being installing them on a home computer and then setting them up to interact with the backend servers. You can download the software <a target="_blank" href="https://www.rabbitmq.com/docs/download">here</a>. However, for ease of usage, we will be utilizing a cloud-based RabbitMQ broker as a service application to generate our server.</p>
<p>To get this done, kindly navigate to <a target="_blank" href="https://www.cloudamqp.com/">https://www.cloudamqp.com/</a> and create an account. For this tutorial, an instance was created and configured to the closest region to me. On successful creation of the instance, the details of the Rabbit MQ will be made available.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/08/cloudAmpq.PNG" alt="CloudAMQP home page" width="600" height="400" loading="lazy"></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/08/instance.PNG" alt="Creating  a free instance on CloudAMQP" width="600" height="400" loading="lazy"></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/08/amqpdets.PNG" alt="Details of the Free instance created" width="600" height="400" loading="lazy"></p>
<p>Moving on, we will be creating a message queue in which both parties can use as a connection pipeline. We will begin by creating a function to send messages.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">sendMessage</span>(<span class="hljs-params">msg</span>) </span>{
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">const</span> connection = <span class="hljs-keyword">await</span> amqp.connect(url);
    <span class="hljs-keyword">const</span> channel = <span class="hljs-keyword">await</span> connection.createChannel();

    <span class="hljs-keyword">await</span> channel.assertQueue(queue);
    <span class="hljs-keyword">await</span> channel.sendToQueue(queue, Buffer.from(msg));
</code></pre>
<p>In the code above, a connection was ensured and maintained. Thereafter, a communication channel was also created. The assert queue function is then declared when executed, ensuring that the existing queue is maintained, and creates the queue if it doesn't exist.</p>
<p>The message attached to the function gets buffered and then sent to the queue created.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">receiveMessage</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">const</span> connection = <span class="hljs-keyword">await</span> amqp.connect(url);
    <span class="hljs-keyword">const</span> channel = <span class="hljs-keyword">await</span> connection.createChannel();

    <span class="hljs-keyword">await</span> channel.assertQueue(queue);
    <span class="hljs-keyword">await</span> channel.consume(queue, <span class="hljs-function">(<span class="hljs-params">msg</span>) =&gt;</span> {
      <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Received message: <span class="hljs-subst">${msg.content.toString()}</span>`</span>);
      channel.ack(msg);
    });
</code></pre>
<p>The receiver function also gets executed to receive any message that gets into the queue by executing the consume method at the exact queue. In our case, the message is outputted as a log message.</p>
<p>The <code>ack</code> function is now executed to acknowledge the message received from the queue.</p>
<p>Here is the full project code:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> amqp = <span class="hljs-built_in">require</span>(<span class="hljs-string">"amqplib"</span>);
<span class="hljs-keyword">const</span> url = <span class="hljs-string">"amqp://localhost"</span>; <span class="hljs-comment">// Replace with your RabbitMQ server URL</span>
<span class="hljs-keyword">const</span> queue = <span class="hljs-string">"queue"</span>;

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">receiveMessage</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">const</span> connection = <span class="hljs-keyword">await</span> amqp.connect(url);
    <span class="hljs-keyword">const</span> channel = <span class="hljs-keyword">await</span> connection.createChannel();

    <span class="hljs-keyword">await</span> channel.assertQueue(queue);
    <span class="hljs-keyword">await</span> channel.consume(queue, <span class="hljs-function">(<span class="hljs-params">msg</span>) =&gt;</span> {
      <span class="hljs-keyword">if</span> (msg !== <span class="hljs-literal">null</span>) {
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Received message: <span class="hljs-subst">${msg.content.toString()}</span>`</span>);
        channel.ack(msg);
      }
    });
  } <span class="hljs-keyword">catch</span> (err) {
    <span class="hljs-built_in">console</span>.error(<span class="hljs-string">"Failed to receive message:"</span>, err);
  }
}

receiveMessage();
</code></pre>
<p>Here's the message publisher application code:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> amqp = <span class="hljs-built_in">require</span>(<span class="hljs-string">"amqplib"</span>);
<span class="hljs-keyword">const</span> url = <span class="hljs-string">"amqp://localhost"</span>; <span class="hljs-comment">// Replace with your RabbitMQ server URL</span>
<span class="hljs-keyword">const</span> queue = <span class="hljs-string">"queue"</span>;

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">sendMessage</span>(<span class="hljs-params">msg</span>) </span>{
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">const</span> connection = <span class="hljs-keyword">await</span> amqp.connect(url);
    <span class="hljs-keyword">const</span> channel = <span class="hljs-keyword">await</span> connection.createChannel();

    <span class="hljs-keyword">await</span> channel.assertQueue(queue);
    <span class="hljs-keyword">await</span> channel.sendToQueue(queue, Buffer.from(msg));

    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Message sent to <span class="hljs-subst">${queue}</span>: <span class="hljs-subst">${msg}</span>`</span>);

    <span class="hljs-keyword">await</span> channel.close();
    <span class="hljs-keyword">await</span> connection.close();
  } <span class="hljs-keyword">catch</span> (err) {
    <span class="hljs-built_in">console</span>.error(<span class="hljs-string">"Failed to send message:"</span>, err);
  }
}

sendMessage(<span class="hljs-string">"Hello, world!"</span>);
</code></pre>
<p>Here is the output of the code:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/08/msg-queue.PNG" alt="Executed Node JS code" width="600" height="400" loading="lazy"></p>
<h2 id="heading-additional-info">Additional info</h2>
<p>So far, we have completed this tutorial on message queueing and its role in facilitating seamless communication across various systems. To further improve your skillset, here are some additional best practices that should be implemented when building complex services:</p>
<ul>
<li><p>Rate limiting</p>
</li>
<li><p>Load balancing</p>
</li>
<li><p>Application monitoring and logging</p>
</li>
<li><p>Continuous integration and deployment</p>
</li>
</ul>
<h2 id="heading-summary">Summary</h2>
<p>We've highlighted the importance of message brokers and how to implement message queueing in a backend application.</p>
<p>Feel free to check out my other articles <a target="_blank" href="https://linktr.ee/tobilyn77">here</a>. Till next time, keep on coding!</p>
 ]]>
                </content:encoded>
            </item>
        
            <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="932" height="473" 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="2099" height="430" 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[ How to Use Queues in Web Applications – Node.js and Redis Tutorial ]]>
                </title>
                <description>
                    <![CDATA[ When you're building large scale web applications, speed is a major priority. Users don't want to wait long for responses anymore, and they shouldn't have to. But some processes take time, and they cannot be made any faster or eliminated. Message que... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-use-queues-in-web-applications/</link>
                <guid isPermaLink="false">66c4c699744830ebca763790</guid>
                
                    <category>
                        <![CDATA[ Node.js ]]>
                    </category>
                
                    <category>
                        <![CDATA[ queue ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Redis ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Zubair Idris Aweda ]]>
                </dc:creator>
                <pubDate>Thu, 06 Jul 2023 16:23:18 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/07/businessmen02.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>When you're building large scale web applications, speed is a major priority. Users don't want to wait long for responses anymore, and they shouldn't have to. But some processes take time, and they cannot be made any faster or eliminated.</p>
<p>Message queues help solve this problem by providing an additional branch to the usual request-response journey. This additional branch helps make sure users can get immediate responses, and the time-consuming processes can be done on the side. Everybody goes home happy.</p>
<p>This article will focus on explaining what message queues are and how to get started with them by building a very simple application. You should be familiar with the basics of Node.js, and you should have Redis installed either locally or on a cloud instance. Learn how to install Redis <a target="_blank" href="https://redis.io/docs/getting-started/installation/">here</a>.</p>
<h2 id="heading-what-is-a-queue">What is a Queue?</h2>
<p>A queue is a data structure that allows you store entities in an order. Queues use a first-in-first-out (FIFO) principle. </p>
<p>The concept of queues in computer science is the same as the concept of queues in everyday life where people line up to get things. You join a queue from the back, wait till it is your turn, then leave the queue from the front after you have been attended to.</p>
<p>In computer science, when a process like an API request is running, and you need to remove a certain task (like sending an email) from the current flow, you push it to a queue and continue the process.</p>
<p>The diagram below illustrates the lifecycle of a queue:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/job-lifecycle.png" alt="Image" width="600" height="400" loading="lazy">
<em>Queue Lifecycle | https://optimalbits.github.io/bull/</em></p>
<h2 id="heading-what-is-a-job">What is a Job?</h2>
<p>A job is any piece of data that is used on a queue, usually a JSON-like object.</p>
<p>As demonstrated in the cover image of this article, you can think of a job as each person on a queue at an airport. Each person holds a briefcase containing specific data, and other instructions (passports and maybe medical papers where required) that will help when it is their turn to be attended to.</p>
<p>New people joining this queue will enter from the back (as the last person), and people will be attended to from the front. That is how jobs are also processed, each job contains data that will be used for its processing. New jobs are added from the back while jobs are taken out from the front.</p>
<h3 id="heading-what-is-a-job-producer">What is a Job Producer?</h3>
<p>A job producer is any piece of code that adds a job to a queue. In real life, this would be the security guard at the airport that gives direction to people, telling them which queue to join for different purposes. </p>
<p>A job producer can exist independently of a job consumer. This means that in a microservice setup, a particular service might just be concerned with adding jobs to a queue, but not how they're processed after.</p>
<h3 id="heading-what-is-a-worker-job-consumer">What is a Worker (Job Consumer)?</h3>
<p>A worker, or job consumer, is a process, or function, that can execute a job. Think of a worker as a bank cashier attending to people on a queue at the bank. When the first person comes in, they join the queue as the only one on the queue. The cashier then calls for them and the queue is emptied. </p>
<p>The cashier requests for specific details to be used to process the transaction from the person. While the cashier attends to that customer, four more customers could have lined up. They will remain on the queue till the cashier is done with the first customer before calling for the next one. This is the same process with queue workers — they pick the first job in the queue, and process it.</p>
<h3 id="heading-what-are-failed-jobs">What are Failed Jobs?</h3>
<p>Often times, some jobs might fail during processing.</p>
<p>Here are some reasons why a job could fail:</p>
<ul>
<li>Invalid or missing input data: When data required for a job to be processed is missing, the job will fail. For example, a job to send an email will fail without the recipient's email address.</li>
<li>Timeout: A job could be failed by the queue mechanism if it is taking longer than usual. This could be due to an issue on a dependency of the job or something else, but usually you don't want a single job running forever.</li>
<li>Network or infrastructure problems: These problems are almost out of your control, but they do happen. A database connection error for example would fail a job.</li>
<li>Dependency issues: Sometimes a job relies on some external resources to function well. Whenever these other resources are unavailable or unsuccessful, the job will fail.</li>
</ul>
<p>When jobs fail, you can configure your queue mechanism to retry them. You can either retry the job immediately, or after a calculated amount of time. You can set a maximum number of attempts, which is recommended. If not, you end up running a job that will always fail infinitely.</p>
<h2 id="heading-why-use-queues">Why Use Queues?</h2>
<p>Queues are useful for creating robust communication channels between microservices. Multiple services can use the same queue. Different services could be tasked with different problems. When a service completes its task, it can push a job to another service that has workers waiting for that job. That service will pick it up and do whatever is needed with the data.</p>
<p>Queues are also useful for offloading heavy tasks from a process. As you'll see in this article, a time consuming task like sending of an email can be put on a queue to avoid slowing down response time.</p>
<p>Queues help avoid single points of failure. A process that has the ability to fail and can be retried is best processed using a queue where it can be retried after a while.</p>
<h2 id="heading-how-to-build-a-simple-application-that-uses-queues">How to Build a Simple Application that Uses Queues</h2>
<p>In this article, we'll build a simple project using Node.js and <a target="_blank" href="https://redis.io/">Redis</a>. We'll use the <a target="_blank" href="https://optimalbits.github.io/bull/">Bull</a> library as it simplifies a lot of the complexities involved in building a queue system. The project will have a single endpoint to send emails.</p>
<h3 id="heading-create-a-new-nodejs-project">Create a New Node.js Project</h3>
<pre><code class="lang-shell">mkdir nodejs-queue-project
cd nodejs-queue-project
npm init -y
</code></pre>
<p>The commands above will create a new folder named <code>nodejs-queue-project</code> and a <code>package.json</code> file in it. The <code>package.json</code> file should look like this:</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"name"</span>: <span class="hljs-string">"nodejs-queue-project"</span>,
  <span class="hljs-attr">"version"</span>: <span class="hljs-string">"1.0.0"</span>,
  <span class="hljs-attr">"description"</span>: <span class="hljs-string">""</span>,
  <span class="hljs-attr">"main"</span>: <span class="hljs-string">"index.js"</span>,
  <span class="hljs-attr">"scripts"</span>: {
    <span class="hljs-attr">"test"</span>: <span class="hljs-string">"echo \"Error: no test specified\" &amp;&amp; exit 1"</span>
  },
  <span class="hljs-attr">"keywords"</span>: [],
  <span class="hljs-attr">"author"</span>: <span class="hljs-string">""</span>,
  <span class="hljs-attr">"license"</span>: <span class="hljs-string">"ISC"</span>
}
</code></pre>
<h3 id="heading-install-the-required-dependencies">Install the Required Dependencies</h3>
<pre><code class="lang-shell">npm i express @types/express @types/node body-parser ts-node ts-lint typescript nodemon nodemailer @types/nodemailer
</code></pre>
<p>The commands above will install the different packages and dependencies required for the project. </p>
<p>After installation, you can update the <code>scripts</code> section of your <code>package.json</code> to have a <code>dev</code> command. Your whole <code>package.json</code> file should look like this now:</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"name"</span>: <span class="hljs-string">"nodejs-queue-project"</span>,
  <span class="hljs-attr">"version"</span>: <span class="hljs-string">"1.0.0"</span>,
  <span class="hljs-attr">"description"</span>: <span class="hljs-string">""</span>,
  <span class="hljs-attr">"main"</span>: <span class="hljs-string">"index.js"</span>,
  <span class="hljs-attr">"scripts"</span>: {
    <span class="hljs-attr">"dev"</span>: <span class="hljs-string">"nodemon src/app.ts"</span>
  },
  <span class="hljs-attr">"keywords"</span>: [],
  <span class="hljs-attr">"author"</span>: <span class="hljs-string">""</span>,
  <span class="hljs-attr">"license"</span>: <span class="hljs-string">"ISC"</span>,
  <span class="hljs-attr">"dependencies"</span>: {
    <span class="hljs-attr">"@types/express"</span>: <span class="hljs-string">"^4.17.17"</span>,
    <span class="hljs-attr">"@types/node"</span>: <span class="hljs-string">"^20.3.3"</span>,
    <span class="hljs-attr">"@types/nodemailer"</span>: <span class="hljs-string">"^6.4.8"</span>,
    <span class="hljs-attr">"body-parser"</span>: <span class="hljs-string">"^1.20.2"</span>,
    <span class="hljs-attr">"express"</span>: <span class="hljs-string">"^4.18.2"</span>,
    <span class="hljs-attr">"nodemailer"</span>: <span class="hljs-string">"^6.9.3"</span>,
    <span class="hljs-attr">"nodemon"</span>: <span class="hljs-string">"^2.0.22"</span>,
    <span class="hljs-attr">"ts-lint"</span>: <span class="hljs-string">"^4.5.1"</span>,
    <span class="hljs-attr">"ts-node"</span>: <span class="hljs-string">"^10.9.1"</span>,
    <span class="hljs-attr">"typescript"</span>: <span class="hljs-string">"^5.1.6"</span>
  }
}
</code></pre>
<p>The file above shows all your installed dependencies. The <code>npm run dev</code> command will run when you use the <code>dev</code> script.</p>
<h2 id="heading-how-to-build-the-endpoint">How to Build the Endpoint</h2>
<p>The first thing to do is to create a new folder named <code>src</code>. This folder will contain all your code files. The first file it will contain is the root file of the application — the <code>app.ts</code> file as defined in the <code>package.json</code> file.</p>
<p>We'll use the <code>app.ts</code> file to import required packages and create a simple server with a single endpoint to send a email as seen below:</p>
<pre><code class="lang-ts"><span class="hljs-keyword">import</span> express <span class="hljs-keyword">from</span> <span class="hljs-string">"express"</span>;
<span class="hljs-keyword">import</span> bodyParser <span class="hljs-keyword">from</span> <span class="hljs-string">"body-parser"</span>;
<span class="hljs-keyword">import</span> nodemailer <span class="hljs-keyword">from</span> <span class="hljs-string">"nodemailer"</span>;

<span class="hljs-keyword">const</span> app = express();

app.use(bodyParser.json());

app.post(<span class="hljs-string">"/send-email"</span>, <span class="hljs-keyword">async</span> (req, res) =&gt; {
  <span class="hljs-keyword">const</span> { <span class="hljs-keyword">from</span>, to, subject, text } = req.body;

  <span class="hljs-comment">// Use a test account as this is a tutorial</span>
  <span class="hljs-keyword">const</span> testAccount = <span class="hljs-keyword">await</span> nodemailer.createTestAccount();

  <span class="hljs-keyword">const</span> transporter = nodemailer.createTransport({
    host: <span class="hljs-string">"smtp.ethereal.email"</span>,
    port: <span class="hljs-number">587</span>,
    secure: <span class="hljs-literal">false</span>,
    auth: {
      user: testAccount.user,
      pass: testAccount.pass,
    },
    tls: {
      rejectUnauthorized: <span class="hljs-literal">false</span>,
    },
  });

  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Sending mail to %s"</span>, to);

  <span class="hljs-keyword">let</span> info = <span class="hljs-keyword">await</span> transporter.sendMail({
    <span class="hljs-keyword">from</span>,
    to,
    subject,
    text,
    html: <span class="hljs-string">`&lt;strong&gt;<span class="hljs-subst">${text}</span>&lt;/strong&gt;`</span>,
  });

  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Message sent: %s"</span>, info.messageId);
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Preview URL: %s"</span>, nodemailer.getTestMessageUrl(info));

  res.json({
    message: <span class="hljs-string">"Email Sent"</span>,
  });
});

app.listen(<span class="hljs-number">4300</span>, <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Server started at http://localhost:4300"</span>);
});
</code></pre>
<p>Now, you can start your server by running <code>npm run dev</code> in your terminal. You should see a message saying <code>Server started at [http://localhost:4300](http://localhost:4300)</code> in your terminal.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/Screenshot-2023-07-01-at-17.41.33.png" alt="Image" width="600" height="400" loading="lazy">
<em>npm run dev message</em></p>
<p>You can now test the endpoint using a tool like Postman:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/Screenshot-2023-07-01-at-17.30.33.png" alt="Image" width="600" height="400" loading="lazy">
<em>Endpoint testing on Postman</em></p>
<p>The request took almost 4 seconds as shown in the screenshot. This is very slow for an endpoint. If you take a look at your terminal, you should also see a URL where you can preview the email that was sent.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/Screenshot-2023-07-01-at-17.43.01.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Opening the link lets you see how the email looks.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/Screenshot-2023-07-01-at-17.43.47.png" alt="Image" width="600" height="400" loading="lazy">
<em>Email content</em></p>
<h2 id="heading-how-to-create-the-queue">How to Create the Queue</h2>
<p>To make the process even faster, the email can be queued to be sent later and a response sent to the user immediately.</p>
<p>To do this, install the <code>bull</code> library and its <code>@types</code> library as we'll use it to create a queue. That is:</p>
<pre><code class="lang-shell">npm i bull @types/bull
</code></pre>
<p>Creating a new queue using <code>bull</code> is as easy as instantiating a new <code>Bull</code> object with a name for the queue:</p>
<pre><code class="lang-ts"><span class="hljs-comment">// This goes at the top of your file</span>
<span class="hljs-keyword">import</span> Bull <span class="hljs-keyword">from</span> <span class="hljs-string">'bull'</span>;

<span class="hljs-keyword">const</span> emailQueue = <span class="hljs-keyword">new</span> Bull(<span class="hljs-string">"email"</span>);
</code></pre>
<p>When the queue is created with just the queue name, it tries to use the default Redis connection URL: <code>localhost:6379</code>. If you prefer using a different URL, simply pass in a second object to the <code>Bull</code> class as an options object:</p>
<pre><code class="lang-ts"><span class="hljs-keyword">const</span> emailQueue = <span class="hljs-keyword">new</span> Bull(<span class="hljs-string">"email"</span>, {
  redis: <span class="hljs-string">"localhost:6379"</span>,
});
</code></pre>
<p>At this point, you can create a simple function to serve as a job producer and add a job to the queue every time a request comes in.</p>
<pre><code class="lang-ts"><span class="hljs-keyword">type</span> EmailType = {
  <span class="hljs-keyword">from</span>: <span class="hljs-built_in">string</span>;
  to: <span class="hljs-built_in">string</span>;
  subject: <span class="hljs-built_in">string</span>;
  text: <span class="hljs-built_in">string</span>;
};

<span class="hljs-keyword">const</span> sendNewEmail = <span class="hljs-keyword">async</span> (email: EmailType) =&gt; {
  emailQueue.add({ ...email });
};
</code></pre>
<p>This newly created function, <code>sendNewEmail</code>, accepts an object containing details of the new email to be sent of type <code>EmailType</code>. There's sender email address (<code>from</code>), recipient email address (<code>to</code>), <code>subject</code> of the email, and the content of the email (<code>text</code>). Then it pushes a new job to the queue. </p>
<p>You can use this function instead of sending the email during the request now. Modify the endpoint to do this:</p>
<pre><code class="lang-ts">app.post(<span class="hljs-string">"/send-email"</span>, <span class="hljs-keyword">async</span> (req, res) =&gt; {
  <span class="hljs-keyword">const</span> { <span class="hljs-keyword">from</span>, to, subject, text } = req.body;

  <span class="hljs-keyword">await</span> sendNewEmail({ <span class="hljs-keyword">from</span>, to, subject, text });

  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Added to queue"</span>);

  res.json({
    message: <span class="hljs-string">"Email Sent"</span>,
  });
});
</code></pre>
<p>At this point, the code is simpler and the process is faster. The request only takes about 40m — about 100x faster than before.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/Screenshot-2023-07-01-at-18.25.40.png" alt="Image" width="600" height="400" loading="lazy">
<em>Endpoint testing with Postman</em></p>
<p>At this point, the email is added to a queue. It will remain on the queue until processed. The job can be processed by the same application or another service (if in a <a target="_blank" href="https://www.freecodecamp.org/news/microservices-architecture-for-humans/">microservice setup</a>).</p>
<h2 id="heading-how-to-process-the-jobs">How to Process the Jobs</h2>
<p>The cycle is incomplete and useless if the mails never leave the queue. We'll create a job consumer to process the jobs and clear the queue.</p>
<p>We can do this by creating the logic for a function that accepts a <code>Job</code> object and sends the email:</p>
<pre><code class="lang-ts"><span class="hljs-keyword">const</span> processEmailQueue = <span class="hljs-keyword">async</span> (job: Job) =&gt; {
  <span class="hljs-comment">// Use a test account as this is a tutorial</span>
  <span class="hljs-keyword">const</span> testAccount = <span class="hljs-keyword">await</span> nodemailer.createTestAccount();

  <span class="hljs-keyword">const</span> transporter = nodemailer.createTransport({
    host: <span class="hljs-string">"smtp.ethereal.email"</span>,
    port: <span class="hljs-number">587</span>,
    secure: <span class="hljs-literal">false</span>,
    auth: {
      user: testAccount.user,
      pass: testAccount.pass,
    },
    tls: {
      rejectUnauthorized: <span class="hljs-literal">false</span>,
    },
  });

  <span class="hljs-keyword">const</span> { <span class="hljs-keyword">from</span>, to, subject, text } = job.data;

  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Sending mail to %s"</span>, to);

  <span class="hljs-keyword">let</span> info = <span class="hljs-keyword">await</span> transporter.sendMail({
    <span class="hljs-keyword">from</span>,
    to,
    subject,
    text,
    html: <span class="hljs-string">`&lt;strong&gt;<span class="hljs-subst">${text}</span>&lt;/strong&gt;`</span>,
  });

  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Message sent: %s"</span>, info.messageId);
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Preview URL: %s"</span>, nodemailer.getTestMessageUrl(info));

  <span class="hljs-keyword">return</span> nodemailer.getTestMessageUrl(info);
};
</code></pre>
<p>The function above accepts a <code>Job</code> object. The object has useful properties that shows the status of and data in a job. Here, we use the <code>data</code> property. </p>
<p>At this point, all we have is a function. It doesn't pick up jobs automatically because it doesn't know which queue to work with.</p>
<p>Before connecting it to the queue, you can go on to add a few jobs to the queue by sending some requests. You can check the email jobs currently queued by running this command in your <code>redis-cli</code>:</p>
<pre><code class="lang-shell">LRANGE bull:email:wait 0 -1
</code></pre>
<p>This checks the email waitlist, and returns the <code>ids</code> of the waiting jobs.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/Screenshot-2023-07-01-at-18.47.35.png" alt="Image" width="600" height="400" loading="lazy">
<em>Redis CLI</em></p>
<p>I have created a few jobs just to show how workers actually work.</p>
<p>Now, connect the worker to the queue by adding this line of code:</p>
<pre><code class="lang-ts">emailQueue.process(processEmailQueue);
</code></pre>
<p>This is what your <code>app.ts</code> file should now look after that:</p>
<pre><code class="lang-ts"><span class="hljs-keyword">import</span> express <span class="hljs-keyword">from</span> <span class="hljs-string">"express"</span>;
<span class="hljs-keyword">import</span> bodyParser <span class="hljs-keyword">from</span> <span class="hljs-string">"body-parser"</span>;
<span class="hljs-keyword">import</span> nodemailer <span class="hljs-keyword">from</span> <span class="hljs-string">"nodemailer"</span>;
<span class="hljs-keyword">import</span> Bull, { Job } <span class="hljs-keyword">from</span> <span class="hljs-string">"bull"</span>;

<span class="hljs-keyword">const</span> app = express();

app.use(bodyParser.json());

<span class="hljs-keyword">const</span> emailQueue = <span class="hljs-keyword">new</span> Bull(<span class="hljs-string">"email"</span>, {
  redis: <span class="hljs-string">"localhost:6379"</span>,
});

<span class="hljs-keyword">type</span> EmailType = {
  <span class="hljs-keyword">from</span>: <span class="hljs-built_in">string</span>;
  to: <span class="hljs-built_in">string</span>;
  subject: <span class="hljs-built_in">string</span>;
  text: <span class="hljs-built_in">string</span>;
};

<span class="hljs-keyword">const</span> sendNewEmail = <span class="hljs-keyword">async</span> (email: EmailType) =&gt; {
  emailQueue.add({ ...email });
};

<span class="hljs-keyword">const</span> processEmailQueue = <span class="hljs-keyword">async</span> (job: Job) =&gt; {
  <span class="hljs-comment">// Use a test account as this is a tutorial</span>
  <span class="hljs-keyword">const</span> testAccount = <span class="hljs-keyword">await</span> nodemailer.createTestAccount();

  <span class="hljs-keyword">const</span> transporter = nodemailer.createTransport({
    host: <span class="hljs-string">"smtp.ethereal.email"</span>,
    port: <span class="hljs-number">587</span>,
    secure: <span class="hljs-literal">false</span>,
    auth: {
      user: testAccount.user,
      pass: testAccount.pass,
    },
    tls: {
      rejectUnauthorized: <span class="hljs-literal">false</span>,
    },
  });

  <span class="hljs-keyword">const</span> { <span class="hljs-keyword">from</span>, to, subject, text } = job.data;

  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Sending mail to %s"</span>, to);

  <span class="hljs-keyword">let</span> info = <span class="hljs-keyword">await</span> transporter.sendMail({
    <span class="hljs-keyword">from</span>,
    to,
    subject,
    text,
    html: <span class="hljs-string">`&lt;strong&gt;<span class="hljs-subst">${text}</span>&lt;/strong&gt;`</span>,
  });

  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Message sent: %s"</span>, info.messageId);
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Preview URL: %s"</span>, nodemailer.getTestMessageUrl(info));
};

emailQueue.process(processEmailQueue);

app.post(<span class="hljs-string">"/send-email"</span>, <span class="hljs-keyword">async</span> (req, res) =&gt; {
  <span class="hljs-keyword">const</span> { <span class="hljs-keyword">from</span>, to, subject, text } = req.body;

  <span class="hljs-keyword">await</span> sendNewEmail({ <span class="hljs-keyword">from</span>, to, subject, text });

  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Added to queue"</span>);

  res.json({
    message: <span class="hljs-string">"Email Sent"</span>,
  });
});

app.listen(<span class="hljs-number">4300</span>, <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Server started at http://localhost:4300"</span>);
});
</code></pre>
<p>Once you save, you'll notice that the server restarts and immediately starts sending out mails. This is because the worker sees the queue and begins processing immediately.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/Screenshot-2023-07-01-at-18.51.14.png" alt="Image" width="600" height="400" loading="lazy">
<em>Server sending out queued emails</em></p>
<p>Now, both the producer and the worker are active. Every new API request will be pushed to the queue, and the worker will immediately process it unless there's some pending jobs already.</p>
<h2 id="heading-summary"><strong>Summary</strong></h2>
<p>I hope this article helped you understand what a message queue is, how to add jobs and create processes to run them, and how you can use them to build better web applications. You can find the code files used in this article on <a target="_blank" href="https://github.com/Zubs/php-redis">GitHub</a>.</p>
<p>If you have any questions or relevant advice, please get in touch with me to share them.</p>
<p>To read more of my articles or follow my work, you can connect with me on <a target="_blank" href="https://www.linkedin.com/in/idris-aweda-zubair-5433121a3/">LinkedIn</a>, <a target="_blank" href="https://twitter.com/AwedaIdris">Twitter</a>, and <a target="_blank" href="https://github.com/Zubs">Github</a>. It’s quick, it’s easy, and it’s free!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Queue Data Structure – Definition and Java Example Code ]]>
                </title>
                <description>
                    <![CDATA[ In this article, we will talk about the queue data structure, its operations, and how to implement these operations using an array in Java.  What Is a Queue? A queue is linear data structure that consists of a collection is of items that follow a fir... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/queue-data-structure-definition-and-java-example-code/</link>
                <guid isPermaLink="false">66b0a35a03036c3282dfd7d3</guid>
                
                    <category>
                        <![CDATA[ data structures ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Java ]]>
                    </category>
                
                    <category>
                        <![CDATA[ queue ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Ihechikara Abba ]]>
                </dc:creator>
                <pubDate>Fri, 04 Mar 2022 00:36:52 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/03/queue-data-structure.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In this article, we will talk about the queue data structure, its operations, and how to implement these operations using an array in Java. </p>
<h2 id="heading-what-is-a-queue">What Is a Queue?</h2>
<p>A <strong>queue</strong> is linear data structure that consists of a collection is of items that follow a <strong>first-in-first-out</strong> sequence. This implies that the first item to be inserted will be the first to be removed. You can also say that items are removed in the order they were inserted.</p>
<p>Using a real world example, we can compare a queue data structure to a queue of individuals standing in line for a service. Once one individual is attended to, they leave the queue for the next person to be attended to. They are helped in the order which they came.</p>
<h2 id="heading-structure-of-a-queue">Structure of a Queue</h2>
<p>A queue is mainly made up of two parts: the front/head and the rear/tail/back. For the purpose of clarity and consistency, we will stick to using front and back.</p>
<p>The <strong>back</strong> is where the items are inserted and the <strong>front</strong> is the part of the queue where items are removed/deleted.</p>
<p>Here is a diagram to help you understand better:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/03/queue-structure-2.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>The image shows an array with various cells. The items are inserted through the <strong>back</strong> and removed through the <strong>front</strong>. There are terms used for the insertion and deletion of items in a queue which we will cover in the next section.</p>
<p>Note that you can reverse the structure of your queue – you can have the front on the right and the back on the left side. Whichever structure you go with, always remember that insertion of items happens through the back and deletion through the front.</p>
<h2 id="heading-common-operations-of-a-queue">Common Operations of a Queue</h2>
<p>The following operations are commonly used in a queue:</p>
<ul>
<li><strong>Enqueue</strong>: Adds an item from the back of the queue.</li>
<li><strong>Dequeue</strong>: Removes an item from the front of the queue.</li>
<li><strong>Front</strong>/<strong>Peek</strong>: Returns the value of the item in front of the queue without dequeuing (removing) the item.</li>
<li><strong>IsEmpty</strong>: Checks if the queue is empty.</li>
<li><strong>IsFull</strong>: Checks if the queue is full.</li>
<li><strong>Display</strong>: Prints all the items in the queue.</li>
</ul>
<p>Before we see how to implement this with code, you need to understand how the <strong>enqueue</strong> and <strong>dequeue</strong> operations work and how they affect the front and back positions. </p>
<p>The indices of arrays in most programming languages start from 0. While implementing our code, we are going to set the index of the front and back values of our array to -1. This will enable us move the front and back position properly as values are added.</p>
<p>Consider the image below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/03/front-and-back.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>The arrows show the position of the front and back of our array. When both positions are at -1, it means the array is empty. </p>
<p>Let us add some items into our array and see what happens.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/03/queue-0.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>We have inserted (enqueued) our first item – 5. The position of the front and back have moved as well. Next, we will see what happens as we enqueue more items</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/03/queue-1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>A second item has been added but only the back moved. This will continue as we enqueue more items. The front and back moved together in the last example so that the front could assume the position of the first item. </p>
<p>Since that was the first and only item then, the front and back sat at that position. But now that we have enqueued more items, the back will keep following the last item. </p>
<p>We will go on and fill up the array so we can see what happens when we dequeue.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/03/queue-4.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>So the back arrow followed the items in the order they were added all the way to the last. Now let's delete (dequeue) some items. </p>
<p>Remember the <strong>first-come-first-out</strong> sequence? When we execute the dequeue operation, it will first remove 5 from the queue. If we execute it again then it will move to the next number which is 10 and continue in that order for as long as we call it.</p>
<p>Here, the first dequeue operation:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/03/dequeue-1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Now the front arrow has moved to index 1. This implies that the item at index 0 has been removed. By removed, we do not mean from the array but from the queue – only items from the front position to the back position are part of the queue.</p>
<p>In the same order, if we keep removing items, it will get to a point where the front arrow meets the back arrow at the end of the queue. If we dequeue again at that point, the front arrow will move past the back arrow and then the queue will be considered empty because there is nothing there to delete. When this happens, we will reset their index to -1 (their initial starting point).</p>
<p>Time for some code!</p>
<h2 id="heading-queue-implementation-in-java">Queue Implementation in Java</h2>
<p>We will break this section down by creating each operation and then putting everything together at the end. </p>
<pre><code class="lang-java"><span class="hljs-keyword">int</span> queueLength = <span class="hljs-number">3</span>;
<span class="hljs-keyword">int</span> items[] = <span class="hljs-keyword">new</span> <span class="hljs-keyword">int</span>[queueLength];
<span class="hljs-keyword">int</span> front = -<span class="hljs-number">1</span>; 
<span class="hljs-keyword">int</span> back = -<span class="hljs-number">1</span>;
</code></pre>
<p>We have created our variables and their parameters. We are using 3 as the maximum number of items that can be enqueued in the array. Like we saw in the images from the previous section, we have set the initial index of the front and back to -1.</p>
<p>Next, we'll define the <strong>isEmpty</strong> and <strong>isFull</strong> functionalities.</p>
<p>For <strong>isEmpty</strong>:</p>
<pre><code class="lang-java"><span class="hljs-function"><span class="hljs-keyword">boolean</span> <span class="hljs-title">isEmpty</span><span class="hljs-params">()</span></span>{
      <span class="hljs-keyword">if</span>(front == -<span class="hljs-number">1</span> &amp;&amp; back == -<span class="hljs-number">1</span>){
          <span class="hljs-keyword">return</span> <span class="hljs-keyword">true</span>;
      } <span class="hljs-keyword">else</span> {
          <span class="hljs-keyword">return</span> <span class="hljs-keyword">false</span>;
      }
  }
</code></pre>
<p>Pretty easy to grasp if you followed along in the last section. The array is empty only if the index of front and back is -1. </p>
<p>For <strong>isFull</strong>:</p>
<pre><code class="lang-java"><span class="hljs-function"><span class="hljs-keyword">boolean</span> <span class="hljs-title">isFull</span><span class="hljs-params">()</span></span>{
      <span class="hljs-keyword">if</span>(back == queueLength - <span class="hljs-number">1</span>){
          <span class="hljs-keyword">return</span> <span class="hljs-keyword">true</span>;
      } <span class="hljs-keyword">else</span> {
          <span class="hljs-keyword">return</span> <span class="hljs-keyword">false</span>;
      }
  }
</code></pre>
<p>This one might seem a little tricky, but here's the logic: our maximum number of items allowed in the array is 3 but three items in an array is not denoted by index 3 but 2 since the first index is 0. So maximum length minus 1 gives us index 2 which is the third cell in an array.</p>
<p>When all the cells have been enqueued with a value up to the third cell, the array is full.</p>
<p>For <strong>enQueue</strong>:</p>
<pre><code class="lang-java"><span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">enQueue</span><span class="hljs-params">(<span class="hljs-keyword">int</span> itemValue)</span> </span>{
      <span class="hljs-keyword">if</span>(isFull()){
          System.out.println(<span class="hljs-string">"Queue is full"</span>);
      } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span>(front == -<span class="hljs-number">1</span> &amp;&amp; back == -<span class="hljs-number">1</span>){
          front = back = <span class="hljs-number">0</span>;
          items[back] = itemValue;
      } <span class="hljs-keyword">else</span>{
          back++;
          items[back] = itemValue;
      }
  }
</code></pre>
<p>If the array is full then we get a message saying it is full. If the front and back is -1 then the item is assigned to the first cell which is index 0 – otherwise, the value is inserted and the back position is incremented.</p>
<p>For <strong>deQueue</strong>:</p>
<pre><code class="lang-java"><span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">deQueue</span><span class="hljs-params">()</span></span>{
      <span class="hljs-keyword">if</span>(isEmpty()){
          System.out.println(<span class="hljs-string">"Queue is empty. Nothing to dequeue"</span>);
      } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (front == back){
          front = back = -<span class="hljs-number">1</span>;
      } <span class="hljs-keyword">else</span> {
          front++;
      }
  }
</code></pre>
<p>Here, if the array is empty, we get the corresponding message. If the front has met the back, we reset their index back to -1 like we saw in the images from the previous section. If the last two conditions are not applicable, then the front is incremented.</p>
<p>For <strong>display</strong>:</p>
<pre><code class="lang-java"><span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">display</span><span class="hljs-params">()</span></span>{
      <span class="hljs-keyword">int</span> i;

      <span class="hljs-keyword">if</span>(isEmpty()){
          System.out.println(<span class="hljs-string">"Queue is empty"</span>);
      } <span class="hljs-keyword">else</span> {
          <span class="hljs-keyword">for</span>(i = front; i &lt;= back; i++){
              System.out.println(items[i]);
          }
      }
  }
</code></pre>
<p>Here, if the array is not empty, we loop through and print all the items.</p>
<p>Lastly, for <strong>peek</strong>:</p>
<pre><code class="lang-java"><span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">peak</span><span class="hljs-params">()</span></span>{
      System.out.println(<span class="hljs-string">"Front value is: "</span> + items[front]);
  }
</code></pre>
<p>This simply prints the value of the front item.</p>
<p>These are all the operations for our queue. Here is all of them in one piece below:</p>
<pre><code class="lang-java"><span class="hljs-comment">// Queue implementation in Java</span>

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Queue</span> </span>{

  <span class="hljs-keyword">int</span> queueLength = <span class="hljs-number">3</span>;
  <span class="hljs-keyword">int</span> items[] = <span class="hljs-keyword">new</span> <span class="hljs-keyword">int</span>[queueLength];
  <span class="hljs-keyword">int</span> front = -<span class="hljs-number">1</span>; 
  <span class="hljs-keyword">int</span> back = -<span class="hljs-number">1</span>;

  <span class="hljs-function"><span class="hljs-keyword">boolean</span> <span class="hljs-title">isFull</span><span class="hljs-params">()</span></span>{
      <span class="hljs-keyword">if</span>(back == queueLength - <span class="hljs-number">1</span>){
          <span class="hljs-keyword">return</span> <span class="hljs-keyword">true</span>;
      } <span class="hljs-keyword">else</span> {
          <span class="hljs-keyword">return</span> <span class="hljs-keyword">false</span>;
      }
  }

  <span class="hljs-function"><span class="hljs-keyword">boolean</span> <span class="hljs-title">isEmpty</span><span class="hljs-params">()</span></span>{
      <span class="hljs-keyword">if</span>(front == -<span class="hljs-number">1</span> &amp;&amp; back == -<span class="hljs-number">1</span>){
          <span class="hljs-keyword">return</span> <span class="hljs-keyword">true</span>;
      } <span class="hljs-keyword">else</span> {
          <span class="hljs-keyword">return</span> <span class="hljs-keyword">false</span>;
      }
  }



  <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">enQueue</span><span class="hljs-params">(<span class="hljs-keyword">int</span> itemValue)</span> </span>{
      <span class="hljs-keyword">if</span>(isFull()){
          System.out.println(<span class="hljs-string">"Queue is full"</span>);
      } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span>(front == -<span class="hljs-number">1</span> &amp;&amp; back == -<span class="hljs-number">1</span>){
          front = back = <span class="hljs-number">0</span>;
          items[back] = itemValue;
      } <span class="hljs-keyword">else</span>{
          back++;
          items[back] = itemValue;
      }
  }

  <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">deQueue</span><span class="hljs-params">()</span></span>{
      <span class="hljs-keyword">if</span>(isEmpty()){
          System.out.println(<span class="hljs-string">"Queue is empty. Nothing to dequeue"</span>);
      } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (front == back){
          front = back = -<span class="hljs-number">1</span>;
      } <span class="hljs-keyword">else</span> {
          front++;
      }
  }

  <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">display</span><span class="hljs-params">()</span></span>{
      <span class="hljs-keyword">int</span> i;

      <span class="hljs-keyword">if</span>(isEmpty()){
          System.out.println(<span class="hljs-string">"Queue is empty"</span>);
      } <span class="hljs-keyword">else</span> {
          <span class="hljs-keyword">for</span>(i = front; i &lt;= back; i++){
              System.out.println(items[i]);
          }
      }
  }

  <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">peak</span><span class="hljs-params">()</span></span>{
      System.out.println(<span class="hljs-string">"Front value is: "</span> + items[front]);
  }

}
</code></pre>
<p>Now let us execute the operations:</p>
<pre><code class="lang-java"> <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
    Queue myQueue = <span class="hljs-keyword">new</span> Queue();

    myQueue.enQueue(<span class="hljs-number">3</span>);
    myQueue.enQueue(<span class="hljs-number">2</span>);
    myQueue.enQueue(<span class="hljs-number">1</span>);


    myQueue.display();

    myQueue.peak();


  }
</code></pre>
<p><code>enQueue(3)</code> inserts 3 to our queue, similar to the next two lines of code.</p>
<p><code>display()</code> prints out the items in the array.</p>
<p><code>peak()</code> prints the value of the front item.</p>
<p>We did not execute <code>deQueue</code> so you can go on and try it yourself – display your array and take a peek after you dequeue and see what happens. There are various ways to modify the code, so have fun!</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this article, we defined a queue and its structure. We went on to see some examples using images to show how the front and back positions of a queue react when items are enqueued and dequeued.</p>
<p>Lastly, we saw how to implement the queue data structure using arrays in Java.</p>
<p>Thank you for reading and happy coding!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ An introduction to RabbitMQ, a broker that deals in messages ]]>
                </title>
                <description>
                    <![CDATA[ By Chandrabhan Singh An introduction to RabbitMQ, message broker, AMQP model and more. In distributed systems, communication between various applications plays an important role. Effectively passing messages between applications was always a crucial ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/rabbitmq-9e8f78194993/</link>
                <guid isPermaLink="false">66d45dd936c45a88f96b7cc3</guid>
                
                    <category>
                        <![CDATA[ message broker ]]>
                    </category>
                
                    <category>
                        <![CDATA[ General Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ queue ]]>
                    </category>
                
                    <category>
                        <![CDATA[ rabbitmq ]]>
                    </category>
                
                    <category>
                        <![CDATA[ technology ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Fri, 05 Apr 2019 20:42:10 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*HCpBJmTd_sELllvhVOaevg.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Chandrabhan Singh</p>
<h4 id="heading-an-introduction-to-rabbitmq-message-broker-amqp-model-and-more">An introduction to RabbitMQ, message broker, AMQP model and more.</h4>
<p>In distributed systems, communication between various applications plays an important role. Effectively passing messages between applications was always a crucial decision in system design. One of the elegant solutions to pass messages around your distributed system is a message broker.</p>
<p>In distributed systems, communication between various applications plays an important role. Effectively passing messages between applications was always a crucial decision in system design. One of the elegant solutions to pass messages around your distributed system is a message broker.</p>
<p>They bring in decoupling between the applications and provide an effective way to communicate. With message brokers, an application needs no prior knowledge of their recipients to communicate.</p>
<p>However, what is RabbtiMQ? How does RabbitMQ fit in this picture? Also, what is AMQP?</p>
<p>By the end of this article, we will be able to answer these questions. I also added a few animations so that you can visualize RabbitMQ concepts.</p>
<p>So are you excited? I am! If you ever had difficulties understanding message brokers, as I did, then this article is the right place to start your journey. Stay with me ?</p>
<h1 id="heading-message-broker">Message Broker</h1>
<p>In general, a broker is a person who facilitates trades between a buyer and a seller. An example could be a real estate agent or a stockbroker.</p>
<p>Similarly, if we want to trade messages between two distributed software components, we need a mediator. This mediator is known as the message broker. It receives incoming messages from a sender and sends them to a recipient. This way the sender and receiver can be totally isolated.</p>
<p>Another analogy for a message broker can be a Post Office (see Figure 1). Let’s take a scenario where you are going to send a letter to your cousin living in another city. Then as per this analogy, you are a producer, your cousin is a consumer, and the post office is a message broker.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*nUaJxRXwLbgZyM4KWwDfig.png?q=20" alt="Image" width="48" height="24" loading="lazy">
<em>Figure 1: Analogy for message broker</em></p>
<h1 id="heading-rabbitmq-as-message-broker">RabbitMQ as message broker</h1>
<p>Now we know that the purpose of a message broker is to route messages from a producer to a consumer. Let’s examine one such message broker — RabbitMQ. It’s one of the most extensively used message brokers these days.</p>
<p>The way RabbitMQ routes messages depends upon the messaging protocol it implements. RabbitMQ supports multiple messaging protocols. However, the one we are interested in is AMQP. It is an acronym for Advanced Message Queuing Protocol.</p>
<p>So without any further ado let’s have a closer look at the AMQP protocol model.</p>
<h1 id="heading-advanced-message-queuing-protocol">Advanced Message Queuing Protocol</h1>
<p>The conceptual model of AMQP is quite simple and straightforward. It has three entities:</p>
<ol>
<li>Queue</li>
<li>Binding</li>
<li>Exchange</li>
</ol>
<p>When a publisher pushes a message to RabbitMQ, it first arrives at an exchange. The exchange then distributes copies of these messages to variously connected queues. Finally, consumers receive these messages.</p>
<p>Consider a message as a piece of data. It is necessarily a package with a payload and some meta-data. The payload contains full data whereas meta-data are properties used by RabbitMQ.</p>
<p>Figure 2 depicts a graphical representation of the AMQP model.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*F1NaCmmz72StUZZHfRfpvw.png?q=20" alt="Image" width="48" height="25" loading="lazy">
<em>Figure 2: AMQP model</em></p>
<p>AMQP is a programmable protocol. Programmers have the liberty to use libraries to configure entities (exchange, binding, and queue) as per their own needs. A RabbitMQ admin has no role in setting up these entities.</p>
<p>There are plenty of libraries available to work with RabbitMQ. You can choose from <a target="_blank" href="http://www.squaremobius.net/amqp.node/">Nodejs</a>, <a target="_blank" href="https://pypi.org/project/pika/">Python</a>, .<a target="_blank" href="https://github.com/rabbitmq/rabbitmq-dotnet-client">Net</a>, <a target="_blank" href="https://github.com/rabbitmq/rabbitmq-java-client/">Java</a>, and many more.</p>
<h1 id="heading-queues">Queues</h1>
<p>These queues are somehow similar to the queues from our data structure classes. RabbitMQ queues also follow FIFO — First-In-First-Out methodology. A queue is a place where RabbitMQ stores messages/data.</p>
<p>Programmers can configure queues through available programming libraries. You can make a queue durable ( with the <code>Durability</code> property) to safeguard your data in case the broker crashes. You can also provide a name(with the <code>Name</code> property) to a queue. Other than <code>Name</code> and <code>Durability</code>, a queue has a few other properties like auto-delete, exclusive, and arguments.</p>
<p>Before moving any further, it’s important to understand who is a direct consumer of these queues. Moreover, how many ways can a user consume messages from a queue?</p>
<h1 id="heading-consumers">Consumers</h1>
<p>Consumers are the ones who are going to use messages stored in a queue. It is possible to connect more than one consumer to a queue at a time. Consumers can either pull the message from the queue by pooling it or queues can even push the message to various connect consumers.</p>
<h1 id="heading-bindings">Bindings</h1>
<p>Bindings are the rules that a queue defines while establishing a connection with an exchange. You can have a queue connected to multiple exchanges. Every queue is also connected to a default exchange. An exchange will use these bindings to route messages to queues.</p>
<h1 id="heading-exchanges-and-their-types">Exchanges and their types</h1>
<p>An Exchange is a gateway to RabbitMQ for your messages. The distance the message has to travel inside RabbitMQ depends on the type of exchange. Primarily there are four types.</p>
<ul>
<li>Direct</li>
<li>Fanout</li>
<li>Topic</li>
<li>Header</li>
</ul>
<h2 id="heading-direct">Direct</h2>
<p>The name explains it all! — A direct exchange delivers a message directly to the queues that satisfy the below condition:</p>
<pre><code>Routing key == Binding key
</code></pre><p>A routing key is an attribute of the message. On the other hand, a binding key is something you specify while creating a binding between a queue and an exchange.</p>
<p>Figure 3 is a visual explanation of how messages flow while using a direct exchange.</p>
<p>A message originates from a producer (green circle) with a routing key — <code>img.resize</code>. Once it reaches the exchange (Orange circle), the exchange will try to find all queues with binding key — <code>img.resize</code>. In case of a match, the message is pushed to all matched queues (resize in our case). If there is no match found, the message can be sent back to the producer or can even be discarded. We are lucky that we found a match in our example ?</p>
<p>[gif image]</p>
<p>Once the message reaches the desired queue (resize in our case), they are distributed in round-robin fashion to all the connected consumers (resizer.1/resizer.2 in our case).</p>
<p>By distributing messages in a round-robin fashion, RabbitMQ makes sure that the messages are load balanced.</p>
<p>You must have noticed that the queue named <strong>crop</strong> is not receiving any messages. Because the routing key in this example is <code>img.resize</code>. To send messages to this queue, we need to send messages with a routing key that would match the binding key (say <code>img.crop</code> for instance).</p>
<h2 id="heading-fanout">Fanout</h2>
<p>A Fanout exchange ignores routing keys and distributes a message to all the connected queues. No wonder it is called Fanout (blowing messages to all connected queues! ?).</p>
<p>One of the use cases for this type of exchange is message broadcast.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/07/1_f4bddksBjxqZjYq3VDa3wg.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Please note that RabbitMQ will still do round robin if there is more than one consumer of the queue.</p>
<h2 id="heading-topic">Topic</h2>
<p>A topic exchange routes a message by matching routing key with a pattern in the binding key.</p>
<pre><code>Routing key == Pattern <span class="hljs-keyword">in</span> binding key.
</code></pre><p>RabbitMQ uses two wild card characters for pattern matching <code>*</code> and <code>#</code>. Use a <code>*</code> to match 1 word and a <code>#</code> to match 0 or more words.</p>
<p>Figure 5 is a visual depiction of a topic exchange. Messages with routing key — <code>logs.error</code> will match patterns — <code>logs.error</code> and <code>logs.*</code>. Hence these messages will end up in the queues — <code>only error</code> and <code>all logs</code>.</p>
<p>Whereas for the producer at the bottom-left, messages with routing key— <code>logs.success</code> will match patterns of binding key <code>#success</code> and <code>logs.*</code> . Hence these messages will end up in the queues — <code>all logs</code>and <code>only success</code> .</p>
<p>[gif]</p>
<p>This type of exchange has a vast range of use cases. It can be used in the publish-subscribe pattern, distributing relevant data to desiring workers processes and many more.</p>
<h1 id="heading-header">Header</h1>
<p>A header is a particular type of exchange that routes messages based on keys present in the message header. It overlooks routing key attribute of the message.</p>
<p>When creating bindings for a header exchange, it is possible to bind a queue to match more than one header. In such a case, RabbitMQ should know from the producer if it should match all or any of these keys.</p>
<p>A producer/application can do this by providing an extra flag called ‘x-match’. ‘x-match’ can have <code>any</code> or <code>all</code> values. The first one mandates that only one value should match while the latter mandates that all must match.</p>
<h1 id="heading-message-acknowledgement">Message Acknowledgement</h1>
<p>Once a message reaches its destination, the broker should delete the message from the queue. It is necessary because a queue overflow can occur if it keeps accumulating messages.</p>
<p>Before deleting any message, the broker must have a delivery acknowledgment. There are two possible ways to acknowledge message delivery.</p>
<ol>
<li>Automatic acknowledgment: Once a consumer receives the message</li>
<li>Explicit acknowledgment: When a consumer sends back an acknowledgment</li>
</ol>
<p>In most cases, explicit acknowledgment is used as it makes sure that the consumer has consumed the message without any failover.</p>
<h1 id="heading-whats-next">What’s next</h1>
<p>RabbitMQ is a very mature and useful product. This article is only a high-level introduction to RabbitMQ. I simplified the concepts to provide a reference point for you to move further. Visit the <a target="_blank" href="https://www.rabbitmq.com/">RabbitMQ</a> website for more complex topics.</p>
<p>Hope you like the article. Don’t forget to clap(or applaud ?). Follow to read my upcoming stories. Until next time, keep Queuing.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ A Gentle Introduction to Data Structures: How Queues Work ]]>
                </title>
                <description>
                    <![CDATA[ By Michael Olorunnisola Black Friday’s right around the corner, and the new Microsoft Surface Studio out in stores (I’m a loyal windows guy ?). So let’s talk about everyone’s favorite shopping past-time: waiting in line. And that age-old data structu... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/a-gentle-introduction-to-data-structures-how-queues-work-f8b871938e64/</link>
                <guid isPermaLink="false">66c3429d42d4db64acf4cbaa</guid>
                
                    <category>
                        <![CDATA[ data structures ]]>
                    </category>
                
                    <category>
                        <![CDATA[ General Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ queue ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Software Engineering ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Stacks ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Sun, 06 Nov 2016 04:38:49 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*vQPzNuz_TAOwQAkBfuaC6A.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Michael Olorunnisola</p>
<p>Black Friday’s right around the corner, and the new Microsoft Surface Studio out in stores (I’m a loyal windows guy ?). So let’s talk about everyone’s favorite shopping past-time: waiting in line. And that age-old data structure, the queue.</p>
<p>Feel free to share this post with your friends who’ll be heading out to get the latest and greatest. But be warned — people have been known to forget how queues work on Black Friday.</p>
<h3 id="heading-queues">Queues</h3>
<p>A queue is a line (yep, the same one from kindergarten…no cutting still!)</p>
<p>Additions (<strong>enqueues</strong>) always add to the back of the line</p>
<p>Removals (<strong>dequeues</strong>) always remove from the front of the line</p>
<p>Queues follow the pattern of <strong>F</strong>irst item <strong>I</strong>n is the <strong>F</strong>irst item <strong>O</strong>ut (FIFO).</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/GMjTKmWR6yBI5GEXVEnsZ81dlQHLK5L2dKei" alt="Image" width="300" height="196" loading="lazy"></p>
<h4 id="heading-example-use-cases"><strong>Example use cases</strong></h4>
<ul>
<li>Resolving simultaneous server requests from multiple users, such as 3 people buying the last ticket for a plane at almost the same time</li>
<li>Queuing up data during a <a target="_blank" href="https://en.wikipedia.org/wiki/Breadth-first_search">breadth-first search</a>.</li>
</ul>
<p>Let’s tackle the first use case by helping Microsoft create a queue data structure to manage all their requests for the new Surface Studio. I’m too busy coding and writing these posts to go get one myself, so if you’re a Microsoft representative reading this, please feel free to ship one my way. ?</p>
<p>Before we get started, a quick note on JavaScript arrays. Similar to <a target="_blank" href="https://medium.freecodecamp.com/data-structures-stacks-on-stacks-c25f2633c529#.cj82kpcg8">stacks</a>, JavaScript arrays naturally have the functionality of a queue built in.</p>
<h3 id="heading-how-to-represent-queues-using-javascript-arrays">How to represent queues using JavaScript arrays</h3>
<p><strong>Enqueue</strong> adds to the back of the array:</p>
<pre><code><span class="hljs-built_in">Array</span>.push(someVal)
</code></pre><p><strong>Dequeue</strong> removes and returns first item in array:</p>
<pre><code><span class="hljs-built_in">Array</span>.shift()
</code></pre><p>If for some reason you’re feeling rebellious (what coder doesn’t ?) you could add to the front of the array, then remove from the back.</p>
<p><strong>Enqueue</strong> adds item to the front of the array:</p>
<pre><code><span class="hljs-built_in">Array</span>.unshift(someVal)
</code></pre><p><strong>Dequeue</strong> removes item from the back of the array:</p>
<pre><code><span class="hljs-built_in">Array</span>.pop()
</code></pre><p>That said, for the sake of being thorough, you’re going to rebuild it using a JavaScript Object.</p>
<p>So first thing you need to do for Microsoft is to create the actual Queue where you’re going to hold the individual members who click the buy button on their website.</p>
<pre><code><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Queue</span></span>{  <span class="hljs-keyword">constructor</span>(){    <span class="hljs-built_in">this</span>._storage = {};    <span class="hljs-built_in">this</span>._start = <span class="hljs-number">-1</span>; <span class="hljs-comment">//replicating 0 index used for arrays    this._end = -1; //replicating 0 index used for arrays  }    size(){   return this._end - this._start;  }}</span>
</code></pre><pre><code><span class="hljs-keyword">let</span> appleQueue = <span class="hljs-keyword">new</span> Queue();
</code></pre><p>As a quick reminder the _ just means this is a private variable, and shouldn’t be accessed directly.</p>
<p>Unlike the <a target="_blank" href="https://medium.freecodecamp.com/data-structures-stacks-on-stacks-c25f2633c529#.cj82kpcg8">stack data structure</a>, where additions and removals happen on the same side, the nature of the queue requires us to keep track of both ends. Because of that, you create the start variable to always track the front of the queue, and the end variable to track the end of the queue.</p>
<p>Lastly, the easiest way to keep track of a queue’s size (without creating an unnecessary counter variable) is to keep track of the difference between your start and end points.</p>
<p>First, you should create a way for people who click buy to be added to the queue. You can do this via the enqueue method:</p>
<pre><code><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Queue</span></span>{  <span class="hljs-keyword">constructor</span>(){    <span class="hljs-built_in">this</span>._storage = {};    <span class="hljs-built_in">this</span>._start = <span class="hljs-number">-1</span>; <span class="hljs-comment">//replicating 0 index used for arrays    this._end = -1; //replicating 0 index used for arrays  }    enqueue(val){    this._storage[++this._end] = val;          //++this._end just means increment the end variable first    //It's equivalent to    //this._end++   //-&gt;    //this._storage[this._end] = val;  }    size(){   return this._end - this._start;  }}</span>
</code></pre><pre><code><span class="hljs-keyword">let</span> microsoftQueue = <span class="hljs-keyword">new</span> Queue();
</code></pre><pre><code>microsoftQueue.enqueue(<span class="hljs-string">"{user: ILoveWindows@gmail.com}"</span>)microsoftQueue.enqueue(<span class="hljs-string">"{user: cortanaIsMyBestFriend@hotmail.com}"</span>)microsoftQueue.enqueue(<span class="hljs-string">"{user: InternetExplorer8Fan@outlook.com}"</span>)microsoftQueue.enqueue(<span class="hljs-string">"{user: IThrowApplesOutMyWindow@yahoo.com}"</span>)
</code></pre><p>Great! Now your microsoftQueue storage is going to look a little something like this:</p>
<pre><code>{
</code></pre><pre><code>  <span class="hljs-number">0</span>: <span class="hljs-string">"{email: ILoveWindows@gmail.com}"</span>
</code></pre><pre><code>  <span class="hljs-number">1</span>: <span class="hljs-string">"{email: cortanaIsMyBestFriend@hotmail.com}"</span>
</code></pre><pre><code>  <span class="hljs-number">2</span>: <span class="hljs-string">"{email: InternetExplorer8Fan@outlook.com}"</span>
</code></pre><pre><code>  <span class="hljs-number">3</span>: <span class="hljs-string">"{email: IThrowApplesOutMyWindow@yahoo.com}"</span>
</code></pre><pre><code>}
</code></pre><p>So a quick note on the way users are being represented above ({user: …}).</p>
<p>When a user clicks the buy button on the client side, they’re sending all their relevant information to the server, which will handle the request. When data is often exchanged between systems, such as the client and server side, it’s most commonly sent as <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON">JSON</a> (<strong>J</strong>ava<strong>S</strong>cript <strong>O</strong>bject <strong>N</strong>otation), via <a target="_blank" href="http://www.w3schools.com/xml/ajax_intro.asp">Ajax</a>.</p>
<p>This is similar to JavaScript objects, in that it’s just a stringified version of key-value pairs. For those not familiar with JavaScript, it’s similar to a dictionary or hash table (which we’ll get to later in this series). For more information about this , there’s a great post <a target="_blank" href="http://stackoverflow.com/questions/383692/what-is-json-and-why-would-i-use-it">here</a> on StackOverflow by Andreas Grech.</p>
<p>Now back to your queue.</p>
<p>Thanks to the queue you created, Microsoft now has an efficient way of tracking all of the people who have purchased the Surface Studio, and in chronological order in which they purchased it. To make sure these people are served in the correct order, you need to create an accurate dequeue method that keeps track of the order of the buyers, and removes them from the queue once they’ve been served.</p>
<pre><code><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Queue</span></span>{  <span class="hljs-keyword">constructor</span>(){    <span class="hljs-built_in">this</span>._storage = {};    <span class="hljs-built_in">this</span>._start = <span class="hljs-number">-1</span>; <span class="hljs-comment">//replicating 0 index used for arrays    this._end = -1; //replicating 0 index used for arrays  }    enqueue(val){    this._storage[++this._end] = val;   }</span>
</code></pre><pre><code>  dequeue(){    <span class="hljs-keyword">if</span>(<span class="hljs-built_in">this</span>._end &gt; <span class="hljs-built_in">this</span>._start){ <span class="hljs-comment">//check if there are values      let nextUp = this._storage[++this._start];      delete this._storage[this._start];      return nextUp;    }  }      size(){   return this._end - this._start;  }}</span>
</code></pre><pre><code><span class="hljs-keyword">let</span> microsoftQueue = <span class="hljs-keyword">new</span> Queue();
</code></pre><pre><code>microsoftQueue.enqueue(<span class="hljs-string">"{user: ILoveWindows@gmail.com}"</span>)microsoftQueue.enqueue(<span class="hljs-string">"{user: cortanaIsMyBestFriend@hotmail.com}"</span>)microsoftQueue.enqueue(<span class="hljs-string">"{user: InternetExplorer8Fan@outlook.com}"</span>)microsoftQueue.enqueue(<span class="hljs-string">"{user: IThrowApplesOutMyWindow@yahoo.com}"</span>)
</code></pre><pre><code><span class="hljs-comment">//Function to send everyone their Surface Studio!let sendSurface = recepient =&gt; {   sendTo(recepient);}</span>
</code></pre><pre><code><span class="hljs-comment">//When your server is ready to handle this queue, execute this:</span>
</code></pre><pre><code><span class="hljs-keyword">while</span>(microsoftQueue.size() &gt; <span class="hljs-number">0</span>){  sendSurface(microsoftQueue.dequeue());}
</code></pre><p>And there it is folks! Everyone who was waiting in the microsoftQueue now gets their awesome new Surface Studio thanks to you.</p>
<p>To be thorough, there are definitely some quick optimizations that can make code work more logically.</p>
<ol>
<li>You can reset your start and end values to 0 once everyone in the queue has been served. It’s unlikely that your queue would ever hit the <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER">“max” JavaScript number</a>, but it’s better to be safe than sorry.</li>
<li>You can switch out the “ end &gt; start check ” with the size method, thanks to 0 being evaluated as “false” due to JavaScript type coercion. Read all about <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Glossary/Falsy">it h</a>ere.</li>
</ol>
<pre><code>dequeue(){    <span class="hljs-keyword">if</span>(<span class="hljs-built_in">this</span>.size()){ <span class="hljs-comment">//0 is a falsey value...coerced to return false      let nextUp = this._storage[++this._start];      delete this._storage[this._start];</span>
</code></pre><pre><code>      <span class="hljs-keyword">if</span>(!<span class="hljs-built_in">this</span>.size()){ <span class="hljs-comment">//Recheck after incrementing (!0 == true)        this._start = -1;        this._end = -1;       }            return nextUp;    }}</span>
</code></pre><p>And there you go, you’ve finished writing your basic Queue!</p>
<h3 id="heading-a-time-complexity-analysishttpbigocheatsheetcom-on-the-queue-methods">A <a target="_blank" href="http://bigocheatsheet.com/">time complexity analysis</a> on the queue methods</h3>
<p>Here’s the code again:</p>
<pre><code><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Queue</span></span>{  <span class="hljs-keyword">constructor</span>(){    <span class="hljs-built_in">this</span>._storage = {};    <span class="hljs-built_in">this</span>._start = <span class="hljs-number">-1</span>; <span class="hljs-comment">//replicating 0 index used for arrays    this._end = -1; //replicating 0 index used for arrays  }    enqueue(val){    this._storage[++this._end] = val;   }</span>
</code></pre><pre><code>  dequeue(){    <span class="hljs-keyword">if</span>(<span class="hljs-built_in">this</span>.size()){ /      <span class="hljs-keyword">let</span> nextUp = <span class="hljs-built_in">this</span>._storage[++<span class="hljs-built_in">this</span>._start];      <span class="hljs-keyword">delete</span> <span class="hljs-built_in">this</span>._storage[<span class="hljs-built_in">this</span>._start];
</code></pre><pre><code>      <span class="hljs-keyword">if</span>(!<span class="hljs-built_in">this</span>.size()){         <span class="hljs-built_in">this</span>._start = <span class="hljs-number">-1</span>;        <span class="hljs-built_in">this</span>._end = <span class="hljs-number">-1</span>;       }            <span class="hljs-keyword">return</span> nextUp;    }  }    size(){   <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>._end - <span class="hljs-built_in">this</span>._start;  }}
</code></pre><p>The same logic for stacks also applies here:</p>
<p><strong>Enqueue</strong> (addition) is <strong>O(1)</strong>. Since you’ll always know where the end of the queue is (thanks to your end variable), you don’t have to iterate to add an item.</p>
<p><strong>Dequeue</strong> (removal) is <strong>O(1)</strong>. No iteration is necessary for removal since you always have the current start position.</p>
<p><strong>Size</strong> is <strong>O(1)</strong>. The size is always known thanks to your start and end variables.</p>
<p>One really important thing to note here is that queues aren’t meant to be infinite, although our queue class and JavaScript array will allow you to keep on adding items until the system runs out of memory.</p>
<p>One way to optimize is by making a space-limited array to create a circular queue. Damian Gordon provides a really good <a target="_blank" href="https://www.youtube.com/watch?v=ia__kyuwGag">video walk-through</a> on YouTube. This will also be handy for when we get to hash tables in future articles!</p>
<h3 id="heading-time-for-a-quick-recap">Time for a quick recap</h3>
<p>Queues:</p>
<ol>
<li>Follow a First In First Out (FIFO) pattern</li>
<li>Have a start and end property to track the front and back of your queue</li>
<li>Have an enqueue (add) and dequeue (remove) method to manage the contents of your queue</li>
<li>Have a size property that allows you to track how large your queue is</li>
</ol>
<h3 id="heading-heres-a-quick-challenge"><strong>Here’s a quick challenge</strong></h3>
<p>Using what you now know about Stacks and what you learned today about Queues, try re-implementing a Queue using just stacks.</p>
<p>As a quick hint, you’ll only need two stacks.</p>
<p>Thanks to Jason Holtkamp for coming up with this quick challenge!</p>
<h3 id="heading-further-reading"><strong>Further reading</strong></h3>
<p><a target="_blank" href="https://en.wikipedia.org/wiki/Queue_(abstract_data_type)">Wikipedia</a> as always ?</p>
<p><a target="_blank" href="https://en.wikipedia.org/wiki/Priority_queue">This Wikipedia article</a> on priority queue. We’ll come back to this in future articles.</p>
<p>A nice <a target="_blank" href="https://www.khanacademy.org/computer-programming/queue-structure/6427851233820672">demo</a> by Larry Serflaten on Khan Academy, where he uses push and pull in place of enqueue and dequeue.</p>
<p>And here’s the <a target="_blank" href="http://stackoverflow.com/questions/69192/how-to-implement-a-queue-using-two-stacks">Answer</a> for the quick challenge. Only look at this after trying it out for a bit yourself. You can also check out <a target="_blank" href="http://stackoverflow.com/users/3128926/levent-divilioglu">Levent Divilioglu</a>’s answer for a fantastic graphical representation.</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
