<?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: Dhaval Singh</title>
    <description>The latest articles on DEV Community by Dhaval Singh (@dhavalsingh).</description>
    <link>https://dev.to/dhavalsingh</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%2F704262%2F19ef9f51-e722-4d65-8810-20c15004b7dd.jpeg</url>
      <title>DEV Community: Dhaval Singh</title>
      <link>https://dev.to/dhavalsingh</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dhavalsingh"/>
    <language>en</language>
    <item>
      <title>How Truly Random are Random Numbers?</title>
      <dc:creator>Dhaval Singh</dc:creator>
      <pubDate>Sun, 07 Jan 2024 09:27:43 +0000</pubDate>
      <link>https://dev.to/dhavalsingh/how-truly-random-are-random-numbers-db7</link>
      <guid>https://dev.to/dhavalsingh/how-truly-random-are-random-numbers-db7</guid>
      <description>&lt;p&gt;We have all generated random numbers at one point or another, be it for calculations or HTTP cookies. If you haven’t manually generated one and you are working on a real-life project, there is a high chance somewhere it is being generated for you in "Sumdi" &lt;em&gt;('Sumdi' is a Marathi word which means to do your work quietly and not let anyone take notice).&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In this post, I want to dive into how these random numbers are generated, how random are they actually and what goes behind the scenes. It is really interesting and even though you won’t be "using" this knowledge irl, it will generate a lot of interesting conversations and deepen your understanding of the technology you interact with daily&lt;/p&gt;

&lt;p&gt;Most of you might have heard of Cloudflare's Lava Lamps. It's probably the most famous way to generate "truly" random bytes. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--uu_48wUc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://blog.cloudflare.com/content/images/2017/11/lava-lamps-camera.jpg%2520align%3D%2522left%2522" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uu_48wUc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://blog.cloudflare.com/content/images/2017/11/lava-lamps-camera.jpg%2520align%3D%2522left%2522" alt="cf lava" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It is very well-documented how it works and why they use this, you can read about it &lt;a href="https://blog.cloudflare.com/randomness-101-lavarand-in-production"&gt;here&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;In this post, I want to explore how random numbers/bytes are generated in programming languages. I will use Ruby as an example, but pretty much all languages have a similar implementation.&lt;/p&gt;

&lt;h3&gt;
  
  
  class Random
&lt;/h3&gt;

&lt;p&gt;Okay, before we jump into what happens, it's important to understand the terminology and a few small things to understand and appreciate this subject better.&lt;/p&gt;

&lt;p&gt;Let's take the &lt;code&gt;class Random&lt;/code&gt; of Ruby and start from there, the introduction covers most of the terms necessary for us to jump-start this journey. Here is what the docs say, read it once, and I will break down the more uncommon terms that we require.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Qy-0s3gm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/jpebWFb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Qy-0s3gm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/jpebWFb.png" alt="random class" width="800" height="191"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  PRNG
&lt;/h4&gt;

&lt;p&gt;"PRNG" means "Pseudorandom Number Generator" which means that a sequence of numbers (bits, bytes...) is produced from an algorithm that looks random, but is in fact deterministic (the sequence is generated from some unknown internal state), hence pseudorandom.&lt;/p&gt;

&lt;p&gt;There is another term CSPRNG: Cryptographically Secure Pseudo-Random Number Generator. We will get into this later.&lt;/p&gt;

&lt;p&gt;In simple terms, all you need to understand is PRNG is not truly random, and here is where the right question comes in, &lt;strong&gt;if it's not truly random, then how random is it?&lt;/strong&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Mersenne Twister with a period of 2&lt;sup&gt;19937&lt;/sup&gt;-1
&lt;/h4&gt;

&lt;p&gt;A Mersenne prime is a prime number that can be written in the form of 2&lt;sup&gt;n&lt;/sup&gt; - 1, where n is an integer. Not all numbers of this form are prime, but when they are, they're called Mersenne primes.&lt;/p&gt;

&lt;p&gt;The Mersenne Twister is a type of pseudorandom number generator (PRNG). It's known for providing fast and high-quality random numbers. Its name comes from the fact that its period length is a Mersenne prime. The most common version of the Mersenne Twister, MT19937, has a period of  2&lt;sup&gt;19937&lt;/sup&gt;-1.&lt;/p&gt;

&lt;p&gt;The period of a PRNG is the length of the sequence of numbers it produces before it starts repeating. The Mersenne Twister with a period of  2&lt;sup&gt;19937&lt;/sup&gt;-1 means it can generate 2&lt;sup&gt;19937&lt;/sup&gt;-1 numbers before the sequence repeats, an extraordinarily large number.&lt;/p&gt;

&lt;p&gt;How &lt;a href="https://en.wikipedia.org/wiki/Mersenne_Twister"&gt;Mersenne Twister works&lt;/a&gt; is pretty complex and it's above my paygrade. Very interesting nonetheless. &lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---6Kb3g6w--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/oVwN8uB.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---6Kb3g6w--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/oVwN8uB.jpeg" alt="PRNG" width="800" height="446"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's move ahead with the part I want to talk more about!&lt;/p&gt;
&lt;h4&gt;
  
  
  SecureRandom
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;As this algorithm is not for cryptographical use, you must use SecureRandom for security purpose, instead of this PRNG.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Okay, this makes sense. For security purposes, we need numbers that are completely unpredictable and Ruby recommends we don't use this class instead use &lt;em&gt;SecureRandom&lt;/em&gt;. Let's see what that class definition says.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--m53o4ueC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/qV5yi1I.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--m53o4ueC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/qV5yi1I.png" alt="SR" width="800" height="318"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here I will focus on &lt;code&gt;/dev/urandom&lt;/code&gt; but all three offer more or less the same result.&lt;/p&gt;

