<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ actor model - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ actor model - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Fri, 22 May 2026 17:40:40 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/actor-model/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ The boring technology behind a one-person Internet company ]]>
                </title>
                <description>
                    <![CDATA[ By Wenbin Fang Listen Notes is a podcast search engine and database. The technology behind Listen Notes is actually very very boring. No AI, no deep learning, no blockchain. “Any man who must say I am using AI is not using True AI” :) After reading t... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/the-boring-technology-behind-a-one-person-internet-company/</link>
                <guid isPermaLink="false">66d4617c2472e5ed2fa07bc7</guid>
                
                    <category>
                        <![CDATA[ actor model ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Entrepreneurship ]]>
                    </category>
                
                    <category>
                        <![CDATA[ podcast ]]>
                    </category>
                
                    <category>
                        <![CDATA[ solopreneur  ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Startups ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Mon, 10 Jun 2019 21:51:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2019/06/1_83ZzjS6ZhVWvZdnoozElOw.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Wenbin Fang</p>
<p><a target="_blank" href="https://www.listennotes.com/">Listen Notes</a> is a podcast search engine and database. The technology behind Listen Notes is actually very very boring. No AI, no deep learning, no blockchain. <a target="_blank" href="https://www.youtube.com/watch?v=4sJY7BTIuPY">“Any man who must say I am using AI is not using True AI”</a> :)</p>
<p>After reading this post, you should be able to replicate what I build for Listen Notes or easily do something similar. You don’t need to hire a lot of engineers. Remember, <a target="_blank" href="https://www.crunchbase.com/organization/instagram#section-funding-rounds">when Instagram raised $57.5M and got acquired by Facebook for $1B</a>, they had only <a target="_blank" href="https://www.businessinsider.com/instagram-employees-and-investors-2012-4">13 employees</a> — not all of them were engineers. The Instagram story happened in early 2012. It’s 2019 now, it’s more possible than ever to build something meaningful with a tiny engineering team — even one person.</p>
<p>If you haven’t used Listen Notes yet , try it now:</p>
<p><a target="_blank" href="https://www.listennotes.com/">https://www.listennotes.com/</a></p>
<h3 id="heading-overview">Overview</h3>
<p>Let’s start with requirements or features of this Listen Notes project.</p>
<p>Listen Notes provides two things to end users:</p>
<ul>
<li>A website <a target="_blank" href="https://www.listennotes.com/">ListenNotes.com</a> for podcast listeners. It provides a search engine, a podcast database, <a target="_blank" href="https://www.listennotes.com/listen/?s=nav">Listen Later</a> playlists, <a target="_blank" href="https://www.listennotes.com/clips/?s=nav">Listen Clips</a> that allows you to cut a segment of any podcast episode, and <a target="_blank" href="https://www.listennotes.com/alerts">Listen Alerts</a> that notifies you when a specified keyword is mentioned in new podcasts on the Internet.</li>
<li><a target="_blank" href="https://www.listennotes.com/api/">Podcast Search &amp; Directory APIs</a> for developers. We need to track the API usage, get money from paid users, do customer support, and more.</li>
</ul>
<p>I run everything on AWS. There are 20 production servers (as of May 5, 2019):</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/06/1__HqlSoEW7JEDVnJ9rFSj7w.png" alt="Image" width="600" height="400" loading="lazy">
<em>The servers that run Listen Notes</em></p>
<p>You can easily guess what does each server do from the hostname.</p>
<ul>
<li><strong>production-web</strong> serves web traffics for <a target="_blank" href="https://www.listennotes.com/">ListenNotes.com</a>.</li>
<li><strong>production-api</strong> serves api traffics. We run two versions of API (as of May 4, 2019), thus v1api (the legacy version) and v2api (the new version).</li>
<li><strong>production-db</strong> runs PostgreSQL (primary and replica)</li>
<li><strong>production-es</strong> runs an Elasticsearch cluster.</li>
<li><strong>production-worker</strong> runs offline processing tasks to keep the podcast database always up-to-date and to provide some magical things (e.g., search result ranking, episode/podcast recommendations…).</li>
<li><strong>production-lb</strong> is the load balancer. I also run Redis &amp; RabbitMQ on this server, for convenience. I know this is not ideal. But I’m not a perfect person :)</li>
<li><strong>production-pangu</strong> is the production-like server that I sometimes run one-off scripts and test changes. What’s the meaning of “<a target="_blank" href="https://en.wikipedia.org/wiki/Pangu">pangu</a>”?</li>
</ul>
<p>Most of these servers can be horizontally scaled. That’s why I name them <em>production-something1</em>, <em>production-something2</em>… It could be very easy to add <em>production-something3</em> and <em>production-something4</em> to the fleet.</p>
<h3 id="heading-backend">Backend</h3>
<p>The entire backend is written in Django / Python3. The operating system of choice is Ubuntu.</p>
<p>I use <a target="_blank" href="https://uwsgi-docs.readthedocs.io/en/latest/">uWSGI</a> to serve web traffics. I put <a target="_blank" href="https://www.nginx.com/">NGINX</a> in front of uWSGI processes, which also serves as load balancer.</p>
<p>The main data store is <a target="_blank" href="https://www.postgresql.org/">PostgreSQL</a>, which I’ve got a lot of development &amp; operational experience over many years — battle tested technology is good, so I can sleep well at night. <a target="_blank" href="https://redis.io/">Redis</a> is used for various purposes (e.g., caching, stats,…). It’s not hard to guess that <a target="_blank" href="https://www.elastic.co/">Elasticsearch</a> is used somewhere. Yes, I use Elasticsearch to index podcasts &amp; episodes and to serve search queries, just like <a target="_blank" href="https://medium.com/netflix-techblog/tagged/elasticsearch">most</a> <a target="_blank" href="https://engineeringblog.yelp.com/2017/06/moving-yelps-core-business-search-to-elasticsearch.html">boring</a> <a target="_blank" href="https://eng.uber.com/tag/elasticsearch/">companies</a>.</p>
<p><a target="_blank" href="http://www.celeryproject.org/">Celery</a> is used for offline processing. And <a target="_blank" href="http://docs.celeryproject.org/en/latest/userguide/periodic-tasks.html">Celery Beat</a> is for scheduling tasks, which is like Cron jobs but a bit nicer. If in the future Listen Notes gains traction and Celery &amp; Beat cause some scaling issues, I probably will switch to the two projects I did for my previous employer: <a target="_blank" href="https://github.com/Nextdoor/ndkale">ndkale</a> and <a target="_blank" href="https://github.com/Nextdoor/ndscheduler">ndscheduler</a>.</p>
<p><a target="_blank" href="http://supervisord.org/">Supervisord</a> is used for process management on every server.</p>
<p>Wait, how about Docker / Kubernetes / serverless? Nope. As you gain experience, you know when not to over-engineer. I actually did some early Docker work for my previous employer back in 2014, which was good for a mid-sized billion-dollar startup but may be overkill for a one-person tiny startup.</p>
<h3 id="heading-frontend">Frontend</h3>
<p>The web frontend is primarily built with <a target="_blank" href="https://reactjs.org/">React</a> + <a target="_blank" href="https://redux.js.org/">Redux</a> + <a target="_blank" href="https://webpack.js.org/">Webpack</a> + <a target="_blank" href="https://en.wikipedia.org/wiki/ECMAScript">ES</a>. This is pretty standard nowadays. When deploying to production, JS bundles would be uploaded to <a target="_blank" href="https://aws.amazon.com/s3/">Amazon S3</a> and served via <a target="_blank" href="https://aws.amazon.com/cloudfront/">CloudFront</a>.</p>
<p>On <a target="_blank" href="https://www.listennotes.com/">ListenNotes.com</a>, most web pages are half server-side rendered (<a target="_blank" href="https://docs.djangoproject.com/en/2.0/topics/templates/">Django template</a>) and half client-side rendered (<a target="_blank" href="https://reactjs.org/">React</a>). The server-side rendered part provides a boilerplate of a web page, and the client-side rendered part is basically an interactive web app. But a few web pages are rendered entirely via server side, because of my laziness to make things perfect &amp; some potential SEO goodies.</p>
<h4 id="heading-audio-player">Audio player</h4>
<p>I use a heavily modified version of <a target="_blank" href="https://github.com/souporserious/react-media-player">react-media-player</a> to build the audio player on ListenNotes.com, which is used in several places, including <a target="_blank" href="https://www.listennotes.com/p/321dd0ce5b974079bd3fc8d65d132912/">Listen Notes Website</a>, <a target="_blank" href="https://twitter.com/ListenHistoryFM/status/955913550605688832">Twitter embedded player</a>, and embedded player on 3rd party websites:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/06/1_R9SqwWtGOKvL0MqOBvsMrA.png" alt="Image" width="600" height="400" loading="lazy">
<em>Embedded player on 3rd party websites</em></p>
<h3 id="heading-podcast-api">Podcast API</h3>
<p>We provide a simple and reliable <a target="_blank" href="https://www.listennotes.com/api/">podcast API</a> to developers. Building the API is similar to building <a target="_blank" href="https://www.listennotes.com/">the website</a>. I use the same Django/Python stack for the backend, and ReactJs for the frontend (e.g., API dashboard, documentation…).</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/06/1_6s_rx2FAKEJiHy7K6gEwdA.png" alt="Image" width="600" height="400" loading="lazy">
<em>Listen API dashboard</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/06/1_dYUinicZH-m6HZPpE1MXBg.png" alt="Image" width="600" height="400" loading="lazy">
<em>Listen API documentation</em></p>
<p>For the API, we need to track how many requests a user use in current billing cycle, and charge $$$ at the end of a billing cycle. It’s not hard to imagine that Redis is heavily used here :)</p>
<h3 id="heading-devops">DevOps</h3>
<h4 id="heading-machine-provisioning-amp-code-deployment">Machine provisioning &amp; code deployment</h4>
<p>I use <a target="_blank" href="http://docs.ansible.com/">Ansible</a> for machine provisioning. Basically, I wrote a bunch of yaml files to specify what type of servers need to have what configuration files &amp; what software. I can spin up a server with all correct configuration files &amp; all software installed with one button push. This is the directory structure of those Ansible yaml files:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/06/1_oql35nt1Iak2FzniugFPSw.png" alt="Image" width="600" height="400" loading="lazy">
<em>I could’ve done a better job in naming things. But again, it’s good enough for now.</em></p>
<p>I also use Ansible to deploy code to production. Basically, I have a wrapper script <em>deploy.sh</em> that is run on macOS:</p>
<blockquote>
<p><em>./deploy.sh production HEAD web</em></p>
</blockquote>
<p>The deploy.sh script takes three arguments:</p>
<ul>
<li><strong>Environment</strong>: production or staging.</li>
<li><strong>Version of the listennotes repo</strong>: HEAD means “just deploy the latest version”. If a SHA of a git commit is specified, then it’ll deploy a specific version of code — this is particularly useful when I need to rollback from a bad deployment.</li>
<li><strong>What kind of servers</strong>: web, worker, api, or all. I don’t have to deploy to all servers all at once. Sometimes I make changes on Javascript code, then I just need to deploy to web, without touching api or worker.</li>
</ul>
<p>The deployment process is mostly orchestrated by Ansible yaml files, and of course, it’s dead simple:</p>
<ul>
<li><strong>On my Macbook Pro</strong>, if it’s to deploy to web servers, then build Javascript bundles and upload to S3.</li>
<li><strong>On the target servers</strong>, git clone the listennotes repo to a timestamp-named folder, check out the specific version, and pip install new Python dependencies if any.</li>
<li><strong>On the target servers</strong>, switch symlink to the above timestamp-named folder and restart servers via supervisorctl.</li>
</ul>
<p>As you can see, I don’t use those fancy CI tools. Just dead simple things that actually work.</p>
<h4 id="heading-monitoring-amp-alerting">Monitoring &amp; alerting</h4>
<p>I use <a target="_blank" href="https://www.datadoghq.com/">Datadog</a> for monitoring &amp; alerting. I’ve got some high level metrics in a simple dashboard. Whatever I do here is to boost my confidence when I am messing around the production servers.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/06/1_nrvlxilaFwNJtZDeGt01fQ.png" alt="Image" width="600" height="400" loading="lazy">
<em>Datadog dashboard for Listen Notes, as of Dec 2017.</em></p>
<p>I connect <a target="_blank" href="https://www.datadoghq.com/">Datadog</a> to PagerDuty. If something goes wrong, <a target="_blank" href="https://www.pagerduty.com/">PagerDuty</a> will send me alerts via phone call &amp; SMS.</p>
<p>I also use <a target="_blank" href="https://rollbar.com/">Rollbar</a> to keep an eye on the health of Django code, which will catch unexpected exceptions and notify me via email &amp; Slack as well.</p>
<p>I use <a target="_blank" href="https://slack.com/">Slack</a> a lot. Yes, this is a one-person company, so I don’t use Slack for communicating with human beings. I use Slack to monitor interesting application-level events. In addition to integrating Datadog and Rollbar with Slack, I also use <a target="_blank" href="https://api.slack.com/incoming-webhooks">Slack incoming webhooks</a> in Listen Notes backend code to notify me whenever a user signs up or performs some interesting actions (e.g., adding or deleting things). This is a very common practice in tech companies. When you read some books about Amazon or PayPal’s early history, you’ll know that both companies had similar notification mechanism: whenever a user signed up, there would be a “ding” sound to notify everyone in the office.</p>
<p>Since launched in early 2017, Listen Notes hasn’t got any big outage (&gt; 5 minutes) except for <a target="_blank" href="https://broadcast.listennotes.com/postmortem-on-apr-22-2018-outage-e5a87723d003">this one</a>. I’m always very careful &amp; practical in these operational stuffs. The web servers are significantly over-provisioned, just in case there’s some huge spike due to press events or whatever.</p>
<h3 id="heading-development">Development</h3>
<p>I work in a <a target="_blank" href="https://refer.wework.com/i/WenbinFang">WeWork</a> coworking space in San Francisco. Some people may wonder why not just work from home or from some random coffee shops. Well, I value productivity a lot and I’m willing to invest money in productivity. I don’t believe piling time helps software development (or any soft of knowledge/creativity work). It’s rare that I work over 8 hours in a day (Sorry, <a target="_blank" href="https://www.nytimes.com/2019/04/29/technology/china-996-jack-ma.html">996 people</a>). I want to make every minute count. Thus, a nice &amp; relatively expensive private office is what I need :) Instead of optimizing for spending more time &amp; saving money, I optimize for spending less time &amp; making money :)</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/06/1_LqJym-17rqU-vyNzanCiVA.jpeg" alt="Image" width="600" height="400" loading="lazy">
<em>My office at WeWork</em></p>
<p>I’m using a MacBook Pro. I run the (almost) identical infrastructure inside <a target="_blank" href="https://www.vagrantup.com/">Vagrant</a> + <a target="_blank" href="https://www.virtualbox.org/wiki/Downloads">VirtualBox</a>. I use the same set of Ansible yaml files as described above to provision the development environment inside Vagrant.</p>
<p>I subscribe to the <a target="_blank" href="https://danluu.com/monorepo/">monolithic repo</a> philosophy. So there’s one and only one listennotes repo, containing DevOps scripts, frontend &amp; backend code. This listennotes repo is hosted as a GitHub private repo. I do all development work on the main branch. I rarely use feature branches.</p>
<p>I write code and run the dev servers (Django runserver &amp; webpack dev server) by using <a target="_blank" href="https://www.jetbrains.com/pycharm/">PyCharm</a>. Yea, I know, it’s boring. After all, it’s not Visual Studio Code or Atom or whatever cool IDEs. But PyCharm works just fine for me. I’m old school.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/06/1_0qlv-bne1Ld2wuUxCeDFwQ.png" alt="Image" width="600" height="400" loading="lazy">
<em>My PyCharm</em></p>
<h3 id="heading-miscellaneous">Miscellaneous</h3>
<p>There are a bunch of useful tools &amp; services that I use to build Listen Notes as a product and a company:</p>
<ul>
<li><a target="_blank" href="https://www.iterm2.com/">iTerm2</a> and <a target="_blank" href="https://github.com/tmux/tmux/wiki">tmux</a> for the terminal stuffs.</li>
<li><a target="_blank" href="https://www.notion.so/?r=d1e4526dd2924f4796cd10235cbe132e">Notion</a> for TODO lists, wiki, taking notes, design documents…</li>
<li><a target="_blank" href="https://gsuite.google.com/">G Suite</a> for @listennotes.com email account, calendar, and other Google services.</li>
<li><a target="_blank" href="http://www.mailchimp.com/monkey-rewards/?utm_source=freemium_newsletter&amp;utm_medium=email&amp;utm_campaign=monkey_rewards&amp;aid=da29e56f1e479faf6b4ef3f72&amp;afl=1">MailChimp</a> for sending the <a target="_blank" href="https://us16.campaign-archive.com/home/?u=da29e56f1e479faf6b4ef3f72&amp;id=ba72067923">monthly email newsletter</a>.</li>
<li><a target="_blank" href="https://aws.amazon.com/ses/">Amazon SES</a> for sending transactional &amp; some marketing emails.</li>
<li><a target="_blank" href="https://gusto.com/r/wenbin">Gusto</a> to pay myself and contractors who are not from Upwork.</li>
<li><a target="_blank" href="https://www.upwork.com/">Upwork</a> to find contractors.</li>
<li><a target="_blank" href="https://admanager.google.com/home/">Google Ads Manager</a> to mange direct sales ads and track performance.</li>
<li><a target="_blank" href="https://www.carbonads.net/">Carbon Ads</a> and <a target="_blank" href="https://www.buysellads.com/">BuySellAds</a> for fallback ads.</li>
<li><a target="_blank" href="https://www.cloudflare.com/">Cloudflare</a> for DNS management, CDN, and firewall.</li>
<li><a target="_blank" href="https://zapier.com/">Zapier</a> and <a target="_blank" href="https://trello.com/">Trello</a> to streamline the <a target="_blank" href="https://www.listennotes.com/interviews/">podcaster interview</a> workflow.</li>
<li><a target="_blank" href="https://broadcast.listennotes.com/">Medium</a> for the company blog (obviously).</li>
<li><a target="_blank" href="https://www.godaddy.com/">Godaddy</a> and <a target="_blank" href="https://www.namecheap.com/">Namecheap</a> for domain names.</li>
<li><a target="_blank" href="https://stripe.com/">Stripe</a> for getting money from users (primarily for <a target="_blank" href="https://www.listennotes.com/api/">API</a>).</li>
<li><a target="_blank" href="https://cloud.google.com/speech-to-text/">Google speech-to-text API</a> to transcribe episodes.</li>
<li><a target="_blank" href="https://healthy.kaiserpermanente.org/">Kaiser Permanente</a> for health insurance.</li>
<li><a target="_blank" href="https://atlas.stripe.com/">Stripe Atlas</a> to incorporate Listen Notes, Inc.</li>
<li><a target="_blank" href="https://www.clerky.com/">Clerky</a> to generate legal documents for fund raising (SAFE) and hiring contractors who are not from Upwork.</li>
<li><a target="_blank" href="https://www.referquickbooks.com/s/Wenbin">Quickbooks</a> for bookkeeping.</li>
<li><a target="_blank" href="https://1password.com/">1password</a> to manage login credentials for tons of services.</li>
<li><a target="_blank" href="http://brex.com/signup?rc=oPLQ0ZQ">Brex</a> for charge card — you can get incremental $5000 AWS credits, which can be applied on top of the AWS credits from WeWork or Stripe Atlas.</li>
<li><a target="_blank" href="http://refer.amex.us/WENBIFIUoH?XLINK=MYCP">Bonvoy Business Amex Card</a> — You can earn Marriott Bonvoy points for luxury hotels and flights. It’s the best credit card points for traveling :)</li>
<li><a target="_blank" href="https://www.capitalone.com/small-business-bank/">Capital One Spark</a> for checking account.</li>
</ul>
<h3 id="heading-keep-calm-and-carry-on">Keep calm and carry on…</h3>
<p>As you can see, we are living in a wonderful age to start a company. There are so many off-the-shelf tools and services that save us time &amp; money and increase our productivity. It’s more possible than ever to build something useful to the world with a tiny team (or just one person), using simple &amp; boring technology.</p>
<p>As time goes, companies become smaller and smaller. You don’t need to hire tons of full-time employees. You can hire services (SaaS) and on-demand contractors to get things done.</p>
<p>Most of time, the biggest obstacle of building &amp; shipping things is over thinking. What if this, what if that. Boy, you are not important at all. Everyone is busy in their own life. No one cares about you and the things you build, until you prove that you are worth other people’s attention. Even you screw up the initial product launch, few people will notice. <a target="_blank" href="https://hackernoon.com/think-big-start-small-act-fast-6fdab1f771ea">Think big, start small, act fast</a>. It’s absolutely okay to use the boring technology and start something simple (even ugly), as long as you actually solve problems.</p>
<div class="embed-wrapper">
        <blockquote class="twitter-tweet">
          <a href="https://twitter.com/wenbinf/status/1082725746160746496?ref_src=twsrc%5Etfw%7Ctwcamp%5Etweetembed%7Ctwterm%5E1082725746160746496&amp;ref_url=https%3A%2F%2Fbroadcast.listennotes.com%2Fmedia%2F622ba96d011f0ebfd9712504b7e353c3%3FpostId%3D56697c2e347b"></a>
        </blockquote>
        <script defer="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script></div>
