<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Chanh Le</title>
    <description>The latest articles on DEV Community by Chanh Le (@chanh_le).</description>
    <link>https://dev.to/chanh_le</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1317948%2F3c242a51-855f-4600-a1bc-7ca456c24470.jpeg</url>
      <title>DEV Community: Chanh Le</title>
      <link>https://dev.to/chanh_le</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/chanh_le"/>
    <language>en</language>
    <item>
      <title>Is Unit Test really a MUST?</title>
      <dc:creator>Chanh Le</dc:creator>
      <pubDate>Tue, 17 Dec 2024 18:29:32 +0000</pubDate>
      <link>https://dev.to/chanh_le/is-unit-test-really-a-must-c6n</link>
      <guid>https://dev.to/chanh_le/is-unit-test-really-a-must-c6n</guid>
      <description>&lt;p&gt;I have read the Refactoring book from Martin Fowler, and I am quite confused with the idea of using unit tests for refactoring.&lt;/p&gt;

&lt;p&gt;I feel like what we actually need is integration test instead. Because when we do refactoring we will inevitably change the “unit” and then the unit test become outdated and useless and we have to remove them eventually. In the other hand, the integration test is still valid and doing its job, catching bugs and side-effects.&lt;/p&gt;

&lt;p&gt;Now, I don’t know whether we still need unit tests for any reason! Yes, running integration tests takes time but we will not run them too frequently and also they will less likely outdated over time or be deleted during refactoring.&lt;/p&gt;

&lt;p&gt;Does it make sense? Am I getting anything wrong somewhere? &lt;/p&gt;

</description>
      <category>oop</category>
      <category>unittest</category>
      <category>programming</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Is Clean Code really practical?</title>
      <dc:creator>Chanh Le</dc:creator>
      <pubDate>Tue, 17 Dec 2024 18:07:00 +0000</pubDate>
      <link>https://dev.to/chanh_le/is-clean-code-really-practical-10ha</link>
      <guid>https://dev.to/chanh_le/is-clean-code-really-practical-10ha</guid>
      <description>&lt;p&gt;Small functions are easy to understand? What if we have too many of them? &lt;/p&gt;

&lt;p&gt;Meaningful function names? Is it that easy? &lt;/p&gt;

&lt;p&gt;Avoid switch statements, boolean arguments? How ? &lt;/p&gt;

&lt;p&gt;When I first read the Clean Code book, I admit it was mind-blowded to me. I was so excited to practice and try to apply the rules to my side projects. But over time, I start to realize that it isn’t easy to achieve. &lt;/p&gt;

&lt;p&gt;Does anyone feel the same? Can anyone tell a success story about applying Clean Code?&lt;br&gt;
By the way, the Clean Architecture is also too hard for me. I am quite frustrated!&lt;/p&gt;

</description>
      <category>oop</category>
      <category>cleancode</category>
      <category>programming</category>
      <category>solidprinciples</category>
    </item>
    <item>
      <title>System Architecture Overview for Message-Oriented Alarm Processing System</title>
      <dc:creator>Chanh Le</dc:creator>
      <pubDate>Tue, 10 Sep 2024 15:49:24 +0000</pubDate>
      <link>https://dev.to/chanh_le/system-architecture-overview-for-message-oriented-alarm-processing-system-5enj</link>
      <guid>https://dev.to/chanh_le/system-architecture-overview-for-message-oriented-alarm-processing-system-5enj</guid>
      <description>&lt;p&gt;In previous posts, we’ve explored the fundamentals of Message-Oriented Architecture (MOA) and how Redis is utilized as the backbone for our alarm message queue. Now, let’s take a step back and examine the overall architecture. This post provides an overview of the system, highlighting the different components and the reasoning behind key design choices.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Understanding the Big Picture&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Our system is designed to handle the reliable delivery of alarm messages from alarm devices to alarm receiving centers (ARCs). The architecture follows a message-oriented pattern, ensuring the system can scale to handle high volumes of messages efficiently while maintaining reliability and low latency.&lt;/p&gt;