&lt;p&gt;Okay, so what is &lt;em&gt;/dev/urandom ?&lt;/em&gt; How is it more "secure" than the complicated algorithm using large prime numbers?&lt;/p&gt;

&lt;p&gt;Now keep in mind we are going to use &lt;code&gt;SecureRandom&lt;/code&gt; for generating password tokens and whatnot, we need it to be &lt;em&gt;completely&lt;/em&gt; unpredictable! It has to be so unpredictable that even the folks with knowledge of its inner workings are not able to "guess" it. &lt;/p&gt;
&lt;h3&gt;
  
  
  Computers are very deterministic machines (even if they don’t feel like they are)
&lt;/h3&gt;

&lt;p&gt;Now if you think about it, computers are basically built to always sequentially execute the same set of instructions which we call 'code'. We want the same set of instructions to run in the same way across different computers.&lt;/p&gt;

&lt;p&gt;Duh! Seems obvious right?&lt;/p&gt;

&lt;p&gt;But here is where we get in trouble, when generating random stuff we want two different computers to do it completely differently. Otherwise, it's not random anymore!&lt;/p&gt;

&lt;p&gt;So we understand computers are not unpredictable by nature. So, how or where will they find this "randomness" that we require? &lt;/p&gt;

&lt;p&gt;Well, the answer is right there! In the real world, the messy physical world!&lt;/p&gt;
&lt;h3&gt;
  
  
  Unpredictable events
&lt;/h3&gt;

&lt;p&gt;Every time you type on your keyboard or move your mouse, the disk spins a bit to read some data, it happens in the best case just a little differently. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4jSt_-jW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://i.gifer.com/cSs.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4jSt_-jW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://i.gifer.com/cSs.gif" alt="cat typing" width="720" height="720"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now all these events are visible to the kernel. It's the kernel's job to manage these interactions so it keeps track of these events. For example, You move your mouse from (0,1) to (0,3.6). &lt;br&gt;
How wide this range(how spread apart the values are) is what we call &lt;em&gt;entropy&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;The more spread apart they are, the harder they are to predict. What they are not is uniform! You are going to move your cursor in a very non-uniform way and the same goes for other events.&lt;/p&gt;

&lt;p&gt;Now this is good. We have some unpredictability on our hands, but these are not enough to satisfy our random bytes needs. Enter a CSPRNG.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OEQ9pAiW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/I3KfHxE.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OEQ9pAiW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/I3KfHxE.png" alt="csprng" width="800" height="748"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A CSPRNG is a cryptographic tool that generates a stream of random bytes using all and only the input(our random events) you give to it.&lt;/p&gt;

&lt;p&gt;A very simple way to understand how this works is, that we start with a pool just with 0s. Now anytime an event happens &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OHRj_1Gn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/E9UIS91.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OHRj_1Gn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/E9UIS91.png" alt="pool 1" width="596" height="604"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;we convert it into binary&lt;/li&gt;
&lt;li&gt;Hash it with the pool&lt;/li&gt;
&lt;li&gt;Now we have an updated pool.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Rinse and repeat for all events!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GC3_G6FX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/B2LBjS8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GC3_G6FX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/B2LBjS8.png" alt="pool2" width="626" height="573"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We keep doing this and our entropy pool will keep changing. Now for anyone to figure out what my entropy pool is at any point in time, they will have to replicate each and every event of my system, right from mouse movements to hard disk reads in the exact same order with the exact same values! This is pretty much an impossible task!&lt;/p&gt;

&lt;p&gt;Now anytime you want say 1000 random bits, we take the entropy pool, hash with 0, 1, 2, 3... (basically a counter). We get some outputs, join them, and voila! We have 1000 bits as random and unpredictable as the pool itself! &lt;/p&gt;

&lt;p&gt;Now there are some basic properties of the hash function itself like&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;you cant get the input from the output&lt;/li&gt;
&lt;li&gt;all the bits in the input affect all the bits of the output
which ensures it is almost impossible to reverse-engineer this!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So back to our question, What is &lt;code&gt;/dev/urandom&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;It is exactly this! It's a CSPRNG in the (Linux) Kernel. It looks like a file, you read it like a file. Every time you read some bytes, it will run the CSPRNG and stir the contents of the file. Other OS's have something similar to &lt;code&gt;/dev/urandom&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;There is something called &lt;code&gt;/dev/random&lt;/code&gt; too. I'll leave it to you to find the difference and what it's use-case is.&lt;/p&gt;
&lt;h3&gt;
  
  
  Back to SecureRandom
&lt;/h3&gt;

&lt;p&gt;Now the Ruby implementation is pretty much what we talked about. It just reads the file and massages the output in the desired format. Something like...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def self.random_bytes(n=nil)
  File.open("/dev/urandom", File::RDONLY) do|f|
    f.readpartial(n)
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;The current implementation is in C, but you get the idea...&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;And that is why SecureRandom is considered secure. It still relies on a pseudorandom number generator as we would do in Ruby Land, but it has the benefit of using environmental noise, making it astronomically much more difficult to crack, and technically impossible without gathering the exact same environmental data.&lt;/p&gt;

&lt;p&gt;Footnote: There are cases where &lt;code&gt;/dev/urandom&lt;/code&gt; has been exploited during the boot sequence. At that time, the system may not have enough entropy available to provide safe random numbers. When the start sequence is being initiated, the system starts from a known state, always the same (particularly true for virtual images), and mostly the same also on any other identical environment. This is also a pretty interesting rabbit hole if you wish to visit it.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>To raise or not to raise?</title>
      <dc:creator>Dhaval Singh</dc:creator>
      <pubDate>Sun, 26 Nov 2023 18:04:12 +0000</pubDate>
      <link>https://dev.to/dhavalsingh/to-raise-or-not-to-raise-do</link>
      <guid>https://dev.to/dhavalsingh/to-raise-or-not-to-raise-do</guid>
      <description>&lt;p&gt;Did you know they have ashtrays in Airplane bathrooms even tho smoking is banned inside!? It turns out there is a good reason for them, and you’ll be glad they’re there.&lt;br&gt;
