<?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>Forem: mohieddin</title>
    <description>The latest articles on Forem by mohieddin (@mohie93).</description>
    <link>https://forem.com/mohie93</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%2F255164%2F648edad7-7278-4cdc-a1a6-3d28c6c63766.jpeg</url>
      <title>Forem: mohieddin</title>
      <link>https://forem.com/mohie93</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/mohie93"/>
    <language>en</language>
    <item>
      <title>Event tracking with Mixpanel and NodeJs, The Callback in Async scope magic!</title>
      <dc:creator>mohieddin</dc:creator>
      <pubDate>Mon, 21 Mar 2022 16:29:14 +0000</pubDate>
      <link>https://forem.com/mohie93/event-tracking-with-mixpanel-and-nodejs-je6</link>
      <guid>https://forem.com/mohie93/event-tracking-with-mixpanel-and-nodejs-je6</guid>
      <description>&lt;h3&gt;
  
  
  Hello World!
&lt;/h3&gt;

&lt;p&gt;It's been a while (a long long time ago 🙄 ) since my last post, long story short there is no specific reason, just me lazy to post.&lt;/p&gt;

&lt;h3&gt;
  
  
  Note:
&lt;/h3&gt;

&lt;p&gt;I'm not going through what is &lt;a href="https://mixpanel.com/"&gt;Mixpanel&lt;/a&gt; and why we decided to use it at &lt;a href="https://www.supahands.ai/"&gt;Supahands&lt;/a&gt;, the focus here is on a challenge we faced and how we tackled it&lt;/p&gt;

&lt;h3&gt;
  
  
  Use case:
&lt;/h3&gt;

&lt;p&gt;We've been working on integrating an event tracking service to one of our backend APIs, so we can have a clear eye on our users' behaviour and interaction with our platform, so we can prioritise features and manage building iterations in a more user-oriented way, and our integration of choice is &lt;a href="https://mixpanel.com/"&gt;Mixpanel&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Challenge we are trying to solve
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://mixpanel.com/"&gt;Mixpanel&lt;/a&gt; NodeJs library's functions are built as &lt;a href="https://nodejs.org/en/knowledge/getting-started/control-flow/what-are-callbacks/"&gt;callback&lt;/a&gt; and our code base is an ExpressJs app encapsulated in an AWS Lambda using the serverless framework "&lt;em&gt;I'll share why in another post&lt;/em&gt;" and in our code base we are using &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function"&gt;async/await&lt;/a&gt;, And the question at that time was how to integrate the callback behaviour inside an async/await function?&lt;/p&gt;

&lt;p&gt;What we did first 👇&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="c1"&gt;// Mixpanel Service&lt;/span&gt;
&lt;span class="c1"&gt;// path: /src/services/mixpanel-service.js&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mixpanel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mixpanel&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;TOKEN&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// We tried to wrap it with async/await to consist the&lt;/span&gt;
&lt;span class="c1"&gt;// codebase style and to avoid callback hell.&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;track&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;mixpanel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;track&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;track&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="c1"&gt;// Customer Model&lt;/span&gt;
&lt;span class="c1"&gt;// path: /src/models/customer-model.js&lt;/span&gt;

&lt;span class="c1"&gt;// database interface instance&lt;/span&gt;
&lt;span class="c1"&gt;// we are using knex.js -&amp;gt; https://knexjs.org&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../configs/database-configs.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mixpanel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../services/mixpanel-service.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;Customer&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fullName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;brand&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fullName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;fullName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;brand&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;customers&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;insert&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;fullName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;brand&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;mixpanel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;track&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;customer creation succeed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;fullName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;brand&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;mixpanel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;track&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;customer creation failed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;fullName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;brand&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above code did nothing in terms of tracking, and it throw no error and the function did not behave as an async/await function even after we wrapped it with async/await, because the execution is not ruled by the wrapper.&lt;/p&gt;

&lt;p&gt;As a syntax and code execution sequence, there is nothing wrong, but the code execution behaviour does not match the expected behaviour.&lt;/p&gt;