&lt;p&gt;Here’s a breakdown of the key components:&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;1. Alarm Devices&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;These are physical devices that detect and report alarms such as fires or security breaches. Each alarm device is responsible for sending messages with key information to the system:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Message ID&lt;/strong&gt;: A unique identifier for each alarm event.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Signal Code&lt;/strong&gt;: A predefined code that specifies the type of alarm being triggered.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sender ID&lt;/strong&gt;: The ID of the device that triggered the alarm.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Criteria Index&lt;/strong&gt;: Parameters specific to the source device that triggered the alarm.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These messages are then pushed to the message queue for further processing.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;2. Redis Message Queue&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;At the core of the architecture, Redis is used as a &lt;strong&gt;Message Queue&lt;/strong&gt;, but with a specific approach:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Redis Key&lt;/strong&gt;: Instead of placing the full message in the queue, we only push the Redis key (which points to the message hash) into the queue. The Redis key is prefixed by &lt;code&gt;message:&lt;/code&gt; followed by the unique message ID.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Message Hash in Redis&lt;/strong&gt;: Full details about each message—such as its &lt;strong&gt;message ID, signal code, criteria index, device ID, destination group, current state, phase, destination information, and TTL&lt;/strong&gt;—are stored in Redis as a hash. The message hash is assigned an expiration time equal to the TTL of the message to prevent indefinite growth.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;3. Processing Layer&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;This is where alarm messages are taken from the queue and processed by various services in a controlled and scalable manner.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Message Consumers&lt;/strong&gt;: Consumers retrieve Redis keys from the message queue, fetch the corresponding message hash from Redis, and process the alarm accordingly. The system updates the message state (e.g., "received", "processing", "dispatched") during each stage.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;State and Queue Management&lt;/strong&gt;: The system tracks the message’s current queue and state to handle different stages of the processing workflow.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Timeouts and Retries&lt;/strong&gt;: If a message isn't processed within its TTL, the system either retries or escalates the issue to ensure critical messages are addressed.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;4. Alarm Receiving Centers (ARCs)&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Once an alarm message has been processed and routed, it is delivered to an ARC, responsible for handling the final response to the alarm (e.g., dispatching emergency services). The ARCs are decoupled from the processing system, allowing it to scale and process alarms even if some ARCs are temporarily unavailable.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;5. Monitoring and Logging&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Real-time monitoring is vital to this system. The system tracks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Queue Length&lt;/strong&gt;: Ensuring the message queue doesn’t grow uncontrollably.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Processing Time&lt;/strong&gt;: Monitoring how long each message takes to be processed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Health Checks&lt;/strong&gt;: Ensuring the health of each component and alerting the system to potential failures.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Key Design Choices&lt;/strong&gt;
&lt;/h3&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Message-Oriented Architecture&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;The system’s message-oriented architecture allows for decoupling between the various components, improving scalability and resilience. Each layer operates independently, allowing flexibility in how messages are processed and how the system scales to handle high message throughput.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Redis as Message Queue and State Store&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Redis provides the necessary performance and flexibility. By using Redis for both the message queue and as a hash-based state store, the system ensures efficient, real-time processing of alarm messages. Only the Redis key is pushed into the queue, and the full message is stored in Redis as a hash with additional fields like the message ID, signal code, criteria index, and destination group.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Expiration-Based Message Cleanup&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;To prevent indefinite message growth in Redis, message hashes have an expiration time set equal to the TTL of the alarm message. This keeps the system efficient and lightweight by removing old messages when they are no longer needed.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Future Enhancements&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;As the system scales, several improvements could be implemented:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Redis Streams&lt;/strong&gt;: Transitioning from Redis Lists to Redis Streams could provide better support for advanced features such as consumer groups and message acknowledgment.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Event-Driven Architecture&lt;/strong&gt;: Implementing an event-driven system could further enhance the responsiveness of the system by integrating external services like analytics.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Redis Clustering&lt;/strong&gt;: As the message volume increases, Redis clustering can be introduced to ensure consistent performance under high load.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;This architectural overview highlights how the system efficiently processes alarm messages in real-time, leveraging Redis to maintain a high level of performance and scalability. By pushing only the Redis key into the message queue and storing the full message in a hash with an expiration, we maintain efficiency and avoid unbounded growth.&lt;/p&gt;

&lt;p&gt;In the next post, we will explore the lifecycle of an alarm message and how it transitions through the different states in our system.&lt;/p&gt;

