<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-US"><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://andreyuhai.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://andreyuhai.github.io/" rel="alternate" type="text/html" hreflang="en-US" /><updated>2024-12-06T15:53:42+01:00</updated><id>https://andreyuhai.github.io/feed.xml</id><title type="html">Burak Kaymakci</title><subtitle>Documenting my journey with programming languages, foreign languages and other shit.</subtitle><author><name>Burak Kaymakci</name></author><entry><title type="html">Why did the Elixir application keep running despite dependency shutdown?</title><link href="https://andreyuhai.github.io/why-did-the-elixir-application-keep-running-despite-dependency-shutdown/" rel="alternate" type="text/html" title="Why did the Elixir application keep running despite dependency shutdown?" /><published>2024-12-05T00:00:00+01:00</published><updated>2024-12-05T00:00:00+01:00</updated><id>https://andreyuhai.github.io/why-did-the-elixir-application-keep-running-despite-dependency-shutdown</id><content type="html" xml:base="https://andreyuhai.github.io/why-did-the-elixir-application-keep-running-despite-dependency-shutdown/"><![CDATA[<p>Recently, we’ve had an incident with one of our RPC services on production. The root cause was an issue with a PgBouncer instance going down. Although PgBouncer was eventually restored and became operational, our service remained partially functional until the pods were restarted. In this article, I’ll document the root cause of the issue and how we fixed it, effectively answering the question posed in the title.</p>

<h2 id="the-incident">The incident</h2>

<p>During the incident, our service appeared to be partially functional. While we were still receiving and responding to some RPC requests, others were failing due to errors like this:</p>

<div class="language-elixir highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">**</span> <span class="p">(</span><span class="no">RuntimeError</span><span class="p">)</span> <span class="n">could</span> <span class="ow">not</span> <span class="n">lookup</span> <span class="no">Ecto</span> <span class="n">repo</span> <span class="no">Platform</span><span class="o">.</span><span class="no">Repo</span> <span class="n">because</span> <span class="n">it</span> <span class="n">was</span> <span class="ow">not</span> <span class="n">started</span> <span class="ow">or</span> <span class="n">it</span> <span class="n">does</span> <span class="ow">not</span> <span class="n">exist</span>
    <span class="p">(</span><span class="n">ecto</span> <span class="mf">3.10</span><span class="o">.</span><span class="mi">3</span><span class="p">)</span> <span class="n">lib</span><span class="o">/</span><span class="n">ecto</span><span class="o">/</span><span class="n">repo</span><span class="o">/</span><span class="n">registry</span><span class="o">.</span><span class="ss">ex:</span><span class="mi">22</span><span class="p">:</span> <span class="no">Ecto</span><span class="o">.</span><span class="no">Repo</span><span class="o">.</span><span class="no">Registry</span><span class="o">.</span><span class="n">lookup</span><span class="o">/</span><span class="mi">1</span>
    <span class="p">(</span><span class="n">ecto</span> <span class="mf">3.10</span><span class="o">.</span><span class="mi">3</span><span class="p">)</span> <span class="n">lib</span><span class="o">/</span><span class="n">ecto</span><span class="o">/</span><span class="n">repo</span><span class="o">/</span><span class="n">supervisor</span><span class="o">.</span><span class="ss">ex:</span><span class="mi">160</span><span class="p">:</span> <span class="no">Ecto</span><span class="o">.</span><span class="no">Repo</span><span class="o">.</span><span class="no">Supervisor</span><span class="o">.</span><span class="n">tuplet</span><span class="o">/</span><span class="mi">2</span>
    <span class="p">(</span><span class="n">platform</span> <span class="mf">0.0</span><span class="o">.</span><span class="mi">1</span><span class="p">)</span> <span class="n">lib</span><span class="o">/</span><span class="n">repo</span><span class="o">.</span><span class="ss">ex:</span><span class="mi">6</span><span class="p">:</span> <span class="no">Platform</span><span class="o">.</span><span class="no">Repo</span><span class="o">.</span><span class="n">all</span><span class="o">/</span><span class="mi">2</span>
</code></pre></div></div>

<p>That means we could only respond to requests that didn’t interact with <code class="language-plaintext highlighter-rouge">Platform.Repo</code>, however that error still didn’t tell us much, except that the <code class="language-plaintext highlighter-rouge">Platform.Repo</code> we were looking for in the registry couldn’t be found for some reason while handling an RPC call. But why was this happening?</p>

<h2 id="root-cause">Root cause</h2>

<p>Upon further investigation we’ve found logs below from that service’s pods.</p>

<div class="language-elixir highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="no">Application</span> <span class="n">platform</span> <span class="ss">exited:</span> <span class="n">shutdown</span>
</code></pre></div></div>

<p>That meant our application <code class="language-plaintext highlighter-rouge">platform</code>, one of our RPC service’s dependencies, which manages <code class="language-plaintext highlighter-rouge">Platform.Repo</code> had shut down.
But if <code class="language-plaintext highlighter-rouge">platform</code> was down, how was our service still running?
The answer lay in how the application was started. Since this was one of our legacy apps, it was still using Mix (instead of releases) to start the server on production.
Specifically we were using a task to start the application and all its dependencies like this:</p>

<div class="language-elixir highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="no">Application</span><span class="o">.</span><span class="n">ensure_all_started</span><span class="p">(</span><span class="ss">:our_legacy_rpc</span><span class="p">)</span>
</code></pre></div></div>

<p>Here is the key difference:
In a <code class="language-plaintext highlighter-rouge">Mix</code> release, applications are started with a <code class="language-plaintext highlighter-rouge">restart_type</code> of <code class="language-plaintext highlighter-rouge">permanent</code>. However when using <code class="language-plaintext highlighter-rouge">Application.ensure_all_started/1</code>, the <code class="language-plaintext highlighter-rouge">restart_type</code> defaults to <code class="language-plaintext highlighter-rouge">temporary</code>. According to the documentation:</p>

<blockquote>
  <p>:temporary - if app terminates, it is reported but no other applications are terminated (the default).</p>
</blockquote>

<p>This explains why our service kept running even though one of its critical dependencies (<code class="language-plaintext highlighter-rouge">platform</code>) had shut down. Erlang does nothing about shutdown applications, which makes sense, since the top-level supervisor of the application will attempt to restart its children up to <code class="language-plaintext highlighter-rouge">max_retries</code> within <code class="language-plaintext highlighter-rouge">max_seconds</code> (<a href="https://hexdocs.pm/elixir/Supervisor.html#module-supervisor-strategies-and-options">source</a>) before giving up and eventually shutting down the whole application.</p>

<h2 id="resolution">Resolution</h2>

<p>To mitigate the issue we basically started all applications with a <code class="language-plaintext highlighter-rouge">restart_type</code> of <code class="language-plaintext highlighter-rouge">permanent</code> like so:</p>

<div class="language-elixir highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="no">Application</span><span class="o">.</span><span class="n">ensure_all_start</span><span class="p">(</span><span class="ss">:our_legacy_rpc</span><span class="p">,</span> <span class="ss">type:</span> <span class="ss">:permanent</span><span class="p">)</span>
</code></pre></div></div>

<p>This guarantees that, if any dependency of our application (or the application itself) goes down for any reason, everything will be shutdown which will trigger Kubernetes to restart the container because of failing liveness checks.</p>

<blockquote>
  <p>:permanent - if app terminates, all other applications and the entire node are also terminated.</p>
</blockquote>

<p>Just to note it here, to see <code class="language-plaintext highlighter-rouge">restart_type</code>s of all started applications, you can run:</p>

<div class="language-elixir highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="ss">:application_controller</span><span class="o">.</span><span class="n">info</span><span class="p">()</span>
</code></pre></div></div>

<h3 id="sources">Sources</h3>

<p>Some links that helped me understand how Erlang manages applications and the role of <code class="language-plaintext highlighter-rouge">restart_type</code>.</p>

<ul>
  <li>http://erlang.org/documentation/doc-5.2/doc/design_principles/applications.html</li>
  <li>https://blog.plataformatec.com.br/2015/04/build-embedded-and-start-permanent-in-elixir-1-0-4/</li>
  <li>https://stackoverflow.com/a/44665998/4796762</li>
  <li>https://stackoverflow.com/a/39662718/4796762</li>
</ul>]]></content><author><name>Burak Kaymakci</name></author><category term="elixir" /><category term="erlang" /><category term="applications" /><category term="application-restart-strategy" /><summary type="html"><![CDATA[Discover how we resolved a production incident in an Elixir-based RPC service caused by PgBouncer downtime and application restart strategies. Explore the impact of restart_type on applications.]]></summary></entry><entry><title type="html">PostgreSQL 55000 error</title><link href="https://andreyuhai.github.io/postgresql-55000-error/" rel="alternate" type="text/html" title="PostgreSQL 55000 error" /><published>2024-01-29T00:00:00+01:00</published><updated>2024-01-29T00:00:00+01:00</updated><id>https://andreyuhai.github.io/postgresql-55000-error</id><content type="html" xml:base="https://andreyuhai.github.io/postgresql-55000-error/"><![CDATA[<p>We had a Kafka consumer which was crashing with the error below</p>

