<?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: Avash_Mitra</title>
    <description>The latest articles on DEV Community by Avash_Mitra (@avash027).</description>
    <link>https://dev.to/avash027</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%2F996910%2F33efdac3-1b1c-4eda-9ed1-12f7c53c0c8f.jpeg</url>
      <title>DEV Community: Avash_Mitra</title>
      <link>https://dev.to/avash027</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/avash027"/>
    <language>en</language>
    <item>
      <title>The Technical Breakdown: Slack's Near-Miss Database Overloado</title>
      <dc:creator>Avash_Mitra</dc:creator>
      <pubDate>Fri, 12 Jan 2024 19:23:20 +0000</pubDate>
      <link>https://dev.to/avash027/the-technical-breakdown-slacks-near-miss-database-overload-3jo1</link>
      <guid>https://dev.to/avash027/the-technical-breakdown-slacks-near-miss-database-overload-3jo1</guid>
      <description>&lt;p&gt;In the sphere of real-time communication, Slack stands out as a pivotal platform for corporate connectivity and collaboration. However, on October 12, 2022, the system's reliability was put to the test. The Datastores team, responsible for overseeing Slack's database clusters, encountered a significant challenge — a sudden increase in the number of failed database queries pointed to an underlying issue that required immediate attention.&lt;/p&gt;

&lt;h2&gt;
  
  
  Incident Onset and Immediate Response
&lt;/h2&gt;

&lt;p&gt;During an onsite in Amsterdam, the Datastores team, freshly augmented with new engineers, was alerted to a troubling rise in database query failures. An investigation revealed the cause: a long-running asynchronous job was purging substantial amounts of data, leading to an overload on the database cluster. To mitigate this, the team executed a temporary solution known as 'shimming,' which allowed ongoing jobs to complete while halting the initiation of new processes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Recurrence and Escalation
&lt;/h2&gt;

&lt;p&gt;The remedy seemed effective until the very next day when the problem resurfaced with greater severity. This incident shed light on an edge-case bug within Datastores' automation, which had failed to manage a surge in requests, directly affecting customer access to Slack. The team responded by disabling certain features to alleviate the load on the cluster, which provided the necessary room for recovery.&lt;/p&gt;

&lt;h2&gt;
  
  
  Slack's datastore stratergy
&lt;/h2&gt;

&lt;p&gt;Before discussing the trigger and the cascading effects of the incident, it is essential to understand Slack's datastore strategy, which is at the core of its operational integrity. Slack's data architecture is built around Vitess, a database clustering system for horizontal scaling of MySQL. By employing Vitess, Slack effectively shards its extensive dataset across multiple MySQL instances. This not only allows for more efficient data management and retrieval but also ensures that operations can continue seamlessly even if one shard encounters an issue. Each shard contains a portion of the database and operates in conjunction with replicas to balance the load and facilitate quick data access. This setup is designed to maximize uptime and performance, a necessity for a platform supporting millions of concurrent users. The strategic use of sharding and replication is central to Slack's ability to scale dynamically and maintain robust data integrity, even as user numbers and data volumes continue to grow.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Trigger and Subsequent Measures
&lt;/h2&gt;

&lt;p&gt;Upon further analysis, the team identified that the incident was triggered by a customer removing a large number of users from their workspace, an operation that initiated a cascade of data modifications beyond the usual scope. To address the immediate issue, the Datastores team manually provisioned larger instance types for replicas, circumventing the automated systems that were not equipped to handle such an anomaly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Long-Term Solutions and Preventative Actions
&lt;/h2&gt;

&lt;p&gt;Moving forward, the Datastores team has adopted several strategic measures to prevent a recurrence. They have implemented throttling mechanisms and the circuit breaker pattern, both of which serve as safeguards against query overload. These measures enable the team to proactively limit or cancel queries to affected shards, thereby maintaining database stability.&lt;/p&gt;

&lt;p&gt;In addition, to address the specific challenges posed by the 'forgetUser' job, which was central to the incident, the team optimized the job's performance. They streamlined the process to reduce the load on the database during large-scale user removal operations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The incidents of October 2022 highlighted the intricate balance required in managing large-scale, distributed databases. The Datastores team's adept response and the subsequent refinements to their systems underscore the continuous need for vigilance, adaptability, and innovation in database management. As a result of these efforts, Slack's infrastructure has been fortified, showcasing a commitment to resilience and the uninterrupted service that users rely on.&lt;/p&gt;

</description>
      <category>database</category>
      <category>sharding</category>
    </item>
    <item>
      <title>5 database engines you should know about</title>
      <dc:creator>Avash_Mitra</dc:creator>
      <pubDate>Fri, 07 Apr 2023 15:12:52 +0000</pubDate>
      <link>https://dev.to/avash027/5-database-engines-you-should-know-about-18hm</link>
      <guid>https://dev.to/avash027/5-database-engines-you-should-know-about-18hm</guid>
      <description>&lt;p&gt;&lt;em&gt;We will discuss different types of engines, their use cases, pros and cons, and much more.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Database engines, also referred to as storage engines, are software programs that handle CRUD (Create, Read, Update, Delete) operations and disk storage for databases. While some are simple and only manage storage and CRUD, more complex engines offer advanced features like ACID support and transactions. Database systems build their functionalities on top of these engines.&lt;/p&gt;

&lt;p&gt;In this discussion, we will explore various types of database engines, their use cases, and their pros and cons, to provide comprehensive insights into the world of database engines.&lt;/p&gt;

&lt;h3&gt;
  
  
  MyISAM
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Written in C, MyISAM was the first database engine for MySQL.&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;ISAM stands for Indexed Sequential Access Method. In this engine every &lt;strong&gt;index that we create points to a row.&lt;/strong&gt; It uses B-tree for indexing.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Since every index points to a row, &lt;strong&gt;read operations are fast&lt;/strong&gt;. Even the &lt;strong&gt;insert operations are fast because we are appending the new record to the end of the file&lt;/strong&gt; and we always know where the end of the file is. However, the main issue is with the update and delete operations. When we &lt;strong&gt;update/delete existing rows, we change the row size, this changes the offset and all the index pointers need to change.&lt;/strong&gt; This is expensive.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It provides &lt;strong&gt;no Transaction support.&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Database crashes corrupt tables and has to be manually repaired.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It only provides table-level locking. If you want isolation you just have to lock the entire table.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;InnoDB&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;It replaced MyISAM as the default database engine of MySQL and MariaDB.&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;In this engine, the B+ tree is used for indexing. Each index points to a primary key and each primary key points to a row. If there is no primary key then the engine makes one for you.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It supports transactions and therefore implements ACID features.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It also allows row-level locking so you don’t need to lock your entire table. This makes query processing faster.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It also introduces a lot of new features like foreign keys, tablespaces, and spatial operations.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  SQLite
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;It was designed by Dwayne Richard Hipp and written in C language&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BLQaF5Rp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hlcquccxvlix65usy8qh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BLQaF5Rp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hlcquccxvlix65usy8qh.png" alt="SQLite" width="573" height="272"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It is one of the most widely used embedded databases and is used in web browsers, mobile applications, operating systems, etc.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;It used B-Tree for indexing.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It allows all ACID features&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It allows table-level locking. It does not need row-level locking because it is usually used locally and there is only a single user.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It allows concurrent reads and writes.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  LevelDB
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;It was designed by two Google engineers Jeffery Dean and Sanjay Ghemawat and written in C++ language. It was inspired by Google BigTable.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DPpKyQlE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xpagpkicpprnlfcgwbj2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DPpKyQlE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xpagpkicpprnlfcgwbj2.png" alt="LevelDB" width="720" height="297"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;It is &lt;strong&gt;not&lt;/strong&gt; a SQL database. It does not have a relational database model and does not support SQL queries.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It used &lt;strong&gt;Log-Structured Merge Trees for indexing&lt;/strong&gt;. It works &lt;strong&gt;great for high insert volume&lt;/strong&gt;. (unlike B tree that may need to rebalance itself after insert which makes insert operations slow)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It does not allow transactions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It is single-threaded&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;There are levels of files and as the file grows large, levels are merged.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;They also support Write Ahead Logs to ensure durability.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  RocksDB
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;It is a fork of Google’s LevelDB and is further developed by Facebook. It is used as MyRocks for MySQL, MariaDB, and Percona. It is also used by MongoRocks for MongoDB.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Similarities with LevelDB&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;It also uses Log structured merge trees&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It is also key-value pair storage and does not support SQL queries.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;New features added to RocksDB&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;It allows transactions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It also used multi-threading to improve performance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Other features include Geospatial indexing, Bloom filters, merge operators, etc.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In conclusion, understanding different types of database engines and their use cases can greatly impact the performance and functionality of your database system. Each engine has its own strengths and weaknesses, making it crucial to choose the right one based on your specific requirements.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;MyISAM, the first MySQL database engine, provides fast read and insert operations but lacks transaction support and may be prone to table corruption.&lt;/li&gt;
&lt;li&gt;InnoDB, the default MySQL and MariaDB engine, offers ACID compliance, row-level locking, and advanced features like foreign keys and spatial operations.&lt;/li&gt;
&lt;li&gt;SQLite, a popular embedded database, is widely used in web browsers, mobile applications, and operating systems, providing ACID features, table-level locking, and support for concurrent reads and writes.&lt;/li&gt;
&lt;li&gt;LevelDB, inspired by Google's BigTable, is a non-SQL database with Log-Structured Merge Trees for indexing, making it ideal for high insert volume but lacks transaction support and is single-threaded.&lt;/li&gt;
&lt;li&gt;RocksDB, a fork of LevelDB, adds features like transactions, multi-threading, and geospatial indexing, making it suitable for MySQL, MariaDB, Percona, and MongoDB.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Choosing the right database engine depends on your specific use case, performance requirements, and desired features. It is essential to carefully evaluate and compare different engines to make an informed decision and optimize your database system for efficiency and reliability.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Memcached at Scale: How Facebook Scaled and Optimized for Massive Request Volumes</title>
      <dc:creator>Avash_Mitra</dc:creator>
      <pubDate>Thu, 06 Apr 2023 14:35:17 +0000</pubDate>
      <link>https://dev.to/avash027/memcached-at-scale-how-meta-scaled-and-optimized-for-massive-request-volumes-1k2d</link>
      <guid>https://dev.to/avash027/memcached-at-scale-how-meta-scaled-and-optimized-for-massive-request-volumes-1k2d</guid>
      <description>&lt;p&gt;Facebook, one of the world's largest social media platforms, handles billions of requests per second and stores trillions of key-value pairs. To manage this scale, Meta uses Memcached, a simple Key-Value cache that stores data in memory. Since users consume a lot of content than they create caching had significant advantages. It reduced latency, reduced load on database servers, and much more. In this blog, we'll explore Meta's strategy for scaling their Memcached clusters to handle their high demand and discuss optimizations in these areas to improve performance and storage.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Optimizing clusters and regions of Memcache servers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Optimizing a single Memcached server&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Optimizing Clusters to Reduce Latency for Memcached