In case a passenger does illegally sneak a ciggy, planes must have a safe place to put out the butts. &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%2Fi.imgur.com%2F4yqWMfg.jpg" 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%2Fi.imgur.com%2F4yqWMfg.jpg" alt="ashtray"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This intriguing detail has significantly influenced my perspective on system design. Having that ashtray even though smoking is banned just shows how critical it is to ensure safety in Airplanes and I've always wanted the systems I build to be similar in this aspect. Resilient and Robust in the face of a bad input or an error. &lt;/p&gt;

&lt;p&gt;So I started reading about this stuff and boy is it confusing! Rightly so, because exception handling is pretty context-heavy. Right from what the business logic dictates to how "confidently" the code has been written, it can vary quite a bit. &lt;/p&gt;

&lt;p&gt;If you too are tired of seeing nested &lt;code&gt;being/rescue&lt;/code&gt; blocks or abused &lt;code&gt;nil&lt;/code&gt; checks in your codebase, this series is for you!&lt;/p&gt;

&lt;p&gt;So, in this and the following articles as I dive deeper(and implement them) we will be able to gain a much better understanding of how to deal with exceptions or the spaghetti code that surrounds it.&lt;/p&gt;

&lt;p&gt;Let's start with some first-principle thinking.&lt;/p&gt;
&lt;h3&gt;
  
  
  My code works as it is, why should I care?
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;In school you might have heard the expression, "Garbage in, garbage out." That expression is essentially software development's version of caveat emptor: let the user beware.&lt;br&gt;
For production software, garbage in, garbage out isn't good enough. A good program never puts out garbage, regardless of what it takes in. A good program uses "garbage in, nothing out," "garbage in, error message out," or "no garbage allowed in" instead. By today's standards, "garbage in, garbage out" is the mark of a sloppy, nonsecure program.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.amazon.com/Code-Complete-Practical-Handbook-Construction/dp/0735619670" rel="noopener noreferrer"&gt;code complete&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;From the above quote and airplane example, it's evident that handling rogue or incorrect inputs is crucial for system integrity. This is particularly vital in critical systems like banking or payments, where explicit error handling is essential. In less critical systems, logging and moving on may suffice. However, in all cases, mastering failure-handling techniques is key to ensuring our systems are both &lt;strong&gt;reliable&lt;/strong&gt; and &lt;strong&gt;robust&lt;/strong&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Understanding Failures in Programming
&lt;/h3&gt;

&lt;p&gt;Every element in a codebase serves a purpose – if it doesn't, it's probably safe to let it go. When something in that element doesn't do what it's supposed to, that's what we call a &lt;em&gt;failure&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;So how or when can a code element fail? Let's see a few common reasons&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Implementation issue
 h = {:age=&amp;gt; 23}; h["age"] += 1

# External issue
HTTP.get_response(URL).code # =&amp;gt; 500

# System/Hardware issue, eg: ran out of memory 
# NoMemoryError
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Okay, so failure can be caused by us or the hardware or due to someone else’s mistake, but it's our responsibility to handle this and ensure this doesn't break our system.&lt;/p&gt;

&lt;p&gt;Now we understand what is meant by failure, the question that arises is; &lt;br&gt;
"How does our program tell us there is a failure?"&lt;/p&gt;

&lt;p&gt;This question has always confused me since some terms are used interchangeably in software, ie: Exception and Error.&lt;/p&gt;
&lt;h3&gt;
  
  
  Exception vs Error
&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%2Fi.imgur.com%2FeQE5dGu.jpg" 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%2Fi.imgur.com%2FeQE5dGu.jpg" alt="redditmeme"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These terms are commonly used in software so often that it is not my cup of tea to be able to define them(without creating more confusion). So I will just quote sources that made it actually clear for me!&lt;/p&gt;

&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;A failure is the inability of a software element to satisfy its purpose.&lt;/li&gt;
&lt;li&gt;An exception is the occurrence of an abnormal condition during the execution of a software element.&lt;/li&gt;
&lt;li&gt;An error is the presence in the software of some element not satisfying its specification.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;from &lt;a href="https://www.amazon.in/Object-Oriented-Software-Construction-Prentice-hall-International/dp/0136291554" rel="noopener noreferrer"&gt;Object Oriented Software Construction&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;So the answer to the question, how does a program tell us something has failed?&lt;br&gt;
It does so by raising an &lt;strong&gt;Exception&lt;/strong&gt;.&lt;br&gt;
And one might say, these exceptions are caused due to errors.&lt;/p&gt;

&lt;p&gt;Still not clear enough? Steve McConnell explains it beautifully in Code Complete:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Exceptions are a specific means by which code can pass along errors or exceptional events to the code that called it. If code in one routine encounters an unexpected condition that it doesn't know how to handle, it throws an exception, essentially throwing up its hands and yelling, "I don't know what to do about this—I sure hope somebody else knows how to handle it!" Code that has no sense of the context of an error can return control to other parts of the system that might have a better ability to interpret the error and do something useful about it.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;code complete&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;h3&gt;
  
  
  The Exception Tree
&lt;/h3&gt;

&lt;p&gt;Okay now let's talk in terms of Ruby. Exceptions are simply classes that the Ruby library has predefined for us. &lt;/p&gt;