<div class="language-elixir highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="no">Postgrex</span><span class="o">.</span><span class="no">Error</span> <span class="no">ERROR</span> <span class="mi">55000</span> <span class="p">(</span><span class="n">object_not_in_prerequisite_state</span><span class="p">)</span> <span class="n">recovery</span> <span class="n">is</span> <span class="ow">in</span> <span class="n">progress</span>

    <span class="ss">hint:</span> <span class="no">WAL</span> <span class="n">control</span> <span class="n">functions</span> <span class="n">cannot</span> <span class="n">be</span> <span class="n">executed</span> <span class="n">during</span> <span class="n">recovery</span><span class="o">.</span><span class="p">)</span>
</code></pre></div></div>

<p>In that consumer module, there was a function which was eventually trying to get the LSN from the DB by querying something like</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>SELECT pg_last_wal_replay_lsn()::varchar
</code></pre></div></div>

<p>It turns out we were actually querying a replica where WAL was enabled, figured that out quite quickly by asking in #postgresql IRC.
(<em>Well, if you’re querying the LSN it obviously means you’ve got WAL enabled, it’s even in the function name! But didn’t know it back then. ¯_(ツ)</em>/¯_)</p>

<blockquote>
  <p>10:49 &lt; Berge&gt; Note that a replica (using WAL replication) is considered to be in recovery</p>
</blockquote>

<p>Thank you Berge! TIL!</p>]]></content><author><name>Burak Kaymakci</name></author><category term="til" /><category term="postgresql" /><summary type="html"><![CDATA[What was the root cause of PostgreSQL 55000 error in our case]]></summary></entry><entry><title type="html">Firefox custom search engines</title><link href="https://andreyuhai.github.io/firefox-custom-search-engines/" rel="alternate" type="text/html" title="Firefox custom search engines" /><published>2023-11-21T00:00:00+01:00</published><updated>2023-11-21T00:00:00+01:00</updated><id>https://andreyuhai.github.io/firefox-custom-search-engines</id><content type="html" xml:base="https://andreyuhai.github.io/firefox-custom-search-engines/"><![CDATA[<p>A few weeks ago I’ve watched <a href="https://www.imdb.com/title/tt13957560/">Dumb Money</a> which recounts the GameStop story. I was really interested in the story and started researching on the Internet. Eventually I ended up on <a href="https://www.youtube.com/@RoaringKitty">Roaring Kitty’s YouTube channel</a> especially on this <a href="https://www.youtube.com/watch?v=x2CBcthRVKE&amp;ab_channel=RoaringKitty">video</a>. While watching the video I saw he’s created custom search engines for Chrome, which I’d never heard of before. I really liked the idea of being able to search things on specific websites with a few keystrokes so I searched whether the same was possible for Firefox.</p>

<p>It is possible however for Firefox you need to add the preference below to your <code class="language-plaintext highlighter-rouge">about:config</code> and set it to <code class="language-plaintext highlighter-rouge">true</code>.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>browser.urlbar.update2.engineAliasRefresh
</code></pre></div></div>

<p>Then you can go to Settings &gt; Search and you’ll be able to see the “Add” button under the section “Search Shortcuts”. You can see an example of how to add a custom search engine for YouTube, which means that you’ll be able to search on YouTube simply by typing into your URL bar after you hit the shortcut “yt” while the focus is on the URL bar.</p>