</description>
      <category>distributedsystems</category>
      <category>redis</category>
      <category>eventdriven</category>
      <category>moa</category>
    </item>
    <item>
      <title>Setting Up Redis as a Message Queue: A Step-by-Step Guide</title>
      <dc:creator>Chanh Le</dc:creator>
      <pubDate>Tue, 10 Sep 2024 15:29:13 +0000</pubDate>
      <link>https://dev.to/chanh_le/setting-up-redis-as-a-message-queue-a-step-by-step-guide-5gj0</link>
      <guid>https://dev.to/chanh_le/setting-up-redis-as-a-message-queue-a-step-by-step-guide-5gj0</guid>
      <description>&lt;p&gt;In our previous discussion, we introduced the concept of Message-Oriented Architecture (MOA) and its importance in building scalable, resilient systems. Today, we’ll delve deeper into one of the key components of our system: Redis as a Message Queue. Specifically, we’ll explore how Redis can be configured to handle alarm messages by queuing essential metadata and storing full message details separately as hashes.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Why Use Redis as a Message Queue?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Redis is a powerful choice for a message queue, particularly in systems where speed and simplicity are paramount. Here’s why Redis excels in this role:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;High Performance&lt;/strong&gt;: Redis operates entirely in-memory, making it capable of handling high volumes of messages with low latency.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Efficient Data Handling&lt;/strong&gt;: By storing essential metadata (like message IDs) in the queue and full details in separate hashes, Redis minimizes memory usage while maintaining the speed and efficiency of message delivery.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalability&lt;/strong&gt;: Redis supports clustering and sharding, allowing the system to scale as message volumes grow.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flexibility&lt;/strong&gt;: Redis can be tailored to fit various queuing models, including FIFO (First-In, First-Out) and more complex workflows.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Understanding the Message Structure&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;In our project, the Redis message queue is designed to hold minimal information about each alarm message, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Message ID&lt;/strong&gt;: A unique identifier for the message.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sender ID&lt;/strong&gt;: The ID of the device that generated the alarm.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Signal Code&lt;/strong&gt;: A code representing the type of alarm being handled. This code comes from a predefined list that indicates whether it’s a fire alarm, security breach, or other critical event.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Criteria Index&lt;/strong&gt;: A reference to criteria on the source device.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The full details of each message, including its state, phase, destination, and TTL (Time-to-Live), are stored in Redis as a hash, with the key being the message ID prefixed by &lt;code&gt;message:&lt;/code&gt;. To prevent the full message hash from growing indefinitely, an expiration time is set for the hash equal to the TTL of the message.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Setting Up Redis as a Message Queue&lt;/strong&gt;
&lt;/h3&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Step 1: Installing Redis&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;If Redis isn’t already installed on your system, you can easily set it up:&lt;/p&gt;

&lt;p&gt;For Ubuntu:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get update
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install &lt;/span&gt;redis-server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For macOS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew &lt;span class="nb"&gt;install &lt;/span&gt;redis
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After installation, start the Redis server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;redis-server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can interact with Redis using the Redis CLI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;redis-cli
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;strong&gt;Step 2: Configuring Redis for Queuing and Storing Messages&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;In this setup, Redis lists are utilized to create a FIFO queue. The list stores minimal metadata about each message, and the full message details are stored in a Redis hash.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Push Message Metadata to the Queue&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use the &lt;code&gt;LPUSH&lt;/code&gt; command to add metadata to the queue:
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; LPUSH alarm_queue &lt;span class="s1"&gt;'{"id":"msg123", "sender_id":"deviceA", "signal_code":"12345", "criteria_index":1}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Store Full Message Information in a Hash and Set Expiration&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use the &lt;code&gt;HMSET&lt;/code&gt; command to store the full details of the message in a Redis hash, and then set the expiration for the hash based on the TTL of the message:
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; HMSET message:msg123 state &lt;span class="s2"&gt;"new"&lt;/span&gt; phase &lt;span class="s2"&gt;"initial"&lt;/span&gt; destination &lt;span class="s2"&gt;"center1"&lt;/span&gt; ttl 3600
 EXPIRE message:msg123 3600
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This ensures that the full message information will automatically expire and be removed from Redis after 3600 seconds (1 hour), matching the TTL of the message.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Consume Message Metadata from the Queue&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Retrieve and process message metadata using the &lt;code&gt;RPOP&lt;/code&gt; command:
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; RPOP alarm_queue
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The metadata retrieved can then be used to fetch the full message details from the corresponding hash.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Step 3: Implementing Producers and Consumers&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Message Producer&lt;/strong&gt;:&lt;br&gt;
Here’s a simple Python script that acts as a producer, pushing metadata into the Redis queue and storing the full message details in a hash with an expiration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;redis&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;