&lt;p&gt;Below is a list of exception classes that ship with Ruby’s standard library. Third-party gems like Rails will add additional exception classes to this chart. Every additional exception from Rails will inherit from some class on this list.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Exception
 NoMemoryError
 ScriptError
   LoadError
   NotImplementedError
   SyntaxError
 SignalException
   Interrupt
 StandardError
   ArgumentError
   IOError
     EOFError
   IndexError
   LocalJumpError
   NameError
     NoMethodError
   RangeError
     FloatDomainError
   RegexpError
   RuntimeError
   SecurityError
   SystemCallError
   SystemStackError
   ThreadError
   TypeError
   ZeroDivisionError
 SystemExit
 fatal
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So any error that can happen in Ruby will be a part of one of the above classes. Let's see a few of them just to make things clear.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;NoMemoryError&lt;/strong&gt; - This is raised when memory allocation fails and the application must halt.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SignalException::Interrupt&lt;/strong&gt; - This is raised when you press &lt;code&gt;ctrl + c&lt;/code&gt; to stop your program.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ScriptError::SyntaxError&lt;/strong&gt; - Syntax errors mean that when your program comes across things like &lt;code&gt;p "this quote is not closed&lt;/code&gt;, it will raise this.&lt;/li&gt;
&lt;li&gt;__ StandardError__ - As the name implies, StandardError is the most common or standard type of exception Ruby will raise. Most of the usual errors you see are part of this.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Raising these exceptions is Ruby's way of telling us something is wrong and what that is.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimgs.xkcd.com%2Fcomics%2Ferror_code.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%2Fimgs.xkcd.com%2Fcomics%2Ferror_code.png" alt="codes"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  What does Raise actually mean?
&lt;/h3&gt;

&lt;p&gt;When an exception is raised (either explicitly with raise or implicitly by the Ruby runtime), an instance of an &lt;code&gt;Exception class&lt;/code&gt; (or one of its subclasses) is created. This object contains information about the exception, such as an error message and a backtrace.&lt;br&gt;
It also means that an exception object has been created and the normal flow of program execution has been interrupted. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;NOTE: This is not like &lt;code&gt;return ExceptionObj&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This process involves more than just returning an object; it's a specific type of control flow mechanism, in which the normal flow of program execution has been interrupted. &lt;/p&gt;

&lt;p&gt;Let's understand with a simple example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def divide_numbers(x, y)
  result = x / y
  puts "Result of division is #{result}"
end

puts "Program starts"
divide_numbers(10, 0)
puts "Program ends"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;The program prints "Program starts".&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;divide_numbers&lt;/code&gt; method is called with 10 and 0 as arguments.&lt;/li&gt;
&lt;li&gt;Inside divide_numbers, the division x / y is attempted. Since y is 0, Ruby raises a &lt;code&gt;ZeroDivisionError&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The exception interrupts the normal flow of the program. The line&lt;code&gt;puts "Result of division is #{result}"&lt;/code&gt; is never executed because the exception has been raised before this line.&lt;/li&gt;
&lt;li&gt;Since there's no rescue block to catch the ZeroDivisionError, the exception propagates up the call stack. In this case, it propagates back to the top level of the script.&lt;/li&gt;
&lt;li&gt;No part of the script handles the exception, so it causes the program to terminate.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The final puts "Program ends" line is never executed because the program has already been interrupted and terminated by the unhandled exception.&lt;br&gt;
When you run this script, you'll see the "Program starts" message, followed by an error message indicating a &lt;code&gt;ZeroDivisionError&lt;/code&gt;, and the "Program ends" message will not be displayed.&lt;/p&gt;

&lt;p&gt;So, returning an exception object is fundamentally different from raising one. Returning an exception object treats it like any other value, requiring explicit checks and handling by the caller. Hence, an exception is always raised and not returned.&lt;/p&gt;

&lt;p&gt;If you want to manually raise an exception, you can do so using &lt;code&gt;raise&lt;/code&gt; or &lt;code&gt;fail&lt;/code&gt; in Ruby like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;raise "This will raise an exception!"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By default, if you don't specify anything, this will assume the exception is a &lt;code&gt;RuntimeError&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The raise method accepts arguments in this format&lt;br&gt;
&lt;code&gt;raise [EXCEPTION_CLASS], [MESSAGE], [BACKTRACE]&lt;/code&gt;&lt;br&gt;
There is enough documentation on how these methods work, so I won't dive into them.&lt;/p&gt;
&lt;h3&gt;
  
  
  An Exception is raised, what now?
&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%2Fwww.explainxkcd.com%2Fwiki%2Fimages%2Fc%2Fcc%2Funreachable_state.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%2Fwww.explainxkcd.com%2Fwiki%2Fimages%2Fc%2Fcc%2Funreachable_state.png" alt="xkcd"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Now that we understand an exception will break the flow and is just thrown out there for someone to "catch" it, we must mindfully handle these. &lt;/p&gt;

&lt;p&gt;For eg: If in a Rails controller flow, an exception is raised and you don't handle it manually, Rails middleware will handle it and give a &lt;code&gt;500 Internal Server Error&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Ruby gives you the &lt;code&gt;begin..rescue..ensure..end&lt;/code&gt; block to handle these exceptions. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note:  Ruby also has a &lt;code&gt;BEGIN...END block&lt;/code&gt; too, which is different from the &lt;code&gt;begin..end&lt;/code&gt; block.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is how the &lt;code&gt;being..rescue&lt;/code&gt; block looks like&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;begin
  raise 'This exception will be rescued!'