<figure>
<img src="/images/firefox-custom-search-engines/how-to-add-custom-firefox-search-engine.png" alt="How to add Firefox custom search engine?" />
</figure>]]></content><author><name>Burak Kaymakci</name></author><category term="til" /><category term="firefox" /><category term="browser" /><summary type="html"><![CDATA[How to create custom search engines for Firefox? I had no idea about custom search engines until I've watched a totally unrelated finance video.]]></summary></entry><entry><title type="html">Creating a function with inputs from a file at compile time using Elixir AST</title><link href="https://andreyuhai.github.io/creating-a-function-with-inputs-from-a-file-at-compile-time-using-elixir-ast/" rel="alternate" type="text/html" title="Creating a function with inputs from a file at compile time using Elixir AST" /><published>2022-06-27T00:00:00+02:00</published><updated>2022-06-27T00:00:00+02:00</updated><id>https://andreyuhai.github.io/creating-a-function-with-inputs-from-a-file-at-compile-time-using-elixir-ast</id><content type="html" xml:base="https://andreyuhai.github.io/creating-a-function-with-inputs-from-a-file-at-compile-time-using-elixir-ast/"><![CDATA[<p>Let me fill you in on what the problem I was trying to solve was, then we can get to how I’ve solved the problem by creating a function with inputs from a “defaults” file at compile time using Elixir’s Abstract Syntax Tree (AST).</p>

<p>We have a CSV file that has some defaults for our business logic, the file barely changes and is not huge.
The content of the file is transformed into a list of tuples using a script and the script is included in one of the modules as comments.
Using this script (in an <code class="language-plaintext highlighter-rouge">iex</code> shell), you would get the output, which is a list of tuples, and paste it into appropriate function body, which would be used at runtime.
Whenever the CSV file changes you would do the same things described above.</p>

<p>So the script looks something like this</p>
<div class="language-elixir highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># example CSV just in case you want to run this script.</span>
<span class="c1"># Just copy &amp; paste the values below into some CSV file.</span>
<span class="c1">#</span>
<span class="c1"># service_name,base_price,duration</span>
<span class="c1"># Haircut,50,30</span>
<span class="c1"># Manicure,50,60</span>
<span class="c1"># Pedicure,70,90</span>

<span class="s2">"./lib/data.csv"</span>
<span class="o">|&gt;</span> <span class="no">File</span><span class="o">.</span><span class="n">stream!</span><span class="p">()</span>
<span class="o">|&gt;</span> <span class="no">CSV</span><span class="o">.</span><span class="n">decode!</span><span class="p">(</span><span class="ss">headers:</span> <span class="no">true</span><span class="p">)</span>
<span class="o">|&gt;</span> <span class="no">Enum</span><span class="o">.</span><span class="n">map</span><span class="p">(</span><span class="k">fn</span> <span class="n">row</span> <span class="o">-&gt;</span>
  <span class="p">{</span>
    <span class="n">row</span><span class="p">[</span><span class="s2">"service_name"</span><span class="p">],</span>
    <span class="n">row</span><span class="p">[</span><span class="s2">"duration"</span><span class="p">],</span>
    <span class="n">row</span><span class="p">[</span><span class="s2">"base_price"</span><span class="p">]</span>
  <span class="p">}</span>
<span class="k">end</span><span class="p">)</span>
</code></pre></div></div>

<p>When run, this script outputs a list of tuples shown below.</p>
<div class="language-elixir highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">[</span>
  <span class="p">{</span><span class="s2">"Haircut"</span><span class="p">,</span> <span class="s2">"30"</span><span class="p">,</span> <span class="s2">"50"</span><span class="p">},</span>
  <span class="p">{</span><span class="s2">"Manicure"</span><span class="p">,</span> <span class="s2">"60"</span><span class="p">,</span> <span class="s2">"50"</span><span class="p">},</span>
  <span class="p">{</span><span class="s2">"Pedicure"</span><span class="p">,</span> <span class="s2">"90"</span><span class="p">,</span> <span class="s2">"70"</span><span class="p">}</span>
<span class="p">]</span>
</code></pre></div></div>

<p>You would then take the list above and put it inside one of the functions, which would be used at runtime on production for whatever logic and the final module would look something like this.</p>
<div class="language-elixir highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">defmodule</span> <span class="no">Playground</span> <span class="k">do</span>
  <span class="c1"># Script to use whenever necessary to</span>
  <span class="c1"># generate the body of some_important_function/0</span>
  <span class="c1">#</span>
  <span class="c1"># "/path/to/csv"</span>
  <span class="c1"># |&gt; File.stream!()</span>
  <span class="c1"># |&gt; CSV.decode!(headers: true)</span>
  <span class="c1"># |&gt; Enum.map(fn row -&gt;</span>
  <span class="c1">#   {</span>
  <span class="c1">#     row["service_name"],</span>
  <span class="c1">#     row["duration"],</span>
  <span class="c1">#     row["base_price"]</span>
  <span class="c1">#   }</span>
  <span class="c1"># end)</span>

  <span class="k">def</span> <span class="n">some_important_function</span> <span class="k">do</span>
    <span class="p">[</span>
      <span class="p">{</span><span class="s2">"Haircut"</span><span class="p">,</span> <span class="s2">"30"</span><span class="p">,</span> <span class="s2">"50"</span><span class="p">},</span>
      <span class="p">{</span><span class="s2">"Manicure"</span><span class="p">,</span> <span class="s2">"60"</span><span class="p">,</span> <span class="s2">"50"</span><span class="p">},</span>
      <span class="p">{</span><span class="s2">"Pedicure"</span><span class="p">,</span> <span class="s2">"90"</span><span class="p">,</span> <span class="s2">"70"</span><span class="p">}</span>
    <span class="p">]</span>
  <span class="k">end</span>
<span class="k">end</span>
</code></pre></div></div>

<p>Everything is fine so far, except that you have to run the script manually every time the CSV file changes. It works anyway.
The problem started when we wanted to translate some of the strings from the CSV file, which means we would need to wrap some of the strings with <code class="language-plaintext highlighter-rouge">gettext/1</code> macro.</p>

<p>So the outcome we want to achieve is to have <code class="language-plaintext highlighter-rouge">some_important_function</code> as</p>
<div class="language-elixir highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="n">some_important_function</span> <span class="k">do</span>
  <span class="p">[</span>
    <span class="p">{</span><span class="n">gettext</span><span class="p">(</span><span class="s2">"Haircut"</span><span class="p">),</span> <span class="s2">"30"</span><span class="p">,</span> <span class="s2">"50"</span><span class="p">},</span>
    <span class="p">{</span><span class="n">gettext</span><span class="p">(</span><span class="s2">"Manicure"</span><span class="p">),</span> <span class="s2">"60"</span><span class="p">,</span> <span class="s2">"50"</span><span class="p">},</span>
    <span class="p">{</span><span class="n">gettext</span><span class="p">(</span><span class="s2">"Pedicure"</span><span class="p">),</span> <span class="s2">"90"</span><span class="p">,</span> <span class="s2">"70"</span><span class="p">}</span>
  <span class="p">]</span>
<span class="k">end</span>
</code></pre></div></div>

<p>We can’t directly wrap our strings with <code class="language-plaintext highlighter-rouge">gettext/1</code> in our “script” above because,</p>

<ol>
  <li>The strings are not known at compile time, hence can’t be used with macros.</li>
  <li>Moreover, it’s just a script and it’s not actually on production.</li>
</ol>

<p>One solution would be to manually wrap the necessary strings with <code class="language-plaintext highlighter-rouge">gettext/1</code> inside <code class="language-plaintext highlighter-rouge">some_important_function/0</code> above. But that’s too much manual work and error prone.</p>

<h2 id="solving-the-problem-at-compile-time-with-elixir-ast">Solving the problem at compile time with Elixir AST</h2>

<p>Doing some research and asking around in <a href="https://elixir-slackin.herokuapp.com/">Elixir Slack</a> (shout out to @lostkobrakai), I figured we could solve the problem using Elixir AST.</p>

<blockquote>
  <p>What is the AST?</p>

  <p>An AST, acronym for Abstact Syntax Tree, is a representation of code as a data structure. This data structure is used by Elixir to run Elixir code: either by interpreting it directly: executing the commands in the AST by recursively walking it; or by compiling it: translating the AST into another format, namely BEAM bytecode instructions, which then are saved to disk as .beam files.<sup><a href="https://www.botsquad.com/2019/04/11/the-ast-explained/">source: botsquad</a></sup></p>
</blockquote>

<p>We will first read the CSV at compile time and create the tuple list, which will then be used to create an AST with <code class="language-plaintext highlighter-rouge">gettext/1</code> macro used wherever necessary.
Lastly we will <code class="language-plaintext highlighter-rouge">unquote/1</code> this AST within our actual function body which will be used at runtime on production.
Moreover, we will use <a href="https://hexdocs.pm/elixir/main/Module.html#module-external_resource"><code class="language-plaintext highlighter-rouge">@external_resource</code></a> module attribute to make sure that whenever our CSV file changes our module will be recompiled, meaning that our code will always be up to date!
No more running scripts manually. 🎉</p>

<blockquote>
  <p><code class="language-plaintext highlighter-rouge">@external_resource</code></p>

  <p>Tools may use this information to ensure the module is recompiled in case any of the external resources change, see for example: mix compile.elixir. <sup><a href="https://hexdocs.pm/elixir/main/Module.html#module-external_resource">source: Hexdocs</a></sup></p>
</blockquote>

<div class="language-elixir highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">defmodule</span> <span class="no">Playground</span> <span class="k">do</span>
  <span class="c1"># This way our module will be recompiled whenever</span>
  <span class="c1"># you make changes to the CSV file.</span>
  <span class="c1"># Make some changes to the CSV file and recompile to see it in action.</span>
  <span class="nv">@external_resource</span> <span class="s2">"./lib/foo.csv"</span>

	<span class="c1"># Nothing fancy here, we're just creating a list of tuples</span>
  <span class="n">data</span> <span class="o">=</span>
    <span class="nv">@external_resource</span>
    <span class="o">|&gt;</span> <span class="no">File</span><span class="o">.</span><span class="n">stream!</span><span class="p">()</span>
    <span class="o">|&gt;</span> <span class="no">CSV</span><span class="o">.</span><span class="n">decode!</span><span class="p">(</span><span class="ss">headers:</span> <span class="no">true</span><span class="p">)</span>
    <span class="o">|&gt;</span> <span class="no">Enum</span><span class="o">.</span><span class="n">map</span><span class="p">(</span><span class="k">fn</span> <span class="n">row</span> <span class="o">-&gt;</span>
      <span class="p">{</span>
        <span class="n">row</span><span class="p">[</span><span class="s2">"service_name"</span><span class="p">],</span>
        <span class="n">row</span><span class="p">[</span><span class="s2">"duration"</span><span class="p">],</span>
        <span class="n">row</span><span class="p">[</span><span class="s2">"base_price"</span><span class="p">]</span>
      <span class="p">}</span>
    <span class="k">end</span><span class="p">)</span>

  <span class="no">IO</span><span class="o">.</span><span class="n">inspect</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
  <span class="c1"># =&gt;</span>
  <span class="c1"># [</span>
  <span class="c1">#   {"Haircut", "30", "50"},</span>
  <span class="c1">#   {"Manicure", "60", "50"},</span>
  <span class="c1">#   {"Pedicure", "90", "70"}</span>
  <span class="c1"># ]</span>

  <span class="c1"># This is where we build the AST.</span>
  <span class="n">data_ast</span> <span class="o">=</span>
    <span class="no">Enum</span><span class="o">.</span><span class="n">map</span><span class="p">(</span><span class="n">data</span><span class="p">,</span> <span class="k">fn</span> <span class="n">tuple</span> <span class="o">-&gt;</span>
      <span class="n">list</span> <span class="o">=</span>
        <span class="n">tuple</span>
        <span class="o">|&gt;</span> <span class="n">put_elem</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="p">{</span><span class="ss">:gettext</span><span class="p">,</span> <span class="p">[],</span> <span class="p">[</span><span class="n">elem</span><span class="p">(</span><span class="n">tuple</span><span class="p">,</span> <span class="mi">0</span><span class="p">)]})</span>
        <span class="o">|&gt;</span> <span class="no">Tuple</span><span class="o">.</span><span class="n">to_list</span><span class="p">()</span>

      <span class="p">{:{},</span> <span class="p">[],</span> <span class="n">list</span><span class="p">}</span>
    <span class="k">end</span><span class="p">)</span>

  <span class="no">IO</span><span class="o">.</span><span class="n">inspect</span><span class="p">(</span><span class="n">data_ast</span><span class="p">)</span>
  <span class="c1"># =&gt;</span>
  <span class="c1"># [</span>
  <span class="c1">#   {:{}, [], [{:gettext, [], ["Haircut"]}, "30", "50"]},</span>
  <span class="c1">#   {:{}, [], [{:gettext, [], ["Manicure"]}, "60", "50"]},</span>
  <span class="c1">#   {:{}, [], [{:gettext, [], ["Pedicure"]}, "90", "70"]}</span>
  <span class="c1"># ]</span>

  <span class="n">data_ast</span>
  <span class="o">|&gt;</span> <span class="no">Macro</span><span class="o">.</span><span class="n">to_string</span><span class="p">()</span>
  <span class="o">|&gt;</span> <span class="no">IO</span><span class="o">.</span><span class="n">puts</span><span class="p">()</span>
  <span class="c1"># =&gt;</span>
  <span class="c1"># [</span>
  <span class="c1">#   {gettext("Haircut"), "30", "50"},</span>
  <span class="c1">#   {gettext("Manicure"), "60", "50"},</span>
  <span class="c1">#   {gettext("Pedicure"), "90", "70"}</span>
  <span class="c1"># ]</span>

  <span class="c1"># Now, this function would return the same thing</span>
  <span class="c1"># that's returned by Macro.to_string/1 above</span>
  <span class="k">def</span> <span class="n">some_important_function</span> <span class="k">do</span>
    <span class="kn">unquote</span><span class="p">(</span><span class="n">data_ast</span><span class="p">)</span>
  <span class="k">end</span>
<span class="k">end</span>
</code></pre></div></div>]]></content><author><name>Burak Kaymakci</name></author><category term="TIL" /><category term="Elixir" /><category term="elixir" /><category term="elixir-ast" /><category term="abstract-syntax-tree" /><summary type="html"><![CDATA[Create a function with inputs from a file at compile time using Elixir AST.]]></summary></entry><entry><title type="html">How do supervisors not crash?</title><link href="https://andreyuhai.github.io/how-do-supervisors-not-crash-when-linked-process-crashes/" rel="alternate" type="text/html" title="How do supervisors not crash?" /><published>2021-12-13T00:00:00+01:00</published><updated>2021-12-13T00:00:00+01:00</updated><id>https://andreyuhai.github.io/how-do-supervisors-not-crash-when-linked-process-crashes</id><content type="html" xml:base="https://andreyuhai.github.io/how-do-supervisors-not-crash-when-linked-process-crashes/"><![CDATA[<p>How do supervisors not crash when their children do?</p>