&lt;/h2&gt;

&lt;p&gt;When scaling to thousands of servers per cluster, we run into some interesting problems&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Increased latency&lt;/strong&gt; due to the distributed nature in which the data is stored. Since each web server has to get the data from multiple cache servers, the latency increases.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Thundering Herd&lt;/strong&gt; can occur when there is a cache miss and can severely affect the database servers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Cascading failures&lt;/strong&gt; can happen when one Memcached server goes offline and it puts additional strain on other servers&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Users might get &lt;strong&gt;stale data&lt;/strong&gt; if the cache invalidation method is not optimal.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So let's discuss how to solve each issue in detail&lt;/p&gt;

&lt;h3&gt;
  
  
  Reducing Latency by using TCP for Set and Delete, and UDP for Get Requests
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;For &lt;strong&gt;GET&lt;/strong&gt; requests, we use &lt;strong&gt;UDP&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Unlike TCP, UDP is connectionless (No connection needs to be established between the source and destination before you transmit data), so it reduces latency and overhead.&lt;/li&gt;
&lt;li&gt;Also, for GET requests, web servers can directly connect to the Memcached server (instead of connecting through the proxy). This further reduces the overhead.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;NOTE:&lt;/strong&gt; We can use UDP for GET requests because GET requests do not change the state of the cache. So even if the request fails (which might happen because UDP is unreliable) it won't cause data inconsistency.&lt;/li&gt;
&lt;/ul&gt;


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

&lt;p&gt;FOR &lt;strong&gt;SET&lt;/strong&gt; and &lt;strong&gt;DELETE&lt;/strong&gt; requests, we use &lt;strong&gt;TCP&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Since UDP is unreliable, we use TCP to perform these operations. Also, these requests are routed through the proxy.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Parallelizing and Batching Requests to reduce latency
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;To reduce latency, we need to minimize the number of round trips for fetching the data. To do so, we can parallelize the requests. But some data are dependent on other data i.e., we need to fetch the 'parent' data and use it to fetch the 'child' data (look at the example below). So, a Directed Acyclic Graph can be constructed. Now, for the data points that do not have any dependencies, we can send parallel requests to fetch them.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ex:&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CsBRxEbp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jbthwwcvvyf1mbiacenu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CsBRxEbp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jbthwwcvvyf1mbiacenu.png" alt="Parallelizing requests" width="880" height="575"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Preventing Congestion
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Sending a lot of requests parallelly can cause congestion. This can slow down responses, increase load on the Memcached servers, and in the worst case the server can crash. To prevent this from happening, the number of outstanding requests must be controlled. To do so, &lt;strong&gt;web servers use a sliding window.&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In a web server, there is a sliding window for each Memcached server. If the request was successful, the sliding window size increases, but if the request failed it shrinks.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When the window size is very small, the web server has to wait more before sending a request and when the window size is very large the number of parallel requests can cause congestion. So the balance between these two extremes is where we prevent congestion and minimize latency.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Optimizing Clusters to Reduce Load on Servers
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Reducing Load (on Databases) using Leases
&lt;/h3&gt;

&lt;p&gt;This is one of my favorite techniques in this entire blog. This mechanism not only reduces load (and thereby prevents thundering herds) but also addresses the issue of stale data and is quite intuitive. But before discussing the solution let's understand in what scenario will the load on database servers increase.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Suppose 1000 web servers requested a key, but it is missing. Now all 100 web servers make requests to the database server. Now the database server has to 1000 servers at once which can cause it to crash. We call this scenario &lt;strong&gt;Thundering Herd.&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Stale data can be added to the cache due to race conditions. Have a look at the illustration below to understand how it happens&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8h6snfew--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hrtnrqelvuks7kll016y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8h6snfew--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hrtnrqelvuks7kll016y.png" alt="stale values in cache condition" width="880" height="751"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A lease is a 64-bit token that is associated with a key. When there is a cache miss, a lease is assigned to the web server that experienced the cache miss.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The Memcache server regulates the rate at which it assigns a lease token (usually 10 seconds). So, within 10 seconds if any other web server requests for the key, they get a special responsibility to wait for a short amount of time. &lt;strong&gt;This prevents Thundering Herd because instead of sending requests to the database, now the web servers wait for the cache to be updated with the required value.&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Only those servers can update the cache that has the lease token. If the data value is updated in the database, then the key is invalidated in the cache and so is the lease token. In that case, a new token is assigned to the servers that experience cache miss. So we can be ensured that only the latest value is added to the cache. Therefore it also solves the stale data issue.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Assigning different Pools for different types of data
&lt;/h3&gt;

&lt;p&gt;Different types of data have different access patterns, memory footprints, and quality of service requirements. They can negatively affect each other so they are assigned different server pools.&lt;/p&gt;

&lt;p&gt;E.g. A small pool of Memcached servers can be assigned for the keys that are accessed frequently but a cache miss is cheap (A smaller pool means less time is required to search the key) and a large pool for keys that are accessed infrequently but a cache miss is expensive.&lt;/p&gt;

&lt;h3&gt;
  
  
  Distributing Read Requests across the Replicas
&lt;/h3&gt;

&lt;p&gt;We can create replicas of the Memcached servers within the same pool and replicate the keys. Now when we get read requests, we can distribute them across all the replicas. This reduces the load from the main Memcached server.&lt;/p&gt;

&lt;h3&gt;
  
  
  Preventing Cascading Failure
&lt;/h3&gt;

&lt;p&gt;In a distributed system, servers going offline is a norm rather than an exception. To mitigate outages a small set of servers known as &lt;code&gt;Gutter&lt;/code&gt; is used. It is just a Memcached server that is only used when any other Memcached server is offline. When the server sends a request to the Memcached server but does not receive any response, it assumes the server is offline and sends the request to the Gutter Pool.&lt;/p&gt;