rescue StandardError =&amp;gt; e
  puts "Rescued: #{e.inspect}"
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you don't mention anything in rescue, by default Ruby rescues the &lt;code&gt;StandardError&lt;/code&gt; class. This is very much intended. As to why the default is not the &lt;code&gt;Exception&lt;/code&gt; class, this will give you a clear idea. &lt;a href="https://www.honeybadger.io/blog/ruby-exception-vs-standarderror-whats-the-difference/" rel="noopener noreferrer"&gt;https://www.honeybadger.io/blog/ruby-exception-vs-standarderror-whats-the-difference/&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;NOTE: You should never rescue the &lt;code&gt;Exception&lt;/code&gt; class.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now if we want to write the division code shown before with proper error handling, it will be&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def divide(a, b)
  begin
    result = a / b
  rescue ZeroDivisionError =&amp;gt; e
    puts "Error: #{e.message}"
    result = nil
  end
  return result
end

puts divide(10, 2)   # Output: 5
puts divide(10, 0)   # Output: Error: divided by 0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Great! What next?
&lt;/h3&gt;

&lt;p&gt;Okay, so we now understand failures, exceptions, errors and how to address them. The big question is what are the best practices around this? When should I raise an exception manually? How should I write code so it is easy to manage errors? &lt;/p&gt;

&lt;p&gt;Understanding these things is crucial to being confident that your code works as it was intended to. We will cover these things in the next article. But before I go, I will leave you with this quote from Code Complete&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Throw an exception only for conditions that are truly exceptional. Exceptions should be reserved for conditions that are truly exceptional—in other words, for conditions that cannot be addressed by other coding practices.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>rails</category>
      <category>ruby</category>
      <category>errors</category>
      <category>programming</category>
    </item>
    <item>
      <title>What the pluck?</title>
      <dc:creator>Dhaval Singh</dc:creator>
      <pubDate>Fri, 17 Nov 2023 21:01:40 +0000</pubDate>
      <link>https://dev.to/dhavalsingh/what-the-pluck-go7</link>
      <guid>https://dev.to/dhavalsingh/what-the-pluck-go7</guid>
      <description>&lt;p&gt;ActiveRecord is a great ORM, with a ton of nifty little things that make your life easy when dealing with DB queries. &lt;code&gt;pluck&lt;/code&gt; is one such method. I've been using &lt;code&gt;pluck&lt;/code&gt; for as long as I can remember, and even my second oldest &lt;a href="https://www.dsdev.in/jsonb-rails-pluck"&gt;article&lt;/a&gt; is on it!&lt;/p&gt;

&lt;p&gt;Even after using it for so long, recently I found myself debugging a relatively simple query that used &lt;code&gt;pluck&lt;/code&gt; and realized I missed some key points regarding this sweet little AR method. &lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SXWdi8ZC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/Vm2iq2P.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SXWdi8ZC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/Vm2iq2P.png" alt="docs meme" width="590" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://guides.rubyonrails.org/active_record_querying.html#pluck"&gt;Rails Guides&lt;/a&gt; on &lt;code&gt;pluck&lt;/code&gt; is pretty neat, but there are still some things you might miss so I'll try to sum it all up here. If you're just starting out or might have overlooked the documentation, I highly recommend going through this. However, if you're already versed in AR/pluck, feel free to jump to the concluding sections.&lt;/p&gt;
&lt;h3&gt;
  
  
  What is pluck and how does it work?
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;Pluck&lt;/code&gt; is an AR query method that selects one or more attributes(or columns) and returns an &lt;code&gt;Array&lt;/code&gt;, without loading the corresponding records. It uses &lt;code&gt;select&lt;/code&gt; internally and &lt;strong&gt;triggers a query&lt;/strong&gt; for the values.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Customer.pluck(:id)
# SELECT customers.id FROM customers
=&amp;gt; [1,2,3]
# or
Customer.pluck(:id, :first_name)
# SELECT customers.id, customers.first_name FROM customers
=&amp;gt; [[1, "David"], [2, "Fran"], [3, "Jose"]]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are multiple ways to do the above in Rails, &lt;code&gt;pluck&lt;/code&gt; is the most performant out of all in almost all cases.&lt;br&gt;
Basically, you are replacing code that looks like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Customer.select(:id).map { |c| c.id }
# or
Customer.select(:id, :first_name).map { |c| [c.id, c.first_name] }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;to be cleaner and more efficient.&lt;/p&gt;

