<?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" version="2.0"><channel><title><![CDATA[The Dev Tavern RSS Feed]]></title><description><![CDATA[Tutorials, opinions, courses and a lot other geek stuff!]]></description><link>http://github.com/dylang/node-rss</link><generator>GatsbyJS</generator><lastBuildDate>Sat, 03 Sep 2022 19:41:45 GMT</lastBuildDate><item><title><![CDATA[5 Things that will change the way you use AWS Lambda]]></title><description><![CDATA[5 of the most important things that improved my usage of AWS Lambda and that I wish I had known from the start!]]></description><link>https://www.thedevtavern.com/blog/posts/5-things-that-will-change-the-way-you-use-aws-lambda/</link><guid isPermaLink="false">https://www.thedevtavern.com/blog/posts/5-things-that-will-change-the-way-you-use-aws-lambda/</guid><pubDate>Sat, 03 Sep 2022 10:00:08 GMT</pubDate><content:encoded>&lt;style data-emotion=&quot;css-global 12qioua&quot;&gt;html{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;box-sizing:border-box;-webkit-text-size-adjust:100%;}*,*::before,*::after{box-sizing:inherit;}strong,b{font-weight:700;}body{margin:0;color:#fff;font-size:1.1875rem;font-family:&quot;Roboto&quot;,&quot;Helvetica&quot;,&quot;Arial&quot;,sans-serif;font-weight:400;line-height:1.5;letter-spacing:0.00938em;background-color:#102027;}@media print{body{background-color:#fff;}}body::backdrop{background-color:#102027;}&lt;/style&gt;&lt;h2&gt;Introduction&lt;/h2&gt;&lt;p&gt;AWS Lambda is one of the main precursors of Functions as a Service. This paradigm introduced a significant shift in how we develop applications and reason about them. The promise is simple: You push your code, specify your handler and the Functions runtime will take care of running it and scaling it on demand!&lt;/p&gt;&lt;p&gt;However, this apparent simplicity hides a learning curve that is not as flat as it seems. While using Lambda, I stumbled into many issues and learned many things that improved my usage over time and that I wish I had known from the start. Here is a short list of some of the most important things that changed how I use AWS Lambda.&lt;/p&gt;&lt;h3&gt;Lambda timeouts cause cold starts!&lt;/h3&gt;&lt;p&gt;Lambda functions can be configured to timeout after some time. This is useful to guarantee an upper limit to the execution time of function invocations. For a long time, they really seemed harmless to me. But in reality, their occurrence is much more problematic than you think, especially in high throughput or user facing apps. Why? Because they come with a high cost, both performance, and observability wise:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Performance wise:&lt;/strong&gt; When a Lambda Function reaches a timeout (similarly to an out of memory error), Lambda does not only stop the current invocation. It kills the whole execution environment brutally with it! Think of it as a process sigkill against the entire execution environment. Consequently, the environment becomes non-reusable, and the following invocation needs to spin up a new environment again, incurring a cold start and causing a big latency spike in your endpoint. This behavior is documented in the AWS Lambda guide but is not visible enough considering its high impact. You can read about it in the invoke phase in &lt;a href=&quot;https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtime-environment.html&quot;&gt;the Lambda runtime environment page&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;  &lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1024px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/ee17147b15d30c5768c472d4686270cd/669cd/aws-lambda-with-error.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:12.109375%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAACCAYAAABYBvyLAAAACXBIWXMAABYlAAAWJQFJUiTwAAAAgUlEQVQI1wXBWQ6CMBRAUfe/IhOMIRo+DFTCYB9QS2dkF9dzLjo6qulDozxOnpxecZian1ec/sU0DlTK8ZCR1gq3wdD2G3G9U0xNTpamz1zfI8ouXHwpiPPIFkjBUPLObmZS+HJkixahmzdkt9gUWH1CL5bghBI3SkmIiXSzxsbAH2fcjV78aRiCAAAAAElFTkSuQmCC&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;Function with a runtime timeout&quot; title=&quot;Function with a runtime timeout&quot; src=&quot;/static/ee17147b15d30c5768c472d4686270cd/2bef9/aws-lambda-with-error.png&quot; srcSet=&quot;/static/ee17147b15d30c5768c472d4686270cd/6f3f2/aws-lambda-with-error.png 256w,/static/ee17147b15d30c5768c472d4686270cd/01e7c/aws-lambda-with-error.png 512w,/static/ee17147b15d30c5768c472d4686270cd/2bef9/aws-lambda-with-error.png 1024w,/static/ee17147b15d30c5768c472d4686270cd/71c1d/aws-lambda-with-error.png 1536w,/static/ee17147b15d30c5768c472d4686270cd/a878e/aws-lambda-with-error.png 2048w,/static/ee17147b15d30c5768c472d4686270cd/669cd/aws-lambda-with-error.png 3024w&quot; sizes=&quot;(max-width: 1024px) 100vw, 1024px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;/&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Function with a runtime timeout&lt;/figcaption&gt;
  &lt;/figure&gt;