&lt;p&gt;There is another approach, where the key is rehashed and assigned to another server. This is not preferred because it can cause a &lt;strong&gt;cascading failure&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9QK9_8kd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vbifcf0mv00velqa7pza.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9QK9_8kd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vbifcf0mv00velqa7pza.png" alt="cascading failure" width="880" height="880"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Image credits:&lt;/code&gt; &lt;a href="https://interviewready.io/blog/ratelimiting"&gt;&lt;code&gt;https://interviewready.io/blog/ratelimitin&lt;/code&gt;&lt;/a&gt;&lt;code&gt;g&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;For instance, if a highly requested key is assigned to another server, then it might overload that server and crash it. Now, again it'll be assigned to a different server and repeat the same thing as above.&lt;/p&gt;

&lt;p&gt;It'll continue until many servers crash due to overload, so using Gutter servers is a better option.&lt;/p&gt;

&lt;h2&gt;
  
  
  Improving Performance by using regions of Memcached servers
&lt;/h2&gt;

&lt;p&gt;There is an upper limit to how many servers we can add to a cluster before the congestion worsens. Therefore it is better to split the web and Memcached servers into multiple frontend clusters. These clusters, along with a storage cluster that contains the databases, define a &lt;strong&gt;region&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Making regions of Memcached servers has many benefits like reduced latency because the servers are near the end users. It also mitigates the effects of large-scale power outages, natural calamities, etc. This makes the system more reliable and available.&lt;/p&gt;

&lt;h3&gt;
  
  
  Removing stale data from Memcached servers in different regions
&lt;/h3&gt;

&lt;p&gt;A single key-value pair may be replicated to multiple Memcached servers in different regions. So, when the data is updated in the database, we have to invalidate the data from those servers. To do so, the following procedure is followed&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;SQL statements that modify the state have the required Memcached keys embedded in them.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Each database server also has an invalidation daemon called McSqueal. It analyzes the SQL statement, extracts the keys, and broadcasts the updates to different regions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;McSqueal also batches requests to reduce the number of data packets. These packets are then unpacked by the Memcached proxy (Mcrouter).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Optimizing a single Memcached server
&lt;/h2&gt;

&lt;p&gt;A single server can easily become the bottleneck, so it is important to optimize the Memcached server.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using Adaptive Slab Allocator for Better Memory Management
&lt;/h3&gt;

&lt;p&gt;Allocating and Deallocating memory randomly causes &lt;strong&gt;Memory Fragmentation&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Memory fragmentation is when the sum of the available space in a memory heap is large enough to satisfy a memory allocation request but the size of any individual fragment (or contiguous fragments) is too small to satisfy that memory allocation request&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6e_9QUED--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wj69c984p5mn5tau9xzg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6e_9QUED--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wj69c984p5mn5tau9xzg.png" alt="memory fragmentation" width="586" height="625"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It increases the read time as the memory gets more and more fragmented. To prevent this, Memcachedpre- allocates a large chunk and divides it into &lt;strong&gt;slab classes.&lt;/strong&gt; The size of slab classes starts from 64 bytes up to 1MB. It stores the data in the smallest possible slab that can fit the data item.&lt;/p&gt;

&lt;p&gt;Each slab class maintains a list of available memory and requests for more memory when this free list is empty.&lt;/p&gt;

&lt;p&gt;Now, it is worth noting that there might be some wastage of memory inside a slab if the data item is smaller than the slab size (it is called internal fragmentation). But it does not degrade the performance as much as external fragmentation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Choosing the right eviction policy
&lt;/h3&gt;

&lt;p&gt;Memcached uses LRU (Least Recently Used) eviction policy. Each Slab class has its own LRU data structure (generally we use a linked list). When it cannot allocate any more memory in a slab, the least recently used (in other words, the oldest items) is evicted from the slab class.&lt;/p&gt;

&lt;p&gt;This approach has one issue - The eviction rate across slab classes is unbalanced. This can cause performance issues as one slab is constantly evicting and adding data items, while other slabs are not being used. To prevent this, it is important to identify the slabs where the eviction rate is high and the evicted keys can be assigned to other slabs.&lt;/p&gt;

&lt;p&gt;So, if a slab class is evicting a data item and it was used at least 20% (this a threshold) more recently than the average of least recently used items in other slab classes, then the data item is moved to any other class.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reducing Memory Usage by removing short-lived keys
&lt;/h3&gt;

&lt;p&gt;Memcached evicts an item&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;When the expiration time of the item has exceeded while serving a GET request.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Or, when the item has reached the end of LRU&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In short, it removes the data items lazily. Short-lived keys that see a single burst of activity waste memory, until they reach the end of LRU.&lt;/p&gt;

&lt;p&gt;To solve this issue, a hybrid method is used to lazily evict most keys and quickly evict short-lived keys when they expire. All the short-lived items are placed in a circular buffer of a linked list. We have a head pointer that iterates over the circular buffer and advances by one each second. Each second, all of the items in the bucket at the head pointer are evicted and the head pointer advances by one.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using Multi-threading to boost performance
&lt;/h3&gt;

&lt;p&gt;The Memcached server is multi-threaded to boost performance.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;To prevent race conditions, a global lock is used to protect the data structures.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If a single port is used to connect to web servers, then it can easily bottleneck the whole server, so each thread is given its own UDP port.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;In conclusion, Meta's strategy for scaling their Memcached clusters to handle their high demand involves optimizing clusters and regions of Memcached servers as well as optimizing a single Memcached server. They use techniques such as using TCP for Set and Delete requests, UDP for Get requests to reduce latency, parallelizing and batching requests to minimize round trips, and preventing congestion using a sliding window mechanism. They also use leases to reduce the load on databases and prevent thundering herds, and implement cache invalidation methods to address stale data issues.&lt;/p&gt;

&lt;p&gt;These optimizations not only help reduce latency and load on servers, but also prevent cascading failures, thundering herds, and stale data issues, resulting in improved performance and storage for Meta's Memcached clusters. With these strategies in place, Meta can handle billions of requests per second and store trillions of key-value pairs, efficiently serving content to their users and maintaining a seamless user experience on their social media platform.&lt;/p&gt;




&lt;h3&gt;
  
  
  References
&lt;/h3&gt;

&lt;p&gt;Memcached White Paper: &lt;a href="https://www.usenix.org/system/files/conference/nsdi13/nsdi13-final170_update.pdf"&gt;https://www.usenix.org/system/files/conference/nsdi13/nsdi13-final170_update.pdf&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Memcached architecture crash course: &lt;a href="https://www.youtube.com/watch?v=NCePGsRZFus"&gt;https://www.youtube.com/watch?v=NCePGsRZFus&lt;/a&gt;&lt;/p&gt;

</description>
      <category>caching</category>
      <category>architecture</category>
      <category>systems</category>
      <category>memcache</category>
    </item>
    <item>
      <title>Making a Dynamic Renderer with Golang from Scratch</title>
      <dc:creator>Avash_Mitra</dc:creator>
      <pubDate>Tue, 07 Mar 2023 15:01:06 +0000</pubDate>
      <link>https://dev.to/avash027/making-a-dynamic-renderer-with-golang-from-scratch-2gpd</link>
      <guid>https://dev.to/avash027/making-a-dynamic-renderer-with-golang-from-scratch-2gpd</guid>
      <description>&lt;h2&gt;
  
  
  Understanding Dynamic Rendering: Why It Matters for Your Website's SEO
&lt;/h2&gt;

&lt;p&gt;When it comes to building a website, the three key components are HTML, CSS, and Javascript. In recent years, client-side rendering (CSR) has become increasingly popular. With this approach, the browser downloads an empty HTML shell and uses Javascript to generate the content on the client side.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fweb-dev.imgix.net%2Fimage%2FT4FyVKpzu4WKF1kBNvXepbi08t52%2FJFxoxQe847ntctVOdn5u.png%3Fauto%3Dformat%26w%3D845%2520align%3D" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fweb-dev.imgix.net%2Fimage%2FT4FyVKpzu4WKF1kBNvXepbi08t52%2FJFxoxQe847ntctVOdn5u.png%3Fauto%3Dformat%26w%3D845%2520align%3D"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[Image credits: &lt;a href="%5Bhttps://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/JFxoxQe847ntctVOdn5u.png?auto=format&amp;amp;w=845%5D(https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/JFxoxQe847ntctVOdn5u.png?auto=format&amp;amp;w=845)"&gt;web.dev&lt;/a&gt; ]&lt;/p&gt;