&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Redis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;localhost&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;6379&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Example metadata to push into the queue
&lt;/span&gt;&lt;span class="n"&gt;message_metadata&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;msg123&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sender_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;deviceA&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;signal_code&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;12345&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;# From a predefined list
&lt;/span&gt;    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;criteria_index&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Push metadata to the queue
&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lpush&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;alarm_queue&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message_metadata&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="c1"&gt;# Store full message details in a hash and set expiration (TTL)
&lt;/span&gt;&lt;span class="n"&gt;ttl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3600&lt;/span&gt;
&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hmset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;message:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;message_metadata&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;state&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;new&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;phase&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;initial&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;destination&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;center1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ttl&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ttl&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="c1"&gt;# Set expiration for the hash based on TTL
&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;expire&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;message:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;message_metadata&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ttl&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Message metadata pushed to the queue, full message details stored in Redis, and expiration set.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Message Consumer&lt;/strong&gt;:&lt;br&gt;
A basic consumer script would look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;redis&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;

&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Redis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;localhost&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;6379&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# Blocking pop to wait for new messages
&lt;/span&gt;    &lt;span class="n"&gt;metadata&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;brpop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;alarm_queue&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;message_info&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;utf-8&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="c1"&gt;# Retrieve full message details from Redis
&lt;/span&gt;    &lt;span class="n"&gt;full_message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hgetall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;message:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;message_info&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Processing message ID: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;message_info&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; from sender: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;message_info&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;sender_id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Full message details: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;full_message&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;strong&gt;Step 4: Scaling and Optimization&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;As your system grows, Redis can be scaled to handle increased message volumes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Sharding&lt;/strong&gt;: Distribute your queues across multiple Redis instances.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Clustering&lt;/strong&gt;: Use Redis clustering to spread the load across multiple nodes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Optimized Data Handling&lt;/strong&gt;: Consider using Redis Streams if you need more advanced features like message IDs, groups, and consumer tracking.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Step 5: Monitoring and Maintenance&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Monitor your Redis instances regularly using tools like &lt;code&gt;redis-cli&lt;/code&gt;, Redis Sentinel, or third-party monitoring solutions to keep track of key metrics such as queue length, memory usage, and latency.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Using Redis as a message queue, particularly when storing minimal metadata in the queue and full message details in hashes, is an efficient way to manage the flow of alarm messages in a message-oriented architecture. By setting expiration on the full message hashes, matching the TTL, you ensure the system remains clean and avoids uncontrolled growth. The signal code, coming from a predefined list, indicates which kind of alarm is being handled, allowing for specific actions based on alarm type. With Redis, the system remains lightweight, scalable, and fast. In the next post, we’ll dive into how to manage the full lifecycle of these messages, including state management, TTL, and delivery guarantees.&lt;/p&gt;

&lt;p&gt;Stay tuned!&lt;/p&gt;

</description>
      <category>redis</category>
      <category>messagequeue</category>
      <category>alarmsystems</category>
      <category>distributedsystems</category>
    </item>
    <item>
      <title>Understanding Message-Oriented Architecture: The Backbone of Modern Distributed Systems</title>
      <dc:creator>Chanh Le</dc:creator>
      <pubDate>Mon, 09 Sep 2024 16:24:18 +0000</pubDate>
      <link>https://dev.to/chanh_le/understanding-message-oriented-architecture-the-backbone-of-modern-distributed-systems-2al</link>
      <guid>https://dev.to/chanh_le/understanding-message-oriented-architecture-the-backbone-of-modern-distributed-systems-2al</guid>
      <description>&lt;p&gt;In today’s world of complex distributed systems, ensuring that different components communicate efficiently and reliably is crucial. This is where Message-Oriented Architecture (MOA) comes into play. In this blog post, we'll explore what MOA is, its core principles, and why it’s a foundational approach for building scalable, resilient systems.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is Message-Oriented Architecture?
&lt;/h3&gt;

&lt;p&gt;Message-Oriented Architecture (MOA) is a design paradigm used to build systems where components communicate by sending messages to each other, rather than through direct method calls or function invocations. In an MOA, messages are the primary means of communication, decoupling the sender and receiver and allowing for greater flexibility and scalability.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Use MOA?
&lt;/h3&gt;