&lt;h4&gt;
  
  
  So why is it faster?
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;pluck&lt;/code&gt; directly converts the data into a Ruby array skipping the construction of AR objects, thus giving it an edge in performance. Here's an &lt;a href="https://www.rubyinrails.com/2014/06/05/rails-pluck-vs-select-map-collect/"&gt;article benchmarking pluck vs select vs collect/map&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;There are some more points that are well-documented in the guides, so I'll just list them here.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You are not limited to querying fields from a single table, you can query multiple tables as well.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Order.joins(:customer, :books).pluck("orders.created_at, customers.email, books.title")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt; &lt;code&gt;pluck&lt;/code&gt; triggers an immediate query, and thus cannot be chained with any further scopes, although it can work with scopes already constructed earlier:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Customer.pluck(:first_name).limit(1)
=&amp;gt; NoMethodError: undefined method `limit' for #&amp;lt;Array:0x007ff34d3ad6d8&amp;gt;

Customer.limit(1).pluck(:first_name)
=&amp;gt; ["David"]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt; &lt;code&gt;pluck&lt;/code&gt; will trigger eager loading if the relation object contains include values, even if the eager loading is not necessary for the query. As you can see in the example, we don't need the join for customer ids, but &lt;code&gt;pluck&lt;/code&gt; will still go ahead and do it! So be careful when you have eager-loaded associations!
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;irb&amp;gt; assoc = Customer.includes(:reviews)
irb&amp;gt; assoc.pluck(:id)
SELECT "customers"."id" FROM "customers" LEFT OUTER JOIN "reviews" ON "reviews"."id" = "customers"."review_id"

# to avoid this you can do
assoc.unscope(:includes).pluck(:id)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Now we have seen what's in the guides, let's see some cases that might trip you up!
&lt;/h4&gt;




&lt;h3&gt;
  
  
  Plucking jsonb fields in Rails
&lt;/h3&gt;

&lt;p&gt;If you have a jsonb field in your AR object and you want some nested value you can still use &lt;code&gt;pluck&lt;/code&gt;!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;user.metadata = {
  "location": {
    "city": "New York",
    # ... additional data
  }
  # ... other metadata attributes
}

# Using 'pluck' to retrieve the 'city' values from the 'location' key in 'metadata'
cities = user.pluck("metadata -&amp;gt; 'location' -&amp;gt;&amp;gt; 'city'")
=&amp;gt; ["New York"]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Pluck's Overriding Power
&lt;/h3&gt;

&lt;p&gt;Since &lt;code&gt;pluck&lt;/code&gt; uses &lt;code&gt;select&lt;/code&gt; internally. it will override any other selects you do before this. This seems obvious but when writing a complex query one might miss out on this. I'll try to illustrate with a relatively simple example&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Scenario: You want to fetch distinct cities from a user table

# Step 1: Using 'select' with 'distinct' to get unique cities
distinct_cities_query = User.select(:city).distinct

# Step 2: Attempting to use 'pluck' to retrieve the city names
cities = distinct_cities_query.pluck(:city)
# Cities might contain duplicate city names
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Plucking with where
&lt;/h3&gt;

&lt;p&gt;Another common issue can arise when using &lt;code&gt;pluck&lt;/code&gt; with where (remember, pluck fires an immediate query). Hence, it can fire some extra queries where it's not required. Thankfully there’s a &lt;code&gt;PluckInWhere&lt;/code&gt; Rubocop you can use to warn you.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# bad
# will trigger 2 queries
Post.where(user_id: User.active.pluck(:id))
# SELECT id FROM users WHERE /* conditions for active users */;
# SELECT * FROM posts WHERE user_id IN (1, 2, 3, ...);  -- Array of IDs from the first query

# good
# triggers 1 query only
Post.where(user_id: User.active.select(:id))
# SELECT * FROM posts WHERE user_id IN (SELECT id FROM users WHERE /* conditions for active users */);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  When to think twice before using pluck?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;When you have already loaded the AR objects into memory there is no need to use &lt;code&gt;pluck&lt;/code&gt; as it will trigger another query. Rather just use &lt;code&gt;map&lt;/code&gt; or &lt;code&gt;collect&lt;/code&gt;. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When dealing with large datasets be careful with &lt;code&gt;pluck&lt;/code&gt; as it will load everything into your memory.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Instead of using pluck which can consume a lot of memory
# User.pluck(:email).each do |email|
#   # Process email
# end

# Use find_each or find_in_batches for batch processing
User.find_each(batch_size: 1000) do |user|
  email = user.email
  # Process email
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In conclusion, pluck is a versatile and powerful method in Rails for efficiently retrieving specific columns from a database, but it's crucial to understand its nuances and limitations. &lt;br&gt;
Happy Plucking :D&lt;/p&gt;

</description>
      <category>rails</category>
      <category>ruby</category>
      <category>sql</category>
      <category>programming</category>
    </item>
    <item>
      <title>Understanding Rails Callbacks &amp; Common Pitfalls</title>
      <dc:creator>Dhaval Singh</dc:creator>
      <pubDate>Mon, 30 Oct 2023 19:53:27 +0000</pubDate>
      <link>https://dev.to/dhavalsingh/understanding-rails-callbacks-common-pitfalls-4hd1</link>
      <guid>https://dev.to/dhavalsingh/understanding-rails-callbacks-common-pitfalls-4hd1</guid>
      <description>&lt;h3&gt;
  
  
  Context
&lt;/h3&gt;

&lt;p&gt;I recently spent a good chunk of time debugging a bug and in turn, did a lot of research on how Transactions and Touch work with callbacks like &lt;code&gt;after_commit&lt;/code&gt;. Below is the debugging "story" I shared on X, if you like reading those, give it a shot but it's not required for this reading.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://twitter.com/Dhavalsingh7/status/1718171721155399805"&gt;Story&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Foreword
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8anJRLiA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/WyVNZWT.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8anJRLiA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/WyVNZWT.jpg" alt="evil" width="343" height="250"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Callbacks are Evil. There, I said it. Whew, feels good to get this off my chest in the first line itself. Okay, you may ask why or just think I am not a seasoned RoR dev yet to be making this statement(which, by the way, I’m not). But hear me out. &lt;/p&gt;

&lt;p&gt;One of the crowning achievements of Rails is its ability to facilitate rapid development&lt;br&gt;
enabling businesses and ideas to scale quickly.  But with this speed comes a potential pitfall. &lt;br&gt;
What I mean is that you do something in one place of the codebase and soon that pattern will get replicated everywhere. The "intent" of doing something gets lost pretty quickly if someone doesn't keep an eye on it and more so as the codebase gets bigger and complexity goes through the roof. This can make or break an application in the long run.&lt;/p&gt;

&lt;p&gt;There will always be examples of "Oh we were able to do XYZ, if you can't that means you are not doing it right". But here’s the thing: in a framework as powerful as Rails, which often feels magical in its abstraction of complexities, it's really easy to misuse features beyond their intended purpose. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Callbacks are one of those abused things.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now, the point of writing this next part is that I want to share a few edge cases I've come across. Think of this as a compilation of Callback gotchas that one might easily miss.&lt;/p&gt;
&lt;h3&gt;
  
  
  Callback Gotachs
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Callbacks are easy and very convenient to use and that is the worst part.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now the Rails Docs doesn't state anywhere what should ideally go in a callback. It shows how many different types are there and what they do, but what goes into them is still a blur. So you really need to be sure of what you put inside your callbacks before it's too late. But this post is not about what goes in a callback. This is about how it can surprise you once you are already dealing with it.&lt;/p&gt;

&lt;p&gt;Some of the things I will mention are either in the API Docs or the Rails guide, but a few aren't mentioned anywhere(and can actually trip you up). Here are a few things you should keep in mind when dealing with callbacks.&lt;/p&gt;
&lt;h4&gt;
  
  
  &lt;em&gt;1. Callback ordering:&lt;/em&gt;
&lt;/h4&gt;

&lt;p&gt;The non-transactional callbacks run in the order they are defined.&lt;/p&gt;

&lt;p&gt;But..&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XfUVoKs9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/qXZ2Jba.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XfUVoKs9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/qXZ2Jba.png" alt="order" width="651" height="313"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From Rails 7.1 this can be altered via configuration.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;config.active_record.run_after_transaction_callbacks_in_order_defined = false
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The default value from 7.1 is &lt;code&gt;true&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;em&gt;2. Multiple transactional callbacks with the same method name override each other:&lt;/em&gt;
&lt;/h4&gt;

&lt;p&gt;This means only the last one is executed. This goes for &lt;code&gt;after_commit&lt;/code&gt;, &lt;code&gt;after_*_commit&lt;/code&gt;, after_rollback, etc)&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Zo-ZrYc---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/LJnK3zx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Zo-ZrYc---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/LJnK3zx.png" alt="override" width="648" height="546"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The above 2 are mentioned in the Rails Guide, thankfully. The next one is not!&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;em&gt;3. Multiple instances of the same record in a transaction:&lt;/em&gt;
&lt;/h4&gt;

&lt;p&gt;In the context of a single transaction, if you interact with multiple loaded objects that represent the same record in the database, there's a crucial behavior in the &lt;code&gt;after_commit&lt;/code&gt; and &lt;code&gt;after_rollback&lt;/code&gt; callbacks to note. These callbacks are triggered only for the first object of the specific record that undergoes a change within the transaction. Other loaded objects, despite representing the same database record, will not have their respective &lt;code&gt;after_commit&lt;/code&gt; or &lt;code&gt;after_rollback&lt;/code&gt; callbacks triggered.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wunGsIw1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/Bvbcts0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wunGsIw1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/Bvbcts0.png" alt="multi-record" width="800" height="343"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see in the above example, only 2 callbacks are executed. This behavior is not documented anywhere. I've raised a &lt;a href="https://github.com/rails/rails/pull/49831"&gt;PR&lt;/a&gt; to add this in the guides, let's see what happens. Anyway, you need to be careful about this.&lt;/p&gt;

&lt;h3&gt;
  
  
  Some additional gotchas
&lt;/h3&gt;

&lt;p&gt;There are a few more surprises in terms of when a rollback happens, and how &lt;a href="https://makandracards.com/makandra/42885-nested-activerecord-transaction-pitfalls"&gt;Rails handles it&lt;/a&gt;, especially with nested transactions.&lt;br&gt;
Using nested transactions is &lt;a href="https://dmitrytsepelev.dev/service-objects-anti-patterns"&gt;considered an anti-pattern&lt;/a&gt; in a lot of cases, so think twice before using it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bonus: Confusing behavior of Touch with Transaction and &lt;code&gt;after_commit&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Now this is not a bug, but for me, it was the lack of clarity/docs on this that was confusing. &lt;br&gt;
Let's understand this with an example&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LVsS4nwM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/oP6AH95.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LVsS4nwM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/oP6AH95.png" alt="transaction" width="800" height="967"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the above example, the touch SQL queries are coalesced at the end to be more efficient but the &lt;code&gt;Car&lt;/code&gt; model is actually touched after each touch hence triggering the after_commits in a specific order. This can be especially confusing when you are debugging stuck in something I like to call &lt;em&gt;Callback Hell&lt;/em&gt;. This is also not mentioned anywhere, hence I raised another &lt;a href="https://github.com/rails/rails/pull/49833"&gt;PR&lt;/a&gt; to add this to the API docs.&lt;/p&gt;

&lt;p&gt;Overall, callbacks just seem like a bad design, because they are really powerful but so easy to use. It's more of a bad design based on how a human brain works rather than a programming one, but if your codebase already has a lot of these and you need to work with them a general rule to keep in mind when dealing with it would be&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Try without a callback, if you really think it belongs there then move it into a callback. But don't start with a callback.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
      <category>callback</category>
      <category>activerecord</category>
    </item>
    <item>
      <title>From Bloat to Sleek: A Rails Memory Tale With Jemalloc</title>
      <dc:creator>Dhaval Singh</dc:creator>
      <pubDate>Fri, 27 Oct 2023 11:31:15 +0000</pubDate>
      <link>https://dev.to/dhavalsingh/from-bloat-to-sleek-a-rails-memory-tale-with-jemalloc-15i5</link>
      <guid>https://dev.to/dhavalsingh/from-bloat-to-sleek-a-rails-memory-tale-with-jemalloc-15i5</guid>
      <description>&lt;h3&gt;
  
  
  Prelude
&lt;/h3&gt;

&lt;p&gt;In my previous &lt;a href="https://www.dsdev.in/blog/memory-leak-bloat" rel="noopener noreferrer"&gt;blog&lt;/a&gt; we tried to analyze what could be the reason behind a Rails app hogging so much memory. Now there are multiple ways to approach this issue from fixing N+1 queries to profiling shady APIs and debugging them, my most fruitful discovery was a shift to a memory allocator named &lt;strong&gt;jemalloc&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This term kept popping up, and, initially, it was a complete enigma to me.&lt;/p&gt;

&lt;h3&gt;
  
  
  Memory Surges in Multi-Threaded Environment
&lt;/h3&gt;

&lt;p&gt;As mentioned in my previous post, we also migrated to Puma from Unicorn during the K8s migration. Now Unicorn is single-threaded while we started running Puma with 5 threads in production and boom, the memory usage skyrocketed.&lt;/p&gt;

&lt;p&gt;This happens due to something called &lt;strong&gt;per-thread memory arenas&lt;/strong&gt; in the default glibc malloc. While I won't delve deep into the intricacies this &lt;a href="https://www.speedshop.co/2017/12/04/malloc-doubles-ruby-memory.html" rel="noopener noreferrer"&gt;post by Nate Berkopec&lt;/a&gt; does it beautifully.&lt;/p&gt;

&lt;p&gt;For those who just want an ELI5 version, continue on. Otherwise, feel free to jump to the next section.&lt;/p&gt;

&lt;h3&gt;
  
  
  ELI5: Per-thread memory arenas
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Playroom &amp;amp; Rules:&lt;/strong&gt; Imagine a playroom with kids (threads). There's a rule: only one kid can tell a story (execute Ruby code) at a time. This is because of the "Storytelling Rule" (akin to the GVL).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Kids &amp;amp; Toy Boxes:&lt;/strong&gt; Each kid has their own toy box (per-thread memory arena). When they play, they first look for toys in their personal box.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Main Toy Chest:&lt;/strong&gt; There's also a big shared toy chest in the middle (main memory arena). If a kid can't find the toy they want in their personal box, they might go to this big chest to get one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Messy Toy Situations:&lt;/strong&gt; Sometimes, kids don't put toys back neatly. Toys spread out, and soon there's wasted space in the toy boxes and the main toy chest. This is like memory fragmentation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Balancing Toys &amp;amp; Storytime:&lt;/strong&gt; Having many toy boxes means kids can quickly find toys, but it might lead to more mess (fragmentation). Fewer boxes mean tidier storage but might make playtime less spontaneous.&lt;/p&gt;

&lt;p&gt;This is oversimplified but you get the idea. In short, fewer memory areans mean less fragmentation but slower programs. &lt;/p&gt;

&lt;h3&gt;
  
  
  Addressing the Memory Quandary
&lt;/h3&gt;

&lt;p&gt;Reducing the memory areans seems like a straightforward way which you can do by setting the environment variable &lt;code&gt;MALLOC_ARENA_MAX&lt;/code&gt; anywhere from 2-4 (optmial for Ruby).&lt;/p&gt;

&lt;p&gt;But changing the memory allocator seemed to be more effective in other cases. Enter jemalloc. While jemalloc mirrors malloc in its use of per-thread arenas, it manages them more efficiently.&lt;/p&gt;

&lt;p&gt;Configuring Ruby to harness jemalloc is a breeze. Here's a snapshot of my setup process:&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%2Fi.imgur.com%2FBCiJ8Nw.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%2Fi.imgur.com%2FBCiJ8Nw.png" alt="jm"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I've adopted jemalloc version &lt;strong&gt;5.3.0&lt;/strong&gt;. A quick peek revealed that Gitlab utilizes this &lt;a href="https://gitlab.com/gitlab-org/omnibus-gitlab/-/blob/master/config/software/jemalloc.rb?ref_type=heads" rel="noopener noreferrer"&gt;same&lt;/a&gt; version, which cemented my choice.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;A word of caution as you embark on this: jemalloc has had its share of hiccups when paired with Ruby in Alpine-based Docker images, thankfully we are not using it.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The Outcome
&lt;/h3&gt;

&lt;p&gt;To my surprise, it didn’t have any negative side effects(at least none I could see) and it performed way better than I expected.&lt;/p&gt;

&lt;p&gt;As you can see, each pod pre-jemalloc was gobbling up an average of &lt;strong&gt;1.6GB&lt;/strong&gt;. Post-jemalloc, this consumption plummeted to a mere &lt;strong&gt;550 MB&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%2Fi.imgur.com%2FUNL4Akw.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%2Fi.imgur.com%2FUNL4Akw.png" alt="per"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In aggregate terms, total memory usage took a nosedive from 16GB down to 4GB, marking a staggering 75% decrease!&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%2Fi.imgur.com%2Fmrd88Fy.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%2Fi.imgur.com%2Fmrd88Fy.png" alt="total"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We saw similar effects on our other services also, not as pronounced but still significant.&lt;/p&gt;

&lt;p&gt;The biggest winner, no doubt were our Sidekiq workers(as they can utilize up to 32 threads, I think this is way too high, will work on this soon enough)&lt;/p&gt;

&lt;h3&gt;
  
  
  Moving Forward
&lt;/h3&gt;

&lt;p&gt;While I personally haven't encountered a scenario where jemalloc underperformed, the Ruby core team have their &lt;a href="https://bugs.ruby-lang.org/issues/9113" rel="noopener noreferrer"&gt;specific reasons&lt;/a&gt;. Nevertheless, implementing jemalloc appears to be a worthwhile endeavor. I'd strongly recommend giving it a shot. If not jemalloc, tweaking the MALLOC_ARENA_MAX might also be beneficial. &lt;/p&gt;

&lt;p&gt;The outcome? More efficient pods in terms of size and a noticeable reduction in AWS costs. It's definitely worth a try to determine what works best for your setup.&lt;/p&gt;

</description>
      <category>rails</category>
      <category>ruby</category>
      <category>jemalloc</category>
      <category>memory</category>
    </item>
  </channel>
</rss>