&lt;p&gt;The simple straightforward solution we considered was using &lt;a href="https://nodejs.org/dist/latest-v8.x/docs/api/util.html#util_util_promisify_original"&gt;promisify&lt;/a&gt; to force &lt;code&gt;mixpanel-service&lt;/code&gt; to adapt the async/await ( returning promise ) behaviour by wrapping the track function with promisify to change it to a function that returns a promise.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="c1"&gt;// Mixpanel Service&lt;/span&gt;
&lt;span class="c1"&gt;// path: /src/services/mixpanel-service.js&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;util&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;util&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mixpanel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mixpanel&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;TOKEN&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;trackAsync&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;util&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;promisify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mixpanel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;track&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// We tried to wrap it with async/await to consist the&lt;/span&gt;
&lt;span class="c1"&gt;// codebase style and to avoid callback hell.&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;track&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;trackAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;track&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="c1"&gt;// Customer Model&lt;/span&gt;
&lt;span class="c1"&gt;// path: /src/models/customer-model.js&lt;/span&gt;

&lt;span class="c1"&gt;// database interface instance&lt;/span&gt;
&lt;span class="c1"&gt;// we are using knex.js -&amp;gt; https://knexjs.org&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../configs/database-configs.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mixpanel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../services/mixpanel-service.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;Customer&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fullName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;brand&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fullName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;fullName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;brand&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;customers&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;insert&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;fullName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;brand&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;mixpanel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;track&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;customer creation succeed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;fullName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;brand&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;mixpanel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;track&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;customer creation failed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;fullName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;brand&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above code matched the expected output and logged the events inside our Mixpanel project's dashboard.&lt;/p&gt;

&lt;h3&gt;
  
  
  Takeaway notes:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Read&lt;/strong&gt; the library that you want to use in your project and understand its behaviour and implementations.&lt;/li&gt;
&lt;li&gt;Wrapping callback-based function in async/await block will not change that function behaviour if there is no promise implementation to that function&lt;/li&gt;
&lt;li&gt;Learning by doing and researching is a great joy.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sorry in advance for any grammar mistake or typo 👻.&lt;br&gt;
If you have any concerns or feedback I'm all ears👂.&lt;/p&gt;

&lt;p&gt;cheers.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>aws</category>
      <category>node</category>
      <category>serverless</category>
    </item>
    <item>
      <title>Baby Steps in Golang</title>
      <dc:creator>mohieddin</dc:creator>
      <pubDate>Wed, 22 Apr 2020 10:36:37 +0000</pubDate>
      <link>https://forem.com/mohie93/baby-steps-in-golang-4bi3</link>
      <guid>https://forem.com/mohie93/baby-steps-in-golang-4bi3</guid>
      <description>&lt;p&gt;Workplace is a proprietary product of &lt;a href="https://supahands.com/"&gt;Supahands&lt;/a&gt;.&lt;br&gt;
Our Business Operations Managers (BOMs) use the platform to manage our projects and SupaAgents (Supahands’ managed workforce).&lt;/p&gt;

&lt;p&gt;One of the main highlights of Workplace is labels — a feature that allows BOMs to match SupaAgents to projects depending on their skills and qualifications.&lt;/p&gt;

&lt;p&gt;Labels help with describing a SupaAgent’s skills and for our BOMs to identify SupaAgents with relevant skills that are required of them to join a project.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IL1q8vIf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/0xdnszi2hzw2ab8mo74k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IL1q8vIf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/0xdnszi2hzw2ab8mo74k.png" alt="labels"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Labels display the skills of a SupaAgent and requirements of a project.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;For example, Project 5UP4 requires SupaAgents with annotation skills, therefore, BOMs can change the settings of the project, SupaAgents without the label tag to their account will not be able to join the project.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The problem we were trying to solve…&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We experienced unexpected growth in September, where we had three times the number of SupaAgents coming on to Workplace. The platform had to load every single SupaAgent’s information, putting a strain on the system.&lt;/p&gt;

&lt;p&gt;Besides loading issues, the server was not responding due to the large amount of data it had to cope with. We initially attempted to solve the issue by increasing the number of CPUs that run our microservice but eventually came to realize that it was costly and inefficient to do so.&lt;/p&gt;