&lt;p&gt;In a traditional monolithic application, components are tightly coupled, meaning that a failure in one part of the system can have a cascading effect. MOA addresses this issue by introducing a layer of abstraction between components. Here’s why this approach is advantageous:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Decoupling&lt;/strong&gt;: With MOA, components don’t need to know about each other’s existence or how they’re implemented. They simply send and receive messages. This decoupling allows you to change or replace components without impacting the entire system.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Scalability&lt;/strong&gt;: Because messages can be queued and processed asynchronously, MOA makes it easier to scale individual components independently. For example, if a service is receiving more requests than it can handle, you can add more instances of that service without affecting the rest of the system.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Resilience&lt;/strong&gt;: In an MOA, if a component fails, messages can be stored in a queue until the component is back online. This means that the system can continue to function even in the face of individual component failures, leading to higher overall resilience.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Flexibility&lt;/strong&gt;: MOA supports different communication patterns, such as point-to-point (where one sender communicates with one receiver) and publish-subscribe (where messages are broadcast to multiple receivers). This flexibility makes it easier to implement complex workflows.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  How Does MOA Work?
&lt;/h3&gt;

&lt;p&gt;At the heart of an MOA is the message queue or broker, which acts as an intermediary between components. Here’s a simplified workflow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Message Production&lt;/strong&gt;: A sender (also known as a producer) creates a message and sends it to the message queue.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Message Queuing&lt;/strong&gt;: The message queue stores the message until a receiver (also known as a consumer) is ready to process it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Message Consumption&lt;/strong&gt;: The receiver retrieves the message from the queue and processes it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Message Acknowledgment&lt;/strong&gt;: After processing, the receiver sends an acknowledgment back to the queue, indicating that the message has been handled successfully.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This approach allows components to operate asynchronously and independently, improving the overall efficiency and reliability of the system.&lt;/p&gt;

&lt;h3&gt;
  
  
  Real-World Applications of MOA
&lt;/h3&gt;

&lt;p&gt;MOA is widely used across various industries and applications, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;E-commerce&lt;/strong&gt;: Handling orders, payments, and notifications in a decoupled manner, ensuring that no single component overloads the system.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;IoT Systems&lt;/strong&gt;: Managing communication between a vast number of devices and a central server, where devices send data and receive instructions asynchronously.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Financial Services&lt;/strong&gt;: Processing transactions, where different services like payment processing, fraud detection, and account updates operate independently and communicate through messages.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Redis as a Message Queue in MOA
&lt;/h3&gt;

&lt;p&gt;Redis, a popular in-memory data structure store, is often used as a message queue in MOA systems. It offers high performance and flexibility, making it an excellent choice for handling message queuing tasks. In upcoming posts, we’ll dive deeper into how Redis can be leveraged in an MOA, particularly in systems where reliability and speed are critical, such as delivering alarm messages from devices to receiving centers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Message-Oriented Architecture is a powerful design approach that enables building scalable, resilient, and flexible systems. By decoupling components and facilitating asynchronous communication through messaging, MOA allows systems to be more adaptable to change and more robust in the face of failure. As we continue this blog series, we’ll explore practical implementations of MOA using Redis, focusing on real-world scenarios and best practices.&lt;/p&gt;

&lt;p&gt;Stay tuned for our next post, where we’ll dive into the specifics of using Redis as a message queue in an MOA system!&lt;/p&gt;

</description>
      <category>distributedsystems</category>
      <category>redis</category>
      <category>eventdriven</category>
      <category>messageoriented</category>
    </item>
    <item>
      <title>Rust ownership: another way to manage memory</title>
      <dc:creator>Chanh Le</dc:creator>
      <pubDate>Sat, 02 Mar 2024 16:59:58 +0000</pubDate>
      <link>https://dev.to/chanh_le/rust-ownership-another-way-to-manage-memory-3n22</link>
      <guid>https://dev.to/chanh_le/rust-ownership-another-way-to-manage-memory-3n22</guid>
      <description>&lt;p&gt;In Java, we have the garbage collector helps us to clean up unused memory. In C++, we have to allocate and de-allocate memory explicitly using pointers. So, what about Rust? Ownership is a core concept in Rust which we developers, would use to ensure memory safety.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is memory management
&lt;/h2&gt;

&lt;p&gt;Memory in programming has two types: stack and heap. Because stack memory is managed automatically, we will only care about managing data (dynamically sized data) on heap memory.&lt;br&gt;
Memory management is the way we allocate and de-allocate memory for storing variable values, for example values of string or linked-list variables.&lt;/p&gt;
&lt;h2&gt;
  
  
  JVM garbage collector (Java)