<p>When you start an <code class="language-plaintext highlighter-rouge">Agent</code> or <code class="language-plaintext highlighter-rouge">GenServer</code> they will be <strong>linked</strong> to the current process and the current process will crash if the <strong>linked</strong> <code class="language-plaintext highlighter-rouge">Agent</code> or <code class="language-plaintext highlighter-rouge">GenServer</code> crashes.
However <code class="language-plaintext highlighter-rouge">Supervisor</code>s do not crash even if the child processes that are <strong>linked</strong> to the supervisor crash. Well, the answer is obvious.</p>

<p>Because <code class="language-plaintext highlighter-rouge">Supervisor</code>s trap the exit signals.<sup><a href="https://github.com/erlang/otp/blob/maint/lib/stdlib/src/supervisor.erl#L329">source code</a></sup></p>

<p>Assuming that you’ve at least one child spec in your <code class="language-plaintext highlighter-rouge">children</code> list below, you can also confirm that doing:</p>

<div class="language-elixir highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="ss">:ok</span><span class="p">,</span> <span class="n">supervisor</span><span class="p">}</span> <span class="o">=</span> <span class="no">Supervisor</span><span class="o">.</span><span class="n">start_link</span><span class="p">(</span><span class="n">children</span><span class="p">,</span> <span class="ss">strategy:</span> <span class="ss">:one_for_one</span><span class="p">)</span>

<span class="no">Process</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="n">supervisor</span><span class="p">,</span> <span class="ss">:trap_exit</span><span class="p">)</span>
<span class="c1"># =&gt; {:trap_exit, true}</span>
</code></pre></div></div>]]></content><author><name>Burak Kaymakci</name></author><category term="elixir" /><category term="supervisor" /><category term="agent" /><category term="genserver" /><summary type="html"><![CDATA[How do supervisors not crash when their children do?]]></summary></entry><entry><title type="html">Ecto field types from a changeset or a schema struct</title><link href="https://andreyuhai.github.io/how-does-ecto-infer-field-type-from-a-changeset-or-a-schema-struct/" rel="alternate" type="text/html" title="Ecto field types from a changeset or a schema struct" /><published>2021-07-16T00:00:00+02:00</published><updated>2021-07-16T00:00:00+02:00</updated><id>https://andreyuhai.github.io/how-does-ecto-infer-field-type-from-a-changeset-or-a-schema-struct</id><content type="html" xml:base="https://andreyuhai.github.io/how-does-ecto-infer-field-type-from-a-changeset-or-a-schema-struct/"><![CDATA[<p>How does Ecto infer field types from a changeset or a schema struct?</p>

<p>I was wondering how <a href="https://hexdocs.pm/ecto/Ecto.Changeset.html#cast/4"><code class="language-plaintext highlighter-rouge">Ecto.Changeset.cast/4</code></a> function casts attributes from a map into their approriate types in the DB since we do not provide any information about the types explicitly.</p>

<p>Turns out that if you are passing a schema struct to <code class="language-plaintext highlighter-rouge">cast/4</code> Ecto uses the <a href="https://github.com/elixir-ecto/ecto/blob/master/lib/ecto/schema.ex#L598-L600"><code class="language-plaintext highlighter-rouge">__changeset__</code></a> function on it to figure out the types of the fields. Otherwise if you are passing an <code class="language-plaintext highlighter-rouge">Ecto.Changeset</code> to <code class="language-plaintext highlighter-rouge">cast/4</code> then Ecto uses the <a href="https://hexdocs.pm/ecto/Ecto.Changeset.html#module-the-ecto-changeset-struct"><code class="language-plaintext highlighter-rouge">types</code></a> field of the changeset struct.</p>

<hr />

<p>To show you what I mean, we are going to create a Phoenix app called <code class="language-plaintext highlighter-rouge">God</code> with only a <code class="language-plaintext highlighter-rouge">Human</code> schema so we can <strong>c</strong>reate, <strong>r</strong>ead, <strong>u</strong>pdate, <strong>d</strong>elete a <code class="language-plaintext highlighter-rouge">Human</code> (wish it was that easy lol).</p>

<p><em>If you already know what I mean then you can basically skip to <a href="#the-breakdown">the breakdown</a>.</em></p>

<p>Create a Phoenix app:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>mix phx.new god
</code></pre></div></div>

<p>After our project is created, and we ran <code class="language-plaintext highlighter-rouge">mix ecto.create</code> inside the project directory we need to generate our controller, view and context for <code class="language-plaintext highlighter-rouge">Human</code> to be able to CRUD <code class="language-plaintext highlighter-rouge">Human</code>s.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>╰─<span class="nv">$ </span>mix phx.gen.html Creature Human humans name surname to_be_born_on:utc_datetime age_to_die_at:integer will_get_married:boolean

<span class="k">*</span> creating lib/god_web/controllers/human_controller.ex
<span class="k">*</span> creating lib/god_web/templates/human/edit.html.eex
<span class="k">*</span> creating lib/god_web/templates/human/form.html.eex
<span class="k">*</span> creating lib/god_web/templates/human/index.html.eex
<span class="k">*</span> creating lib/god_web/templates/human/new.html.eex
<span class="k">*</span> creating lib/god_web/templates/human/show.html.eex
<span class="k">*</span> creating lib/god_web/views/human_view.ex
<span class="k">*</span> creating <span class="nb">test</span>/god_web/controllers/human_controller_test.exs
<span class="k">*</span> creating lib/god/creature/human.ex
<span class="k">*</span> creating priv/repo/migrations/20210716083409_create_humans.exs
<span class="k">*</span> creating lib/god/creature.ex
<span class="k">*</span> injecting lib/god/creature.ex
<span class="k">*</span> creating <span class="nb">test</span>/god/creature_test.exs
<span class="k">*</span> injecting <span class="nb">test</span>/god/creature_test.exs

Add the resource to your browser scope <span class="k">in </span>lib/god_web/router.ex:

    resources <span class="s2">"/humans"</span>, HumanController


Remember to update your repository by running migrations:

    <span class="nv">$ </span>mix ecto.migrate
</code></pre></div></div>

<p>Basically our <code class="language-plaintext highlighter-rouge">Human</code> will have a <code class="language-plaintext highlighter-rouge">name</code>, <code class="language-plaintext highlighter-rouge">surname</code> and we will also have a <code class="language-plaintext highlighter-rouge">utc_datetime</code> for them <code class="language-plaintext highlighter-rouge">to_be_born_on</code>, an <code class="language-plaintext highlighter-rouge">age_to_die_at</code> and finally whether they <code class="language-plaintext highlighter-rouge">will_get_married</code>.</p>

<p>After we follow the instructions given after running <code class="language-plaintext highlighter-rouge">mix phx.gen.html</code> above we will have a working <code class="language-plaintext highlighter-rouge">God</code> app. :D</p>

<p><img src="https://imgur.com/4oKBi4I.png" alt="A look at our human control center" /></p>

<p>We’ve already created (scheduled maybe?) a human to be born on 05/05/2022 at 07:07 who will sadly die at the age of 88. 🎉</p>

<p><img src="https://media.giphy.com/media/G3fPad8N68GfS/giphy.gif" alt="I am God" /></p>

<hr />

<h1 id="lets-get-serious">Let’s get serious</h1>

<p>So when we navigate to <code class="language-plaintext highlighter-rouge">http://localhost:4000/humans/new</code> we get the form below to create a human.</p>

<p><img src="https://i.imgur.com/B46JIH5.png" alt="New human form" /></p>

<p>After we fill in the details in the form and click the save button, our request follows a path of</p>

<p><code class="language-plaintext highlighter-rouge">endpoint.ex -&gt; router.ex -&gt; HumanController.create/2</code></p>

<p>Below you can see the code for <code class="language-plaintext highlighter-rouge">HumanController.create/2</code> which gets run eventually,</p>