&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Observability wise:&lt;/strong&gt; Lambda timeouts are literally like unplugging the execution environment from the power source. The logs will be cut off, and your code won’t have the chance to report any metrics, logs, traces, or exceptions that would have been useful to debug the issue. In fact, you won’t have much more information in the logs than &lt;code&gt;Task timed out&lt;/code&gt;, and you will likely have no clue where exactly your code hung.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;For these reasons, Lambda timeouts should never be part of an expected workflow: If they happen, it means you have a bug in your application that you should investigate and fix. Treat them as an emergency exit door and set the threshold high enough to have them occur only on extremely rare occasions (ex. a bug that caused your code to hang). Instead, implement a custom timeout logic in your code if you want to set a hard limit to client calls. You can use this opportunity to report an informative error message to the user, a custom status code, and some timing metrics showing what took that much time.&lt;/p&gt;&lt;p&gt;Wondering how to report such custom metrics? Nice transition to the next bullet point!&lt;/p&gt;&lt;h3&gt;Custom metrics from Lambdas via logs using EMF&lt;/h3&gt;&lt;p&gt;AWS introduced a compelling way to report custom metrics from your Lambda functions: The Embedded Metrics Format (or EMF).&lt;/p&gt;&lt;p&gt;EMF lets you report custom metrics in the form of log statements shaped in a specific way described by the &lt;a href=&quot;https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch_Embedded_Metric_Format_Specification.html&quot;&gt;EMF specification&lt;/a&gt;. These logs are automatically intercepted, parsed, and transformed by CloudWatch into fully fledged metrics that you can graph and create alarms on. Your Lambda function can emit those logs using ordinary log reporters (ex. &lt;code&gt;console.log&lt;/code&gt;  for javascript, &lt;code&gt;log4j&lt;/code&gt; for java, etc.) and does not need to perform network calls or depend on additional client libraries. &lt;/p&gt;&lt;p&gt;Here is an example of an EMF formatted log statement:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-json&quot;&gt;{
  &amp;quot;_aws&amp;quot;: {
    &amp;quot;Timestamp&amp;quot;: 1574109732004,
    &amp;quot;CloudWatchMetrics&amp;quot;: [
      {
        &amp;quot;Namespace&amp;quot;: &amp;quot;My Namespace&amp;quot;,
        &amp;quot;Dimensions&amp;quot;: [[&amp;quot;functionVersion&amp;quot;]],
        &amp;quot;Metrics&amp;quot;: [{ &amp;quot;Name&amp;quot;: &amp;quot;time&amp;quot;, &amp;quot;Unit&amp;quot;: &amp;quot;Milliseconds&amp;quot; }]
      }
    ]
  },
  &amp;quot;functionVersion&amp;quot;: &amp;quot;$LATEST&amp;quot;,
  &amp;quot;time&amp;quot;: 100,
  &amp;quot;requestId&amp;quot;: &amp;quot;989ffbf8-9ace-4817-a57c-e4dd734019ee&amp;quot;,
  &amp;quot;sessionId&amp;quot;: &amp;quot;1234&amp;quot;
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The &lt;code&gt;_aws&lt;/code&gt; field contains the metric definition with its name, unit, and a list of dimensions. This needs to be present in every EMF log statement. The other fields contain the metric values, dimension values, and extra properties that attach additional context to the metric statement. The additional properties will not be captured by CloudWatch metrics but can be extremely useful when deep diving into the logs.&lt;/p&gt;&lt;h3&gt;Optimize your Lambdas latency by running your init code once&lt;/h3&gt;&lt;p&gt;Lambda execution environments are reused for multiple invocations. This is referred to as warm starts. Variables initialized outside your handler function &lt;sup id=&quot;fnref-1&quot;&gt;&lt;a href=&quot;#fn-1&quot; class=&quot;footnote-ref&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; will keep their value on subsequent invocations running on the same environment. This is a perfect place to store database connections, http pools, and other objects that are costly to create / initialize. That way, you won’t need to recreate them again on every invocation.&lt;/p&gt;&lt;p&gt;So instead of writing something like this (code example in &lt;code&gt;kotlin&lt;/code&gt;):&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-kotlin&quot; metastring=&quot;highlight=8-9&quot; highlight=&quot;8-9&quot;&gt;class Handler: RequestHandler&amp;lt;Request, String&amp;gt; {

  /**
   * This is your handler function 👇 
   */
  override fun handleRequest(event: Request, context: Context): String {

    // dbPool initialized inside the handler function
    val dbPool = initializeDatabasePool();

    // Do something with your database pool
    ...

    return response;
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;You could write this instead:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-kotlin&quot; metastring=&quot;highlight=3-4&quot; highlight=&quot;3-4&quot;&gt;class Handler: RequestHandler&amp;lt;Request, String&amp;gt; {

  // dbPool initialized outside the handler function
  val dbPool = initializeDatabasePool();

  /**
   * This is your handler function 👇 
   */
  override fun handleRequest(event: Request, context: Context): String {

    // Do something with your database pool
    ...

    return response;
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The &lt;code&gt;initializeDatabasePool()&lt;/code&gt; call in the second snippet will only execute during the init phase (cold starts), and the result will be kept in the &lt;code&gt;dbPool&lt;/code&gt; variable for later invocations that reuse the execution environment.&lt;/p&gt;&lt;h3&gt;Background code will continue to run on the next invocations&lt;/h3&gt;&lt;p&gt;Background processes, threads, and promises that were initiated by your Lambda function and did not complete when the function ended will resume on subsequent invocations if Lambda reuses the execution environment. This can result in surprising behaviors that are very hard to debug.&lt;/p&gt;&lt;p&gt;The explanation is simple: When a function invocation is done, i.e. your handler function returned, the execution environment is frozen, and any code that was still running is paused. When a new invocation starts, the execution environment unfreezes, and all the incomplete processes resume.&lt;/p&gt;&lt;p&gt;This can happen much more easily than you think! Take a look at this innocent-looking javascript code:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;const values = await Promise.all([
    asyncFunction1(), // returns a promise
    asyncFunction2(), // returns a promise
])
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;Promise.all&lt;/code&gt; waits for all the given promises until they all resolve. If any of them fail, &lt;code&gt;Promise.all&lt;/code&gt; returns early and stops waiting for the other promises. In the example above, If the &lt;code&gt;asyncFunction1&lt;/code&gt; promise fails, the &lt;code&gt;Promise.all&lt;/code&gt; call returns and throws an error without waiting for the completion of the &lt;code&gt;asyncFunction2&lt;/code&gt;. In the meantime, &lt;code&gt;asyncFunction2&lt;/code&gt; is potentially still running in the background! If it didn’t complete before the Lambda function returns, it will continue running during the following invocation, potentially causing a resource leak.&lt;/p&gt;&lt;p&gt;Thus, to keep your lambda logic predictable, ensure you are not leaking any background threads or promises across function calls, as they won’t magically disappear!&lt;/p&gt;&lt;p&gt;One way to fix the example above is to use &lt;code&gt;Promise.allSettled&lt;/code&gt; instead of &lt;code&gt;Promise.all&lt;/code&gt; . &lt;code&gt;Promise.allSettled&lt;/code&gt; waits for all the promises even if some of them fail.&lt;/p&gt;&lt;h3&gt;Code size matters&lt;/h3&gt;&lt;p&gt;A common mistake is thinking that the language runtime (ex. JVM) and the logic you put in your init code are the only factors that impact your functions’ cold starts. However, another critical factor that has a significant impact is the package size of your function.&lt;/p&gt;&lt;p&gt;During the init phase, Lambda starts by downloading the function’s package which is stored in an internal &lt;a href=&quot;https://aws.amazon.com/s3/&quot;&gt;Amazon S3&lt;/a&gt; bucket (or &lt;a href=&quot;https://aws.amazon.com/ecr/&quot;&gt;Amazon Elastic Container Registry&lt;/a&gt; if the function uses container packaging).&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:890px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/8d91ed37d84df5a01f5af7e4e02030ce/4ef49/aws-lambda-init-phases.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:22.265625%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAECAIAAAABPYjBAAAACXBIWXMAAAsTAAALEwEAmpwYAAAA2ElEQVQI1y3IsUvDQBiG8fzfjnXRUac6KGgFwa214iYugoNUkRBpEtPYSnKQ1svdpSZ3932vRAvP8OMJ0K2lzM9yO5zXw3Q7WtrT1JzE6jhunz4XLp3I+FbF03b50Hzc6fm0ScZaRF9lpY0OYL8ruTpM3GBWDUJzlLmDUO4/F3uv+j5LKLoQL5cqHNnsRr9f57Orn+h8K942ddN1bQAAzPAO5EAWvvtDb++9JTiCJZDHuvWPpSzEJl+VRSmYOQAYYM/4j3boDzODiZnQBzhDMlHa1LXSugHwCyya2fYADoiqAAAAAElFTkSuQmCC&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;Cold start phases&quot; title=&quot;Cold start phases&quot; src=&quot;/static/8d91ed37d84df5a01f5af7e4e02030ce/4ef49/aws-lambda-init-phases.png&quot; srcSet=&quot;/static/8d91ed37d84df5a01f5af7e4e02030ce/6f3f2/aws-lambda-init-phases.png 256w,/static/8d91ed37d84df5a01f5af7e4e02030ce/01e7c/aws-lambda-init-phases.png 512w,/static/8d91ed37d84df5a01f5af7e4e02030ce/4ef49/aws-lambda-init-phases.png 890w&quot; sizes=&quot;(max-width: 890px) 100vw, 890px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;/&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Cold start phases&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;Thus, the heavier your package is, the longer the download phase will be. It can even reach a point where it outweighs all the other cold start phases.&lt;/p&gt;&lt;p&gt;Thus, the package size should have an important consideration in your attempts to optimize lambdas latency. Common optimization techniques to reduce package sizes include: splitting the code, reducing dependencies, and other language specific techniques like tree shaking in the javascript world. In addition, keeping your package small will keep you further away from the dreaded 260Mb limit above which Lambda will not let you upload your code anymore. Believe me, the frustration is huge when this happens!&lt;/p&gt;&lt;div class=&quot;footnotes&quot;&gt;&lt;hr/&gt;&lt;ol&gt;&lt;li id=&quot;fn-1&quot;&gt;The handler function is the function that contains the logic that runs on every invocation.&lt;a href=&quot;#fnref-1&quot; class=&quot;footnote-backref&quot;&gt;↩&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;</content:encoded></item><item><title><![CDATA[Structured concurrency explained - Part 2: Exceptions and Cancellations]]></title><description><![CDATA[Error handling is an important part to understand in the workflow of structured concurrency. In this post, we will dive deep into this and uncover some of the most surprising and misleading parts of Kotlin coroutines!]]></description><link>https://www.thedevtavern.com/blog/posts/structured-concurrency-exceptions-and-cancellations/</link><guid isPermaLink="false">https://www.thedevtavern.com/blog/posts/structured-concurrency-exceptions-and-cancellations/</guid><pubDate>Wed, 23 Mar 2022 10:00:08 GMT</pubDate><content:encoded>&lt;style data-emotion=&quot;css-global 12qioua&quot;&gt;html{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;box-sizing:border-box;-webkit-text-size-adjust:100%;}*,*::before,*::after{box-sizing:inherit;}strong,b{font-weight:700;}body{margin:0;color:#fff;font-size:1.1875rem;font-family:&quot;Roboto&quot;,&quot;Helvetica&quot;,&quot;Arial&quot;,sans-serif;font-weight:400;line-height:1.5;letter-spacing:0.00938em;background-color:#102027;}@media print{body{background-color:#fff;}}body::backdrop{background-color:#102027;}&lt;/style&gt;&lt;h2&gt;Introduction&lt;/h2&gt;&lt;p&gt;&lt;a href=&quot;../structured-concurrency-explained/&quot;&gt;In part 1 of this series&lt;/a&gt;, we introduced the concept of structured concurrency. We showed how it immediately makes concurrent programs safer, more correct, and easier to reason about. If you missed this part, I definitely recommend checking it out!&lt;/p&gt;&lt;p&gt;To achieve this safety in every situation, including when things fail, structured concurrency is very strict and opinionated about the way exceptions are handled and propagated throughout coroutines job hierarchies. This behavior can sometimes seem counterintuitive and confusing if not understood correctly. This is precisely what we will cover in this part 2 of the series. More specifically, we will go over the following topics:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Exception handling inside a coroutine scope&lt;/li&gt;&lt;li&gt;The confusing part!&lt;/li&gt;&lt;li&gt;Using &lt;code&gt;supervisorScope&lt;/code&gt; when child failures are not fatal&lt;/li&gt;&lt;li&gt;Cancellation and blocking code&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;Ready? Let’s go!&lt;/p&gt;&lt;h2&gt;Exception handling inside a coroutine scope&lt;/h2&gt;&lt;p&gt;Let’s start our journey with this simple example: We want to create a simple pipeline between a &lt;code&gt;Producer&lt;/code&gt; coroutine and a &lt;code&gt;Consumer&lt;/code&gt; coroutine exchanging data through a &lt;a href=&quot;https://kotlinlang.org/docs/channels.html&quot;&gt;channel&lt;/a&gt;. Both coroutines run concurrently within a coroutine scope:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;The &lt;code&gt;Producer&lt;/code&gt; continuously calls the &lt;code&gt;fetchDataFromRemote()&lt;/code&gt; function to download some data from a remote service before piping it out to a channel.&lt;/li&gt;&lt;li&gt;The &lt;code&gt;Consumer&lt;/code&gt; continuously polls data from the channel and prints it on the screen.&lt;/li&gt;&lt;/ul&gt;&lt;pre&gt;&lt;code class=&quot;language-kotlin&quot;&gt;fun runPipeline() {
    coroutineScope {
        val channel = Channel&amp;lt;String&amp;gt;()

        launch(CoroutineName(&amp;quot;Producer&amp;quot;)) {
            while (true) {
                val data = fetchDataFromRemote()
                channel.send(data)
            }
        }

        launch(CoroutineName(&amp;quot;Consumer&amp;quot;)) {
            for (data in channel) {
                println(data)
            }
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;In the setup above, our coroutines job hierarchy would look like the following:&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:960px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/b392f0d7add563d3172964ad816f5bd5/d9199/example-1-hierarchy.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:56.25%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAIAAADwazoUAAAACXBIWXMAAAsTAAALEwEAmpwYAAABBElEQVQoz2MQUFDHRLI6xprmtloWdrI6xnxyqljVCCioM2AKCSpq8MqqCCpq8Mmp4tGJXbOAgjq/gnpWUXlQbDK3tJKgogaxmoWUNNkl5G08/L99/3L7zm1JDX1eOVVc+hkw3cwvryataTBt7rzqljZ+eTUSbBZQUBdV0VbUNWUTl+OTVZXXMRZS0iRKs6CiBpe0kq6lg5SGgYCCOp+cqr6Vk7iaLiT88GkWUtJkE5dzC4q4c+f21NlzmYSl3IMjb9+5PXnWHG4ZZSI0i8l5hUU/evJw9qLFjEJS3uHRj58+nDl/AQ9BzRDEI6OsZ+MMCmRZFV5ZFTibKM0Qb0MCGZmNNcAAzaZnzttI8pAAAAAASUVORK5CYII=&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;Coroutines job Hierarchy describing example 1&quot; title=&quot;Coroutines job Hierarchy describing example 1&quot; src=&quot;/static/b392f0d7add563d3172964ad816f5bd5/d9199/example-1-hierarchy.png&quot; srcSet=&quot;/static/b392f0d7add563d3172964ad816f5bd5/6f3f2/example-1-hierarchy.png 256w,/static/b392f0d7add563d3172964ad816f5bd5/01e7c/example-1-hierarchy.png 512w,/static/b392f0d7add563d3172964ad816f5bd5/d9199/example-1-hierarchy.png 960w&quot; sizes=&quot;(max-width: 960px) 100vw, 960px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;/&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Coroutines job Hierarchy describing example 1&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;Now, let’s imagine that the &lt;code&gt;fetchDataFromRemote()&lt;/code&gt; call throws an exception (ex. connectivity error).&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-kotlin&quot; metastring=&quot;highlight=7-8&quot; highlight=&quot;7-8&quot;&gt;fun runPipeline() {
    coroutineScope {
        val channel = Channel&amp;lt;String&amp;gt;()

        launch(CoroutineName(&amp;quot;Producer&amp;quot;)) {
            while (true) {
                // Boom!! Throws an exception!!!
                val data = fetchDataFromRemote()
                channel.send(data)
            }
        }

        launch(CoroutineName(&amp;quot;Consumer&amp;quot;)) {
            for (data in channel) {
                println(data)
            }
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This would cause the &lt;code&gt;Producer&lt;/code&gt; coroutine to fail. What do you think would happen then? Will the exception go unnoticed as we did not log it anywhere? Will we end up with the &lt;code&gt;Consumer&lt;/code&gt; coroutine running alone forever, desperately waiting for some data to arrive in the channel?&lt;/p&gt;&lt;p&gt;Fortunately, none of those bad things would happen thanks to structured concurrency: The parent job will notice the &lt;code&gt;Producer&lt;/code&gt; coroutine’s failure and will immediately take care of cancelling the other children within the scope (to prevent them from staying active forever) before bubbling the exception up to the outside.&lt;/p&gt;&lt;p&gt;Let’s review this workflow step by step (an animation below will further summarize it):&lt;/p&gt;&lt;ol&gt;&lt;li&gt;It all starts with the &lt;code&gt;fetchFromRemote()&lt;/code&gt; throwing an exception, causing the &lt;code&gt;Producer&lt;/code&gt; coroutine to fail.&lt;/li&gt;&lt;li&gt;The parent job notices the failure of one of its children and, consequently, marks itself as failed and cancels all its other children that are still running.&lt;/li&gt;&lt;li&gt;The child coroutines that are cancelled will throw a &lt;code&gt;CancellationException&lt;/code&gt; on their next call to a suspending function (or immediately if they are already suspended). That’s how they trigger their exit.&lt;/li&gt;&lt;li&gt;Once all child coroutines are stopped, the original exception is forwarded out of the &lt;code&gt;coroutineScope&lt;/code&gt; call.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;These steps are summarized by the animation below&lt;sup id=&quot;fnref-1&quot;&gt;&lt;a href=&quot;#fn-1&quot; class=&quot;footnote-ref&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; :&lt;/p&gt;&lt;video style=&quot;width:100%&quot; controls=&quot;&quot;&gt;&lt;source src=&quot;/ed7d65ffa3b4a9a190a434939c236d50/Coroutines-job-failure-animation.mp4&quot; type=&quot;video/mp4&quot;/&gt;&lt;/video&gt;&lt;p&gt;This is how structured concurrency saves us from leaking exceptions and coroutines when failures occur!&lt;/p&gt;&lt;h2&gt;The confusing part&lt;/h2&gt;&lt;p&gt;The error handling behavior we saw above is desirable in most scenarios. But sometimes, it might be extremely confusing. Especially when we want to handle the exceptions of the child coroutines ourselves.&lt;/p&gt;&lt;p&gt;Let’s demonstrate this using a slightly different example: We want to fetch and print the Github profile of a user on the screen. We decide that failures are not fatal: if we fail to fetch the Github profile of the user (ex. connectivity error), we just want to print an error message on the screen and prevent the exception from bubbling up.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-kotlin&quot;&gt;coroutineScope {
    val profile = async(CoroutineName(&amp;quot;Fetcher&amp;quot;)) {
        // This call might fail!!
        fetchGithubProfile(&amp;quot;wlezzar&amp;quot;)
    }

    try {
        println(profile.await())
    } catch (err: Exception) {
        println(&amp;quot;Failed to fetch data from github: ${err}&amp;quot;)
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The associated job hierarchy would look like this:&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:960px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/b5db6023a1ea37749245d5d7596cde1b/d9199/example-2-hierarchy.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:56.25%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAIAAADwazoUAAAACXBIWXMAAAsTAAALEwEAmpwYAAAA1klEQVQoz2MQUFDHRLI6xprmtloWdrI6xnxyqljVCCioM2AKCSpq8MqqCCpq8Mmp4tGJXbOAgjq/gnpWUXlQbDK3tJKgogaxmoWUNNkl5G08/b99/3L77h1JDX1eOVVc+hkw3cwnpyqhrjdt7ryKxmYeGRWSnc0np8otqSQINos0zYKKGlzSSrqWDmom1qCQI14zVKeVw7kL5zds2SqirMUvryZIgmYpRX1b56s3ru3ct1dERZtPXo3YAIPo55ZW0jS3U9Az5ZFRJiGq4Pp5ZJTxRBJEMwCdHV5WcrcMJQAAAABJRU5ErkJggg==&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;Coroutines job Hierarchy describing example 2&quot; title=&quot;Coroutines job Hierarchy describing example 2&quot; src=&quot;/static/b5db6023a1ea37749245d5d7596cde1b/d9199/example-2-hierarchy.png&quot; srcSet=&quot;/static/b5db6023a1ea37749245d5d7596cde1b/6f3f2/example-2-hierarchy.png 256w,/static/b5db6023a1ea37749245d5d7596cde1b/01e7c/example-2-hierarchy.png 512w,/static/b5db6023a1ea37749245d5d7596cde1b/d9199/example-2-hierarchy.png 960w&quot; sizes=&quot;(max-width: 960px) 100vw, 960px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;/&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Coroutines job Hierarchy describing example 2&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;We would think that catching the exception during the &lt;code&gt;.await()&lt;/code&gt; call would safely prevent the exception from bubbling up. But, unfortunately, that’s not the case! In fact, if you run the program above and simulate a failure in the &lt;code&gt;fetchGithubProfile&lt;/code&gt; call, the whole program will crash, and the exception will propagate outside of the &lt;code&gt;coroutineScope&lt;/code&gt;. Why is that?&lt;/p&gt;&lt;p&gt;Again, the explanation is the same as in the previous example: by the time we catch the exception at the &lt;code&gt;.await()&lt;/code&gt; call, it is already too late, the associated child coroutine (spun up using &lt;code&gt;async&lt;/code&gt; ) would have already failed as we did not catch the exception inside the &lt;code&gt;async { ... }&lt;/code&gt; block. Thus, the same mechanics as previously will happen: The parent job will notice its child failure, marks itself as failed, cancels the other remaining child coroutines, and bubbles the exception up. The &lt;code&gt;try ... catch&lt;/code&gt; around the &lt;code&gt;.await()&lt;/code&gt; only allows us not to exit immediately and gives us a chance to react to the failure (ex. do some resources cleaning).&lt;/p&gt;&lt;p&gt;To prevent this scenario from happening, we have two options:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Either we catch the exception inside the &lt;code&gt;async&lt;/code&gt; block itself. This would prevent the child coroutine from failing in the first place.&lt;/li&gt;&lt;li&gt;Or we could use &lt;code&gt;supervisorScope&lt;/code&gt; instead of &lt;code&gt;coroutineScope&lt;/code&gt; to ignore child coroutine failures.&lt;/li&gt;&lt;/ol&gt;&lt;h2&gt;Using &lt;code&gt;supervisorScope&lt;/code&gt; when child failures are not fatal&lt;/h2&gt;&lt;p&gt;Sometimes, like in the last example, child coroutines failures are not fatal and should not cause the entire job hierarchy to fail. Instead, we would like to react to those failures in our own way. This is why &lt;code&gt;supervisorScope&lt;/code&gt; exists. It lets us do exactly that.&lt;/p&gt;&lt;p&gt;&lt;code&gt;supervisorScope&lt;/code&gt; is a slightly modified version of &lt;code&gt;coroutineScope&lt;/code&gt; . Both have the same purpose of creating a new coroutine scope with an explicit lifetime in which we can spin up child coroutines. The difference between the two is that: &lt;code&gt;supervisorScope&lt;/code&gt; uses a &lt;code&gt;SupervisorJob&lt;/code&gt; as the parent job to hold the child coroutines whereas &lt;code&gt;coroutineScope&lt;/code&gt; uses a regular &lt;code&gt;Job&lt;/code&gt; instead.&lt;/p&gt;&lt;p&gt;&lt;code&gt;SupervisorJob&lt;/code&gt; is a special implementation of &lt;code&gt;Job&lt;/code&gt; that ignores child failures. When those occur, it does not cancel the other children coroutines and does not bubble up the exception.&lt;/p&gt;&lt;p&gt;Here is how it can be used in the previous example:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-kotlin&quot; metastring=&quot;highlight=1&quot; highlight=&quot;1&quot;&gt;supervisorScope {
    val profile = async(CoroutineName(&amp;quot;Fetcher&amp;quot;)) { 
        fetchGithubProfil(&amp;quot;wlezzar&amp;quot;)
    }

    try {
        println(profile.await())
    } catch (err: Exception) {
        println(&amp;quot;Failed to fetch profile data: ${err}&amp;quot;)
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now, when a failure happens in the &lt;code&gt;fetchGithubProfile&lt;/code&gt; call, this will still cause the child coroutine to fail but the parent job (&lt;code&gt;SupervisorJob&lt;/code&gt;) will ignore this failure, and the &lt;code&gt;supervisorScope&lt;/code&gt; will not bubble it up to the outside.&lt;/p&gt;&lt;video style=&quot;width:100%&quot; controls=&quot;&quot;&gt;&lt;source src=&quot;/7fa9e9e38ea94a65dfde732da01d56a9/Coroutines-job-failure-animation-supervisor.mp4&quot; type=&quot;video/mp4&quot;/&gt;&lt;/video&gt;&lt;p&gt;One critical point to keep in mind: whenever we use a supervisor job as a parent in a scope, it becomes very important to catch the exceptions of child coroutines ourselves, otherwise they would be lost!&lt;/p&gt;&lt;p&gt;The way we handle a child coroutine’s exception when using a supervisor job as a parent depends on whether this coroutine was spinned up using &lt;code&gt;launch&lt;/code&gt; or &lt;code&gt;async&lt;/code&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Failures of coroutines spinned using &lt;code&gt;async&lt;/code&gt; are caught by wrapping the &lt;code&gt;.await()&lt;/code&gt; inside a &lt;code&gt;try...catch&lt;/code&gt;.&lt;/li&gt;&lt;li&gt;On the other hand, failures of coroutines spinned up using &lt;code&gt;launch&lt;/code&gt; can be handled using &lt;a href=&quot;https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-exception-handler/index.html&quot;&gt;coroutine exception handlers&lt;/a&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;h2&gt;Cancellation and blocking code&lt;/h2&gt;&lt;p&gt;When failures occur, the parent job is responsible for triggering the cancellation of its child coroutines. However, cancellation is cooperative! This means that when coroutines are asked to cancel, they need to cooperate by listening to those cancellation signals and reacting appropriately (ex. by exiting). You cannot force them to! In this case, we say that a coroutine is cooperative to cancellation or cancellable.&lt;/p&gt;&lt;p&gt;In the Kotlin coroutines world, you rarely need to worry about making your coroutines cooperative because all the suspending functions (like &lt;code&gt;delay&lt;/code&gt;, consuming from a channel, etc.) are natively already cancellable. Thus, your code will usually be cancellable right away without any extra effort.&lt;/p&gt;&lt;p&gt;However, when running a blocking code inside coroutines, &lt;strong&gt;you do need to worry about making it cooperative to cancellation&lt;/strong&gt;.&lt;/p&gt;&lt;p&gt;Here is a hypothetical example:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-kotlin&quot;&gt;// Blocking code
fun someSlowBlockingCode() {
    // Do some computation
}

val job = launch(Dispatchers.IO) {
    someSlowBlockingCode()
}

job.cancel()
job.join() // Will hang until the blocking code is done!
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The call to &lt;code&gt;someSlowBlockingCode()&lt;/code&gt; is not coroutines aware. It will not suspend and will never react to cancellations. Consequently, canceling the associated job will not cause the blocking function to interrupt. Instead, it will keep running until it’s done.&lt;/p&gt;&lt;p&gt;How can we fix this?&lt;/p&gt;&lt;p&gt;There are several approaches depending on whether you own or not the implementation of the blocking code.&lt;/p&gt;&lt;p&gt;One approach to make a blocking code cooperative to cancellations is to wrap it inside a &lt;code&gt;runInterruptible&lt;/code&gt; block, which is specifically built for that purpose.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-kotlin&quot; metastring=&quot;highlight=2&quot; highlight=&quot;2&quot;&gt;val job = launch(Dispatchers.IO) {
    runInterruptible {
        someSlowBlockingCode()
    }
}

job.cancel()
job.join()
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;When the coroutine is cancelled, &lt;code&gt;runInterruptible&lt;/code&gt; interrupts the underlying thread before throwing a &lt;code&gt;CancellationException&lt;/code&gt; to the outside. However, for this to work, the blocking call underneath must itself be cooperative to thread interupts which is not guaranteed! This is usually the case when:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;The thread is blocked on &lt;code&gt;Object.wait()&lt;/code&gt;, &lt;code&gt;Thread.sleep()&lt;/code&gt;, or &lt;code&gt;Thread.join()&lt;/code&gt;&lt;/li&gt;&lt;li&gt;Most &lt;code&gt;java.util.concurrent&lt;/code&gt; structures are interruptible.&lt;/li&gt;&lt;li&gt;When using Java NIO (but not java.io).&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;You can find more information around thread interrupts in &lt;a href=&quot;https://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html#interrupt()&quot;&gt;the &lt;code&gt;Thread.interrupt()&lt;/code&gt; javadoc&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Despite not being a bullet proof solution, the &lt;code&gt;runInterruptible&lt;/code&gt; function is still very useful in many situations, especially when you don’t have control over the implementation of the underlying blocking code.&lt;/p&gt;&lt;p&gt;Otherwise, if you do own the blocking code’s implementation, another way to make it cooperative to cancellations is by periodically watching the value of &lt;a href=&quot;https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/is-active.html&quot;&gt;the isActive property&lt;/a&gt; of the enclosing coroutine scope. When this value is &lt;code&gt;false&lt;/code&gt;, it means that the enclosing scope has been cancelled, and the blocking code should exit. Here is an example:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-kotlin&quot; metastring=&quot;highlight=2&quot; highlight=&quot;2&quot;&gt;fun someSlowBlockingCode(scope: CoroutineScope) {
    while (scope.isActive) {
        // Do some short living blocking operation
    }
}

val job = launch(Dispatchers.IO) {
    someSlowBlockingCode()
}

job.cancel()
job.join()
&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;Conclusion&lt;/h2&gt;&lt;p&gt;Error handling in the context of coroutines is certainly one of the most challenging parts to understand and to master. Hopefully, this post gave you some clarity on its inner workings and the reasons why it was designed this way.&lt;/p&gt;&lt;p&gt;So far we have only seen how to create coroutine scopes inside &lt;code&gt;suspend&lt;/code&gt; functions using &lt;code&gt;coroutineScope&lt;/code&gt; and &lt;code&gt;supervisorScope&lt;/code&gt;. In the third and last part of this series, we will discover another useful way of creating independent scopes that are not tied to the lifetime of a function call. This can be achieved using the &lt;code&gt;CoroutineScope&lt;/code&gt; factory function. We will also talk about context elements and how they allow us to easily pass data to child coroutines. Stay tuned!&lt;/p&gt;&lt;div class=&quot;footnotes&quot;&gt;&lt;hr/&gt;&lt;ol&gt;&lt;li id=&quot;fn-1&quot;&gt;The names used to express the statuses of the jobs in the different steps are for clarity and illustration purpose. Please check &lt;a href=&quot;https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-job/index.html&quot;&gt;the documentation of &lt;code&gt;Job&lt;/code&gt;&lt;/a&gt; for the actual state machine and status names.&lt;a href=&quot;#fnref-1&quot; class=&quot;footnote-backref&quot;&gt;↩&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;</content:encoded></item><item><title><![CDATA[Structured concurrency explained - Part 1: Introduction]]></title><description><![CDATA[This post explains structured concurrency in an intuitive way and shows how it simplifies concurrent programs in practice!]]></description><link>https://www.thedevtavern.com/blog/posts/structured-concurrency-explained/</link><guid isPermaLink="false">https://www.thedevtavern.com/blog/posts/structured-concurrency-explained/</guid><pubDate>Sun, 13 Feb 2022 10:00:08 GMT</pubDate><content:encoded>&lt;style data-emotion=&quot;css-global 12qioua&quot;&gt;html{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;box-sizing:border-box;-webkit-text-size-adjust:100%;}*,*::before,*::after{box-sizing:inherit;}strong,b{font-weight:700;}body{margin:0;color:#fff;font-size:1.1875rem;font-family:&quot;Roboto&quot;,&quot;Helvetica&quot;,&quot;Arial&quot;,sans-serif;font-weight:400;line-height:1.5;letter-spacing:0.00938em;background-color:#102027;}@media print{body{background-color:#fff;}}body::backdrop{background-color:#102027;}&lt;/style&gt;&lt;h2&gt;Introduction&lt;/h2&gt;&lt;p&gt;Structured concurrency is a powerful concept that is important to understand to fully take advantage of the power of Kotlin coroutines.&lt;/p&gt;&lt;p&gt;Today’s post is the first of a series about Structured concurrency: an introduction that takes the challenge of explaining the concepts behind it in a straightforward and intuitive manner. It aims to trigger in you the “Aha!” moment that will make you say: Why doesn’t every single concurrency library use structured concurrency?! Stay tuned ;)&lt;/p&gt;&lt;h2&gt;Unstructured concurrency&lt;/h2&gt;&lt;p&gt;To understand something and build a good intuition around the subject, it is often helpful to start from the problems it tries to solve in the first place. So let’s consider a simple example program that does not use structured concurrency and see what problems can arise.&lt;/p&gt;&lt;p&gt;The following code creates three concurrent tasks that run in the background in separate threads. Each task’s job is to fetch a bunch of data from a remote service using the &lt;code&gt;fetchData&lt;/code&gt; function and add the resulting number to the global &lt;code&gt;sum&lt;/code&gt;.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-kotlin&quot;&gt;val sum = AtomicInteger(0)

// Create 3 concurrent tasks that compute the total sum in parallel
repeat(3) {
    CompletableFuture.runAsync {
        val data: Int = fetchData()
        sum.addAndGet(data)
    }
}

// Do something useful in the meantime while the sum is being computed
Thread.sleep(2000)

// And then use the sum.
println(&amp;quot;The final sum is: $sum&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;You should have already spotted a few problems in the snippet above:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;We never wait for the created tasks (futures) to finish their job before using the final &lt;code&gt;sum&lt;/code&gt;. The &lt;code&gt;fetchData&lt;/code&gt; call might take longer than expected in some of the futures, and we end up using an incomplete sum without being aware.&lt;/li&gt;&lt;li&gt;What if one of the futures fails? The &lt;code&gt;fetchData()&lt;/code&gt; call might raise an exception because of a networking problem. The future’s failure will go unnoticed and will never be propagated to the outside. &lt;strong&gt;In other words, we can leak exceptions!&lt;/strong&gt; Causing, once again, our sum to be incorrect without our awareness.&lt;/li&gt;&lt;li&gt;Last but not least: what if one of the futures gets stuck indefinitely and never ends? Let’s say the &lt;code&gt;fetchData&lt;/code&gt; call hangs and never returns because of a deadlock or a bug in its implementation. In this case, our future and the thread hosting it will keep running in the background forever, consuming unnecessary resources. We will likely never be aware of it and will have no way of shutting it down. &lt;strong&gt;In other words, we can leak threads!&lt;/strong&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;We can try to fix the problems above by adding some boilerplate code to keep track of the futures in a list, wait for them one by one to finish, and forward any exception that would be thrown.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-kotlin&quot;&gt;val sum = AtomicInteger(0)

// A list to keep track of the created futures
val futures = ArrayList&amp;lt;Future&amp;lt;Void&amp;gt;&amp;gt;()

repeat(3) {
    val future = CompletableFuture.runAsync {
        val data: Int = fetchData()
        sum.addAndGet(data)
    }

    // Add the future to the list
    futures.add(future)
}

// Do something useful in the meantime in parallel
Thread.sleep(2000)

// Wait for all the futures and propagate exceptions
for (future in futures) {
    future.get()
}

// And then use the sum.
println(&amp;quot;The final sum is: $sum&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;What we did here is actually “Making our concurrency more structured”: Instead of launching the background futures in the air and losing sight of them, we keep track of them in a list and wait for their completion. That is exactly what we mean by structured concurrency: The start and the end of the concurrent paths are clear and explicit.&lt;/p&gt;&lt;p&gt;However, not only is this boilerplate code cumbersome to write, it is also far from being perfect:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;What if the first future encountered by our &lt;code&gt;for&lt;/code&gt; loop throws an exception? In that case, the &lt;code&gt;for&lt;/code&gt; loop stops iterating and propagates the exception to the outside without waiting for the remaining futures. So if one of them hangs or takes an unreasonably long amount of time to finish, we would still be potentially leaking threads! To solve this edge case, we need to catch the exception and cancel the remaining futures that are still running before propagating the error to the outside. That requires a much more involved boilerplate code than what we wrote.&lt;/li&gt;&lt;li&gt;We didn’t handle user cancellations. What if we want to enable the user to cancel the sum computation in the middle? Doing so would require even more boilerplate code to listen for cancellation signals and to propagate them to the futures we launched one by one.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;In summary, correctly structuring concurrency is complex and requires a lot of boilerplate code to make it bug free and 100% safe in all cases.&lt;/p&gt;&lt;p&gt;The good news is: structured concurrency is baked into the design of the Coroutines library, and we do not have to write any boilerplate code to use it and take advantage of it! So let’s check this out!&lt;/p&gt;&lt;h2&gt;Structured concurrency with Kotlin Coroutines&lt;/h2&gt;&lt;p&gt;Let’s rewrite our code using coroutines and see what that looks like:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-kotlin&quot;&gt;suspend fun distributedSum() {
    val sum = AtomicInteger(0)

    // The coroutine scope acts like a parent that keeps track of
    // all the child coroutines created inside it
    coroutineScope {
        // Create 3 coroutines that compute the total sum concurrently
        repeat(3) {
            launch {
                val data: Int = fetchDataAsync()
                sum.addAndGet(data)
            }
        }
    }

    println(&amp;quot;The final sum is: $sum&amp;quot;)
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This short and extremely simple code is already free from all the problems mentioned in the previous section: It cannot leak exceptions or coroutines, it will never print an incomplete sum or a wrong one, and cancellation is already possible! &lt;/p&gt;&lt;p&gt;Feels like magic? Let’s unpack it step by step to understand how.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-kotlin&quot;&gt;coroutineScope { // this: CoroutineScope (receiver)
    ...
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;We start by calling the &lt;code&gt;coroutineScope&lt;/code&gt; function and giving it a &lt;a href=&quot;https://kotlinlang.org/docs/lambdas.html#lambda-expressions-and-anonymous-functions&quot;&gt;kotlin lambda&lt;/a&gt; inside which we can create any number of background coroutines using &lt;code&gt;launch&lt;/code&gt;. The reason why we are able to use &lt;code&gt;launch&lt;/code&gt; inside this lambda is because its receiver&lt;sup id=&quot;fnref-1&quot;&gt;&lt;a href=&quot;#fn-1&quot; class=&quot;footnote-ref&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; is a &lt;code&gt;CoroutineScope&lt;/code&gt; instance, of which &lt;code&gt;launch&lt;/code&gt; is defined as an &lt;a href=&quot;https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/launch.html&quot;&gt;extension function&lt;/a&gt;.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-kotlin&quot;&gt;coroutineScope { // this: CoroutineScope
    repeat(3) {
        // equivelent to: this.launch
        launch {
            ...
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Any background coroutine created within this block is attached as a child to this &lt;code&gt;CoroutineScope&lt;/code&gt; instance which keeps track of its completion and failure. It is similar to what we tried to achieve by manually keeping track of the completable futures in a list. But instead of a list, the &lt;code&gt;CoroutineScope&lt;/code&gt; uses a fancier hierarchical data structure called &lt;code&gt;Job&lt;/code&gt;. We will dig deeper into this data structure later on in this post.&lt;/p&gt;&lt;p&gt;Here are the goodies that come with this setup:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;We don’t need to keep track of the background coroutines ourselves, the &lt;code&gt;CoroutineScope&lt;/code&gt; itself already does, and the &lt;code&gt;coroutineScope&lt;/code&gt; call will suspend until all of them complete or fail. Thus, we know for sure that after this call, all our background coroutines are done; and we can then confidently use the computed sum.&lt;/li&gt;&lt;li&gt;If any of the background coroutines fails for a reason, the exception is caught by the &lt;code&gt;coroutineScope&lt;/code&gt; and propagated to the outside. But first, it takes care of canceling the remaining coroutines that are still running&lt;sup id=&quot;fnref-2&quot;&gt;&lt;a href=&quot;#fn-2&quot; class=&quot;footnote-ref&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;, thus making sure that no background coroutine is still pending after the exception is propagated.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Our background coroutines now have a clear and explicit lifetime defined by the &lt;code&gt;coroutineScope&lt;/code&gt; block beyond which it is impossible to leak any coroutines or exceptions. That’s the core idea of structured concurrency: &lt;em&gt;“every time our control splits into multiple concurrent paths, we make sure they join up again”&lt;/em&gt; &lt;sup id=&quot;fnref-3&quot;&gt;&lt;a href=&quot;#fn-3&quot; class=&quot;footnote-ref&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;. As a result, our program instantly becomes safer and easier to reason about.&lt;/p&gt;&lt;h2&gt;The CoroutineScope and the Jobs hierarchy&lt;/h2&gt;&lt;p&gt;Let’s take a closer look at the signature of the &lt;code&gt;launch&lt;/code&gt; coroutine builder function:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-kotlin&quot;&gt;public fun CoroutineScope.launch(...): Job
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The &lt;code&gt;launch&lt;/code&gt; function requires a &lt;code&gt;CoroutineScope&lt;/code&gt; to be usable. But why is that?&lt;/p&gt;&lt;p&gt;The reason is to prevent background coroutines from being created in the air without having a parent &lt;code&gt;CoroutineScope&lt;/code&gt; instance to keep track of them. This is the case for &lt;strong&gt;all coroutine builder functions&lt;/strong&gt;, which is how Kotlin enforces structured concurrency.&lt;/p&gt;&lt;p&gt;The &lt;code&gt;CoroutineScope&lt;/code&gt; instance keeps track of its children coroutines using a hierarchical data structure called &lt;code&gt;Job&lt;/code&gt;. You can think of a job as a simple tree that:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Stores children &lt;code&gt;Job&lt;/code&gt; instances to keep track of them (which themselves can have other nested children &lt;code&gt;Job&lt;/code&gt; instances).&lt;/li&gt;&lt;li&gt;And has a status (&lt;code&gt;active&lt;/code&gt;, &lt;code&gt;completed&lt;/code&gt;, etc.).&lt;/li&gt;&lt;/ul&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:960px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/4c1abea3e6ca4caec1c039c2d26de50d/d9199/jobs-simple-hierarchy.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:75%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAIAAABr+ngCAAAACXBIWXMAAAsTAAALEwEAmpwYAAAB30lEQVQoz2MQUFDHRIKKGuLqehLqepIa+hLq+oKKGliVMWAK8curCStrapjZaJjZaFs6aFs5CCtp8surEaUZgnhklMXVdMXVdLlllHGpYcDlbF5ZFW5pZV4ZFV5ZFRKcLaiowSenKq1lOHnm3Kmz5klrGfLJqWLVj0WziLIWg6BEcU3Dn9+/fv38UVzTyCAgIaKsRZRmIUUNVjFZn/DYR08fPnr2yDcijlVUVkhJkzjNSppCihrCChpWrj7Wbj5CChrCypqCBDWDfCuvpqBnJqNpKKKszSurIq1pIKKiraBrIqdjzIvhc4RmfgV1DkkFaQ0DflmQIk4pRRFlbWkNAy5pRQEFDX5ZVWlNAw4pRX55DM2Cihpc0kqZxeU79+xOzM5nFZPTMLNdtGzF/KVLNcxsWcVkk3IKdu7enVlUxi2tBLefAR6rUpoGjx4/fv/p9Z1791jFZMvrW378+vrj59fy+hZWMdk79+69//Tm0ZMnUpoG8JhHOJtPTnXKrLmvXr7qnTydRVTGzivg0uUrly9ftfMOZBGV6Z0y7dXLl5NnzeGVU8XibEhK0LVyEFBQ45dX45JSUjI0VzI055JWAiVseTVdKwe4MvQAEwSTXNJKcON4ZFV4kNImREoQKbQBfCepgejEbiYAAAAASUVORK5CYII=&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;Structured concurrency - Job Hierarchy&quot; title=&quot;Structured concurrency - Job Hierarchy&quot; src=&quot;/static/4c1abea3e6ca4caec1c039c2d26de50d/d9199/jobs-simple-hierarchy.png&quot; srcSet=&quot;/static/4c1abea3e6ca4caec1c039c2d26de50d/6f3f2/jobs-simple-hierarchy.png 256w,/static/4c1abea3e6ca4caec1c039c2d26de50d/01e7c/jobs-simple-hierarchy.png 512w,/static/4c1abea3e6ca4caec1c039c2d26de50d/d9199/jobs-simple-hierarchy.png 960w&quot; sizes=&quot;(max-width: 960px) 100vw, 960px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;/&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Structured concurrency - Job Hierarchy&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;Coroutine builder functions (like &lt;code&gt;launch&lt;/code&gt;) also create their own &lt;code&gt;CoroutineScope&lt;/code&gt; instance as the receiver of their lambda block, making it possible to create nested coroutines! That enables building complex hierarchies of concurrently running background coroutines without ever leaking a single one of them.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-kotlin&quot;&gt;coroutineScope { // this: CoroutineScope
    launch(CoroutineName(&amp;quot;Coroutine A&amp;quot;)) { // this: CoroutineScope (nested CoroutineScope with its own Job)
        launch(CoroutineName(&amp;quot;Coroutine A.1&amp;quot;)) { ... }
        launch(CoroutineName(&amp;quot;Coroutine A.2&amp;quot;)) { ... }
    }

    launch(CoroutineName(&amp;quot;Coroutine B&amp;quot;)) { ... }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The code above would create the following hierarchy:&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:960px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/aa2d5f0adb72dec2405da22c02f66b7b/d9199/jobs-complex-hierarchy.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:75%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAIAAABr+ngCAAAACXBIWXMAAAsTAAALEwEAmpwYAAACQ0lEQVQoz2MQUFCHI355NVFVbWktQyktA2ktQ1kdY2ktQ0FFDWQ1yIgBmcMnpyapqa9n42Ro72Ls4GZk72ri5C6kpMlPjGaQ5QrqHBLyAvLq+jZOrGJyXFKKuKxF1yyoqMEvry6hobdk5eq7d+9XNrbyyCgLEelsISVNVjFZB5+gD5/e3bp77cbt26KqOryyKri8zYBsraCihqyOsaS63qwFC2/euVlYWSukqCGnZ8Inp4pVP0Izu4S8lIa+rJahMMjxahLqenyyKpJqupLq+lKaBhwSCtg1CypqcEopRiRnrNuwsaWrV0RFm19ejU9eDRwEavWtHes2bEzKKeCWURZS0kTRDFEhrKR1/uLF528ev//4zjMkik1cTkRFi01czszZ892HN09fPrz34J6Euh63jDKy+6E2c0sr1bV13rt3b+OWrYr6ZryyKiLKWtJaBor6ZivXrHv48EHv5GlSGvoKeqbomsHJQ5VPTlXP2klCXY9HRplPTpVDUkFK00BQXk1SHZRsRJW1hRU0uKWU2MTl4PpRoopLSpFPTpVfXl1MTaempWPewqV23gHsEvK8siqcUgp2XgG9E6cGxiRySStB9KOnMGFlLWYR6dj0nA+f3jx//Xjbrt08Mir88mpiqjpnzp+/+/DG3ft3DO1cuKQUBRU10DULKYFC3szZ88SpUw8fPahuaecEqVMXVtLctG37qzcvzpw7p25qDQk5BszYg8ScloWdg08QKM7kVIUUNbhllFWMLdMKSkwc3cHGgZwNAM/pv2mY0YR3AAAAAElFTkSuQmCC&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;img class=&quot;gatsby-resp-image-image&quot; alt=&quot;Structured concurrency - Complex hierarchy&quot; title=&quot;Structured concurrency - Complex hierarchy&quot; src=&quot;/static/aa2d5f0adb72dec2405da22c02f66b7b/d9199/jobs-complex-hierarchy.png&quot; srcSet=&quot;/static/aa2d5f0adb72dec2405da22c02f66b7b/6f3f2/jobs-complex-hierarchy.png 256w,/static/aa2d5f0adb72dec2405da22c02f66b7b/01e7c/jobs-complex-hierarchy.png 512w,/static/aa2d5f0adb72dec2405da22c02f66b7b/d9199/jobs-complex-hierarchy.png 960w&quot; sizes=&quot;(max-width: 960px) 100vw, 960px&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;/&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Structured concurrency - Complex hierarchy&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;The &lt;code&gt;coroutineScope&lt;/code&gt; call will suspend and not complete until &lt;code&gt;Coroutine A&lt;/code&gt; and &lt;code&gt;Coroutine B&lt;/code&gt; are done. &lt;code&gt;Coroutine A&lt;/code&gt;, on the other hand, will not complete until &lt;code&gt;Coroutine A.1&lt;/code&gt; and &lt;code&gt;Coroutine A.2&lt;/code&gt; are done. If &lt;code&gt;Coroutine A.1&lt;/code&gt; fails for some reason, then &lt;code&gt;Coroutine A&lt;/code&gt; will fail as a whole, propagating the exception to the parent job, causing &lt;code&gt;coroutineScope&lt;/code&gt; itself to fail. Any coroutine still running in this hierarchy will get canceled during the process.&lt;/p&gt;&lt;h2&gt;Difference between CoroutineScope and CoroutineContext&lt;/h2&gt;&lt;p&gt;One aspect that may confuse a lot of Kotliners is the difference between a &lt;code&gt;coroutineContext&lt;/code&gt; and a &lt;code&gt;CoroutineScope&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;If you check the source code of &lt;code&gt;CoroutineScope&lt;/code&gt;, you will find the following: &lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-kotlin&quot;&gt;public interface CoroutineScope {
    public val coroutineContext: CoroutineContext
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Why do we need a &lt;code&gt;CoroutineScope&lt;/code&gt; then? Why not just use &lt;code&gt;CoroutineContext&lt;/code&gt; instead? The difference between both concepts as &lt;a href=&quot;https://elizarov.medium.com/coroutine-context-and-scope-c8b255d59055&quot;&gt;outlined by Roman Elizarov&lt;/a&gt; is in their intended purpose.&lt;/p&gt;&lt;p&gt;A &lt;code&gt;CoroutineContext&lt;/code&gt; is simply a data structure holding 0 or several context elements. It is just like a &lt;code&gt;HashMap&lt;/code&gt; and serves as a container that coroutines and their schedulers can access at any point in time to retrieve useful information from like the &lt;code&gt;Dispatcher&lt;/code&gt;, the coroutine’s name, etc.&lt;/p&gt;&lt;p&gt;On the other hand, a &lt;code&gt;CoroutineScope&lt;/code&gt; is like a “manager and a tracker for coroutines”. It is the entity that can create background coroutines using coroutine builder functions defined as extension methods to this class (like &lt;code&gt;launch&lt;/code&gt;).&lt;/p&gt;&lt;p&gt;To be able to fullfill its job of creating such coroutines and keeping track of them, the &lt;code&gt;CoroutineScope&lt;/code&gt; needs basically two things:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;A &lt;code&gt;Job&lt;/code&gt; instance to keep track of the children coroutines (to enforce structured concurrency).&lt;/li&gt;&lt;li&gt;Some optional coroutine context elements that we want to propagate to all children coroutines created inside this scope (ex. the Dispatcher).&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;It turns out that both the requirements above can be satisfied by having a single &lt;code&gt;coroutineContext&lt;/code&gt; property:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;The &lt;code&gt;coroutineContext&lt;/code&gt; property can store the &lt;code&gt;Job&lt;/code&gt; instance that will serve as a parent to the children coroutines created by this &lt;code&gt;CoroutineScope&lt;/code&gt;. All the functions that instantiate a &lt;code&gt;CoroutineScope&lt;/code&gt; will create such a &lt;code&gt;Job&lt;/code&gt; and put it there.&lt;/li&gt;&lt;li&gt;It will also hold any additional context element that we want to propagate to the children coroutines.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Roman Elizarov explains this concept clearly in &lt;a href=&quot;https://elizarov.medium.com/coroutine-context-and-scope-c8b255d59055&quot;&gt;his article about the topic&lt;/a&gt;. I highly encourage you to read it as well as his other writings about Kotlin ;).&lt;/p&gt;&lt;h2&gt;Conclusion&lt;/h2&gt;&lt;p&gt;Structured concurrency makes your concurrency intensive programs safer and more understandable. It frees you from all the boilerplate code that you would otherwise need to write to synchronize your background tasks and make sure you are not leaking any of them.&lt;/p&gt;&lt;p&gt;The next topic of this series will be about Error handling and cancellation, maybe one of the trickiest aspects of structured concurrency. Stay tuned if you don’t want to miss out on that one ;) .&lt;/p&gt;&lt;div class=&quot;footnotes&quot;&gt;&lt;hr/&gt;&lt;ol&gt;&lt;li id=&quot;fn-1&quot;&gt;The lambda receiver is the instance referred to by the &lt;code&gt;this&lt;/code&gt; keyword inside this lambda’s block.&lt;a href=&quot;#fnref-1&quot; class=&quot;footnote-backref&quot;&gt;↩&lt;/a&gt;&lt;/li&gt;&lt;li id=&quot;fn-2&quot;&gt;This behavior can be overridden using Supervisor jobs. We will talk mpre about this in the second part of this series around Error Handling and cancellation.&lt;a href=&quot;#fnref-2&quot; class=&quot;footnote-backref&quot;&gt;↩&lt;/a&gt;&lt;/li&gt;&lt;li id=&quot;fn-3&quot;&gt;Quote taken from &lt;a href=&quot;https://vorpus.org/blog/notes-on-structured-concurrency-or-go-statement-considered-harmful/&quot;&gt;Notes on structured concurrency or go statement considered harmful&lt;/a&gt;&lt;a href=&quot;#fnref-3&quot; class=&quot;footnote-backref&quot;&gt;↩&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;</content:encoded></item><item><title><![CDATA[Why are my coroutines slow?]]></title><description><![CDATA[In this post, we will discover the consequences of making blocking calls inside coroutines, what strategies we can use to deal with them, and how to detect illegitimate blocking calls inside coroutines in practice using Blockhound!]]></description><link>https://www.thedevtavern.com/blog/posts/why-are-my-coroutines-slow/</link><guid isPermaLink="false">https://www.thedevtavern.com/blog/posts/why-are-my-coroutines-slow/</guid><pubDate>Mon, 27 Dec 2021 10:47:08 GMT</pubDate><content:encoded>&lt;style data-emotion=&quot;css-global 12qioua&quot;&gt;html{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;box-sizing:border-box;-webkit-text-size-adjust:100%;}*,*::before,*::after{box-sizing:inherit;}strong,b{font-weight:700;}body{margin:0;color:#fff;font-size:1.1875rem;font-family:&quot;Roboto&quot;,&quot;Helvetica&quot;,&quot;Arial&quot;,sans-serif;font-weight:400;line-height:1.5;letter-spacing:0.00938em;background-color:#102027;}@media print{body{background-color:#fff;}}body::backdrop{background-color:#102027;}&lt;/style&gt;&lt;h2&gt;Introduction&lt;/h2&gt;&lt;p&gt;Coroutines are one of Kotlin’s killer features! They do a great job simplifying concurrency intensive programs, making them feel more accessible and intuitive to write.&lt;/p&gt;&lt;p&gt;However, coroutines are also easy enough to misuse. One of the common mistakes that programmers make is accidentally injecting blocking calls inside coroutines (we will see what that means in a second), causing the whole application to perform slower and feel unresponsive. It might not even be you who introduced this blocking call in the first place, but a library function marked as &lt;code&gt;suspend&lt;/code&gt; that you are using deep inside your program! And when this happens, chances are that it will take more than a few minutes to troubleshoot and figure out why.&lt;/p&gt;&lt;p&gt;This blog post is here to hopefully save you from wasting your time as I once did! 😅 . We will see how to quickly detect illegitimate blocking calls with &lt;a href=&quot;https://github.com/reactor/BlockHound&quot;&gt;BlockHound&lt;/a&gt;. But before that, we will cover some theory around how coroutines work, what causes them to be blocked, and a few strategies to handle blocking calls within a coroutines-based application. If you are already a coroutines expert and are not interested in the theory part, feel free to skip to the last part of this post, where we demo the usage of BlockHound.&lt;/p&gt;&lt;h2&gt;The symptoms: what causes coroutines to become slow?&lt;/h2&gt;&lt;p&gt;When you start feeling that your coroutines based application is becoming slow and unresponsive, in most cases (bets on the table!), the cause is one of these two:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;The CPU of your machine is the bottleneck!&lt;/strong&gt; This is probably the first thing to check. The coroutines machinery is a complex beast and needs CPU to run! Orchestrating and scheduling the many coroutines you have in your application is, in fact, a CPU-intensive task. If all the cores of your machines are nearing 100% when your program is running, then the whole machine will become slow, not only your coroutines! The way out in this case is to either optimize your program to use less CPU, distribute the work more evenly across the available cores, or simply upgrade your machine.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;You are inadvertently blocking your coroutines!&lt;/strong&gt; This mistake is unfortunately easy to make but often hard to find and recover from. This is what we will focus on in the rest of this post.&lt;/li&gt;&lt;/ul&gt;&lt;h2&gt;How is a coroutine blocked?&lt;/h2&gt;&lt;p&gt;Let’s take a step back and try to form a high-level understanding of how coroutines work behind the scenes and what blocking them means.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-kotlin&quot;&gt;launch {
    println(&amp;quot;Hey I&amp;#x27;m a coroutine!!&amp;quot;)
    delay(5000) // suspends
    println(&amp;quot;I&amp;#x27;m done!&amp;quot;)
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Coroutines are often referred to as “lightweight threads”. When a coroutine is created, like in the example above, it runs concurrently alongside other coroutines. However, the analogy with threads stops pretty much here.&lt;/p&gt;&lt;p&gt;Coroutines are run by one or a small number of threads (typically the number of cores in your machine). Those threads are called workers in Kotlin’s jargon. One Worker (thread) juggles between several coroutines. It starts working on a coroutine, then suddenly stops its execution in the middle (suspension) to resume working on a completely unrelated coroutine (continuation). This suspension and continuation all happen behind the scenes with the help of some magic from the Kotlin compiler!&lt;/p&gt;&lt;p&gt;A worker (thread) is only allowed to do this jump from one coroutine to the other when it meets &lt;strong&gt;a suspension point&lt;/strong&gt; inside the coroutine it is currently running. A suspension point is declared via &lt;a href=&quot;https://github.com/JetBrains/kotlin/blob/v1.6.10/libraries/stdlib/src/kotlin/coroutines/Continuation.kt#L132-L149&quot;&gt;the &lt;code&gt;suspendCoroutine&lt;/code&gt; function or the likes&lt;/a&gt;. In practice, however, you will rarely encounter those functions directly. Instead, you will typically use higher-level functions marked with the &lt;code&gt;suspend&lt;/code&gt; keyword that use these lower-level constructs behind the scenes.&lt;/p&gt;&lt;p&gt;Problems start when your coroutine takes a long time executing code without suspending. Consider the following example:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-kotlin&quot;&gt;suspend fun httpRequest(url: String): String {
    ...
}

fun saveResponse(response: String, filename: String) {
    ...
}

launch {
    val response = httpRequest(&amp;quot;https://example.com/data.json&amp;quot;) // Takes about 5s!
    saveResponse(response, filename=&amp;quot;/tmp/response.txt&amp;quot;) // Takes about 2s!
}

&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;In the code above, the coroutine created via the &lt;code&gt;launch&lt;/code&gt; builder starts by performing an http request to fetch some remote data. This call takes around 5s. As it is suspending (i.e., the function is marked with the &lt;code&gt;suspend&lt;/code&gt; keyword, and we assume the author’s implementation is correctly suspending), our Worker is not blocked during that time! It will jump out of this coroutine’s execution to progress on other coroutines while the http call is in progress. Thus, the Worker’s time here is not being wasted. So far, so good!&lt;/p&gt;&lt;p&gt;Now, 5s have elapsed, the http call is done, our worker thread comes back to resume from where it left off. The next step is to write the response into a file. This step takes around 2s. However, the call is not suspending! (Note the absence of the &lt;code&gt;suspend&lt;/code&gt; keyword in the &lt;code&gt;saveResponse&lt;/code&gt; function’s signature). Consequently, the worker thread has no other choice than to sit idle waiting for the call to finish. It cannot jump out to make progress on any other coroutine. In other words, our worker thread is blocked!&lt;/p&gt;&lt;p&gt;In a multithreaded runtime like Kotlin’s, the default coroutine dispatcher usually has multiple worker threads, so the issue is not as bad as if it were to happen in a single-threaded runtime like Javascript’s or Python’s. But still, if you block all your worker threads this way, no progress is made on any of the other coroutines, and that’s when you start noticing slowness or unresponsiveness in your app!&lt;/p&gt;&lt;h2&gt;What should I do if I need to block inside my coroutines?&lt;/h2&gt;&lt;p&gt;In the previous section, we have seen that blocking calls inside coroutines should be avoided. However, in reality, this is not something we can do all the time! Sometimes you might need to use a library function that synchronously performs blocking tasks, and you don’t find an asynchronous alternative (with futures or callbacks). There are, unfortunately, tons of examples in the Java ecosystem. A few that I encountered myself include &lt;a href=&quot;https://github.com/kubernetes-client/java&quot;&gt;the Kubernetes java client&lt;/a&gt; or &lt;a href=&quot;https://github.com/apache/kafka/blob/trunk/clients/src/main/java/org/apache/kafka/clients/consumer/KafkaConsumer.java&quot;&gt;the Kafka consumer client&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;So how can we perform those blocking calls within our coroutines based application while keeping it performant and responsive?&lt;/p&gt;&lt;p&gt;The general idea is to run them in a separate worker pool or dedicated threads to keep your main worker pool&lt;sup id=&quot;fnref-1&quot;&gt;&lt;a href=&quot;#fn-1&quot; class=&quot;footnote-ref&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;, where most of your coroutines are running, free from blocking code. There are multiple ways how you can achieve this in practice.&lt;/p&gt;&lt;h4&gt;Using &lt;a href=&quot;http://dispatchers.io/&quot;&gt;Dispatchers.IO&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;The first solution is the simplest and the most widely used.&lt;/p&gt;&lt;p&gt;The idea is to isolate your blocking code by running it within the &lt;code&gt;Dispatchers.IO&lt;/code&gt;, a global shared pool of worker threads whose primary purpose is to run blocking tasks. This worker pool contains 64 threads by default, making it less sensitive to blocking tasks. You would need to make all of the 64 threads simultaneously blocked for it to start causing slowness or unresponsiveness to your app!&lt;/p&gt;&lt;p&gt;Using this dispatcher can be done as the following:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-kotlin&quot;&gt;launch {
    val response = httpCient.request()
    withContext(Dispatchers.IO) {
        saveResponse(response, filename=&amp;quot;/tmp/response.txt&amp;quot;)
    }
}

&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;It is easy to feel safe using this dispatcher widely across your application whenever you have a blocking call to make. However, you need to be careful: this pool has a limited number of workers. And as it is global, shared across your whole application, and might also be used by your library functions without you knowing, it’s much easier to exhaust than you might think! It happened to me more than once that I ran into performance issues in my coroutines and then realized that I was saturating the &lt;code&gt;Dispatchers.IO&lt;/code&gt; threads!&lt;/p&gt;&lt;p&gt;That’s why I’m usually reluctant to using this dispatcher unless I’m writing a small application or when the predictability of performance is not critical.&lt;/p&gt;&lt;p&gt;The good news is: these issues are entirely mitigated by using &lt;code&gt;Dispatchers.IO&lt;/code&gt; views, a feature available since version 1.6.0 of &lt;code&gt;kotlinx-coroutines-core&lt;/code&gt;, making this dispatcher much more useful and safer to use!&lt;/p&gt;&lt;h4&gt;Creating views from the &lt;code&gt;Dispatchers.IO&lt;/code&gt;&lt;/h4&gt;&lt;p&gt;Since version 1.6.0 of &lt;code&gt;kotlinx-coroutines-core&lt;/code&gt;, it is possible to create “views” from coroutine dipsatchers. This feature, especially when used on &lt;code&gt;Dispatchers.IO&lt;/code&gt;, is a very effective way to isolate blocking calls.&lt;/p&gt;&lt;p&gt;Let’s check an example of the usage before explaining the underlying concepts:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-kotlin&quot; metastring=&quot;highlight=1,5&quot; highlight=&quot;1,5&quot;&gt;val dispatcher = Dispatchers.IO.limitedParallelism(100)

launch {
    val response = httpCient.request()
    withContext(dispatcher) {
        saveResponse(response, filename=&amp;quot;/tmp/response.txt&amp;quot;)
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The &lt;code&gt;limitedParallelism&lt;/code&gt; function creates a “view” of the current dispatcher that limits the parallelism to the given value (100 in the example above). The resulting view uses the original dispatcher for execution but guarantees that no more than the specified number of coroutines are executed simultaneously.&lt;/p&gt;&lt;p&gt;Generally, you cannot create a view with a parallelism level that is superior to the original dispatcher’s parallelism level. However, the &lt;code&gt;Dispatchers.IO&lt;/code&gt; has a unique property of elasticity when creating views, allowing you to create as many views as you want with the desired level of parallelism. You can read more about this important behavior &lt;a href=&quot;https://github.com/Kotlin/kotlinx.coroutines/blob/1.6.0/kotlinx-coroutines-core/jvm/src/Dispatchers.kt#L103-L122&quot;&gt;here&lt;/a&gt;. That’s the reason why, in the example above, we were able to create a view with a parallelism level of 100 even though the &lt;code&gt;Dispatchers.IO&lt;/code&gt; is capped to 64 threads! That was not a mistake 😉.&lt;/p&gt;&lt;p&gt;This is my default approach for handling blocking calls in most situations unless I am using an older version of Coroutines.&lt;/p&gt;&lt;h4&gt;Using a dedicated thread pool as a Coroutine Dispatcher&lt;/h4&gt;&lt;p&gt;You can also create a dedicated thread pool to offload your blocking calls. This approach is a good alternative if you don’t want to rely on the shared &lt;code&gt;Dispatchers.IO&lt;/code&gt; (before dispatcher views became available).&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-kotlin&quot;&gt;val dispatcher = newFixedThreadPoolContext(10)

// or
val dispatcher = Executors.newCachedThreadPool().asCoroutineDispatcher()

launch(dispatcher) {
    ...
}

// It becomes your responsibility to close the resulting dispatcher!
dispatcher.close()
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The resulting dispatcher becomes your responsibility to manage. In particular, you need to remember to close it when you are done with it.&lt;/p&gt;&lt;h4&gt;Spinning up a dedicated thread to run a long-running blocking task&lt;/h4&gt;&lt;p&gt;I often use this approach when I have a long-running blocking task that produces some data that I want to pass to my coroutines through a Channel or a Flow. A nice example of this is using the Kafka consumer client and making it poll records from Kafka as a Flow:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-kotlin&quot;&gt;fun &amp;lt;K, V&amp;gt; KafkaConsumer&amp;lt;K, V&amp;gt;.pollAsFlow(topics: List&amp;lt;String&amp;gt;): Flow&amp;lt;ConsumerRecord&amp;lt;K, V&amp;gt;&amp;gt; =
    callbackFlow {
        thread(name = &amp;quot;kafka-consumer-flow-thread&amp;quot;) {
            try {
                subscribe(topics)
                // `isActive` here refers to the producer scope of the `callbackFlow`
                while (isActive) {
                    // Consume new records from Kafka (blocking)
                    val records = poll(Duration.ofSeconds((3)))
                    for (record in records) {
                        // Send the record downstream using the flow&amp;#x27;s `trySendBlocking` method
                        trySendBlocking(record).getOrThrow()
                    }
                    commitSync() // Blocking
                }
            } catch (exception: Exception) {
                close(exception)
            } finally {
                close()
            }
        }

        awaitClose {}
    }

// usage
launch {
    consumer
        .pollAsFlow(listOf(&amp;quot;my_topic&amp;quot;))
        .collect { println(it) }
}

&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If you are not familiar with flows, I highly recommend checking them out! They will very likely level up your asynchronous programming skills!&lt;/p&gt;&lt;h2&gt;Using Blockhound to detect blocking calls inside coroutines&lt;/h2&gt;&lt;p&gt;Enough with theory! Let’s get to the fun part!&lt;/p&gt;&lt;p&gt;In practice, one efficient way to detect blocking calls inside your coroutines is by using &lt;a href=&quot;https://github.com/reactor/BlockHound&quot;&gt;BlockHound&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;BlockHound is a Java Agent built by the Reactor team that detects blocking calls from non-blocking threads. When it does, BlockHound throws an exception with a helpful error message pointing us to the exact place where the blocking call occurred. It is suitable for local debugging during development, unit, and integration tests.&lt;/p&gt;&lt;p&gt;But first, we need to instruct BlockHound what threads we consider non-blocking (i.e., in which we want to forbid blocking calls). This is done through &lt;a href=&quot;https://github.com/reactor/BlockHound/blob/master/docs/custom_integrations.md&quot;&gt;integrations&lt;/a&gt;. BlockHound already provides built-in integrations with Reactor &amp;amp; RxJava, allowing it to accurately detect illegitimate blocking calls in both frameworks’ event loops.&lt;/p&gt;&lt;p&gt;Fortunately for us, the Kotlin team also built a BlockHound integration for Kotlin Coroutines. It is packaged &amp;amp; distributed via the &lt;a href=&quot;https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-debug/index.html&quot;&gt;kotlinx-coroutines-debug&lt;/a&gt; project.&lt;/p&gt;&lt;p&gt;This integration configures BlockHound to intercept blocking calls in Coroutines launched in the &lt;code&gt;Dispatchers.Default&lt;/code&gt; worker pool. This is an important thing to keep in mind when using this integration: Blocking calls in coroutines spun up in other dispatchers (including those you build yourself) will not be intercepted. If this part is not clear, no worries, it will become more apparent after the demo below.&lt;/p&gt;&lt;p&gt;To demonstrate the usage of BlockHound, let’s consider a short Kotlin code with a &lt;code&gt;suspend&lt;/code&gt; function containing an ugly blocking call:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-kotlin&quot;&gt;/**
* A suspend function with an awful blocking sleep!
*/
suspend fun httpCall() {
    Thread.sleep(200)
    delay(5000)
}

fun main(): Unit = runBlocking {
    httpCall()
}

&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Obviously, in reality, the evil blocking calls inside your coroutines will rarely be this visible! Usually, you will have to find them hidden deep inside your functions in unexpected places (such as middlewares, callbacks, etc.).&lt;/p&gt;&lt;p&gt;To use Blockhound, we need to inject its maven coordinates in our build system and &lt;code&gt;kotlinx-coroutines-debug&lt;/code&gt; as it provides the coroutines Blockhound integration. The example below uses Gradle:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-kotlin&quot; metastring=&quot;highlight=7-8&quot; highlight=&quot;7-8&quot;&gt;dependencies {
    implementation(platform(&amp;quot;org.jetbrains.kotlin:kotlin-bom&amp;quot;))

    implementation(&amp;quot;org.jetbrains.kotlin:kotlin-stdlib-jdk8&amp;quot;)
    implementation(&amp;quot;org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.2&amp;quot;)

    implementation(&amp;quot;org.jetbrains.kotlinx:kotlinx-coroutines-debug:1.5.2&amp;quot;)
    implementation(&amp;quot;io.projectreactor.tools:blockhound:1.0.6.RELEASE&amp;quot;)
}

&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;To prepare BlockHound to monitor our threads, we should call the &lt;code&gt;BlockHound.install()&lt;/code&gt; method and supply it with a &lt;code&gt;CoroutinesBlockHoundIntegration&lt;/code&gt; instance:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-kotlin&quot; metastring=&quot;highlight=16&quot; highlight=&quot;16&quot;&gt;import kotlinx.coroutines.debug.CoroutinesBlockHoundIntegration
import kotlinx.coroutines.delay
import kotlinx.coroutines.runBlocking
import reactor.blockhound.BlockHound

/**
* A suspend function with an awful blocking sleep!
*/

suspend fun httpCall() {
    Thread.sleep(200)
    delay(5000)
}

fun main(): Unit = runBlocking {
    BlockHound.install(CoroutinesBlockHoundIntegration())
    httpCall()
}

&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now, if you run this program, surprisingly, nothing happens! BlockHound did not intercept our blocking call. As I mentioned above, this is due to how this integration is built: it only intercepts blocking calls when running in the context of &lt;code&gt;Dispatchers.Default&lt;/code&gt; (or &lt;code&gt;Dispatchers.Main&lt;/code&gt;). So let’s modify our program to use that context instead:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-kotlin&quot; metastring=&quot;highlight=16&quot; highlight=&quot;16&quot;&gt;import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.debug.CoroutinesBlockHoundIntegration
import kotlinx.coroutines.delay
import kotlinx.coroutines.runBlocking
import reactor.blockhound.BlockHound

/**
* A suspend function with an awful blocking sleep!
*/

suspend fun httpCall() {
    Thread.sleep(200)
    delay(5000)
}

fun main(): Unit = runBlocking(Dispatchers.Default) {
    BlockHound.install(CoroutinesBlockHoundIntegration())
    httpCall()
}

&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now, if we rerun our program, we will get a nice error message pointing it to the exact place where the blocking call is happening:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;Exception in thread &amp;quot;main&amp;quot; reactor.blockhound.BlockingOperationError: Blocking call! java.lang.Thread.sleep
        at java.base/java.lang.Thread.sleep(Thread.java)
        at coroutines.debug.MainKt.httpCall(Main.kt:13)
        at coroutines.debug.MainKt$main$1.invokeSuspend(Main.kt:19)
        at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)

&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;Conclusion&lt;/h2&gt;&lt;p&gt;Accidental blocking calls are one of the main causes of performance issues in Coroutines-based applications. They can come from your library functions, middlewares, or other unexpected places. Using BlockHound in your automated tests should allow you to detect them preemptively before they reach your production environment. Once you identify your guilty blocking calls, you can use the strategies we have seen earlier to deal with them.&lt;/p&gt;&lt;p&gt;Last but not least, I am currently creating an online course dedicated to learning Kotlin Coroutines. If you are interested, make sure to &lt;a href=&quot;/courses&quot;&gt;check it out and subscribe for updates to be notified of its release&lt;/a&gt; 😉.&lt;/p&gt;&lt;div class=&quot;footnotes&quot;&gt;&lt;hr/&gt;&lt;ol&gt;&lt;li id=&quot;fn-1&quot;&gt;Usually the &lt;code&gt;Dispatchers.Default&lt;/code&gt;&lt;a href=&quot;#fnref-1&quot; class=&quot;footnote-backref&quot;&gt;↩&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;</content:encoded></item></channel></rss>