&lt;/h2&gt;

&lt;p&gt;In Java, we don't have to know about how to manage memory because that is the job of JVM's garbage collector. This component of JVM will periodically scan for unused references (variables) and un-reference(de-allocate) them. So, the memory would be clean up automatically.&lt;/p&gt;
&lt;h2&gt;
  
  
  C++ pointer
&lt;/h2&gt;

&lt;p&gt;In C++, we have to manage the memory manually and explicitly  using pointer. When we need memory for a variable, we ask for a memory allocation by using the &lt;code&gt;new&lt;/code&gt; keyword. We will receive a pointer to reference to the location where our data would be stored. Then, when the variable is no more needed (out of scope), we will use &lt;code&gt;delete&lt;/code&gt; keyword to un-reference the pointer. So, the memory at that location would be cleaned up and released. And if we forgot to &lt;code&gt;delete&lt;/code&gt; the pointer, that segment of memory would never be released. Eventually, we would encounter memory leak problems.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;new&lt;/code&gt; and &lt;code&gt;delete&lt;/code&gt; in C++:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;pointer_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// ask for heap memory allocation&lt;/span&gt;
&lt;span class="c1"&gt;// Code using pointer_name variable&lt;/span&gt;
&lt;span class="k"&gt;delete&lt;/span&gt; &lt;span class="n"&gt;pointer_name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// de-allocate the memory segment&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Rust ownership
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Ownership
&lt;/h3&gt;

&lt;p&gt;Each value in Rust has an owner. The owner here is actually the variable associated with that value. When we assign a variable to another variable, the ownership is transferred.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;hello_str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"hello"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// `hello_str` variable is the owner of the heap segment storing value `hello`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Ownership transferring
&lt;/h3&gt;

&lt;p&gt;When ownership is transferred or moved, the original variable becomes invalid and unusable. Variable assignment and parameter passing would trigger ownership transfer.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;hello_str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"hello"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;new_hello_str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;hello_str&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// `new_hello_str` is now the owner, `hello_str` is no more usable&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Reference borrowing
&lt;/h3&gt;

&lt;p&gt;In case you just want to use the value and not want to take ownership, you could borrow a reference (&lt;code&gt;&amp;amp;&lt;/code&gt;) to that value. If you also want to modify the value, you could borrow a mutable reference(&lt;code&gt;&amp;amp;mut&lt;/code&gt;) instead.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;greeting&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;greeting_str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"hello "&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;greeting_str&lt;/span&gt;&lt;span class="nf"&gt;.push_str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;greeting_str&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Chanh"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Create a reference to the name string&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;name_ref&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Pass the reference to the greeting function&lt;/span&gt;
    &lt;span class="nf"&gt;greeting&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name_ref&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// The original name can still be used&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"My name is: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Copy/Clone
&lt;/h3&gt;

&lt;p&gt;In case you do want to have ownership on a value, but in the same time do not want make the original variable invalid, you could copy the value to a new memory location using &lt;code&gt;clone&lt;/code&gt; method. You would assign the ownership to a new local variable and have a full control on it without any affect on the original variable.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;greeting&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="nf"&gt;.insert_str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Mr. "&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;greeting_str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"hello "&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;greeting_str&lt;/span&gt;&lt;span class="nf"&gt;.push_str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{greeting_str}"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Chanh"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Pass the mutable reference of the cloned value to the greeting function&lt;/span&gt;
    &lt;span class="nf"&gt;greeting&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="nf"&gt;.clone&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

    &lt;span class="c1"&gt;// The original name can still be used&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"My name is: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;As you could see, Rust uses a new approach for managing memory allocation. The developers do not have support on cleaning data up automatically like in Java. They also do not need to manually, explicitly do that like in C++. Instead, they need to participate on helping the Rust Ownership System to know when which memory segment should be cleaned and freed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://doc.rust-lang.org/book/ch04-01-what-is-ownership.html" rel="noopener noreferrer"&gt;Ownership in Rust book