<div class="language-elixir highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="n">create</span><span class="p">(</span><span class="n">conn</span><span class="p">,</span> <span class="p">%{</span><span class="s2">"human"</span> <span class="o">=&gt;</span> <span class="n">human_params</span><span class="p">})</span> <span class="k">do</span>
  <span class="k">case</span> <span class="no">Creature</span><span class="o">.</span><span class="n">create_human</span><span class="p">(</span><span class="n">human_params</span><span class="p">)</span> <span class="k">do</span>
    <span class="p">{</span><span class="ss">:ok</span><span class="p">,</span> <span class="n">human</span><span class="p">}</span> <span class="o">-&gt;</span>
      <span class="n">conn</span>
      <span class="o">|&gt;</span> <span class="n">put_flash</span><span class="p">(</span><span class="ss">:info</span><span class="p">,</span> <span class="s2">"Human created successfully."</span><span class="p">)</span>
      <span class="o">|&gt;</span> <span class="n">redirect</span><span class="p">(</span><span class="ss">to:</span> <span class="no">Routes</span><span class="o">.</span><span class="n">human_path</span><span class="p">(</span><span class="n">conn</span><span class="p">,</span> <span class="ss">:show</span><span class="p">,</span> <span class="n">human</span><span class="p">))</span>

    <span class="p">{</span><span class="ss">:error</span><span class="p">,</span> <span class="p">%</span><span class="no">Ecto</span><span class="o">.</span><span class="no">Changeset</span><span class="p">{}</span> <span class="o">=</span> <span class="n">changeset</span><span class="p">}</span> <span class="o">-&gt;</span>
      <span class="n">render</span><span class="p">(</span><span class="n">conn</span><span class="p">,</span> <span class="s2">"new.html"</span><span class="p">,</span> <span class="ss">changeset:</span> <span class="n">changeset</span><span class="p">)</span>
  <span class="k">end</span>
<span class="k">end</span>
</code></pre></div></div>

<p>which in fact calls a function <code class="language-plaintext highlighter-rouge">Creature.create_human/1</code> which you can see below.</p>

<div class="language-elixir highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="n">create_human</span><span class="p">(</span><span class="n">attrs</span> <span class="p">\\</span> <span class="p">%{})</span> <span class="k">do</span>
  <span class="p">%</span><span class="no">Human</span><span class="p">{}</span>
  <span class="o">|&gt;</span> <span class="no">Human</span><span class="o">.</span><span class="n">changeset</span><span class="p">(</span><span class="n">attrs</span><span class="p">)</span>
  <span class="o">|&gt;</span> <span class="no">Repo</span><span class="o">.</span><span class="n">insert</span><span class="p">()</span>
<span class="k">end</span>
</code></pre></div></div>

<p>This function also calls <code class="language-plaintext highlighter-rouge">Human.changeset/2</code> which you can see below.</p>

<div class="language-elixir highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="n">changeset</span><span class="p">(</span><span class="n">human</span><span class="p">,</span> <span class="n">attrs</span><span class="p">)</span> <span class="k">do</span>
  <span class="n">human</span>
  <span class="o">|&gt;</span> <span class="n">cast</span><span class="p">(</span><span class="n">attrs</span><span class="p">,</span> <span class="p">[</span><span class="ss">:name</span><span class="p">,</span> <span class="ss">:surname</span><span class="p">,</span> <span class="ss">:to_be_born_on</span><span class="p">,</span> <span class="ss">:age_to_die_at</span><span class="p">,</span> <span class="ss">:will_get_married</span><span class="p">])</span>
  <span class="o">|&gt;</span> <span class="n">validate_required</span><span class="p">([</span><span class="ss">:name</span><span class="p">,</span> <span class="ss">:surname</span><span class="p">,</span> <span class="ss">:to_be_born_on</span><span class="p">,</span> <span class="ss">:age_to_die_at</span><span class="p">,</span> <span class="ss">:will_get_married</span><span class="p">])</span>
<span class="k">end</span>
</code></pre></div></div>

<p>If we insert a <code class="language-plaintext highlighter-rouge">require IEx; IEx.pry()</code> after the function head and before the function end like below,</p>

<div class="language-elixir highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="n">changeset</span><span class="p">(</span><span class="n">human</span><span class="p">,</span> <span class="n">attrs</span><span class="p">)</span> <span class="k">do</span>
  <span class="kn">require</span> <span class="no">IEx</span><span class="p">;</span> <span class="no">IEx</span><span class="o">.</span><span class="n">pry</span><span class="p">()</span>
  <span class="n">human</span> <span class="o">=</span> <span class="n">human</span>
  <span class="o">|&gt;</span> <span class="n">cast</span><span class="p">(</span><span class="n">attrs</span><span class="p">,</span> <span class="p">[</span><span class="ss">:name</span><span class="p">,</span> <span class="ss">:surname</span><span class="p">,</span> <span class="ss">:to_be_born_on</span><span class="p">,</span> <span class="ss">:age_to_die_at</span><span class="p">,</span> <span class="ss">:will_get_married</span><span class="p">])</span>
  <span class="o">|&gt;</span> <span class="n">validate_required</span><span class="p">([</span><span class="ss">:name</span><span class="p">,</span> <span class="ss">:surname</span><span class="p">,</span> <span class="ss">:to_be_born_on</span><span class="p">,</span> <span class="ss">:age_to_die_at</span><span class="p">,</span> <span class="ss">:will_get_married</span><span class="p">])</span>
  <span class="kn">require</span> <span class="no">IEx</span><span class="p">;</span> <span class="no">IEx</span><span class="o">.</span><span class="n">pry</span><span class="p">()</span>
  <span class="n">human</span>
<span class="k">end</span>
</code></pre></div></div>

<p>and inspect the <code class="language-plaintext highlighter-rouge">attrs</code> map. We will get:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pry<span class="o">(</span>1<span class="o">)&gt;</span> attrs
%<span class="o">{</span>
  <span class="s2">"age_to_die_at"</span> <span class="o">=&gt;</span> <span class="s2">"99"</span>,
  <span class="s2">"name"</span> <span class="o">=&gt;</span> <span class="s2">"John"</span>,
  <span class="s2">"surname"</span> <span class="o">=&gt;</span> <span class="s2">"Doe"</span>,
  <span class="s2">"to_be_born_on"</span> <span class="o">=&gt;</span> %<span class="o">{</span>
    <span class="s2">"day"</span> <span class="o">=&gt;</span> <span class="s2">"1"</span>,
    <span class="s2">"hour"</span> <span class="o">=&gt;</span> <span class="s2">"0"</span>,
    <span class="s2">"minute"</span> <span class="o">=&gt;</span> <span class="s2">"0"</span>,
    <span class="s2">"month"</span> <span class="o">=&gt;</span> <span class="s2">"1"</span>,
    <span class="s2">"year"</span> <span class="o">=&gt;</span> <span class="s2">"2016"</span>
  <span class="o">}</span>,
  <span class="s2">"will_get_married"</span> <span class="o">=&gt;</span> <span class="s2">"true"</span>
<span class="o">}</span>
</code></pre></div></div>

<p>As you can see all the values are of string which is what we can only get after a form submission anyway.</p>

<p>If we also inspect the <code class="language-plaintext highlighter-rouge">human</code> after the piping we get the changeset below.</p>

<div class="language-elixir highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">pry</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span><span class="o">&gt;</span> <span class="n">human</span>
<span class="c1">#Ecto.Changeset&lt;</span>
  <span class="ss">action:</span> <span class="no">nil</span><span class="p">,</span>
  <span class="ss">changes:</span> <span class="p">%{</span>
    <span class="ss">age_to_die_at:</span> <span class="mi">99</span><span class="p">,</span>
    <span class="ss">name:</span> <span class="s2">"John"</span><span class="p">,</span>
    <span class="ss">surname:</span> <span class="s2">"Doe"</span><span class="p">,</span>
    <span class="ss">to_be_born_on:</span> <span class="sx">~U[2016-01-01 00:00:00Z]</span><span class="p">,</span>
    <span class="ss">will_get_married:</span> <span class="no">true</span>
  <span class="p">},</span>
  <span class="ss">errors:</span> <span class="p">[],</span>
  <span class="ss">data:</span> <span class="c1">#God.Creature.Human&lt;&gt;,</span>
  <span class="ss">valid?:</span> <span class="no">true</span>
<span class="o">&gt;</span>
</code></pre></div></div>

<h3 id="the-question-is">The question is…</h3>

<p>So here, how does <code class="language-plaintext highlighter-rouge">Ecto.Changeset.cast/4</code> know how to cast attributes into their DB appropriate types? We have only passed <code class="language-plaintext highlighter-rouge">Ecto.Changeset.cast/4</code> a <code class="language-plaintext highlighter-rouge">Human</code> schema struct and a map of attributes consisting of only string values.</p>

<h3 id="the-breakdown">The Breakdown</h3>