&lt;p&gt;We knew we had to take the next course of action ⁠ — to rewrite the microservice of Workplace.&lt;/p&gt;

&lt;p&gt;The previous microservice was built using Java (spring-boot framework) and GraphQL (neo4j), which were not suitable choices for rapid scaling. The software architecture was built in a way that could only allow us to handle the amount of SupaAgents that we had at that time. Naturally, as the number of users on the platform grew, Workplace began breaking.&lt;/p&gt;

&lt;p&gt;While faster load time was the priority in the reason for rewriting the microservice. Additionally, we needed to make changes to how information is displayed. The current view of labels for Projects and SupaAgents are presented separately. We needed to have them on display side by side as it allows our BOMs to match our Projects and SupaAgents faster.&lt;/p&gt;

&lt;p&gt;We started with looking for other programming languages, we initially looked at Typescript, C# as solutions. However, after taking a look at what other at scale tech companies were using as well and comparing the available languages from the criteria of succinctness, efficiency, performance, power, reliability and community support, we arrived at using Golang.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why Golang?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KeJS_tGi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/4qs8zj03a0zxz6oe73t3.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KeJS_tGi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/4qs8zj03a0zxz6oe73t3.jpeg" alt="Golang"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Golang is a procedural programming language developed in 2007 by Robert Griesemer, Rob Pike, and Ken Thompson at Google. It was launched in 2009 as an open-source programming language.&lt;/p&gt;

&lt;p&gt;Golang fulfilled all of our criteria as well as having the bonus of being open source and the community that grew around it was a vibrant, welcoming and fun group.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Roadblocks faced while learning Golang&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Golang is a new programming language within the engineering team. We had to learn it from scratch, from the concepts of how the language is built on to the actual application of it.&lt;/p&gt;

&lt;p&gt;It was only natural that we faced roadblocks along the way…&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Syntax&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Golang syntax is new for a person with a background in python, ruby on rails and javascript, in terms of defining functions, manipulating arrays and defining classes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vckbvRWt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/8q7onxmd3fbvjk0dbtff.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vckbvRWt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/8q7onxmd3fbvjk0dbtff.png" alt="Syntax"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Golang’s representation of Object-Oriented Programming&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Golang’s representation of Object Oriented Programming concepts in a different way so you have structs instead of classes and you can apply inheritance by embedding the parent structure inside child structure.&lt;/p&gt;

&lt;p&gt;For example, to define a class in Javascript, C#, Typescript, you can use the keyword Class&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CM72nleT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/mc5ldl1d3kd5v5lui91f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CM72nleT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/mc5ldl1d3kd5v5lui91f.png" alt="class1"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But on Golang it’s a different class represented by a data-structure called struct&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--p4NeWWNU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/qtkcyotj0kitz7mp5vuv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--p4NeWWNU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/qtkcyotj0kitz7mp5vuv.png" alt="class2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Another example is an inheritance, to inherit from a class in PHP, we can use the keyword extends&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--i7lby9KX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/kjf1gjueprkpnbvog3qx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--i7lby9KX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/kjf1gjueprkpnbvog3qx.png" alt="class3"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In C#, we can use the symbol “ : ”&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8VHcqsb0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/as3q45vqfk0ffmxrf3rt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8VHcqsb0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/as3q45vqfk0ffmxrf3rt.png" alt="class4"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But in Golang, you are embedding a struct into another one, ex:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vp6gAicV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/b5u2pn3b4cruzqx8jrxh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vp6gAicV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/b5u2pn3b4cruzqx8jrxh.png" alt="class5"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;All in all, Golang is a solid programming language, providing simplicity, efficiency, speed, and reliability with less code to write. As I’ve just started my Golang journey, I have received large community support, so it’s easy to find an answer to any questions you may have. You can spend three to four hours to learn the concepts of the language, then you can easily start building applications because Golang provides a large pool of packages and frameworks to make your life easier, and the good thing most of (if not all) packages are open-source, so you can easily modify them to serve your needs.&lt;/p&gt;

</description>
      <category>go</category>
      <category>babysteps</category>
      <category>learning</category>
    </item>
  </channel>
</rss>