&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.baeldung.com/jvm-garbage-collectors" rel="noopener noreferrer"&gt;JVM Garbage Collector&lt;/a&gt;&lt;/li&gt;
&lt;li&gt; &lt;a href="https://www.geeksforgeeks.org/new-and-delete-operators-in-cpp-for-dynamic-memory/" rel="noopener noreferrer"&gt;&lt;code&gt;new&lt;/code&gt; and &lt;code&gt;delete&lt;/code&gt; in C++&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>rust</category>
      <category>beginners</category>
      <category>memory</category>
      <category>ownership</category>
    </item>
    <item>
      <title>Result in Rust: another way of error handling</title>
      <dc:creator>Chanh Le</dc:creator>
      <pubDate>Fri, 01 Mar 2024 18:16:56 +0000</pubDate>
      <link>https://dev.to/chanh_le/result-in-rust-a-new-way-of-error-handling-49fl</link>
      <guid>https://dev.to/chanh_le/result-in-rust-a-new-way-of-error-handling-49fl</guid>
      <description>&lt;p&gt;I've just started learning Rust in 2 days. And the first thing I was surprised about was how Rust handles errors. I have used several different programming languages and I thought that the only way to handle errors or exceptions is catching them with &lt;a href="https://www.w3schools.com/java/java_try_catch.asp" rel="noopener noreferrer"&gt;try/catch statement&lt;/a&gt;. But you know what there is no try/catch at all in Rust. Yeah, that's true I swear!&lt;/p&gt;

&lt;h2&gt;
  
  
  Traditional way to handle error/exception
&lt;/h2&gt;

&lt;p&gt;In other programming languages like Java, Python, we usually use the &lt;a href="https://www.baeldung.com/java-exceptions" rel="noopener noreferrer"&gt;Exception Approach for handling errors&lt;/a&gt;. More specifically, we would throw exception or raise error when we want to signal the caller of our code that there is an error it needs to handle. And the caller would use try/catch statement to catch the error in order to handle it. That's the way of handling error that we all know I guess. But that's not true with Rust. So, how exactly does Rust handle error?&lt;/p&gt;

&lt;p&gt;Java try/catch statement:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;//  Block of code to try&lt;/span&gt;
  &lt;span class="n"&gt;myFunction&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Exception&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;//  Block of code to handle errors&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  An Result always returned even in case of error
&lt;/h2&gt;

&lt;p&gt;Yes, I say that. No mistake or typo here. But first, you need to know what Result is. &lt;a href="https://doc.rust-lang.org/std/result/" rel="noopener noreferrer"&gt;Result in Rust&lt;/a&gt; is a built-in enum. It has two variants: Ok (for normal case) and Err (in case of any error occurred during runtime).&lt;br&gt;
In case of no error, the caller of your code would receive a Result object of Ok variant. And if there was an error occurred, the Result object would be an Err variant.&lt;br&gt;
And the caller would use the &lt;a href="https://doc.rust-lang.org/rust-by-example/flow_control/match.html" rel="noopener noreferrer"&gt;match statement&lt;/a&gt; to handle both variants.&lt;/p&gt;

&lt;p&gt;Handling Result using match statement (&lt;a href="https://doc.rust-lang.org/stable/book/ch02-00-guessing-game-tutorial.html#handling-invalid-input" rel="noopener noreferrer"&gt;Guessing Game&lt;/a&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;my_function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;//guess.trim().parse()&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;guess&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u32&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;continue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, Rust uses Result with Err variant to signal the caller of your code about error occurrences. The caller would handle the error using match statement. He could skip the error and retry if the error is &lt;a href="https://doc.rust-lang.org/book/ch09-02-recoverable-errors-with-result.html" rel="noopener noreferrer"&gt;recoverable&lt;/a&gt;, otherwise he could stop the program from running immediately using &lt;a href="https://doc.rust-lang.org/book/ch09-01-unrecoverable-errors-with-panic.html" rel="noopener noreferrer"&gt;panic! marco&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Error handling in Rust uses a different approach compared to other common programming languages like Java, Python. There is nothing like try/catch statement in Rust. Instead, Rust provides a built-in enum called Result which would carry the error objects for us to handle using match statement.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;Actually, there is another surprise to me about Rust, which is the concept of ownership. There's a complete new world for me to explore there. And that's what I would like to learn and write about next. So, stay tune!&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://doc.rust-lang.org/stable/book/ch02-00-guessing-game-tutorial.html#handling-invalid-input" rel="noopener noreferrer"&gt;Guessing Game &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://doc.rust-lang.org/book/ch09-00-error-handling.html" rel="noopener noreferrer"&gt;Error handling in Rust&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>rust</category>
      <category>result</category>
      <category>beginners</category>
      <category>enum</category>
    </item>
  </channel>
</rss>