<p>The breakdown will be two-fold. One for when you are passing a schema struct to <code class="language-plaintext highlighter-rouge">cast/4</code> and the other one for when you are passing a <code class="language-plaintext highlighter-rouge">Ecto.Changeset</code> to <code class="language-plaintext highlighter-rouge">cast/4</code>.</p>

<hr />

<p>In the case, when you pass a schema struct to <code class="language-plaintext highlighter-rouge">Ecto.Changeset.cast/4</code>, it turns out that there’s a <code class="language-plaintext highlighter-rouge">__changeset__</code> function you can call on a schema struct which will give you</p>

<div class="language-elixir highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">iex</span><span class="p">(</span><span class="mi">12</span><span class="p">)</span><span class="o">&gt;</span> <span class="no">God</span><span class="o">.</span><span class="no">Creature</span><span class="o">.</span><span class="no">Human</span><span class="o">.</span><span class="n">__changeset__</span>
<span class="p">%{</span>
  <span class="ss">age_to_die_at:</span> <span class="ss">:integer</span><span class="p">,</span>
  <span class="ss">id:</span> <span class="ss">:id</span><span class="p">,</span>
  <span class="ss">inserted_at:</span> <span class="ss">:naive_datetime</span><span class="p">,</span>
  <span class="ss">name:</span> <span class="ss">:string</span><span class="p">,</span>
  <span class="ss">surname:</span> <span class="ss">:string</span><span class="p">,</span>
  <span class="ss">to_be_born_on:</span> <span class="ss">:utc_datetime</span><span class="p">,</span>
  <span class="ss">updated_at:</span> <span class="ss">:naive_datetime</span><span class="p">,</span>
  <span class="ss">will_get_married:</span> <span class="ss">:boolean</span>
<span class="p">}</span>
</code></pre></div></div>

<p>and this <code class="language-plaintext highlighter-rouge">__changeset__</code> function gets injected by a private <code class="language-plaintext highlighter-rouge">schema/4</code> function which is called by <code class="language-plaintext highlighter-rouge">schema</code> and <code class="language-plaintext highlighter-rouge">embedded_schema</code> macros. You can <a href="https://github.com/elixir-ecto/ecto/blob/master/lib/ecto/schema.ex#L516">take a look at them on GitHub</a>.</p>

<p>If you further inspect the <a href="https://github.com/elixir-ecto/ecto/blob/master/lib/ecto/changeset.ex#L489-L491"><code class="language-plaintext highlighter-rouge">Ecto.Changeset.cast/4</code></a> function which accepts a struct, you will see that the <code class="language-plaintext highlighter-rouge">__changeset__</code> function is being used like so:</p>

<div class="language-elixir highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="n">cast</span><span class="p">(%{</span><span class="ss">__struct__:</span> <span class="n">module</span><span class="p">}</span> <span class="o">=</span> <span class="n">data</span><span class="p">,</span> <span class="n">params</span><span class="p">,</span> <span class="n">permitted</span><span class="p">,</span> <span class="n">opts</span><span class="p">)</span> <span class="k">do</span>
  <span class="n">cast</span><span class="p">(</span><span class="n">data</span><span class="p">,</span> <span class="n">module</span><span class="o">.</span><span class="n">__changeset__</span><span class="p">(),</span> <span class="p">%{},</span> <span class="n">params</span><span class="p">,</span> <span class="n">permitted</span><span class="p">,</span> <span class="n">opts</span><span class="p">)</span>
<span class="k">end</span>
</code></pre></div></div>

<p>If you create your own struct and try to pass it to <code class="language-plaintext highlighter-rouge">Ecto.Changeset.cast/4</code> you will obviously get an error.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>iex<span class="o">(</span>18<span class="o">)&gt;</span> defmodule Foo <span class="k">do</span>
...<span class="o">(</span>18<span class="o">)&gt;</span> defstruct <span class="o">[</span>:name, :age]
...<span class="o">(</span>18<span class="o">)&gt;</span> end
<span class="o">{</span>:module, Foo,
 <span class="o">&lt;&lt;</span><span class="no">70</span><span class="sh">, 79, 82, 49, 0, 0, 6, 152, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 0, 180,
   0, 0, 0, 18, 10, 69, 108, 105, 120, 105, 114, 46, 70, 111, 111, 8, 95, 95,
   105, 110, 102, 111, 95, 95, 10, 97, 116, ...&gt;&gt;, %Foo{age: nil, name: nil}}

iex(19)&gt; Ecto.Changeset.cast(%Foo{}, %{name: "Burak"}, [:name])
** (UndefinedFunctionError) function Foo.__changeset__/0 is undefined or private
    Foo.__changeset__()
    (ecto 3.6.2) lib/ecto/changeset.ex:489: Ecto.Changeset.cast/4
</span></code></pre></div></div>

<hr />

<p>In the case, when you pass an <code class="language-plaintext highlighter-rouge">Ecto.Changeset</code> to <a href="https://github.com/elixir-ecto/ecto/blob/master/lib/ecto/changeset.ex#L482-L487"><code class="language-plaintext highlighter-rouge">Ecto.Changeset.cast/4</code></a> below function gets invoked.</p>

<div class="language-elixir highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="n">cast</span><span class="p">(%</span><span class="no">Changeset</span><span class="p">{</span><span class="ss">changes:</span> <span class="n">changes</span><span class="p">,</span> <span class="ss">data:</span> <span class="n">data</span><span class="p">,</span> <span class="ss">types:</span> <span class="n">types</span><span class="p">,</span> <span class="ss">empty_values:</span> <span class="n">empty_values</span><span class="p">}</span> <span class="o">=</span> <span class="n">changeset</span><span class="p">,</span>
		    <span class="n">params</span><span class="p">,</span> <span class="n">permitted</span><span class="p">,</span> <span class="n">opts</span><span class="p">)</span> <span class="k">do</span>
  <span class="n">opts</span> <span class="o">=</span> <span class="no">Keyword</span><span class="o">.</span><span class="n">put_new</span><span class="p">(</span><span class="n">opts</span><span class="p">,</span> <span class="ss">:empty_values</span><span class="p">,</span> <span class="n">empty_values</span><span class="p">)</span>
  <span class="n">new_changeset</span> <span class="o">=</span> <span class="n">cast</span><span class="p">(</span><span class="n">data</span><span class="p">,</span> <span class="n">types</span><span class="p">,</span> <span class="n">changes</span><span class="p">,</span> <span class="n">params</span><span class="p">,</span> <span class="n">permitted</span><span class="p">,</span> <span class="n">opts</span><span class="p">)</span>
  <span class="n">cast_merge</span><span class="p">(</span><span class="n">changeset</span><span class="p">,</span> <span class="n">new_changeset</span><span class="p">)</span>
<span class="k">end</span>
</code></pre></div></div>

<p>As you can also see below, there’s a field called <code class="language-plaintext highlighter-rouge">types</code> in an <code class="language-plaintext highlighter-rouge">Ecto.Changeset</code> hence when you pass an <code class="language-plaintext highlighter-rouge">Ecto.Changeset</code> to <code class="language-plaintext highlighter-rouge">cast/4</code>, Ecto will use the <code class="language-plaintext highlighter-rouge">types</code> field to figure out how to cast attributes properly.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>iex<span class="o">(</span>63<span class="o">)&gt;</span> ch <span class="o">=</span> God.Creature.Human.changeset<span class="o">(</span>%God.Creature.Human<span class="o">{}</span>, %<span class="o">{</span>name: <span class="s2">"John"</span>, surname: <span class="s2">"Doe"</span>, to_be_born_on: <span class="s2">"2022-05-05 00:00:00"</span>, age_to_die_at: <span class="s2">"99"</span><span class="o">})</span>
<span class="c">#Ecto.Changeset&lt;</span>
  action: nil,
  changes: %<span class="o">{</span>
    age_to_die_at: 99,
    name: <span class="s2">"John"</span>,
    surname: <span class="s2">"Doe"</span>,
    to_be_born_on: ~U[2022-05-05 00:00:00Z]
  <span class="o">}</span>,
  errors: <span class="o">[]</span>,
  data: <span class="c">#God.Creature.Human&lt;&gt;,</span>
  valid?: <span class="nb">true</span>
<span class="o">&gt;</span>
iex<span class="o">(</span>64<span class="o">)&gt;</span> ch.types
%<span class="o">{</span>
  age_to_die_at: :integer,
  <span class="nb">id</span>: :id,
  inserted_at: :naive_datetime,
  name: :string,
  surname: :string,
  to_be_born_on: :utc_datetime,
  updated_at: :naive_datetime,
  will_get_married: :boolean
<span class="o">}</span>
</code></pre></div></div>

<hr />

<h3 id="lastly">Lastly</h3>

<p>You don’t always need a schema struct or an <code class="language-plaintext highlighter-rouge">Ecto.Changeset</code> to be able to use <code class="language-plaintext highlighter-rouge">cast/4</code>. As you can see in <a href="https://github.com/elixir-ecto/ecto/blob/master/lib/ecto/changeset.ex#L474-L476"><code class="language-plaintext highlighter-rouge">lib/ecto/changeset.ex</code></a></p>