<p>There are so many <a target="_blank" href="http://stevemcconnell.com/articles/cargo-cult-software-engineering/">cargo-cult</a>-type people now. Ignore the noises. Keep calm and carry on.</p>
<hr>
<p>If you haven’t used Listen Notes yet , try it now:</p>
<p><a target="_blank" href="https://www.listennotes.com/">https://www.listennotes.com/</a></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to implement an Object-Pool with an Actor in Kotlin ]]>
                </title>
                <description>
                    <![CDATA[ By osha1 We use object pool in jasync-sql to manage connections to the database. In this post, I will share how it is done in a performant, lock-free manner using Kotlin coroutines with an Actor. An object pool has a very simple API to work with. It ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-implement-an-object-pool-with-an-actor-in-kotlin-ed06d3ba6257/</link>
                <guid isPermaLink="false">66c352b4c2631756f9f063d3</guid>
                
                    <category>
                        <![CDATA[ actor model ]]>
                    </category>
                
                    <category>
                        <![CDATA[ concurrency ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Kotlin ]]>
                    </category>
                
                    <category>
                        <![CDATA[ General Programming ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Fri, 09 Nov 2018 19:33:37 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/0*0aDugHie8xlGjhOZ" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By osha1</p>
<p>We use object pool in <a target="_blank" href="https://github.com/jasync-sql/jasync-sql">jasync-sql</a> to manage connections to the database. In this post, I will share how it is done in a performant, lock-free manner using Kotlin coroutines with an Actor.</p>
<p>An object pool has a very simple API to work with. It is a pool of objects with two methods: <code>take()</code> and <code>return()</code>.</p>
<p>On first sight it looks like a very simple problem. The main catch here is that it has to be both performant and thread-safe, and that’s what makes it interesting and tricky to implement.</p>
<h3 id="heading-but-hey-why-do-we-need-an-object-pool-anyway">But hey! Why do we need an object pool anyway?</h3>
<p><a target="_blank" href="https://github.com/jasync-sql/jasync-sql">jasync-sql</a> is a library to access relational databases like MySQL and PostgreSQL. Database connections are a great example of the need for object pools. The access to the database is done by obtaining a connection from a <strong>Connection-Pool</strong>, using it and returning it back to the pool.</p>
<p>With a connection pool we get a couple of advantages over creating connections per each SQL query:</p>
<ul>
<li><em>Reusing connections</em> — since the overhead of initiating a connection to the database is high (handshake, etc), connection pools allow keeping connections alive, thus reducing that overhead.</li>
<li><em>Limiting resources</em> — creating a DB connection per user request can be overwhelming to the DB. Using a pool effectively adds a barrier, limiting the number of maximum number of concurrent connections.</li>
</ul>
<blockquote>
<p>Well, I am sold, but…</p>
</blockquote>
<h3 id="heading-isnt-a-connection-pool-a-solved-problem-in-the-java-world">Isn’t a Connection Pool a solved problem in the Java world?</h3>
<p>Yes it is a solved problem if you’re using <a target="_blank" href="https://docs.oracle.com/javase/8/docs/technotes/guides/jdbc/">JDBC</a>. In that case <a target="_blank" href="https://brettwooldridge.github.io/HikariCP/">HikariCP</a> is an excellent choice from my experience, but there are a lot of others. In the case of jasync-sql it is not possible to use <a target="_blank" href="https://brettwooldridge.github.io/HikariCP/">HikariCP</a>, because <a target="_blank" href="https://brettwooldridge.github.io/HikariCP/">HikariCP</a> works with the JDBC API, and the jasync-sql driver is not implementing that full-fledged API, only a subset of it.</p>
<blockquote>
<p>What about other Object pools in Java world?</p>
</blockquote>
<p>There are numerous implementations, but it turns out that you usually find some specific requirement that was not implemented by that pool you’re using.</p>
<p>In our case, that requirement was non-blocking. In our pool, all operations have to be non-blocking since the library is async. For example, the <code>take()</code> operation in most implementations returns an object immediately or blocks until an object is ready. Our <code>take()</code> returns a <code>Future&lt;Connecti</code>on&gt;, which will be completed and continued when the connection is ready to use.</p>
<p>I haven’t seen such an implementation in the wild.</p>
<p>I really like this answer from Stack Exchange:</p>
<p><a target="_blank" href="https://softwareengineering.stackexchange.com/questions/115163/is-object-pooling-a-deprecated-technique"><strong>Is object pooling a deprecated technique?</strong></a><br><a target="_blank" href="https://softwareengineering.stackexchange.com/questions/115163/is-object-pooling-a-deprecated-technique">_Software Engineering Stack Exchange is a question and answer site for professionals, academics, and students working…_softwareengineering.stackexchange.com</a></p>
<p>Another requirement that makes it hard to find an alternative is the need to try and stay compatible as much as possible with the current implementation we have.</p>
<p>In case you want to see other implementations you can check here:</p>
<p><a target="_blank" href="https://www.google.co.il/search?q=object+pool+in+java"><strong>object pool in java - Google Search</strong></a><br><a target="_blank" href="https://www.google.co.il/search?q=object+pool+in+java">_object pool is a collection of a particular object that an application will create and keep on hand for those…_www.google.co.il</a></p>
<h3 id="heading-so-how-did-we-implement-object-pool">So how did we implement Object Pool?</h3>
<p>Before we dive into the details, let’s observe other requirements from the object pool that were omitted above for clarity but are necessary details.</p>
<h4 id="heading-interfaces">Interfaces</h4>
<p>The Object pool interface looks like this:</p>
<pre><code>interface AsyncObjectPool&lt;T&amp;gt; {  fun take(): CompletableFuture&amp;lt;T&gt;  fun giveBack(item: T): CompletableFuture&lt;AsyncObjectPool&lt;T&gt;&gt;  fun close(): CompletableFuture&lt;AsyncObjectPool&lt;T&gt;&gt;
</code></pre><pre><code>}
</code></pre><p>In addition, when a pool wants to create new objects (connections) it will call the <code>ObjectFactory</code>. The factory has a couple more methods to handle the object lifecycle:</p>
<ul>
<li><em>validate</em> — a method to check that the object is still valid. The method should be fast and check only in-memory constructs. For connections we usually check that the last query did not throw an exception and did not get a termination message from <a target="_blank" href="https://netty.io/">netty</a>.</li>
<li><em>test</em> — similar to validate, but a more exhaustive check. We allow test method to be slow and access the network etc. This method is used to check that idle objects are still valid. For connections, that will be something similar to <code>select 0</code>.</li>
<li><em>destroy</em> — called to clean up the object when the pool is not using it anymore.</li>
</ul>
<p>The complete interface is:</p>
<pre><code>interface ObjectFactory&lt;T&gt; {  fun create(): CompletableFuture&lt;;out T&gt;  fun destroy(item: T)  fun validate(item: T): Try&lt;T&gt;  fun test(item: T): CompletableFuture&lt;T&gt;
</code></pre><pre><code>}
</code></pre><p>For pool configuration we have the following properties:</p>
<ul>
<li><code>maxObjects</code> — maximum number of connections we allow.</li>
<li><code>maxIdle</code> — time that we leave the connection open without use. After that time it will be reclaimed.</li>
<li><code>maxQueueSize</code> — when a request for a connection arrives and no connection is available, we put the request on hold in a queue. In case the queue is full (its size passed <code>maxQueueSize</code>) it will not wait but instead return an error.</li>
<li><code>createTimeout</code> — maximum time to wait for a new connection to be created.</li>
<li><code>testTimeout</code> — maximum time to wait for a test query on an idle connection. If it passes we will consider the connection as erroneous.</li>
<li><code>validationInterval</code> — on this interval, we will test if the idle connections are active and free up connections that passed <code>maxIdle</code>. We will also remove connections that passed <code>testTimeout</code>.</li>
</ul>
<h4 id="heading-original-implementation">Original implementation</h4>
<p>The first implementation of object pool was single threaded. All operations were sent to a worker thread that was responsible to execute them. This method is known as <a target="_blank" href="https://www.javaspecialists.eu/archive/Issue218.html">thread-confinement</a>. Object creation and test operations were blocking and query execution itself was non-blocking.</p>
<p>This method is problematic because operations are done one after another. On top of that, there are a couple of operations that are blocking as mentioned above. There were various cases of high latency when working in some scenarios and use cases (like <a target="_blank" href="https://github.com/mauricio/postgresql-async/issues/91">here</a> for example).</p>
<p>As a workaround <code>PartitionedPool</code> was introduced. This is a workaround to the <em>block</em> issue with the above single-threaded approach. The partitioned pool creates multiple <code>SingleThreadedObjectPools</code>, each with its own worker. When a connection is requested, a pool is selected by a modulus on the thread id. The partitioned pool is actually a pool of pools ;-)</p>
<p>I mentioned this is a workaround since it has its own problems: you might still be blocking, but at a lower rate — plus it consume more threads and resources.</p>
<h4 id="heading-actor-based-implementation">Actor based implementation</h4>
<p>An Actor is an entity that has a mailbox. It receives messages to its mailbox and processes them one after the other. The mailbox is a sort of a channel to pass events from the outside world to the actor.</p>
<p>A coroutines actor employs lock-free algorithms to allow fast and performant execution of events without the need for locks and <code>synchronized</code> blocks.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/0*T1B40xs7Fsf-gnfZ" alt="Image" width="800" height="450" loading="lazy">
_“wall rack filled with paper document lot” by [Unsplash](https://unsplash.com/@californong?utm_source=medium&amp;utm_medium=referral" rel="noopener" target="_blank" title=""&gt;Nong Vang on &lt;a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral" rel="noopener" target="<em>blank" title=")</em></p>
<p>You can see an elaborated explanation <a target="_blank" href="https://www.brianstorti.com/the-actor-model/">here</a>.</p>
<p>In our case those events will be <code>take</code> and <code>giveBack</code>. In addition to those, we will have internal messages that the actor sends to itself like <code>objectCreated</code> etc. That allows the actor to have states that does not suffer from concurrency problems, as it is always confined to the same sequential execution. In addition the channel that passes those events is a queue that is using lock-free algorithms so it is very efficient, avoids contention, and generally has very high performance.</p>
<p>There is an excellent video explaining how this was implemented (note that this is “heavy” algorithmic staff):</p>
<p>Let’s recap what we have until now:</p>
<ul>
<li>An actor receives messages and processes them one by one.</li>
<li>Usually messages will contain a <code>CompletableFuture</code> that should be completed when the actor processes it.</li>
</ul>
<p>Messages will be completed immediately or delayed (like in case we are waiting for a connection to be created). If it is delayed the actor will put the <code>Future</code> in a queue, and will use a callback mechanism to notify itself when the original future can be completed.</p>
<ul>
<li>Message processing in the actor should not be blocked or delay the actor. If this happens, it will delay all messages waiting to be processed in the queue and will slow down the entire actor operation.</li>
</ul>
<p><strong>That’s why, in case we have long running operations inside the actor, we use the callback mechanism.</strong></p>
<h4 id="heading-lets-see-more-details-on-the-use-cases">Let’s see more details on the use cases</h4>
<p><code>Take</code> — someone wants an object from the pool. It will send a message with a callback to the actor. The actor will do one of the following things:</p>
<ul>
<li>If the object is available — the actor will simply return it.</li>
<li>If the pool hasn’t passed the limit of created objects — the actor will create a new object and return it when the object is ready.</li>
</ul>
<p>In such a case, object creation can take time, so the actor will connect the callback from the object creation to the original take request callback.</p>
<ul>
<li>Will put the request in a queue for an available object (unless the queue is full and in that case will just return an error).</li>
</ul>
<p><code>GiveBack</code> — someone wants to give an object back to the pool (release it). This is also done by a message to the actor. The actor will do one of the following:</p>
<ul>
<li>If someone is waiting on the wait queue — it will borrow the object to it.</li>
<li>In other cases it will just keep the object on the pool for requests to come, so the object remains idle.</li>
</ul>
<p><code>Test</code> — periodically, someone from outside will notify the actor to test connections:</p>
<ul>
<li>The actor will release the idle connection that hasn’t been used for a long time (it’s configurable).</li>
<li>The actor will test other idle objects using the <code>ObjectFactory</code>. It will send a callback to the factory and mark those objects as <em>In Use</em>, to prevent from borrowing them until the test is completed.</li>
<li>The actor will check for timeouts in tests and destroy time-outed objects.</li>
</ul>
<p>Those are the main use cases.</p>
<h4 id="heading-leaks">Leaks</h4>
<p><img src="https://cdn-media-1.freecodecamp.org/images/0*64dZ7F9trDtbSdWq" alt="Image" width="800" height="529" loading="lazy">
_“selective focus photography of brown faucet” by [Unsplash](https://unsplash.com/@leipuri?utm_source=medium&amp;utm_medium=referral" rel="noopener" target="_blank" title=""&gt;Jouni Rajala on &lt;a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral" rel="noopener" target="<em>blank" title=")</em></p>
<p>There can be all sort of leaks in an object pool. Some are internal bugs which I hope are easier to spot and fix, and others are objects that were taken but not returned due to some user error. In such cases, objects might remain in the “<em>In Use”</em> queue forever.</p>
<p>To avoid such cases, the <em>“In Use”</em> Map is using Java’s <a target="_blank" href="https://www.baeldung.com/java-weakhashmap">WeakHashMap</a>. So if a user lost a connection it will be automatically removed from the map when it is cleaned by Java’s Garbage-Collector.</p>
<p>In addition we added a log message in such cases that says: <strong>“LEAK-DETECTED”</strong>.</p>
<h3 id="heading-thats-it">That’s it!</h3>
<p>The full Kotlin source code of the object pool is available here:</p>
<p><a target="_blank" href="https://github.com/jasync-sql/jasync-sql/blob/bacdd12243d89a5e2a46501bb5303815a9fd11e7/db-async-common/src/main/java/com/github/jasync/sql/db/pool/ActorBasedObjectPool.kt"><strong>jasync-sql/jasync-sql</strong></a><br><a target="_blank" href="https://github.com/jasync-sql/jasync-sql/blob/bacdd12243d89a5e2a46501bb5303815a9fd11e7/db-async-common/src/main/java/com/github/jasync/sql/db/pool/ActorBasedObjectPool.kt">_Java async database driver for MySQL and PostgreSQL written in Kotlin - jasync-sql/jasync-sql_github.com</a></p>
<p>In an upcoming post I will compare performance metrics of the different implementations.</p>
<p>If you want to read more about Kotlin there is a nice introduction here:</p>
<p>And for coroutines in general check out this video:</p>
<p>Finally if you want to learn more about Actors implementation using coroutines in Kotlin, then head over here:</p>
<p><a target="_blank" href="https://github.com/Kotlin/kotlinx.coroutines/blob/master/docs/shared-mutable-state-and-concurrency.md"><strong>Kotlin/kotlinx.coroutines</strong></a><br><a target="_blank" href="https://github.com/Kotlin/kotlinx.coroutines/blob/master/docs/shared-mutable-state-and-concurrency.md">_Library support for Kotlin coroutines . Contribute to Kotlin/kotlinx.coroutines development by creating an account on…_github.com</a></p>
<p>Thanks for reading! ❤️</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/0*0aDugHie8xlGjhOZ" alt="Image" width="800" height="599" loading="lazy">
_“aerial photography of woman on pink swimming floats” by [Unsplash](https://unsplash.com/@tom_grimbert?utm_source=medium&amp;utm_medium=referral" rel="noopener" target="_blank" title=""&gt;Tom Grimbert on &lt;a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral" rel="noopener" target="<em>blank" title=")</em></p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