&lt;p&gt;However, while CSR may work well for users, it creates a significant problem for search engines and other bots. Bots rely on the generated HTML content to gather data and index your website. But when a bot visits a client-side rendered page, there is no data available because the Javascript hasn't been executed yet. As a result, the bot only sees an empty website, which can severely impact your website's SEO.&lt;/p&gt;

&lt;p&gt;That's where dynamic rendering comes in. Dynamic rendering is the process of rendering a fully formed HTML page on the server side and sending it to bots, while still using client-side rendering for users. This approach allows bots to access the fully rendered HTML content and gather the data they need to index your website, without affecting the user experience.&lt;/p&gt;

&lt;p&gt;In this article, we'll explore dynamic rendering in more detail and show you how to build a dynamic renderer using Golang, a powerful and efficient programming language, from scratch. With this knowledge, you'll be able to create high-performance web applications that not only deliver a great user experience but also rank well in search engines.&lt;/p&gt;

&lt;h2&gt;
  
  
  But do I even need Dynamic Rendering?
&lt;/h2&gt;

&lt;p&gt;Well, that depends.&lt;/p&gt;

&lt;p&gt;❌ &lt;strong&gt;You don't need dynamic rendering when&lt;/strong&gt; -&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;If you are working with meta frameworks like NextJS, NuxtJS, Remix, etc. Because these are server-side rendering applications.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If your codebase is small and you can migrate it to server-side rendering applications&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;✅ &lt;strong&gt;You need dynamic rendering when&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When your codebase is huge and you don't have the bandwidth to migrate it to server-side rendering applications. Also, you want to improve your website as soon as possible.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But keep in mind,&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Dynamic rendering is a workaround and not a long-term fix for problems with javascript.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Implementing Dynamic Rendering
&lt;/h2&gt;

&lt;p&gt;Let's first discuss the high-level overview, before jumping into the code.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Since we need to render the HTML before sending it to the bot, we need a server.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We will define a middleware, it intercepts the request made to the web app.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We will use the user agent to check if the request was made by a bot or a user.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If the request was made by a user, we send the client-side rendered app.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;But if the request was made by a bot, we generate the HTML content (with something like &lt;strong&gt;puppeteer&lt;/strong&gt;) and then send the rendered HTML to the bot&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now that we are done with the high-level overview, let's jump into the implementation&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting up server
&lt;/h3&gt;

&lt;p&gt;For setting up the server, I will be using the Gin framework.&lt;/p&gt;

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

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&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;gin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Default&lt;/span&gt;&lt;span class="p"&gt;()&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;Use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;our_middleware&lt;/span&gt;&lt;span class="p"&gt;)&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;Static&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="s"&gt;"./frontend/dist"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&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;Run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;":3000"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&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;This starts our server at port 3000. Our CSR frontend files are present in the folder &lt;code&gt;frontend/dist&lt;/code&gt;. Now when someone sends a request for a page, we serve HTML, CSS, and JS from this folder.&lt;/p&gt;

&lt;p&gt;Now we need middleware to intercept the traffic. So let's implement it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding a middleware
&lt;/h3&gt;

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

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;dynamicRenderer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="n"&gt;gin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandlerFunc&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;gin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;// Check if request is from a bot&lt;/span&gt;
        &lt;span class="n"&gt;isBot&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;checkforBot&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;isBot&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="c"&gt;// render page and send the rendered page&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c"&gt;// If not a bot, continue to serve as usual&lt;/span&gt;
        &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Next&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&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;gin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Default&lt;/span&gt;&lt;span class="p"&gt;()&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;Use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dynamicRenderer&lt;/span&gt;&lt;span class="p"&gt;())&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;Static&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="s"&gt;"./frontend/dist"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&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;Run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;":3000"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&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;Now that the middleware is set up, let's write the code for rendering the HTML file. But before that, we need to run our front end on some other port. Because the puppeteer scrapes data from the website. So let's write code to start the frontend&lt;/p&gt;

&lt;h3&gt;
  
  
  Serving the actual front end from another port
&lt;/h3&gt;

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

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// code&lt;/span&gt;

    &lt;span class="n"&gt;cmd&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;exec&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Command&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;"to"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;"serve"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;"your"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;"frontend"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Dir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"./frontend"&lt;/span&gt;
    &lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Stderr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Stderr&lt;/span&gt;

    &lt;span class="n"&gt;wait_for_files_to_be_served&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&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;Run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;":3000"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&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;
  
  
  Writing the code for the renderer
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;dynamicRenderer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="n"&gt;gin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandlerFunc&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;gin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;isBot&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;checkForBot&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;isBot&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c"&gt;// Connect to Puppeteer&lt;/span&gt;
            &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cancel&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;chromedp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Background&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
          &lt;span class="c"&gt;// We cancel the connection once the response is sent&lt;/span&gt;
            &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;cancel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

            &lt;span class="c"&gt;// Navigate to the page and wait for it to load&lt;/span&gt;
            &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;"http://localhost:"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;reactPort&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;URL&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Path&lt;/span&gt;
            &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;html&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;

          &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;chromedp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;chromedp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Navigate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="n"&gt;chromedp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;InnerHTML&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"html"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;chromedp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NodeVisible&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;chromedp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ByQuery&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AbortWithStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusInternalServerError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;

            &lt;span class="c"&gt;// Send back the rendered HTML&lt;/span&gt;
            &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusOK&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"text/html; charset=utf-8"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
          &lt;span class="c"&gt;// We are done serving&lt;/span&gt;
            &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AbortWithStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusOK&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c"&gt;// If not a bot, continue to serve the React app as usual&lt;/span&gt;
        &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Next&lt;/span&gt;&lt;span class="p"&gt;()&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;Here's a short explanation of what happening:-&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Once we know it's a bot, we connect to the puppeteer.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We then navigate to the URL, using &lt;code&gt;chromedp.Navigate(url)&lt;/code&gt; .&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We wait for all the children of the HTML tag to load by using &lt;code&gt;chromedp.NodeVisible&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Once the javascript has generated all the HTML content we store it in &lt;code&gt;html&lt;/code&gt; variable and send it to the bot.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Well, that's the entire implementation !! (sort of). I have left some boring parts out, but if you want you can check this &lt;a href="https://github.com/Avash027/dynamic-rendering-go" rel="noopener noreferrer"&gt;&lt;strong&gt;repository&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Now, let's look at the result
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Our webpage looks like this&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1678199585818%2F8bfc3ecb-cda8-42c5-aad9-81ee55f21c7a.png%2520align%3D" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1678199585818%2F8bfc3ecb-cda8-42c5-aad9-81ee55f21c7a.png%2520align%3D"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;When the user is requesting for a file, we get&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1678199472768%2F0acce655-0561-48e3-a6e1-11bca335d9cd.png%2520align%3D" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1678199472768%2F0acce655-0561-48e3-a6e1-11bca335d9cd.png%2520align%3D"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;But when a bot requests a file, we get&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1678199517497%2F350e558a-888b-47e5-a936-a618b96266ed.png%2520align%3D" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1678199517497%2F350e558a-888b-47e5-a936-a618b96266ed.png%2520align%3D"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Notice that the HTML is all rendered.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; When we send a rendered page there is not JS. So it won't function. But for a bot that is not an issuse because it does not use JS in any way&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Well that's all. Thanks for reading. If you have any doubt, you can post it it comment. I'll try my best to clear your doubts&lt;/p&gt;

</description>
      <category>go</category>
      <category>webdev</category>
      <category>react</category>
    </item>
    <item>
      <title>Mastering Factory Design Patterns through the Construction of a Banking System</title>
      <dc:creator>Avash_Mitra</dc:creator>
      <pubDate>Tue, 31 Jan 2023 01:39:35 +0000</pubDate>
      <link>https://dev.to/avash027/mastering-factory-design-patterns-through-the-construction-of-a-banking-system-4i34</link>
      <guid>https://dev.to/avash027/mastering-factory-design-patterns-through-the-construction-of-a-banking-system-4i34</guid>
      <description>&lt;p&gt;First of all, let's define the&lt;/p&gt;

&lt;h3&gt;
  
  
  Requirements of our problem
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;There can be multiple banks&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;All banks &lt;strong&gt;share some common attributes and behavior&lt;/strong&gt; like&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Behavior - &lt;code&gt;showBalance()&lt;/code&gt; , &lt;code&gt;withdraw()&lt;/code&gt; , &lt;code&gt;addBalance()&lt;/code&gt; etc&lt;/li&gt;
&lt;li&gt;Attributes - &lt;code&gt;amount_left&lt;/code&gt; , &lt;code&gt;num_of_users&lt;/code&gt; etc.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Banks can also implement their unique methods and attributes&lt;/p&gt;&lt;/li&gt;