<div class="language-elixir highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="n">cast</span><span class="p">({</span><span class="n">data</span><span class="p">,</span> <span class="n">types</span><span class="p">},</span> <span class="n">params</span><span class="p">,</span> <span class="n">permitted</span><span class="p">,</span> <span class="n">opts</span><span class="p">)</span> <span class="ow">when</span> <span class="n">is_map</span><span class="p">(</span><span class="n">data</span><span class="p">)</span> <span class="k">do</span>
  <span class="n">cast</span><span class="p">(</span><span class="n">data</span><span class="p">,</span> <span class="n">types</span><span class="p">,</span> <span class="p">%{},</span> <span class="n">params</span><span class="p">,</span> <span class="n">permitted</span><span class="p">,</span> <span class="n">opts</span><span class="p">)</span>
<span class="k">end</span>
</code></pre></div></div>

<p>You can just pass a tuple consisting of a <code class="language-plaintext highlighter-rouge">data</code> map and a <code class="language-plaintext highlighter-rouge">types</code> map which has the types of the values like so:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>iex<span class="o">(</span>15<span class="o">)&gt;</span> data <span class="o">=</span> %<span class="o">{}</span>
%<span class="o">{}</span>
iex<span class="o">(</span>16<span class="o">)&gt;</span> types <span class="o">=</span> %<span class="o">{</span>name: :string, age: :integer, likes_elixir: :boolean<span class="o">}</span>
%<span class="o">{</span>age: :integer, likes_elixir: :boolean, name: :string<span class="o">}</span>
iex<span class="o">(</span>17<span class="o">)&gt;</span> Ecto.Changeset.cast<span class="o">({</span> %<span class="o">{}</span>, types<span class="o">}</span>, %<span class="o">{</span>name: <span class="s2">"Burak"</span>, age: <span class="s2">"99"</span>, likes_elixir: <span class="s2">"true"</span><span class="o">}</span>, <span class="o">[</span>:name, :age, :likes_elixir]<span class="o">)</span>
<span class="c">#Ecto.Changeset&lt;</span>
  action: nil,
  changes: %<span class="o">{</span>age: 99, likes_elixir: <span class="nb">true</span>, name: <span class="s2">"Burak"</span><span class="o">}</span>,
  errors: <span class="o">[]</span>,
  data: %<span class="o">{}</span>,
  valid?: <span class="nb">true</span>
<span class="o">&gt;</span>
</code></pre></div></div>

<p><img src="https://media.giphy.com/media/8Iv5lqKwKsZ2g/source.gif" alt="Cheers!" /></p>]]></content><author><name>Burak Kaymakci</name></author><category term="TIL" /><category term="Elixir" /><category term="elixir" /><category term="ecto" /><category term="cast" /><summary type="html"><![CDATA[I was wondering how Ecto.Changeset.cast/4 casts attributes from a map into their appropriate types in the DB and here I explain just that.]]></summary></entry><entry><title type="html">Lazy way to insert debugging code for Elixir in Vim</title><link href="https://andreyuhai.github.io/elixir-easier-way-to-insert-iex-pry-in-vim/" rel="alternate" type="text/html" title="Lazy way to insert debugging code for Elixir in Vim" /><published>2021-06-29T00:00:00+02:00</published><updated>2021-06-29T00:00:00+02:00</updated><id>https://andreyuhai.github.io/elixir-easier-way-to-insert-iex-pry-in-vim</id><content type="html" xml:base="https://andreyuhai.github.io/elixir-easier-way-to-insert-iex-pry-in-vim/"><![CDATA[<p>When I’m writing Elixir code, I’ve been using <code class="language-plaintext highlighter-rouge">require IEx; IEx.pry()</code> a lot to debug my code that it became annoying having to type it all the time again and again. Hence I was thinking about a lazier way to have it inserted there in Vim and of course I was not the only one annoyed with this problem.</p>

<div class="language-vim highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">map</span> <span class="p">,</span>P Orequire IEx; IEx<span class="p">.</span>pry<span class="p">()&lt;</span>ESC<span class="p">&gt;</span>
<span class="nb">map</span> <span class="p">,</span><span class="k">p</span> orequire IEx; IEx<span class="p">.</span>pry<span class="p">()&lt;</span>ESC<span class="p">&gt;</span>
</code></pre></div></div>

<p>After inserting above code into your <code class="language-plaintext highlighter-rouge">.vimrc</code> you can basically insert pry line into your code with the keyboard shortcuts <code class="language-plaintext highlighter-rouge">,p</code> and <code class="language-plaintext highlighter-rouge">,P</code>. Uppercase version of the shortcut inserts the line above the current line and lowercase version inserts the line below the current line.</p>]]></content><author><name>Burak Kaymakci</name></author><category term="TIL" /><category term="Vim" /><category term="elixir" /><category term="vim" /><category term="iex" /><category term="pry" /><summary type="html"><![CDATA[When I’m writing Elixir code, I’ve been using require IEx; IEx.pry() a lot to debug my code that it became annoying having to type it all the time again and again. Hence I was thinking about a lazier way to have it inserted there in Vim and of course I was not the only one annoyed with this problem.]]></summary></entry><entry><title type="html">Programming Phoenix 1.4 | How do the websockets connect only on the video page</title><link href="https://andreyuhai.github.io/programming-phoenix-how-does-websocket-work-only-on-video-page/" rel="alternate" type="text/html" title="Programming Phoenix 1.4 | How do the websockets connect only on the video page" /><published>2021-05-19T00:00:00+02:00</published><updated>2021-05-19T00:00:00+02:00</updated><id>https://andreyuhai.github.io/programming-phoenix-how-does-websocket-work-only-on-video-page</id><content type="html" xml:base="https://andreyuhai.github.io/programming-phoenix-how-does-websocket-work-only-on-video-page/"><![CDATA[<p>In the book Programming Phoenix 1.4, we are creating a web application where users can annotate YouTube videos and annotations get brodcast by WebSockets to all the users that are on the same video page. We can also see that the browser tries to connect to a socket only on the video page, namely <code class="language-plaintext highlighter-rouge">rumbl_web/templates/watch/show.html.eex</code>. The chapter were this topic is covered in the book is the chapter 10. I was trying to understand how we are connecting to a socket only on the video page and here is how it happens.</p>

<p>If you take a look at <code class="language-plaintext highlighter-rouge">assets/js/app.js</code>, we can see that we call</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">Video</span><span class="p">.</span><span class="nx">init</span><span class="p">(</span><span class="nx">socket</span><span class="p">,</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="dl">"</span><span class="s2">video</span><span class="dl">"</span><span class="p">))</span>
</code></pre></div></div>

<p>If you inspect where <code class="language-plaintext highlighter-rouge">Video.init</code> is defined, which is <code class="language-plaintext highlighter-rouge">assets/js/video.js</code>, you can see the snippet below,</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">let</span> <span class="nx">Video</span> <span class="o">=</span> <span class="p">{</span>
  <span class="nx">init</span><span class="p">(</span><span class="nx">socket</span><span class="p">,</span> <span class="nx">element</span><span class="p">)</span> <span class="p">{</span> <span class="k">if</span><span class="p">(</span><span class="o">!</span><span class="nx">element</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="p">}</span>
    <span class="kd">let</span> <span class="nx">playerId</span> <span class="o">=</span> <span class="nx">element</span><span class="p">.</span><span class="nx">getAttribute</span><span class="p">(</span><span class="dl">"</span><span class="s2">data-player-id</span><span class="dl">"</span><span class="p">)</span>
    <span class="kd">let</span> <span class="nx">videoId</span>  <span class="o">=</span> <span class="nx">element</span><span class="p">.</span><span class="nx">getAttribute</span><span class="p">(</span><span class="dl">"</span><span class="s2">data-id</span><span class="dl">"</span><span class="p">)</span>
    <span class="nx">socket</span><span class="p">.</span><span class="nx">connect</span><span class="p">()</span>
    <span class="nx">Player</span><span class="p">.</span><span class="nx">init</span><span class="p">(</span><span class="nx">element</span><span class="p">.</span><span class="nx">id</span><span class="p">,</span> <span class="nx">playerId</span><span class="p">,</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="p">{</span>
      <span class="k">this</span><span class="p">.</span><span class="nx">onReady</span><span class="p">(</span><span class="nx">videoId</span><span class="p">,</span> <span class="nx">socket</span><span class="p">)</span>
    <span class="p">})</span>
  <span class="p">},</span>
</code></pre></div></div>

<p>What the <code class="language-plaintext highlighter-rouge">Video.init</code> function does is, if the <code class="language-plaintext highlighter-rouge">element</code> doesn’t exist on the page we directly return without trying to connecting to the socket. However if you basically insert a <code class="language-plaintext highlighter-rouge">div</code> with an id <code class="language-plaintext highlighter-rouge">video</code> on any page, you can see that the browser will try to connect to a websocket just because we have the video element on the page.</p>

<p>In <code class="language-plaintext highlighter-rouge">templates/watch/show.html.eex</code> you can see the snippet below which basically creates an element with an id of <code class="language-plaintext highlighter-rouge">video</code>, hence, the browser tries to connect to a socket on the video page.</p>
<div class="language-elixir highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">&lt;%=</span> <span class="n">content_tag</span> <span class="ss">:div</span><span class="p">,</span> <span class="ss">id:</span> <span class="s2">"video"</span><span class="p">,</span> <span class="ss">data:</span> <span class="p">[</span><span class="ss">id:</span> <span class="nv">@video</span><span class="o">.</span><span class="n">id</span><span class="p">,</span> <span class="ss">player_id:</span> <span class="n">player_id</span><span class="p">(</span><span class="nv">@video</span><span class="p">)]</span> <span class="k">do</span> <span class="p">%</span><span class="o">&gt;</span>
<span class="o">&lt;</span><span class="p">%</span> <span class="k">end</span> <span class="p">%</span><span class="o">&gt;</span>
</code></pre></div></div>]]></content><author><name>Burak Kaymakci</name></author><category term="TIL" /><category term="Elixir" /><category term="elixir" /><category term="phoenix" /><category term="websockets" /><summary type="html"><![CDATA[In the book Programming Phoenix 1.4, we are creating a web application where users can annotate YouTube videos and annotations get brodcast by WebSockets to all the users that are on the same video page. We can also see that the browser tries to connect to a socket only on the video page, namely rumbl_web/templates/watch/show.html.eex. The chapter were this topic is covered in the book is the chapter 10. I was trying to understand how we are connecting to a socket only on the video page and here is how it happens.]]></summary></entry><entry><title type="html">Elixir boolean operators</title><link href="https://andreyuhai.github.io/elixir-operators/" rel="alternate" type="text/html" title="Elixir boolean operators" /><published>2021-05-04T00:00:00+02:00</published><updated>2021-05-04T00:00:00+02:00</updated><id>https://andreyuhai.github.io/elixir-operators</id><content type="html" xml:base="https://andreyuhai.github.io/elixir-operators/"><![CDATA[<p>There’s subtle difference between Elixir boolean operators. Namely between <code class="language-plaintext highlighter-rouge">or</code> and <code class="language-plaintext highlighter-rouge">||</code>, <code class="language-plaintext highlighter-rouge">and</code> and <code class="language-plaintext highlighter-rouge">&amp;&amp;</code>, <code class="language-plaintext highlighter-rouge">not</code> and <code class="language-plaintext highlighter-rouge">!</code>.</p>

<p>These operators expect <code class="language-plaintext highlighter-rouge">true</code> or <code class="language-plaintext highlighter-rouge">false</code> as their first argument:</p>
<div class="language-elixir highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">a</span> <span class="ow">or</span> <span class="n">b</span>	<span class="c1"># true if a is true; otherwise b</span>
<span class="n">a</span> <span class="ow">and</span> <span class="n">b</span> <span class="c1"># false if a is false; otherwise b</span>
<span class="ow">not</span> <span class="n">a</span>	<span class="c1"># false if a is true; otherwise b</span>
</code></pre></div></div>

<p>These operators take arguments of any type. Any value apart from <code class="language-plaintext highlighter-rouge">nil</code> or <code class="language-plaintext highlighter-rouge">false</code> is interpreted as <code class="language-plaintext highlighter-rouge">true</code>:</p>
<div class="language-elixir highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">a</span> <span class="o">||</span> <span class="n">b</span>	<span class="c1"># a if a is truthy; otherwise b</span>
<span class="n">a</span> <span class="o">&amp;&amp;</span> <span class="n">b</span>	<span class="c1"># b if a is truthy; otherwise a</span>
<span class="n">!a</span>	<span class="c1"># false if a is truthy; otherwise true</span>
</code></pre></div></div>

<p>Examples:</p>
<div class="language-elixir highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">iex</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span><span class="o">&gt;</span> <span class="mi">1</span> <span class="ow">or</span> <span class="mi">2</span>
<span class="o">**</span> <span class="p">(</span><span class="no">BadBooleanError</span><span class="p">)</span> <span class="n">expected</span> <span class="n">a</span> <span class="n">boolean</span> <span class="n">on</span> <span class="n">left</span><span class="o">-</span><span class="n">side</span> <span class="n">of</span> <span class="s2">"or"</span><span class="p">,</span> <span class="ss">got:</span> <span class="mi">1</span>

<span class="n">iex</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span><span class="o">&gt;</span> <span class="mi">1</span> <span class="o">||</span> <span class="mi">2</span>
<span class="mi">1</span>

<span class="n">iex</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span><span class="o">&gt;</span> <span class="no">true</span> <span class="ow">or</span> <span class="no">false</span>
<span class="no">true</span>

<span class="n">iex</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span><span class="o">&gt;</span> <span class="s2">"foo"</span> <span class="ow">and</span> <span class="s2">"bar"</span>
<span class="o">**</span> <span class="p">(</span><span class="no">BadBooleanError</span><span class="p">)</span> <span class="n">expected</span> <span class="n">a</span> <span class="n">boolean</span> <span class="n">on</span> <span class="n">left</span><span class="o">-</span><span class="n">side</span> <span class="n">of</span> <span class="s2">"and"</span><span class="p">,</span> <span class="ss">got:</span> <span class="s2">"foo"</span>

<span class="n">iex</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span><span class="o">&gt;</span> <span class="s2">"foo"</span> <span class="o">&amp;&amp;</span> <span class="s2">"bar"</span>
<span class="s2">"bar"</span>

<span class="n">iex</span><span class="p">(</span><span class="mi">3</span><span class="p">)</span><span class="o">&gt;</span> <span class="ow">not</span> <span class="s2">"foo"</span>
<span class="o">**</span> <span class="p">(</span><span class="no">ArgumentError</span><span class="p">)</span> <span class="n">argument</span> <span class="n">error</span>
    <span class="ss">:erlang</span><span class="o">.</span><span class="ow">not</span><span class="p">(</span><span class="s2">"foo"</span><span class="p">)</span>

<span class="n">iex</span><span class="p">(</span><span class="mi">3</span><span class="p">)</span><span class="o">&gt;</span> <span class="n">!</span><span class="s2">"foo"</span>
<span class="no">false</span>
</code></pre></div></div>]]></content><author><name>Burak Kaymakci</name></author><category term="TIL" /><category term="Elixir" /><category term="elixir" /><summary type="html"><![CDATA[There’s subtle difference between Elixir boolean operators. Namely between or and ||, and and &amp;&amp;, not and !.]]></summary></entry><entry><title type="html">macOS openssl file not found while installing Ruby gems</title><link href="https://andreyuhai.github.io/macos-openssl-file-not-found-error-while-installing-ruby-gems/" rel="alternate" type="text/html" title="macOS openssl file not found while installing Ruby gems" /><published>2021-05-04T00:00:00+02:00</published><updated>2021-05-04T00:00:00+02:00</updated><id>https://andreyuhai.github.io/macos-openssl-file-not-found-error-while-installing-ruby-gems</id><content type="html" xml:base="https://andreyuhai.github.io/macos-openssl-file-not-found-error-while-installing-ruby-gems/"><![CDATA[<p>While installing Ruby gems on macOS, you might encounter an error like:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>In file included from binder.cpp:20:
./project.h:119:10: fatal error: <span class="s1">'openssl/ssl.h'</span> file not found
<span class="c">#include &lt;openssl/ssl.h&gt;</span>
         ^~~~~~~~~~~~~~~
1 error generated.
make: <span class="k">***</span> <span class="o">[</span>binder.o] Error 1

make failed, <span class="nb">exit </span>code 2

Gem files will remain installed <span class="k">in</span> /Users/burak/.rvm/gems/ruby-3.0.1/gems/eventmachine-1.2.7 <span class="k">for </span>inspection.
</code></pre></div></div>

<p>That was the case for me when I was trying to install <code class="language-plaintext highlighter-rouge">jekyll</code> gem using <code class="language-plaintext highlighter-rouge">gem install jekyll</code>.</p>

<p>Solution is to do:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>gem install jekyll -- --with-cppflags=-I/opt/homebrew/opt/openssl/include
</code></pre></div></div>]]></content><author><name>Burak Kaymakci</name></author><category term="TIL" /><category term="Ruby" /><category term="ruby" /><category term="ruby-gems" /><category term="macOS" /><category term="jekyll" /><summary type="html"><![CDATA[While installing Ruby gems on macOS, you might encounter an error like: ```bash In file included from binder.cpp:20: ./project.h:119:10: fatal error: ‘openssl/ssl.h’ file not found #include &lt;openssl/ssl.h&gt; ^~~~~~~~~~~~~~~ 1 error generated. make: *** [binder.o] Error 1]]></summary></entry></feed>