&lt;/ul&gt;

&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Provide a simple interface to the user for creating &lt;code&gt;bank&lt;/code&gt; objects of their choice (i.e., users should now be responsible for)&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;strong&gt;Our solution should follow S.O.L.I.D. Principle&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  Having Multiple Banks
&lt;/h3&gt;

&lt;p&gt;Let's start by defining two banks classes - &lt;code&gt;A1&lt;/code&gt; and &lt;code&gt;A2&lt;/code&gt;&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="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;A1&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;private:&lt;/span&gt;
        &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;amount_left&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;num_of_users&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// .. other params&lt;/span&gt;
    &lt;span class="nl"&gt;public:&lt;/span&gt;
        &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;NumOfUsers&lt;/span&gt;&lt;span class="p"&gt;(){...}&lt;/span&gt; 
        &lt;span class="c1"&gt;// Other attributes&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;A2&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;private:&lt;/span&gt;
        &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;amount_left&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;num_of_users&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// .. other params&lt;/span&gt;
    &lt;span class="nl"&gt;public:&lt;/span&gt;
        &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;NumOfUsers&lt;/span&gt;&lt;span class="p"&gt;(){...}&lt;/span&gt; 
        &lt;span class="c1"&gt;// other attributes&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice something wrong.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;First of all, there is a ton of code duplication&lt;/strong&gt;. Since there are a lot of common attributes and methods we will be writing, the same code again and again.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Secondly,&lt;/strong&gt; there is no guarantee that all classes will define the common attributes and methods.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To solve these issues, we can define a &lt;strong&gt;common interface.&lt;/strong&gt; This &lt;strong&gt;common interface&lt;/strong&gt; will have all common attributes and methods. All other classes that &lt;strong&gt;implement&lt;/strong&gt; this &lt;strong&gt;common interface&lt;/strong&gt; will have to define the methods.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;It solves the code duplication part, as we don't need to redefine the attributes and methods in the subclasses. (&lt;strong&gt;classes that implement the interface&lt;/strong&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Any class that implements the common interface needs to define the methods.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's have a look at the code now.&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="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Bank&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;protected:&lt;/span&gt;
        &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;amount_left&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;num_of_users&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// .. other common attributes&lt;/span&gt;
    &lt;span class="nl"&gt;public:&lt;/span&gt;
        &lt;span class="k"&gt;virtual&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;NumOfUsers&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt; &lt;span class="c1"&gt;// Subclass can redefine this&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;num_of_users&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; 
        &lt;span class="k"&gt;virtual&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;getBalance&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;const&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;//Subclass have to redefine this&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;A1&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Bank&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;private:&lt;/span&gt;
        &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;special_params&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;public:&lt;/span&gt;
       &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;getBalance&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt;&lt;span class="p"&gt;{...}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;A2&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Bank&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;private:&lt;/span&gt;
        &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;special_params&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;public:&lt;/span&gt;
       &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;getBalance&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="k"&gt;override&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;Okay, now that this is taken care of, let's focus on the second requirement.&lt;/p&gt;

&lt;h3&gt;
  
  
  Provide a simple interface to the user for creating &lt;code&gt;a bank&lt;/code&gt; objects of their choice
&lt;/h3&gt;

&lt;p&gt;In our existing code, if a user wants to create a bank object then&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;void&lt;/span&gt; &lt;span class="nf"&gt;client&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
    &lt;span class="n"&gt;A1&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;a1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;A1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;cout&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;a1&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;getBalance&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;Well, this doesn't look that bad, but we are exposing too much of our backend logic to the client. Ideally, the client shouldn't know about every subclass. We should be providing a centralized code for bank selection. Let's define a new class for this.&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="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BankCreator&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Bank&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;getBankInstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="n"&gt;bankName&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="k"&gt;switch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bankName&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
            &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s"&gt;"a1"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;A1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s"&gt;"a2"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;A2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="nl"&gt;default:&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;client&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
    &lt;span class="n"&gt;BankCreator&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;backCreator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;BankCreator&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;Bank&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;a1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;backCreator&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;getBankInstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"a1"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;Bank&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;a2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;backCreator&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;getBankInstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"a2"&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;blockquote&gt;
&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; All the objects created by the &lt;code&gt;BankCreator&lt;/code&gt; class should have a common superclass.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now, this looks great. But do you notice something wrong with our code?&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;BankCreator&lt;/code&gt; class violates the &lt;strong&gt;Open For Extension and Closed for Modification Principle.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When we are adding a new bank (subclass) we need to modify the &lt;code&gt;BankCreator&lt;/code&gt; class (add another case to the switch statement).&lt;/p&gt;

&lt;p&gt;So, we need to define the creator class in such a way that whenever we add/remove a bank subclass, we do so without modifying the creator class. To do this&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We first make the creator a class an interface&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;*&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="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BankCreator&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nl"&gt;protected:&lt;/span&gt;
              &lt;span class="k"&gt;virtual&lt;/span&gt; &lt;span class="n"&gt;Bank&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;getBankInstance&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;const&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="p"&gt;};&lt;/span&gt;
    &lt;span class="err"&gt;```&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;endraw&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;Now&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;add&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;raw&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="n"&gt;bank&lt;/span&gt;&lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;endraw&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;we&lt;/span&gt; &lt;span class="n"&gt;simply&lt;/span&gt; &lt;span class="n"&gt;implement&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt; &lt;span class="n"&gt;interface&lt;/span&gt;

&lt;span class="o"&gt;*&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;raw&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
 &lt;span class="err"&gt;```&lt;/span&gt;&lt;span class="n"&gt;cpp&lt;/span&gt;
      &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;A1Creator&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;BankCreator&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="n"&gt;Bank&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;getBankInstance&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;A1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;};&lt;/span&gt;

      &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;A2Creator&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;BankCreator&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="n"&gt;Bank&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;getBankInstance&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;A2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="err"&gt;```&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;endraw&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;


    &lt;span class="n"&gt;Since&lt;/span&gt; &lt;span class="n"&gt;we&lt;/span&gt; &lt;span class="n"&gt;can&lt;/span&gt; &lt;span class="n"&gt;add&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;bank&lt;/span&gt; &lt;span class="n"&gt;subclasses&lt;/span&gt; &lt;span class="n"&gt;without&lt;/span&gt; &lt;span class="n"&gt;modifying&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;creator&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;we&lt;/span&gt; &lt;span class="n"&gt;can&lt;/span&gt; &lt;span class="n"&gt;say&lt;/span&gt; &lt;span class="n"&gt;that&lt;/span&gt; &lt;span class="n"&gt;we&lt;/span&gt; &lt;span class="n"&gt;are&lt;/span&gt; &lt;span class="n"&gt;following&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="o"&gt;**&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;mark&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;Open&lt;/span&gt; &lt;span class="n"&gt;For&lt;/span&gt; &lt;span class="n"&gt;Extension&lt;/span&gt; &lt;span class="n"&gt;and&lt;/span&gt; &lt;span class="n"&gt;Closed&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;Modification&lt;/span&gt; &lt;span class="n"&gt;Principle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;mark&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;**&lt;/span&gt;


&lt;span class="n"&gt;Now&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="n"&gt;can&lt;/span&gt; &lt;span class="n"&gt;create&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;bank&lt;/span&gt; &lt;span class="n"&gt;object&lt;/span&gt; &lt;span class="n"&gt;in&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;following&lt;/span&gt; &lt;span class="n"&gt;way&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;raw&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="err"&gt;```&lt;/span&gt;&lt;span class="n"&gt;cpp&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;client&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
    &lt;span class="n"&gt;A1Creator&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;a1creator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;A1Creator&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;A1&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;a1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a1creator&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;getBankInstance&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;A1&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;a11&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a1creator&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;getBankInstance&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;blockquote&gt;
&lt;p&gt;Also, it might look like we are exposing too much of our backend logic, but that's not the case. The client is not concerned about the implementation of the concrete subclasses (&lt;code&gt;bank subclasses&lt;/code&gt;) but is only aware of creator classes.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Before moving forward, here's the entire&lt;/p&gt;

&lt;h3&gt;
  
  
  Pseudo code for Factory Design Pattern
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="c1"&gt;//This is an Abstract class. But you can also make it an interface &lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Bank&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;protected:&lt;/span&gt;
        &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;amount_left&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;num_of_users&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// .. other common attributes&lt;/span&gt;
    &lt;span class="nl"&gt;public:&lt;/span&gt;
        &lt;span class="k"&gt;virtual&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;NumOfUsers&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt; &lt;span class="c1"&gt;// Subclass can redefine this&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;num_of_users&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; 
        &lt;span class="k"&gt;virtual&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;getBalance&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;const&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;//Subclass have to redefine this&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;A1&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Bank&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;private:&lt;/span&gt;
        &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;special_params&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;public:&lt;/span&gt;
       &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;getBalance&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt;&lt;span class="p"&gt;{...}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;A2&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Bank&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;private:&lt;/span&gt;
        &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;special_params&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;public:&lt;/span&gt;
       &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;getBalance&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt;&lt;span class="p"&gt;{...}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BankCreator&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nl"&gt;protected:&lt;/span&gt;
          &lt;span class="k"&gt;virtual&lt;/span&gt; &lt;span class="n"&gt;Bank&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;getBankInstance&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;const&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="p"&gt;};&lt;/span&gt;

 &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;A1Creator&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;BankCreator&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;Bank&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;getBankInstance&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;A1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;A2Creator&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;BankCreator&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;Bank&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;getBankInstance&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;A2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;client&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
    &lt;span class="n"&gt;A1Creator&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;a1creator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;A1Creator&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;A1&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;a1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a1creator&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;getBankInstance&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;A1&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;a11&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a1creator&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;getBankInstance&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;Now, let's discuss the pros and cons of this pattern&lt;/p&gt;

&lt;h2&gt;
  
  
  ✅ Pros
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;It follows the  Single Responsibility Principle.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;creator&lt;/code&gt; class and each &lt;code&gt;concrete creator&lt;/code&gt; subclass have only one responsibility. Tldr, there is a segregation of responsibility.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It follows the &lt;strong&gt;Open For Extension and Closed for Modification Principle.&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;There is &lt;strong&gt;loose coupling&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Instead of adding the logic to decide the type of object in the &lt;code&gt;creator&lt;/code&gt; class, we are assigning the responsibility to some other class&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  ❌ Cons
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Code can become &lt;strong&gt;too complex.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Since we are adding a lot of subclasses.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Cover image credit: &lt;a href="https://www.freepik.com/free-vector/factory-concept-illustration_12892954.htm#query=factory&amp;amp;position=0&amp;amp;from_view=keyword" rel="noopener noreferrer"&gt;Image by storyset&lt;/a&gt; on Freepik&lt;/p&gt;

</description>
      <category>perl</category>
      <category>software</category>
      <category>oop</category>
      <category>productivity</category>
    </item>
    <item>
      <title>How do databases recover from failure?</title>
      <dc:creator>Avash_Mitra</dc:creator>
      <pubDate>Sun, 29 Jan 2023 04:16:27 +0000</pubDate>
      <link>https://dev.to/avash027/how-do-databases-recover-from-failure-3aa7</link>
      <guid>https://dev.to/avash027/how-do-databases-recover-from-failure-3aa7</guid>
      <description>&lt;p&gt;In today's fast-paced and data-driven world, a reliable and robust database is essential for any business or organization. Unfortunately, database failures can occur due to a variety of reasons, such as hardware failures, software bugs, or human error. The impact of a database failure can be severe, causing lost revenue, customer dissatisfaction, and reputational damage. In this blog, we will discuss one of the most widely used recovery techniques called &lt;strong&gt;Log-Based Recovery.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blogs.avash.in/newsletter" rel="noopener noreferrer"&gt;Subscribe to my newsletter&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Well, first let's discuss what is&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Log-Based recovery?
&lt;/h2&gt;

&lt;p&gt;Log-based recovery is a technique used to ensure data consistency and integrity in the event of a database failure. By using a log of all the transactions that have occurred on the database, log-based recovery allows for a precise and efficient recovery process that can minimize the impact of a failure and get your database back up and running as quickly as possible.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Now, let's dive deeper&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;What are logs?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;To put it simply, logs are just a sequence of records, recording all activities. An update log has (generally) three fields&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Transaction Identifier&lt;/strong&gt;: Unique identifier of the transaction that performed the write operation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Data item identifier&lt;/strong&gt;: Unique identifier of the location of the disk where the new data item was written.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Old value&lt;/strong&gt;: Value of the data item before the update.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;New value&lt;/strong&gt;: Value of the updated data item.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Recovery after system crashes&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;A transaction is always atomic, which means the transaction is either executed completely or rollback. A transaction is never executed partially. So after the system is online our recovery mechanism must detect which transactions were completed and which weren’t. It must redo the ones that were completed and undo the incomplete ones.&lt;/p&gt;

&lt;p&gt;Before we jump into the process, here are some important bits of information&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Here, we are considering databases that use deferred modification. All the modifications are stored in memory and only flushed to the database once the transactions are committed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;[T(i), start]&lt;/strong&gt; indicates the start of the transaction&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;[T(i), end]&lt;/strong&gt; indicates the end of the transaction&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Format for each update/write statement in the transaction will be &lt;strong&gt;[T(i), X(j), old_val, new_val]&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Phase 1: Redo Phase&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;We will go through the logs in the order in which they were carried out.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;When we encounter a &lt;strong&gt;[T(i), start]&lt;/strong&gt;, we add &lt;strong&gt;T(i)&lt;/strong&gt; to undo list. (Keep this one in mind.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When we encounter a log &lt;strong&gt;[T(i), X(j), old_val, new_val]&lt;/strong&gt; we write new_val to X(j).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When we encounter a log &lt;strong&gt;[T(i), end]&lt;/strong&gt; we remove T(i) from the undo list.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the transaction was completed, then all queries in it were redone. But in the process, we might have also redone queries from incomplete transactions. So how are we going to handle it? Well to handle that case we have a second phase.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Phase 2: Undo Phase&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;In this phase, we will go through the logs backward.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;When we encounter a log &lt;strong&gt;[T(i), X(j), old_val, new_val]&lt;/strong&gt;, we check our undo list. If T(i) is present in the list we write old_val to X(j) basically undoing the operation done by the redo phase.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When we encounter the log &lt;strong&gt;[T(i), start]&lt;/strong&gt;, we remove T(i) from the undo list and add &lt;strong&gt;[T(i), abort]&lt;/strong&gt; at the end of the log.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It is terminated after all action has been performed.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1674965233215%2F3f75b170-1aa8-4854-8a97-50e82b8975c9.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1674965233215%2F3f75b170-1aa8-4854-8a97-50e82b8975c9.webp" width="720" height="729"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Optimizing Recovery Process&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Did you notice any problem with this approach? Y*&lt;em&gt;es, every time there is a failure we have to perform the recovery algorithm on the entire log. But we can optimize this using Checkpoint.&lt;/em&gt;*&lt;/p&gt;

&lt;p&gt;To explain it simply, a checkpoint makes all the changes before it is permanent i.e., it writes all the updates to the disk and flushes all the data in the main memory to stable storage. It is also important to note that while the checkpoint is doing this no transactions are allowed to make write/update operations. So now instead of performing our recovery algorithm on the entire logs, we will start it from the latest checkpoint. A checkpoint is in the format [Checkpoint, L] where L represents Logs before the checkpoint.&lt;/p&gt;

&lt;p&gt;But you might be thinking why do we need the L? Well, consider a case, where a transaction starts before Checkpoint but then aborts after the checkpoint. In that case, we need to roll back that transaction. The rest of the transactions that were committed can be erased to reduce occupied space.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;What if we lose logs during a system crash, then we cannot redo or undo operations?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Well, this is where the concept of stable storage comes into play. How it works is beyond the scope of this article but in short, it replicates data in regular intervals to different non-volatile storage with independent failure recovery modes.&lt;/p&gt;




&lt;p&gt;Credits for cover image: &lt;a href="https://www.freepik.com/free-vector/tiny-people-examining-operating-system-error-warning-web-page-isolated-flat-illustration_11235921.htm#query=system%20failure&amp;amp;position=0&amp;amp;from_view=search&amp;amp;track=sph" rel="noopener noreferrer"&gt;Image by pch. vector&lt;/a&gt; on Freepik&lt;/p&gt;

</description>
      <category>smartcontract</category>
      <category>web3</category>
      <category>blockchain</category>
      <category>crypto</category>
    </item>
    <item>
      <title>Preventing Goroutine Leaks: Best Practices and Tips for Go Developers</title>
      <dc:creator>Avash_Mitra</dc:creator>
      <pubDate>Fri, 27 Jan 2023 13:50:31 +0000</pubDate>
      <link>https://dev.to/avash027/preventing-goroutine-leaks-best-practices-and-tips-for-go-developers-2gd3</link>
      <guid>https://dev.to/avash027/preventing-goroutine-leaks-best-practices-and-tips-for-go-developers-2gd3</guid>
      <description>&lt;p&gt;This is the first blog in the series of Concurrency Design Patterns in Golang. I'll be adding more blogs with many complicated design patterns. If you want to be notified do subscribe to my &lt;a href="https://blogs.avash.in/newsletter" rel="noopener noreferrer"&gt;Newsletter&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Before starting with the design pattern, here are some prerequisites.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It would be best if you were comfortable with Golang's syntax.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's brush up on a few concepts before discussing the design pattern. (If you know all of these feel free to skip to the design pattern)&lt;/p&gt;

&lt;h2&gt;
  
  
  Goroutines
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;To put it simply, a goroutine is a part of code that run concurrently alongside other code. We won't go into much theory (we can leave that for some other blog).&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;To declare a goroutine you just have to use the go prefix while invoking a function.&lt;/p&gt;

&lt;p&gt;Here's a simple example:&lt;/p&gt;

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

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;

&lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;" "&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}()&lt;/span&gt;

&lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;" "&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&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;The output of this code snippet will be something like this:&lt;/p&gt;

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

&lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;6&lt;/span&gt; &lt;span class="m"&gt;7&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt; &lt;span class="m"&gt;8&lt;/span&gt; &lt;span class="m"&gt;9&lt;/span&gt; &lt;span class="m"&gt;4&lt;/span&gt;
&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="n"&gt;It&lt;/span&gt; &lt;span class="n"&gt;does&lt;/span&gt; &lt;span class="n"&gt;not&lt;/span&gt; &lt;span class="n"&gt;have&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;be&lt;/span&gt; &lt;span class="n"&gt;exactly&lt;/span&gt; &lt;span class="n"&gt;same&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Channels&lt;/p&gt;

&lt;p&gt;Channels are one of the most essential building blocks of our concurrency design patterns. To put it very simply&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Channels are just queues that can be used to send data from one goroutine to another.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Here are a few important facts about channels:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Channels can be either &lt;strong&gt;buffered&lt;/strong&gt; (can hold one or more values) or &lt;strong&gt;unbuffered&lt;/strong&gt; (cannot hold any values)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Channels are blocking.&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;If you are pushing an object to a filled channel then the program won't proceed further until another object is popped from the channel&lt;/li&gt;
&lt;li&gt;If you are popping the element from an empty channel then the program won't proceed further until an object is pushed to the channel.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

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

&lt;span class="c"&gt;// This is a read channel. You can only read values&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;readChannel&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="k"&gt;chan&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt; 

&lt;span class="c"&gt;// This is a write channel. You can only write values to this channel&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;writeChannel&lt;/span&gt; &lt;span class="k"&gt;chan&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="c"&gt;//You can read as well as write to this channel&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;channel&lt;/span&gt; &lt;span class="k"&gt;chan&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="n"&gt;channel1&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="c"&gt;// we are pushing a value to a channel&lt;/span&gt;
&lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;channel2&lt;/span&gt; &lt;span class="c"&gt;// we are reading from a channel&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Now let's jump to the fun part&lt;/p&gt;

&lt;h3&gt;
  
  
  What is a goroutine leak?
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;We use a goroutine to perform some operations, and after some time send us the result and terminate. But what happens if it doesn't terminate? well, this is what we call a goroutine leak.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Even though goroutines are lightweight, if we invoke a lot of goroutines then we will be wasting a lot of resources.&lt;/p&gt;

&lt;p&gt;Before we discuss, how we are gonna prevent goroutine leaks, let's check out an example:&lt;/p&gt;

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

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;test&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="k"&gt;chan&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;outStream&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;chan&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;outStream&lt;/span&gt; &lt;span class="k"&gt;chan&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;outStream&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}(&lt;/span&gt;&lt;span class="n"&gt;outStream&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;outStream&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;inStream&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;test&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="n"&gt;inStream&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Second&lt;/span&gt;&lt;span class="p"&gt;)&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;Here we have a &lt;em&gt;test&lt;/em&gt; function that returns a read channel (we can only read values from this channel). It then invokes a goroutine and passes the channel as a write channel (we can only write to this channel). We are running a for loop and writing values to the channel. But here's the interesting part, &lt;strong&gt;the for loop is infinite!!. We have done this to mimic the case where our goroutine does not terminate and keeps sending value.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When we run the code, we get the following output:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fir9emzjeftmadam1v92w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fir9emzjeftmadam1v92w.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We stopped the loop after 10 iterations but it can go on forever.&lt;/p&gt;

&lt;h3&gt;
  
  
  We stopped the loop after 10 iterations but it can go on forever.
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;To stop the goroutine from executing forever, the parent needs to send it some signal. &lt;strong&gt;By parent, we mean the function that invoked the goroutine.&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When the child receives the signal, it stops its operation. Since goroutines can only communicate via channels, the parent will send a channel to its child goroutine.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Once the parent wants to terminate the child it simply closes the channel. This signal is received by the child and it also terminates its action.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's look at the code implementation to understand it better&lt;/p&gt;

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

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;terminate&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="k"&gt;chan&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="k"&gt;chan&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;outStream&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;chan&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;terminate&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="k"&gt;chan&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;outStream&lt;/span&gt; &lt;span class="k"&gt;chan&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="nb"&gt;close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;outStream&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// Channel is closed when the function is finishes executing&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="n"&gt;terminate&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Child Terminating"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt;
            &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;outStream&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}(&lt;/span&gt;&lt;span class="n"&gt;terminate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;outStream&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;outStream&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;terminate&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;chan&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;inStream&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;terminate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ok&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="n"&gt;inStream&lt;/span&gt;

       &lt;span class="c"&gt;// If !ok, then it means channel is closed and we won't receive new value&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;ok&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Channel closed"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Second&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nb"&gt;close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;terminate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&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;Okay, let's discuss how this code works&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;We make a new channel called &lt;strong&gt;'terminate'&lt;/strong&gt;, and pass it as a read-only channel to the child.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Inside the infinite for-loop, we use a select statement. (A select statement is like a switch statement, it executes blocks of codes when their corresponding &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Now, when the channel is closed by the parent, a closing signal is sent to the child. It then executes its corresponding code block i.e., &lt;strong&gt;a return statement. which breaks the infinite loop.&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Now the goroutine terminates, and closes the 'outstream' channel and thus terminating the child.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now if we execute the code, it looks something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl4t5r21099eu1rf1kp84.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl4t5r21099eu1rf1kp84.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thanks for reading till the end. If you liked my blog then do subscribe to my &lt;a href="https://blogs.avash.in/newsletter" rel="noopener noreferrer"&gt;newsletter&lt;/a&gt; for more awesome content.&lt;/p&gt;

&lt;p&gt;Cover picture credit: &lt;a href="https://www.storj.io/blog/finding-goroutine-leaks-in-tests" rel="noopener noreferrer"&gt;https://www.storj.io/blog/finding-goroutine-leaks-in-tests&lt;/a&gt;&lt;/p&gt;

</description>
      <category>go</category>
      <category>designpatterns</category>
      <category>concurrency</category>
    </item>
    <item>
      <title>Designing a Robust Web Crawler: From Requirements to Implementation</title>
      <dc:creator>Avash_Mitra</dc:creator>
      <pubDate>Tue, 27 Dec 2022 16:37:19 +0000</pubDate>
      <link>https://dev.to/avash027/designing-a-robust-web-crawler-from-requirements-to-implementation-3mod</link>
      <guid>https://dev.to/avash027/designing-a-robust-web-crawler-from-requirements-to-implementation-3mod</guid>
      <description>&lt;p&gt;Have you ever wondered how a search engine knows about the contents of a web page? How does it know when the contents of the page are updated? Well, the simple answer is web crawlers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;But what is a web crawler?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;A web crawler is a bot that downloads and indexes contents from all over the internet. The goal of such bot is to learn what every page on the web is about, so the information can be retrieved when needed. - Cloudflare&lt;/em&gt;&lt;/p&gt;



&lt;h3&gt;
  
  
  We need to overcome a few obstacles while designing our web crawler
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;There are billions of web pages so are system should be** efficient in terms of memory and CPU usage**&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It should be &lt;strong&gt;scalable&lt;/strong&gt; (Especially horizontally scalable). Because as the web grows we can add more machines to compensate for that.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It should be fast. Our system should be able to process hundreds (or even thousands) of web pages in one second.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Web servers have implicit and explicit policies regulating the rate at which a crawler can visit them. These &lt;strong&gt;politeness policies must be respected.&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It should crawl high-quality web pages frequently. The priority of a page should be a function of both its change rate and its quality&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;



&lt;h3&gt;
  
  
  Let's list down the steps required while crawling websites and build components for each step
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.leetcode.com%2Fusers%2Fimages%2F9cf0e80c-4689-45c1-b64e-7ae4046f6cc2_1671981374.0457256.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.leetcode.com%2Fusers%2Fimages%2F9cf0e80c-4689-45c1-b64e-7ae4046f6cc2_1671981374.0457256.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Get the URL to be crawled from the queue (It's called an URL frontier but we will get to that later)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use DNS resolution to find the IP Address of the web page&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fetch the HTML content from the web page&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If the content is already seen then discard the page&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Parse the content and get all the anchor tags on the page. These anchor tags contain the next set of URLs. If the URLs are not seen then these URLs are added to the URL frontier. &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Designing the URL Frontier
&lt;/h3&gt;

&lt;p&gt;Before discussing the design of URL frontier, let's discuss why don't we use a standard queue. Well, a standard queue is FIFO. In the case of crawling, it is unacceptable because the in a page most URLs point to other pages hosted on the same server.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This can cause two types of problems&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;If we send the requests serially, We will be sending a burst of requests to the same server i.e., we will be spamming the server&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If we send requests in parallel, the head of the queue would return an URL whose server has no outstanding requests.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note: This implementation of URL frontier is based on the implementation in the Mercator web crawler&lt;/p&gt;

&lt;p&gt;Components of URL frontiers are :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Front queues&lt;/strong&gt; - This set of queues implement prioritization. Each queue has a priority label. The higher the priority, the sooner the URL popped from the queue.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Back queues&lt;/strong&gt; - This set of queues implement politeness. Each queue contains URLs from only one host.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Min - Heap&lt;/strong&gt; - There is one entry for each back queue. Each entry contains the server/host address and the earliest time when the request can be made (let's say t).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Caller threads&lt;/strong&gt; - When we extract an URL from the back queue this thread group fetches the URLs and assigns URLs to the back queues.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;How URL Frontier works:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The caller thread pops the top of the heap and waits for t seconds.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It gets the URL from the back queue and makes a fetch request.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If the back queue is not empty, it repeats the process.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If the back queue is empty (let's call this queue x), it picks one of the front queues (usually biased towards higher priority queues) and picks a URL from there.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Keep in mind, each back queue holds URLs belonging to the same host. So it checks if the URL's host is there in any back queue then the URL is pushed to that back queue.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If no queue is found it is pushed into back queue x and a new entry is added to the heap.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Well, if this feels overwhelming, don't worry. Here's the flow chart that summarizes all of it properly.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.leetcode.com%2Fusers%2Fimages%2F56c3c8c2-b585-4b51-a3df-36dbb88d2394_1671980878.9980042.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.leetcode.com%2Fusers%2Fimages%2F56c3c8c2-b585-4b51-a3df-36dbb88d2394_1671980878.9980042.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Diagram of URL Frontier&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.leetcode.com%2Fusers%2Fimages%2Fdc5b572d-de0f-4eb4-b520-89be7d0300e8_1671980933.3735294.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.leetcode.com%2Fusers%2Fimages%2Fdc5b572d-de0f-4eb4-b520-89be7d0300e8_1671980933.3735294.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;h3&gt;
  
  
  Overcoming the bottleneck of DNS Resolution
&lt;/h3&gt;

&lt;p&gt;DNS Resolution is the process of finding the IP Address of a web page from its URL. In this process, we make requests to Domain Name Service and get the IP Address in response. We won't go into the details of how DNS resolution works but it can take multiple requests before we get the IP Address, so it can take a few seconds per request. This is unacceptable since we need to index hundreds of pages per second.&lt;/p&gt;

&lt;p&gt;We can solve this bottleneck by&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Caching the IP Addresses&lt;/strong&gt; - We can use cache to store the key-value pair of hostname and IP address.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Fetching the IP Addresses asynchronously&lt;/strong&gt; - When we are performing synchronous lookups the crawler thread is blocked until we get the IP Address, to prevent this we can use multi-threading for performing DNS lookups in parallel.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We have separate worker threads that send requests to the DNS servers. Then it sleeps for a specified amount of time and only wakes up when the time quantum expires or another thread wakes it up&lt;/li&gt;
&lt;li&gt;Another single separate thread is listening to the standard DNS port. Upon receiving the response send it to the appropriate thread (one of the worker threads).&lt;/li&gt;
&lt;li&gt;If the thread does not receive the IP Address in a specified amount of time it makes a retry. There is a limit to the number of requests. If the lookup fails and the maximum number of retries is reached then it is aborted.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.leetcode.com%2Fusers%2Fimages%2F269bde70-8055-41b3-84df-d8b9532149d8_1671981113.6925728.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.leetcode.com%2Fusers%2Fimages%2F269bde70-8055-41b3-84df-d8b9532149d8_1671981113.6925728.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Fetching content from the web page
&lt;/h3&gt;

&lt;p&gt;We will be fetching the webpage corresponding to a given URL using the appropriate network protocol. There can be multiple protocols like HTTP, FTP, etc.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Each fetch module will have multiple worker threads to make sure that there is no blocking.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;To prevent the crawler from sending bursts of requests to the same host, we assign each host to one particular thread. We can achieve this by hashing the hostname and then assigning it to the thread.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;For example, if there are threads from 0 to N, then we can use the hash function h(host_name)%N. The result is the thread number.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Also, we must specify the maximum number of retries while fetching the content. If the number of tries exceeds it we will abort the process.&lt;/p&gt;&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.leetcode.com%2Fusers%2Fimages%2F209d647c-0ca8-4d99-b76e-4175bb7a520e_1671981196.5869918.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.leetcode.com%2Fusers%2Fimages%2F209d647c-0ca8-4d99-b76e-4175bb7a520e_1671981196.5869918.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Designing the 'Content Seen' Module
&lt;/h3&gt;

&lt;p&gt;If we use the naive approach, we store the entire content of a web page (either in cache or in secondary memory), and then whenever we get a new web page we compare it with the previous one.&lt;/p&gt;

&lt;p&gt;This approach is simple, but it consumes a lot of time and memory. So, we won't be using this.&lt;/p&gt;

&lt;p&gt;Instead, we use a structure called the document fingerprint set that stores a 64-bit checksum of the contents of each web page. Fingerprints offer provably strong probabilistic guarantees that two different strings will not have the same fingerprint.&lt;/p&gt;

&lt;p&gt;It also consumes less memory and time.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The implementation of content seen module in Mercator uses Broder's implementation of Rabin's fingerprinting algorithm.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Like all other modules, we will have multiple worker threads to process web pages in parallel.&lt;/p&gt;



&lt;h3&gt;
  
  
  Designing the 'URL Seen' Test
&lt;/h3&gt;

&lt;p&gt;This one seems really similar to the 'content seen' test. We can calculate the fingerprint for each URL and compare it with the rest.&lt;/p&gt;

&lt;p&gt;While this approach works, it is far more efficient to hash the URL and store it for comparison. But there can be false positives if we just use the hash function so we use a data structure called Bloom Filters.&lt;/p&gt;

&lt;p&gt;We won't go into much detail about the working of bloom filters, but here's a short explanation&lt;/p&gt;

&lt;p&gt;&lt;em&gt;It uses a large bit vector (only contains 0s and 1s). An element is added to the set by computing n hash functions of the element and setting the corresponding bits. An element is deemed to be in the set if the bits at all n of the element's hash locations are set.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;By using a bloom filter&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We make sure that a fixed amount of memory is used.&lt;/li&gt;
&lt;li&gt;There are no false negatives and the probability of false positives is very less.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the URL is not seen we add it to the URL Frontier and repeat the process.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Now that we are done, let's look at how our final architecture of web crawler looks&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.leetcode.com%2Fusers%2Fimages%2Faf54e9fa-0cc8-47fc-b9c2-eaaee8652e28_1671981423.7491693.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.leetcode.com%2Fusers%2Fimages%2Faf54e9fa-0cc8-47fc-b9c2-eaaee8652e28_1671981423.7491693.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>system</category>
      <category>architecture</category>
    </item>
  </channel>
</rss>
