<?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[Piotr Mionskowski]]></title><description><![CDATA[Piotr Mionskowski's thoughts on software, technology, architecture, design patterns and programming in general.]]></description><link>https://miensol.pl/</link><generator>GatsbyJS</generator><lastBuildDate>Sat, 16 Dec 2023 21:22:25 GMT</lastBuildDate><item><title><![CDATA[First steps with AWS Bedrock]]></title><description><![CDATA[AI is taking over the world. At Bright Inventions, we’ve already helped several clients with generative AI. In this blog post, we’ll see how to use aws-cdk to create a simple API that responds to prompts. Request Bedrock model access If you haven’t used Bedrock before, the first step is to request model access. You can…]]></description><link>undefined/aws-cdk-bedrock-basics/</link><guid isPermaLink="false">undefined/aws-cdk-bedrock-basics/</guid><pubDate>Sun, 17 Dec 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;AI is taking over the world. At Bright Inventions, we’ve already helped several clients with generative AI.&lt;br&gt;
In this blog post, we’ll see how to use aws-cdk to create a simple API that responds to prompts.&lt;/p&gt;
&lt;h2 id=&quot;request-bedrock-model-access&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#request-bedrock-model-access&quot; aria-label=&quot;request bedrock model access permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Request Bedrock model access&lt;/h2&gt;
&lt;p&gt;If you haven’t used Bedrock before, the first step is to request model access.&lt;/p&gt;
&lt;p&gt;You can do so
in &lt;a href=&quot;https://eu-central-1.console.aws.amazon.com/bedrock/home?region=eu-central-1#/modelaccess&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;AWS Console &gt; Bedrock Model &gt; access page&lt;/a&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;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 57.50000000000001%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAACXBIWXMAABYlAAAWJQFJUiTwAAABwUlEQVQoz4VTi27bMAz0//9d6ySLna5tsDZN4pest2I5VxwTF1uxYQQISvLxeKLo4uGxxLaqUa7W2PzYYlvX6AcFNY5/d20waItBGyilxAel0PUDRq1RPJYrVPUO5XqNh7LEar3BtqrkrN49SWRBFqrqGtufe2yef2Hz9IrqeY/17gWv+z0+jscb4dv7O+hd38N7jxACnPdwzkn8Y+8cgqztzX2A9QEhBhhrb4TDMODcNAJOKeFyuYhP0yQFeB3vg+xjjLKPccElTJcLQoxyZWMsCoKbtkXOGbR5nmVNZxIVcn29XoU0hChxwdBlP92wxZQz+r7H+dxIpCom05zzOJ1bNG0H67wUI4ZKaTfcFdM846iTtKAge9d16PlK4/ilhmatw+F4wuncwFgnhNoYicQIjsrzjMMY4cKdkAqGQcGHIIk5z1+k/7KFcCGlUXnBA6VGaG3E2dilnzElWOfE2Wue8+G+E2Yqj1kECSH7tpD8bqLYWLm6u2P4UN8tz1f0foIPEQUrcnTarhNFTEgciWkSZZwt9o3EfEVrrXxjXrqPWEgJp9HDOI+CCRzKZTD/5yTnLB4+jvIrjsZAaS2FyPEJ6dCchW4yNi0AAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/a8bf521bc9d40e14c89a639beed14d50/8ac56/bedrock-request-model-access.webp 240w,
/static/a8bf521bc9d40e14c89a639beed14d50/d3be9/bedrock-request-model-access.webp 480w,
/static/a8bf521bc9d40e14c89a639beed14d50/e46b2/bedrock-request-model-access.webp 960w,
/static/a8bf521bc9d40e14c89a639beed14d50/f992d/bedrock-request-model-access.webp 1440w,
/static/a8bf521bc9d40e14c89a639beed14d50/882b9/bedrock-request-model-access.webp 1920w,
/static/a8bf521bc9d40e14c89a639beed14d50/e91b7/bedrock-request-model-access.webp 2090w&quot;
              sizes=&quot;(max-width: 960px) 100vw, 960px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/a8bf521bc9d40e14c89a639beed14d50/8ff5a/bedrock-request-model-access.png 240w,
/static/a8bf521bc9d40e14c89a639beed14d50/e85cb/bedrock-request-model-access.png 480w,
/static/a8bf521bc9d40e14c89a639beed14d50/d9199/bedrock-request-model-access.png 960w,
/static/a8bf521bc9d40e14c89a639beed14d50/07a9c/bedrock-request-model-access.png 1440w,
/static/a8bf521bc9d40e14c89a639beed14d50/29114/bedrock-request-model-access.png 1920w,
/static/a8bf521bc9d40e14c89a639beed14d50/10c1e/bedrock-request-model-access.png 2090w&quot;
            sizes=&quot;(max-width: 960px) 100vw, 960px&quot;
            type=&quot;image/png&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/a8bf521bc9d40e14c89a639beed14d50/d9199/bedrock-request-model-access.png&quot;
            alt=&quot;bedrock-request-model-access.png&quot;
            title=&quot;Request model access&quot;
            loading=&quot;lazy&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;For Claude and Claude Instant models describe your use case briefly.&lt;/p&gt;
&lt;h2 id=&quot;define-your-aws-lambda-function-with-aws-cdk&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#define-your-aws-lambda-function-with-aws-cdk&quot; aria-label=&quot;define your aws lambda function with aws cdk permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Define your AWS Lambda function with aws-cdk&lt;/h2&gt;
&lt;p&gt;Declaring an AWS Lambda function with aws-cdk is straightforward. Our function needs to invoke Bedrock models, hence
appropriate IAM permissions are necessary. For simplicity, we’ll use AWS Lambda Function URLs with authentication type
NONE.
You should use that only for evaluation purposes.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;BrightBedrockSimpleStack&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;cdk&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Stack &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;scope&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Construct&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; props&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; cdk&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;StackProps&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;scope&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; props&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; lambdaPrompt &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;NodejsFunction&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;lambda&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      architecture&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Architecture&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;ARM_64&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      timeout&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Duration&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;seconds&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;30&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      entry&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; path&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;process&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;cwd&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;lib&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;bedrock-client&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;simple-api.lambda.ts&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    lambdaPrompt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addToRolePolicy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PolicyStatement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      actions&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;bedrock:InvokeModel&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      resources&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;*&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; functionUrl &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; lambdaPrompt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addFunctionUrl&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      authType&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; FunctionUrlAuthType&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NONE&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CfnOutput&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;function-url&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      value&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; functionUrl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;url
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;invoking-bedrock-amazontitan-text-express-v1&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#invoking-bedrock-amazontitan-text-express-v1&quot; aria-label=&quot;invoking bedrock amazontitan text express v1 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Invoking Bedrock amazon.titan-text-express-v1&lt;/h2&gt;
&lt;p&gt;Bedrock provides multiple models. The models differ not only in terms of their capabilities but also in their API. For
starters, let’s use Titan Text Express.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; handler&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;APIGatewayProxyHandlerV2&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;event&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; context&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; body &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; event&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;body&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; response &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; bedrock&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;InvokeModelCommand&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    body&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;stringify&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      inputText&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; body&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    contentType&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;application/json&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    modelId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;amazon.titan-text-express-v1&quot;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; modelResponseJson &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;body&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;transformToString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    statusCode&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;$metadata&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;httpStatusCode &lt;span class=&quot;token operator&quot;&gt;??&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;500&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    headers&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token string&quot;&gt;&apos;Content-Type&apos;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;contentType
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    body&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; modelResponseJson
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;After we deploy the code, we can invoke our function and ask basic questions, e.g.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;shell&quot;&gt;&lt;pre class=&quot;language-shell&quot;&gt;&lt;code class=&quot;language-shell&quot;&gt;&lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; -s -X POST --location &lt;span class=&quot;token string&quot;&gt;&quot;https://&lt;span class=&quot;token variable&quot;&gt;${YOUR_LAMBDA_ID}&lt;/span&gt;.lambda-url.eu-central-1.on.aws&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;
    -H &lt;span class=&quot;token string&quot;&gt;&quot;Content-Type: text/plain&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;
    -d &lt;span class=&quot;token string&quot;&gt;&apos;Which country has the highest GDP?&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; jq
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token string&quot;&gt;&quot;inputTextTokenCount&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;7&lt;/span&gt;,
  &lt;span class=&quot;token string&quot;&gt;&quot;results&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token string&quot;&gt;&quot;tokenCount&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;34&lt;/span&gt;,
      &lt;span class=&quot;token string&quot;&gt;&quot;outputText&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token entity&quot; title=&quot;\n&quot;&gt;\n&lt;/span&gt;The country that has the highest GDP is the United States. Its total GDP is &lt;span class=&quot;token variable&quot;&gt;$23&lt;/span&gt;.07 trillion in terms of purchasing power parity (PPP).&quot;&lt;/span&gt;,
      &lt;span class=&quot;token string&quot;&gt;&quot;completionReason&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;FINISH&quot;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;titan-text-express-configuration&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#titan-text-express-configuration&quot; aria-label=&quot;titan text express configuration permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Titan Text Express configuration&lt;/h2&gt;
&lt;p&gt;We can control and tweak some the aspects of how the model responds to our prompts. For example, for Titan Text Express
we can
configure:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;temperature: Float value to control randomness in the response (0 to 1, default 0). Lower values decrease randomness.&lt;/li&gt;
&lt;li&gt;topP: Float value to control the diversity of options (0 to 1, default 1). Lower values ignore less probable options.&lt;/li&gt;
&lt;li&gt;maxTokenCount: Integer specifying the maximum number of tokens in the generated response (0 to 8,000, default 512).&lt;/li&gt;
&lt;li&gt;stopSequences: Array of strings indicating where the model should stop generating text. Use the pipe character (|) to
separate different sequences (up to 20 characters).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let’s modify our lambda to allow controlling the parameters.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; response &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; bedrock&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;InvokeModelCommand&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  body&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;stringify&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    inputText&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; body&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    textGenerationConfig&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      temperature&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;parseFloat&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;event&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;queryStringParameters&lt;span class=&quot;token operator&quot;&gt;?.&lt;/span&gt;temperature &lt;span class=&quot;token operator&quot;&gt;??&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;undefined&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      topP&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;parseFloat&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;event&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;queryStringParameters&lt;span class=&quot;token operator&quot;&gt;?.&lt;/span&gt;topP &lt;span class=&quot;token operator&quot;&gt;??&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;undefined&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      maxTokenCount&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;parseInt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;event&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;queryStringParameters&lt;span class=&quot;token operator&quot;&gt;?.&lt;/span&gt;maxTokenCount &lt;span class=&quot;token operator&quot;&gt;??&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;undefined&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  contentType&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;application/json&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  modelId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;amazon.titan-text-express-v1&quot;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;After deploying, we can control the model parameters through query string parameters:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;shell&quot;&gt;&lt;pre class=&quot;language-shell&quot;&gt;&lt;code class=&quot;language-shell&quot;&gt;&lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; -X POST --location &lt;span class=&quot;token string&quot;&gt;&quot;https://g66m7el4jcrtwarntzrcfps2tq0yduar.lambda-url.eu-central-1.on.aws?temperature=0.9&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;
    -H &lt;span class=&quot;token string&quot;&gt;&quot;Content-Type: text/plain&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;
    -d &lt;span class=&quot;token string&quot;&gt;&apos;What is the country that has the most freedom of speech in the world?&apos;&lt;/span&gt;
    
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token string&quot;&gt;&quot;inputTextTokenCount&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;15&lt;/span&gt;,
  &lt;span class=&quot;token string&quot;&gt;&quot;results&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token string&quot;&gt;&quot;tokenCount&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;28&lt;/span&gt;,
      &lt;span class=&quot;token string&quot;&gt;&quot;outputText&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token entity&quot; title=&quot;\n&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;token entity&quot; title=&quot;\&amp;quot;&quot;&gt;\&quot;&lt;/span&gt;The United States has the most freedom of speech in the world, according to the 2022 Freedom House Index.&lt;span class=&quot;token entity&quot; title=&quot;\&amp;quot;&quot;&gt;\&quot;&lt;/span&gt; &quot;&lt;/span&gt;,
      &lt;span class=&quot;token string&quot;&gt;&quot;completionReason&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;FINISH&quot;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;    &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The results will be more elaborate if we change &lt;code class=&quot;language-text&quot;&gt;topP&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;shell&quot;&gt;&lt;pre class=&quot;language-shell&quot;&gt;&lt;code class=&quot;language-shell&quot;&gt;&lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; -X POST --location &lt;span class=&quot;token string&quot;&gt;&quot;https://g66m7el4jcrtwarntzrcfps2tq0yduar.lambda-url.eu-central-1.on.aws?temperature=0.9&amp;amp;topP=0.1&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;
    -H &lt;span class=&quot;token string&quot;&gt;&quot;Content-Type: text/plain&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;
    -d &lt;span class=&quot;token string&quot;&gt;&apos;What is the country that has the most freedom of speech in the world?&apos;&lt;/span&gt;
    
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token string&quot;&gt;&quot;inputTextTokenCount&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;15&lt;/span&gt;,
  &lt;span class=&quot;token string&quot;&gt;&quot;results&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token string&quot;&gt;&quot;tokenCount&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;51&lt;/span&gt;,
      &lt;span class=&quot;token string&quot;&gt;&quot;outputText&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token entity&quot; title=&quot;\n&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;token entity&quot; title=&quot;\&amp;quot;&quot;&gt;\&quot;&lt;/span&gt;The United States is considered the country that has the most freedom of speech in the world. This freedom is protected by the First Amendment of the U.S. Constitution, which guarantees the right to freedom of expression, assembly, and religion.&lt;span class=&quot;token entity&quot; title=&quot;\&amp;quot;&quot;&gt;\&quot;&lt;/span&gt; &quot;&lt;/span&gt;,
      &lt;span class=&quot;token string&quot;&gt;&quot;completionReason&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;FINISH&quot;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;    &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;summary&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#summary&quot; aria-label=&quot;summary permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Summary&lt;/h2&gt;
&lt;p&gt;As you see, it is straightforward to get started with AWS Bedrock. The full example of this blog post is available in
&lt;a href=&quot;https://github.com/bright/bright-aws-cdk-bedrock&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;GitHub repo&lt;/a&gt;.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Migrate EC2-Classic RDS to a VPC - Step 2 - DNS]]></title><description><![CDATA[In the plan blog post I sketched a plan to migrate an
EC2-Classic RDS database to a VPC. Now we can perform the 2nd step of the plan.
This is a simple step. Albeit, we have to understand what are the consequences.
In your case, this approach might need adjustments!  The RDS endpoint DNS When you create an RDS database…]]></description><link>undefined/migrating-ec2-classic-rds-to-vpc-step-2/</link><guid isPermaLink="false">undefined/migrating-ec2-classic-rds-to-vpc-step-2/</guid><pubDate>Sun, 01 May 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;In &lt;a href=&quot;/migrating-ec2-classic-rds-to-vpc-plan&quot;&gt;the plan blog post&lt;/a&gt; I sketched a plan to migrate an
EC2-Classic RDS database to a VPC. Now we can perform the 2nd step of the plan.
This is a simple step. Albeit, we have to understand what are the consequences.
In your case, this approach might need adjustments!&lt;/p&gt;
&lt;p&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/8415c67da538b9830f2c19b70aea7bb7/21b4d/dns-generic.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(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAAsTAAALEwEAmpwYAAACi0lEQVQoz1WSSWgUQRSGK5qZaARR0YNX0ZsHFxRR3FARJEEQ1HhSPCiCqIgIgnoRvHoQMQrG3ZkkeEhcMAc3UNFZkgxxNDGiUUjMwkxXVXdX9UTCJ91tXA4/9d7h/+t/7/0iqyw5aZh8u6VPQRkGfEtn2eVcYYQLxWH6tMdgEDAUwlb44Fo6pf8fNystIixyKm46f4sNGcurMY8FbSVEUwlxbYS1j76RG3No6h/lau8wRcflo/bJlL2IG2sYRDYStGSkiQT7XMPbks/6pxpxwyWR9qhKGcStEnPufkFcH4k+WNUxRI8Z57OtkHH82KUKHSpDRlq6lM+Pis/Jbo/qlKI6LUmmJVPTkjn3JVNTLuKOIpnWJMP69EsaGh/y8PsYXdqQkzZ2GDrr1pbHwz4NbzS1rQpxT1HT4lCV0kxJx0g0S6pbNDOfwLTzL0iubkAs24eoP8OJ7CDvvYCMEwlaCq5h43OFuCGZ1iKpaVbUtjokWxSJZk0irUi0ekxpHEAcb6f64CXm1W8huWQXYs1RZt/5wuuyRz4cOVxotzZseBbuTCFua8TNGOHYUX9dIlITiDPtzFi5jZoVDczdXsf0pbtJbD3FygffoqOEY/8decTnQFazP+NyIBvjSN7jcM7jUEZxvAibL7chlm9CLN5JzcZNiEX1zFp3kI4hh4JXiQ4rJs8din7yfL4aw6C1DAeG0YqlPG4pB4aACTqKH1m45xg7zl5h78VbzK87wrGmdvJuEGnEsVE2Onm4y3eOIefEWSwqS6+2UYw+uYY+7TMQ/KSoDJ+DcfrHJ3hV0vRUJiJ+djLYeWn5F13KUtCG956hzw1dG/o9G6E3FPcsPdqnS3oUdEC27JOX5g//F3e7vmdfBtCyAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/8415c67da538b9830f2c19b70aea7bb7/8ac56/dns-generic.webp 240w,
/static/8415c67da538b9830f2c19b70aea7bb7/d3be9/dns-generic.webp 480w,
/static/8415c67da538b9830f2c19b70aea7bb7/e46b2/dns-generic.webp 960w,
/static/8415c67da538b9830f2c19b70aea7bb7/af3f0/dns-generic.webp 1280w&quot;
              sizes=&quot;(max-width: 960px) 100vw, 960px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/8415c67da538b9830f2c19b70aea7bb7/8ff5a/dns-generic.png 240w,
/static/8415c67da538b9830f2c19b70aea7bb7/e85cb/dns-generic.png 480w,
/static/8415c67da538b9830f2c19b70aea7bb7/d9199/dns-generic.png 960w,
/static/8415c67da538b9830f2c19b70aea7bb7/21b4d/dns-generic.png 1280w&quot;
            sizes=&quot;(max-width: 960px) 100vw, 960px&quot;
            type=&quot;image/png&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/8415c67da538b9830f2c19b70aea7bb7/d9199/dns-generic.png&quot;
            alt=&quot;dns generic&quot;
            title=&quot;DNS generic&quot;
            loading=&quot;lazy&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;the-rds-endpoint-dns&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#the-rds-endpoint-dns&quot; aria-label=&quot;the rds endpoint dns permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;The RDS endpoint DNS&lt;/h2&gt;
&lt;p&gt;When you create an RDS database instance or RDS database cluster AWS provides you with endpoint
addresses. The addresses can be used to connect to the database.
You cannot change the endpoint address of the RDS database.
It is something generated by AWS that you have no influence over.&lt;/p&gt;
&lt;p&gt;As planned we want to update the DNS entry when migrating to VPC based RDS instance.
For this to work, we need a custom DNS entry. One that we can control.&lt;/p&gt;
&lt;h2 id=&quot;private-hosted-zone&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#private-hosted-zone&quot; aria-label=&quot;private hosted zone permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Private hosted zone&lt;/h2&gt;
&lt;p&gt;Often, when deploying services inside a VPC it makes sense to use a private DNS hosted zone.
Such an approach allows us to define e.g. &lt;code class=&quot;language-text&quot;&gt;internal&lt;/code&gt; DNS space which we can freely use.
With AWS-CDK defining such hosted zone is simple:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;NetworkStack&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Stack&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;readonly&lt;/span&gt; privateHostedZone&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IPrivateHostedZone
  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;scope&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Construct&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; props&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; StackProps&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;scope&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; props&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; vpc &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Vpc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;vpc&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;privateHostedZone &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PrivateHostedZone&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;internal&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      vpc&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; vpc&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      zoneName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;internal&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      comment&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;private DNS space for registering services&apos;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;custom-dns-record-for-database-endpoint&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#custom-dns-record-for-database-endpoint&quot; aria-label=&quot;custom dns record for database endpoint permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Custom DNS record for database endpoint&lt;/h2&gt;
&lt;p&gt;Now that we have a private hosted zone we can define a custom DNS record for the database.
The record should be used to connect to the database from our service(s).
This way once we change the record the application will establish connections to a new database running
inside VPC.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CnameRecord&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;database cname record&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  domainName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;current-classical-database-endpoint&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  zone&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;privateHostedZone&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  recordName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;database&apos;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;With the above configuration deployed all that is left to do is to update our service configuration.
The database hostname that we set should now look like &lt;code class=&quot;language-text&quot;&gt;database.internal&lt;/code&gt;. Please note that we are
still connected to the non-VPC, classical RDS instance.&lt;/p&gt;
&lt;h2 id=&quot;important-considerations&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#important-considerations&quot; aria-label=&quot;important considerations permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Important considerations&lt;/h2&gt;
&lt;p&gt;The approach that we have selected is simple. However, it is not without downsides.
The main issue is that the DNS update will not immediately cause all services to connect to the new database.
In many cases this is fine.
Moreover, we need to make sure that our database clients do not cache DNS entries for too long.&lt;/p&gt;
&lt;p&gt;If you need the connections to be moved to a new database instance in a more controllable fashion it is still possible.
A deployment with an update of the database configuration of services might be enough.
If such a deployment is not an option we can introduce a network proxy e.g. using a network load balancer, ProxySQL or HAProxy.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Migrate EC2-Classic RDS to a VPC - Step 1 - Replication]]></title><description><![CDATA[In the last blog post I sketched a plan to migrate an
EC2-Classic RDS database to a VPC. It is time to dive into the details of setting up replication. There
are great blog posts with an in-depth
explanation of the SQL and PostgreSQL related aspects
. We are going to focus on the automation of the replication setup…]]></description><link>undefined/migrating-ec2-classic-rds-to-vpc-step-1/</link><guid isPermaLink="false">undefined/migrating-ec2-classic-rds-to-vpc-step-1/</guid><pubDate>Sun, 30 Jan 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;In &lt;a href=&quot;/migrating-ec2-classic-rds-to-vpc-plan&quot;&gt;the last blog post&lt;/a&gt; I sketched a plan to migrate an
EC2-Classic RDS database to a VPC. It is time to dive into the details of setting up replication. There
are great blog posts with an in-depth
explanation &lt;a href=&quot;https://www.percona.com/blog/postgresql-logical-replication-using-an-rds-snapshot/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;of the SQL and PostgreSQL related aspects&lt;/a&gt;
. We are going to focus on the automation of the replication setup using AWS-CDK.&lt;/p&gt;
&lt;p&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/4fe052a2f06e2fbcfb9fe84566d74b6a/b78fc/replica.jpg&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: 150%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAeABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAIDBAX/xAAYAQADAQEAAAAAAAAAAAAAAAABAgMABP/aAAwDAQACEAMQAAAB6kbpTnuIAqk3zBmHl//EABwQAAICAgMAAAAAAAAAAAAAAAECABEhMRASQv/aAAgBAQABBQLzp6vhhkHBMeDTNGhPU//EABgRAQADAQAAAAAAAAAAAAAAAAEAAhEQ/9oACAEDAQE/AU5aiGzZ/8QAFxEAAwEAAAAAAAAAAAAAAAAAAQIQEf/aAAgBAgEBPwGBtM//xAAZEAABBQAAAAAAAAAAAAAAAAAAAhAhMGH/2gAIAQEABj8CpTrQf//EABsQAQADAQADAAAAAAAAAAAAAAEAESExEHGR/9oACAEBAAE/IahNInSTpU1PjVJ7jpJqwymta/kUZDif/9oADAMBAAIAAwAAABC49z3/xAAYEQEBAAMAAAAAAAAAAAAAAAABABARIf/aAAgBAwEBPxBAG5bCw//EABYRAQEBAAAAAAAAAAAAAAAAAAEAEf/aAAgBAgEBPxAbGDAsv//EAB4QAQACAgIDAQAAAAAAAAAAAAEAESExQVFhcYGh/9oACAEBAAE/EMPqWfR/JRAcR092MZLVBTKiPEs3YiJNcxpUhlpS1rdALx5m9rVHuLVlmf/Z&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/4fe052a2f06e2fbcfb9fe84566d74b6a/8ac56/replica.webp 240w,
/static/4fe052a2f06e2fbcfb9fe84566d74b6a/d3be9/replica.webp 480w,
/static/4fe052a2f06e2fbcfb9fe84566d74b6a/e46b2/replica.webp 960w,
/static/4fe052a2f06e2fbcfb9fe84566d74b6a/b0d42/replica.webp 987w&quot;
              sizes=&quot;(max-width: 960px) 100vw, 960px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/4fe052a2f06e2fbcfb9fe84566d74b6a/09b79/replica.jpg 240w,
/static/4fe052a2f06e2fbcfb9fe84566d74b6a/7cc5e/replica.jpg 480w,
/static/4fe052a2f06e2fbcfb9fe84566d74b6a/6a068/replica.jpg 960w,
/static/4fe052a2f06e2fbcfb9fe84566d74b6a/b78fc/replica.jpg 987w&quot;
            sizes=&quot;(max-width: 960px) 100vw, 960px&quot;
            type=&quot;image/jpeg&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/4fe052a2f06e2fbcfb9fe84566d74b6a/6a068/replica.jpg&quot;
            alt=&quot;replica&quot;
            title=&quot;replicated lollipops&quot;
            loading=&quot;lazy&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;the-source-ec2-classic-rds-database-parameters&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#the-source-ec2-classic-rds-database-parameters&quot; aria-label=&quot;the source ec2 classic rds database parameters permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;The source EC2-Classic RDS database parameters&lt;/h2&gt;
&lt;p&gt;In the case of our client, the EC2-Classic RDS PostgreSQL database was deployed with CloudFormation.
With AWS-CDK it is possible to import an existing CloudFormation template and thus gradually switch
to a more modern approach. Once imported it is easy enough to update the parameters
through &lt;a href=&quot;https://docs.aws.amazon.com/cdk/api/v2//docs/aws-cdk-lib.aws_rds.ParameterGroup.html#initializer&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;ParameterGroup&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; included&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; CfnInclude &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;loadCloudFormationTemplate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; cfnDatabase&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; CfnDBInstance &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; included&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getResource&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Database&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; CfnDBInstance&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; parameterGroup &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ParameterGroup&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Replication Source Parameters&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  engine&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; DatabaseInstanceEngine&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;postgres&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    version&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; PostgresEngineVersion&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;VER_11&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  parameters&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    max_replication_slots&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;10&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    max_wal_senders&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;10&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    max_worker_processes&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;10&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    track_commit_timestamp&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;1&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    wal_level&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;logical&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

cfnDatabase&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;dbParameterGroupName &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; parameterGroup&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;bindToInstance&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;parameterGroupName&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If the database has a custom parameter group we need to modify its properties instead of creating a
new one. Changing the above database parameters sometimes requires a reboot. It is thus important to
schedule it ahead of time in the low traffic hours.&lt;/p&gt;
&lt;h2 id=&quot;create-a-replication-user-with-aws-cdk&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#create-a-replication-user-with-aws-cdk&quot; aria-label=&quot;create a replication user with aws cdk permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Create a replication user with AWS-CDK&lt;/h2&gt;
&lt;p&gt;It is best to create a dedicated replication user at a database level. Running SQL through
CloudFormation can be cumbersome. Thankfully we have developed
the &lt;a href=&quot;https://www.npmjs.com/package/cloudformation-sql-run&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;cloudformation-sql-run&lt;/a&gt; AWS-CDK construct
to make this easier.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; replicationUserPassword &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;secretmanager&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Secret&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Replication User Password&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  generateSecretString&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    excludeCharacters&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;DEFAULT_PASSWORD_EXCLUDE_CHARS&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; sourceDatabaseConnection &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; SqlRunConnection&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fromDriverTypeHostPort&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  password&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; SqlSecret&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fromSecretsManager&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sourceDatabasePassword&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  username&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; cfnDatabase&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;masterUsername&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  driverType&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;postgresql&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  database&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; cfnDatabase&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;dbName&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  host&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; cfnDatabase&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;attrEndpointAddress&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  port&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; cfnDatabase&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;attrEndpointPort&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; createReplicationUser &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;SqlRun&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Create Replication User&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  vpc&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; vpc&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  connection&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; sourceDatabaseConnection&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  up&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    run&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      sql&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;CREATE USER pgrepuser WITH password &apos;&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;replicationUserPassword&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;secretValue&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      sql&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;GRANT rds_replication TO pgrepuser&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      sql&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;GRANT SELECT ON ALL TABLES IN SCHEMA public TO pgrepuser&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  down&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    run&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      sql&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;DROP USER IF EXISTS pgrepuser&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;setup-replication-slots-at-source-rds-database&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#setup-replication-slots-at-source-rds-database&quot; aria-label=&quot;setup replication slots at source rds database permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Setup replication slots at source RDS database&lt;/h2&gt;
&lt;p&gt;We create a dedicated SQL user for replication purposes. Now it is time to prepare for the
replication itself. Thankfully this is easy and all we need is 2 additional SQL commands&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; createPublication &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;SqlRun&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Create Publication&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  vpc&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; vpc&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  connection&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; sourceDatabaseConnection&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  up&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    run&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      sql&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;CREATE PUBLICATION pglogical_rep01 FOR ALL TABLES&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      sql&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;SELECT pg_create_logical_replication_slot(&apos;pglogical_rep01&apos;, &apos;pgoutput&apos;)&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  down&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    run&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      sql&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;DROP PUBLICATION IF EXISTS pglogical_rep01&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;create-snapshot-at-the-original-database&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#create-snapshot-at-the-original-database&quot; aria-label=&quot;create snapshot at the original database permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Create snapshot at the original database&lt;/h2&gt;
&lt;p&gt;To speed up replication we’ll use take a snapshot and restore approach. First, we use a snapshot is
to create a new VPC based RDS database. Then we set up a logical replication using the above
preparation. Unfortunately at the moment taking a snapshot of a database with AWS-CDK requires a
custom construct. I will create another blog post describing the details of such construct. However,
for the time being, it is enough for you to know that creating and using it is relatively easy:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; cfnDatabase&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; CfnDBInstance &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; included&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getResource&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Database&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; CfnDBInstance&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; sourceDataseSnapshot &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;DatabaseSnapshot&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Source Database Snapshot&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  dbInstanceIdentifier&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; cfnDatabase&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;dbInstanceIdentifier
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The snapshot name is going to be available at &lt;code class=&quot;language-text&quot;&gt;sourceDataseSnapshot.dbInstanceSnapshotIdentifier&lt;/code&gt;&lt;/p&gt;
&lt;h2 id=&quot;create-a-new-database-from-snapshot&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#create-a-new-database-from-snapshot&quot; aria-label=&quot;create a new database from snapshot permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Create a new database from snapshot&lt;/h2&gt;
&lt;p&gt;It is time to finally create a new RDS database in the target VPC. We create the database from the
snapshot created above. The database will use the same database parameter group. It will not receive
any production traffic yet. Notice that we create a database cluster instead of a database instance.
It doesn’t matter though. The procedure is the same for the database instance.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; vpc&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IVpc &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;vpc
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; targetDatabaseCluster &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;DatabaseClusterFromSnapshot&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Database&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  instanceProps&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    vpc&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; vpc&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  engine&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; DatabaseClusterEngine&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;auroraPostgres&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    version&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; AuroraPostgresEngineVersion&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;VER_11_4&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  snapshotIdentifier&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; databaseSnapshot&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;dbInstanceSnapshotIdentifier&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  parameterGroup&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; parameterGroup
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;finding-out-where-to-start-replication-from&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#finding-out-where-to-start-replication-from&quot; aria-label=&quot;finding out where to start replication from permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Finding out where to start replication from&lt;/h2&gt;
&lt;p&gt;Once the database cluster restored from a snapshot is ready we have to start replication. First we
create a subscription. Notice that we’re using references to source RDS database.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; createSubscription &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;SqlRun&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Create Subscription&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  vpc&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; vpc&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  connection&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; SqlRunConnection&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fromDatabaseCluster&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;targetDatabaseCluster&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  up&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    run&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      sql&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;CREATE SUBSCRIPTION pglogical_sub01 
CONNECTION &apos;host=&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;cfnDatabase&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;attrEndpointAddress&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; port=5432 dbname=&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;cfnDatabase&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;dbName&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; 
user=pgrepuser password=&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;replicationUserPassword&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;secretValue&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos; PUBLICATION pglogical_rep01
WITH (
  copy_data = false,
  create_slot = false,
  enabled = false,
  connect = true,
  slot_name = &apos;pglogical_rep01&apos;
)&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      sql&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;SELECT &apos;pg_&apos;||oid::text AS &quot;external_id&quot;
FROM pg_subscription 
WHERE subname = &apos;pglogical_sub01&apos;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  down&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    run&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      sql&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;DROP SUBSCRIPTION IF EXISTS pglogical_sub01&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now that we have a subscription ready to synchronize data. However, we need to advance the
replication into the correct position. To do that we need to find the latest log file
positions. The RDS service provides API for that. For now, we’ll assume we have
a &lt;code class=&quot;language-text&quot;&gt;LatestLogPosition&lt;/code&gt; AWS-CDK construct that reads the position for us. In the next blog post, I’ll
describe how to create such a construct.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; externalId &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; createSubscription&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getStatementResult&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;external_id&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; latestLogFile &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;LatestLogPosition&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Replication Position&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  cluster&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; targetDatabaseCluster
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;


&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; advanceAndEnableSubscription &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;SqlRun&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Enable Subscription&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  vpc&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; vpc&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  connection&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; SqlRunConnection&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fromDatabaseCluster&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;targetDatabaseCluster&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  up&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    run&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      sql&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;SELECT pg_replication_origin_advance(:externalId, :logFilePosition)&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      parameters&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        externalId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; externalId&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        logFilePosition&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; latestLogFile&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;logFilePosition
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      sql&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;ALTER SUBSCRIPTION pglogical_sub01 ENABLE&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  down&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    run&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      sql&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;ALTER SUBSCRIPTION pglogical_sub01 DISABLE&apos;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In the last SQL statement, we have enabled the subscription. Now the VPC based RDS database is
synchronized with EC2-Classic instance!
For the above to work we need to make sure the source database allows establishing connections from
VPC-based database on a network level.&lt;/p&gt;
&lt;h2 id=&quot;summary&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#summary&quot; aria-label=&quot;summary permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Summary&lt;/h2&gt;
&lt;p&gt;Automating the above process is cumbersome. However, it gives us a solid way to test the approach in
a pre-production environment. This way we can find any loopholes in our approach. We can also
better estimate how long the procedure is going to take on production. We have also not caused any downtime or degradation of performance to the source database. This is very important since it is still used by our clients!&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Migrate EC2-Classic RDS to a VPC - Planning]]></title><description><![CDATA[By end of
August AWS will shut down EC2-Classic networking
. All resources using EC2-Classic networking will stop working. Yes, this includes RDS databases. One of our clients was running a PostgreSQL RDS instance in EC2-Classic. We’ve notified the client
about the necessary migration right after AWS published the news…]]></description><link>undefined/migrating-ec2-classic-rds-to-vpc-plan/</link><guid isPermaLink="false">undefined/migrating-ec2-classic-rds-to-vpc-plan/</guid><pubDate>Fri, 21 Jan 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;By end of
August &lt;a href=&quot;https://aws.amazon.com/blogs/aws/ec2-classic-is-retiring-heres-how-to-prepare/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;AWS will shut down EC2-Classic networking&lt;/a&gt;
. All resources using EC2-Classic networking will stop working. Yes, this includes RDS databases.&lt;/p&gt;
&lt;p&gt;One of our clients was running a PostgreSQL RDS instance in EC2-Classic. We’ve notified the client
about the necessary migration right after AWS published the news. Since the database was used for
mission-critical features it was vital to plan the migration carefully.&lt;/p&gt;
&lt;p&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/84624e4ad5ff2ff7ea337afc77b46999/0376e/database-files.jpg&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: 66.66666666666666%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAABAAB/8QAFgEBAQEAAAAAAAAAAAAAAAAAAAED/9oADAMBAAIQAxAAAAFAGH0Jsq//xAAYEAEBAQEBAAAAAAAAAAAAAAACAQADEP/aAAgBAQABBQJWTB2rMxQ84fP/xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAVEQEBAAAAAAAAAAAAAAAAAAAQIf/aAAgBAgEBPwGn/8QAGRAAAwADAAAAAAAAAAAAAAAAAAEQESFR/9oACAEBAAY/AhZc2dn/xAAaEAEAAgMBAAAAAAAAAAAAAAABADERIVFB/9oACAEBAAE/ITdswcg0YuFTunjyJZ2usKn/2gAMAwEAAgADAAAAEBff/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPxA//8QAFREBAQAAAAAAAAAAAAAAAAAAERD/2gAIAQIBAT8QFP/EABsQAQACAwEBAAAAAAAAAAAAAAEAETFBcSFh/9oACAEBAAE/EAdQuDbyW80xDBICDA+8Taxu26fkcf/Z&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/84624e4ad5ff2ff7ea337afc77b46999/8ac56/database-files.webp 240w,
/static/84624e4ad5ff2ff7ea337afc77b46999/d3be9/database-files.webp 480w,
/static/84624e4ad5ff2ff7ea337afc77b46999/e46b2/database-files.webp 960w,
/static/84624e4ad5ff2ff7ea337afc77b46999/f992d/database-files.webp 1440w,
/static/84624e4ad5ff2ff7ea337afc77b46999/882b9/database-files.webp 1920w,
/static/84624e4ad5ff2ff7ea337afc77b46999/a3f95/database-files.webp 2370w&quot;
              sizes=&quot;(max-width: 960px) 100vw, 960px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/84624e4ad5ff2ff7ea337afc77b46999/09b79/database-files.jpg 240w,
/static/84624e4ad5ff2ff7ea337afc77b46999/7cc5e/database-files.jpg 480w,
/static/84624e4ad5ff2ff7ea337afc77b46999/6a068/database-files.jpg 960w,
/static/84624e4ad5ff2ff7ea337afc77b46999/644c5/database-files.jpg 1440w,
/static/84624e4ad5ff2ff7ea337afc77b46999/0f98f/database-files.jpg 1920w,
/static/84624e4ad5ff2ff7ea337afc77b46999/0376e/database-files.jpg 2370w&quot;
            sizes=&quot;(max-width: 960px) 100vw, 960px&quot;
            type=&quot;image/jpeg&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/84624e4ad5ff2ff7ea337afc77b46999/6a068/database-files.jpg&quot;
            alt=&quot;database files&quot;
            title=&quot;database files&quot;
            loading=&quot;lazy&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;the-plan&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#the-plan&quot; aria-label=&quot;the plan permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;The plan&lt;/h2&gt;
&lt;p&gt;There are several risks at play when migrating data. They can be divided into 2 major categories:&lt;/p&gt;
&lt;p&gt;a) data loss&lt;/p&gt;
&lt;p&gt;b) service outage&lt;/p&gt;
&lt;p&gt;Preparing a thorough migration plan helps to reduce those risks. Losing data was not an option. We
could also afford only limited degradation of service. With a database size of several hundreds of
GB, any operation isn’t instant. It will take a couple of hours just to copy the data. The client
agreed that it would be ok if the service showed stale data for a couple of minutes.&lt;/p&gt;
&lt;p&gt;With the constraint defined we’ve come up with the following plan.&lt;/p&gt;
&lt;h2 id=&quot;step-1-replicate-database&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#step-1-replicate-database&quot; aria-label=&quot;step 1 replicate database permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Step 1: Replicate database&lt;/h2&gt;
&lt;p&gt;As I mentioned it will take several hours to just copy the data. This rules out a simple take
snapshot &amp;#x26; restore approach. Fortunately, databases have solved this problem a long time ago with
replication. The first step is thus to create a fresh new RDS database inside VPC. We can use a
snapshot of the source database to speed up initial replication. Please note that at this point the
fresh database isn’t used by any production service yet!
Once the data wills start flowing from the EC2-Classic RDS instance to VPC based one we can safely
prepare for the next step.&lt;/p&gt;
&lt;h2 id=&quot;step-2-setup-a-custom-database-host-dns-record&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#step-2-setup-a-custom-database-host-dns-record&quot; aria-label=&quot;step 2 setup a custom database host dns record permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Step 2: Setup a custom database host DNS record&lt;/h2&gt;
&lt;p&gt;We need to have a way to instruct all clients connecting to the database to switch to a new
database. One way to achieve that is to use DNS. During the migration, we’ll update the DNS record.
This method isn’t ideal. Existing connections will not be automatically served. However, in the case
of our clients, it was perfectly ok to request rolling reboots of database client service.&lt;/p&gt;
&lt;h2 id=&quot;step-3-migration&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#step-3-migration&quot; aria-label=&quot;step 3 migration permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Step 3: Migration!&lt;/h2&gt;
&lt;p&gt;Once we have a fresh, up-to-date database instance ready inside VPC we can finally switch to the new
database. Simply swapping the DNS record would put us at risk of violating data integrity. To
mitigate that we’ll put the source database into read-only mode right before swapping the DNS
record. Such a change ensure that once the DNS switch takes place, any writes happen only at the VPC
based database!&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#conclusion&quot; aria-label=&quot;conclusion permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Migrating production services is challenging and risky. However, with the right plan, the risk can
be mitigated to an acceptable level. In my opinion, automating most if not the whole process reduces
the risk further. This is why we’ve implemented the migration from EC2-Classic to VPC using AWS-CDK.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;In the following posts, I’ll share more details on the automation that we’ve implemented.&lt;/em&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;/migrating-ec2-classic-rds-to-vpc-step-1&quot;&gt;Step 1: Replicate database&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;</content:encoded></item><item><title><![CDATA[5 Top Programming Books For Junior and Mid-level Developers]]></title><description><![CDATA[I encourage everyone to read books. There are so many titles worth
reading that entire lists have been created. Depending on the stage of your career you’ll need books covering various topics. Here is a list I
recommend every junior and mid-level software engineer should read. Head First Design Patterns by Eric Freeman…]]></description><link>undefined/5-top-programming-books-for-junior-and-regular-developers/</link><guid isPermaLink="false">undefined/5-top-programming-books-for-junior-and-regular-developers/</guid><pubDate>Fri, 31 Dec 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I encourage everyone to read books. There are so many titles worth
reading &lt;a href=&quot;https://github.com/EbookFoundation/free-programming-books&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;that entire lists have been created&lt;/a&gt;. Depending on the stage of your career you’ll need books covering various topics. Here is a list I
recommend every junior and mid-level software engineer should read.&lt;/p&gt;
&lt;h2 id=&quot;head-first-design-patterns-by-eric-freeman-elisabeth-robson&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#head-first-design-patterns-by-eric-freeman-elisabeth-robson&quot; aria-label=&quot;head first design patterns by eric freeman elisabeth robson permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;a href=&quot;https://www.amazon.pl/Head-First-Design-Patterns-Object-Oriented/dp/149207800X&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Head First Design Patterns by Eric Freeman, Elisabeth Robson&lt;/a&gt;&lt;/h2&gt;
&lt;p&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/f793fac341ea4b4aea8a15d60c14f261/ee0d2/head-first.jpg&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: 115.83333333333334%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAXABQDASIAAhEBAxEB/8QAFwABAAMAAAAAAAAAAAAAAAAAAAMEBf/EABYBAQEBAAAAAAAAAAAAAAAAAAEAA//aAAwDAQACEAMQAAAB2J69YdBETPrmzMG//8QAHBAAAQQDAQAAAAAAAAAAAAAAAQACAxEEEhQi/9oACAEBAAEFAt6KC1szGjG7x1tU+QJAMxoH/8QAFhEAAwAAAAAAAAAAAAAAAAAAASAh/9oACAEDAQE/ARU//8QAFxEAAwEAAAAAAAAAAAAAAAAAAAESEP/aAAgBAgEBPwHIRCP/xAAbEAADAAIDAAAAAAAAAAAAAAAAARESIQIgkf/aAAgBAQAGPwJ9Fx3KbZcX6JRomDP/xAAaEAEAAwEBAQAAAAAAAAAAAAABABExIWFR/9oACAEBAAE/IU2L32DZcFG3Erx36zhQ6deMBGk6aoBjBvYbxek//9oADAMBAAIAAwAAABA4F7z/xAAXEQADAQAAAAAAAAAAAAAAAAAAAREh/9oACAEDAQE/EEqEFmoh/8QAGBEAAwEBAAAAAAAAAAAAAAAAAAFhEBH/2gAIAQIBAT8Qb4siRP/EAB0QAQEAAwACAwAAAAAAAAAAAAERACExQWGhsdH/2gAIAQEAAT8QHpRGxH1MIxYlKTFkvbS5Md6dF573GfToo6fLbPWbRTRpH18TOMa3x+ZPBogd5eTAXp7z/9k=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/f793fac341ea4b4aea8a15d60c14f261/8ac56/head-first.webp 240w,
/static/f793fac341ea4b4aea8a15d60c14f261/d3be9/head-first.webp 480w,
/static/f793fac341ea4b4aea8a15d60c14f261/e46b2/head-first.webp 960w,
/static/f793fac341ea4b4aea8a15d60c14f261/f992d/head-first.webp 1440w,
/static/f793fac341ea4b4aea8a15d60c14f261/882b9/head-first.webp 1920w,
/static/f793fac341ea4b4aea8a15d60c14f261/e2ff3/head-first.webp 2214w&quot;
              sizes=&quot;(max-width: 960px) 100vw, 960px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/f793fac341ea4b4aea8a15d60c14f261/09b79/head-first.jpg 240w,
/static/f793fac341ea4b4aea8a15d60c14f261/7cc5e/head-first.jpg 480w,
/static/f793fac341ea4b4aea8a15d60c14f261/6a068/head-first.jpg 960w,
/static/f793fac341ea4b4aea8a15d60c14f261/644c5/head-first.jpg 1440w,
/static/f793fac341ea4b4aea8a15d60c14f261/0f98f/head-first.jpg 1920w,
/static/f793fac341ea4b4aea8a15d60c14f261/ee0d2/head-first.jpg 2214w&quot;
            sizes=&quot;(max-width: 960px) 100vw, 960px&quot;
            type=&quot;image/jpeg&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/f793fac341ea4b4aea8a15d60c14f261/6a068/head-first.jpg&quot;
            alt=&quot;head first design patterns cover&quot;
            title=&quot;head first design patterns cover&quot;
            loading=&quot;lazy&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Design patterns surround us everywhere. They are prevalent in every framework and most libraries we
use. The “Head First Design Patterns” presents the most common design patterns in a succinct and easy to
remember fashion. Before you’ll finish the book, you’ll already better understand the design choices
behind libraries and frameworks that you use!
The form of writing that the book uses is especially enjoyable. You’ll not be bored by
this one.&lt;/p&gt;
&lt;h2 id=&quot;clean-architecture-by-robert-c-martin&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#clean-architecture-by-robert-c-martin&quot; aria-label=&quot;clean architecture by robert c martin permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;a href=&quot;https://www.amazon.com/Clean-Architecture-Craftsmans-Software-Structure/dp/0134494164&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Clean Architecture by Robert C. Martin&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 600px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/3d11473412b6f8c6d5c34108dd59e1b8/b4294/clean.jpg&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: 130.41666666666666%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAaABQDASIAAhEBAxEB/8QAGQAAAgMBAAAAAAAAAAAAAAAAAAMCBAUB/8QAFgEBAQEAAAAAAAAAAAAAAAAAAgAB/9oADAMBAAIQAxAAAAHOfG4xnFg2QK6FIWV//8QAHBAAAwABBQAAAAAAAAAAAAAAAAECESAhIiMx/9oACAEBAAEFAlOSeI/Yg65l0jJuxrR//8QAFREBAQAAAAAAAAAAAAAAAAAAASD/2gAIAQMBAT8BY//EABYRAQEBAAAAAAAAAAAAAAAAAAEQEf/aAAgBAgEBPwEJs//EAB4QAAECBwEAAAAAAAAAAAAAAAABMRAREiBBQoGR/9oACAEBAAY/Asemq9g8h6lGS/8A/8QAHhABAAIBBAMAAAAAAAAAAAAAAQARIRAxUaFhcZH/2gAIAQEAAT8hAX2g7k9sjh8YznBEvX4ZewJL1VzydxB0dP/aAAwDAQACAAMAAAAQo9CN/8QAGREBAAIDAAAAAAAAAAAAAAAAAQARECEx/9oACAEDAQE/EGOkuC1yVj//xAAYEQEBAQEBAAAAAAAAAAAAAAABABEhUf/aAAgBAgEBPxBDsh7atv/EAB0QAQEBAAIDAQEAAAAAAAAAAAERACFhMUGRgaH/2gAIAQEAAT8QAhHUX5qkdEkJ3uYIZ2H3UUParLhFZ6nH3fi6eXThB04Fk/1oJR/cqtWve4Scbz53/9k=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/3d11473412b6f8c6d5c34108dd59e1b8/8ac56/clean.webp 240w,
/static/3d11473412b6f8c6d5c34108dd59e1b8/d3be9/clean.webp 480w,
/static/3d11473412b6f8c6d5c34108dd59e1b8/e88ff/clean.webp 600w&quot;
              sizes=&quot;(max-width: 600px) 100vw, 600px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/3d11473412b6f8c6d5c34108dd59e1b8/09b79/clean.jpg 240w,
/static/3d11473412b6f8c6d5c34108dd59e1b8/7cc5e/clean.jpg 480w,
/static/3d11473412b6f8c6d5c34108dd59e1b8/b4294/clean.jpg 600w&quot;
            sizes=&quot;(max-width: 600px) 100vw, 600px&quot;
            type=&quot;image/jpeg&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/3d11473412b6f8c6d5c34108dd59e1b8/b4294/clean.jpg&quot;
            alt=&quot;clean architecture cover&quot;
            title=&quot;clean architecture cover&quot;
            loading=&quot;lazy&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Every book by “Uncle Bob” is worth reading. I’ve picked the “Clean Architecture” for the list as it
provides a base and set of pillars with which you can create software services that are easier to
reason about. The book describes many important rules. At its core, a high-level approach to
application architecture is
summarized &lt;a href=&quot;https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;in the author’s blog post&lt;/a&gt;
. Make no mistake though, you’ll gain much more from reading the book end-to-end!&lt;/p&gt;
&lt;h2 id=&quot;continuous-delivery-reliable-software-releases-through-build-test-and-deployment-automation-by-jez-humbe-and-david-farley&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#continuous-delivery-reliable-software-releases-through-build-test-and-deployment-automation-by-jez-humbe-and-david-farley&quot; aria-label=&quot;continuous delivery reliable software releases through build test and deployment automation by jez humbe and david farley permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;a href=&quot;https://www.amazon.com/Continuous-Delivery-Deployment-Automation-Addison-Wesley/dp/0321601912&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Continuous Delivery: Reliable Software Releases through Build, Test, and Deployment Automation by Jez Humbe and David Farley &lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 800px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/827a40906ada1570f644d3761f877aa6/4b190/cicd.jpg&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: 132.08333333333334%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAaABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAEEAgX/xAAWAQEBAQAAAAAAAAAAAAAAAAADBQH/2gAMAwEAAhADEAAAAecb1m7EDVnsgbSqhA1v/8QAGxAAAgIDAQAAAAAAAAAAAAAAAAECEQMgMUH/2gAIAQEAAQUCLPLGpC5ZLPF6Ln//xAAYEQACAwAAAAAAAAAAAAAAAAAAAQIRMf/aAAgBAwEBPwGiOITojh//xAAVEQEBAAAAAAAAAAAAAAAAAAAQEf/aAAgBAgEBPwGkP//EABkQAAIDAQAAAAAAAAAAAAAAAAABECAxMv/aAAgBAQAGPwKEYY55oj//xAAdEAACAQQDAAAAAAAAAAAAAAAAAREhQZGhEDFR/9oACAEBAAE/IW0rIh4haBUdsjVpFCE4GFMhOUnxJrH/2gAMAwEAAgADAAAAELj8PP/EABgRAQEBAQEAAAAAAAAAAAAAAAEAMXGR/9oACAEDAQE/EBOEPIkxY8L/xAAWEQEBAQAAAAAAAAAAAAAAAAABADH/2gAIAQIBAT8QQbOyHSdv/8QAHBABAQEBAAIDAAAAAAAAAAAAAREAMSFRYZGh/9oACAEBAAE/EIgt94VCVe+cYVMWCQHa84o4npcIUkNyXx6mdK8hXN8mFx11e3fmb//Z&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/827a40906ada1570f644d3761f877aa6/8ac56/cicd.webp 240w,
/static/827a40906ada1570f644d3761f877aa6/d3be9/cicd.webp 480w,
/static/827a40906ada1570f644d3761f877aa6/d00b9/cicd.webp 800w&quot;
              sizes=&quot;(max-width: 800px) 100vw, 800px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/827a40906ada1570f644d3761f877aa6/09b79/cicd.jpg 240w,
/static/827a40906ada1570f644d3761f877aa6/7cc5e/cicd.jpg 480w,
/static/827a40906ada1570f644d3761f877aa6/4b190/cicd.jpg 800w&quot;
            sizes=&quot;(max-width: 800px) 100vw, 800px&quot;
            type=&quot;image/jpeg&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/827a40906ada1570f644d3761f877aa6/4b190/cicd.jpg&quot;
            alt=&quot;continuous delivery cover&quot;
            title=&quot;continuous delivery cover&quot;
            loading=&quot;lazy&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The book was a hit when it was first published over 10 years ago. If you want to know more about
Continuous Integration and Continuous Deployment this book is a must-read. It unfolds and explains
multiple techniques and approaches to improve the delivery of software. You’ll learn not only what to do
to improve how you develop software. You’ll also learn why some techniques work while others don’t.
Such knowledge helps immensely with managing the backlog of non-functional features.&lt;/p&gt;
&lt;h2 id=&quot;rework&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#rework&quot; aria-label=&quot;rework permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;a href=&quot;https://www.amazon.com/Rework-Jason-Fried/dp/0307463745&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Rework&lt;/a&gt;&lt;/h2&gt;
&lt;p&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/202ff0dcfacfd10236a9deb9994279b6/9291b/rework.jpg&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: 151.25%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAeABQDASIAAhEBAxEB/8QAGAABAAMBAAAAAAAAAAAAAAAAAAEEBQL/xAAVAQEBAAAAAAAAAAAAAAAAAAAAAf/aAAwDAQACEAMQAAABxIXZc9Cy5fxZOQf/xAAcEAACAgMBAQAAAAAAAAAAAAACAwAEARAhESL/2gAIAQEAAQUC+fOTMASMnViWuVm4Uy48CHXNf//EABURAQEAAAAAAAAAAAAAAAAAAAEg/9oACAEDAQE/ARj/xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAECAQE/AR//xAAbEAACAgMBAAAAAAAAAAAAAAABAgARECAxcf/aAAgBAQAGPwLNL2Br9GLPDKVgdf/EABsQAAICAwEAAAAAAAAAAAAAAAERADEQIUFR/9oACAEBAAE/IWnW+x+Yj1UGRklCsYq6scmiJTMA2gUMBdEfjH//2gAMAwEAAgADAAAAEMsUAP/EABgRAAIDAAAAAAAAAAAAAAAAAAERABBB/9oACAEDAQE/EEZCWb//xAAVEQEBAAAAAAAAAAAAAAAAAAARIP/aAAgBAgEBPxAj/8QAHhABAAICAgMBAAAAAAAAAAAAAQARITFBgRBhkbH/2gAIAQEAAT8QxhpDD7MDeHGMyz5poXuEbaAu2N0jyeHAamoG8dhF5taCp3o/fCHJ3GjDv2x3qp//2Q==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/202ff0dcfacfd10236a9deb9994279b6/8ac56/rework.webp 240w,
/static/202ff0dcfacfd10236a9deb9994279b6/d3be9/rework.webp 480w,
/static/202ff0dcfacfd10236a9deb9994279b6/e46b2/rework.webp 960w,
/static/202ff0dcfacfd10236a9deb9994279b6/f992d/rework.webp 1440w,
/static/202ff0dcfacfd10236a9deb9994279b6/289e4/rework.webp 1688w&quot;
              sizes=&quot;(max-width: 960px) 100vw, 960px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/202ff0dcfacfd10236a9deb9994279b6/09b79/rework.jpg 240w,
/static/202ff0dcfacfd10236a9deb9994279b6/7cc5e/rework.jpg 480w,
/static/202ff0dcfacfd10236a9deb9994279b6/6a068/rework.jpg 960w,
/static/202ff0dcfacfd10236a9deb9994279b6/644c5/rework.jpg 1440w,
/static/202ff0dcfacfd10236a9deb9994279b6/9291b/rework.jpg 1688w&quot;
            sizes=&quot;(max-width: 960px) 100vw, 960px&quot;
            type=&quot;image/jpeg&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/202ff0dcfacfd10236a9deb9994279b6/6a068/rework.jpg&quot;
            alt=&quot;rework cover&quot;
            title=&quot;rework cover&quot;
            loading=&quot;lazy&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The guidance provided by Jason Fried and David Hansson will help you understand a lot on how
a company can and should work. In my opinion the advice helps in surprising ways. Not only in the context of work!
Since pandemic started many of us switched to working from home.
The book shares some tips on how a company and more importantly people can work remotely efficiently.&lt;/p&gt;
&lt;h2 id=&quot;release-it-design-and-deploy-production-ready-software&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#release-it-design-and-deploy-production-ready-software&quot; aria-label=&quot;release it design and deploy production ready software permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;a href=&quot;https://www.amazon.com/Release-Design-Deploy-Production-Ready-Software/dp/1680502395&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Release It!: Design and Deploy Production-Ready Software&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 600px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/2aa4615de54421722c82a8c2d468f2fa/b4294/releaseit.jpg&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: 120%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAYABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAAQCBf/EABYBAQEBAAAAAAAAAAAAAAAAAAACAf/aAAwDAQACEAMQAAAB6lOMFKUc+cqZxr//xAAbEAADAAIDAAAAAAAAAAAAAAAAAQIDEhARE//aAAgBAQABBQK8UOp4bN0j2Q8nVPIbs//EABURAQEAAAAAAAAAAAAAAAAAABAR/9oACAEDAQE/ASn/xAAVEQEBAAAAAAAAAAAAAAAAAAAQEf/aAAgBAgEBPwEh/8QAHBABAAEEAwAAAAAAAAAAAAAAAQACERIgITGR/9oACAEBAAY/AlaXbKwsefZ1P//EAB0QAQACAgIDAAAAAAAAAAAAAAERIQAQMUFRYYH/2gAIAQEAAT8hZEXscQlERoZuF1PaZXOIl8Zeu7xTGWl8z//aAAwDAQACAAMAAAAQEABA/8QAFREBAQAAAAAAAAAAAAAAAAAAEBH/2gAIAQMBAT8QhR//xAAVEQEBAAAAAAAAAAAAAAAAAAAREP/aAAgBAgEBPxBYJ//EAB4QAQADAAICAwAAAAAAAAAAAAEAESFBURAxYXGB/9oACAEBAAE/ENKcuBz7igcUC/D6Um1ezjgRJqBYe2sF9qz52GgTYiYOjiv2Psg7Qk//2Q==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/2aa4615de54421722c82a8c2d468f2fa/8ac56/releaseit.webp 240w,
/static/2aa4615de54421722c82a8c2d468f2fa/d3be9/releaseit.webp 480w,
/static/2aa4615de54421722c82a8c2d468f2fa/e88ff/releaseit.webp 600w&quot;
              sizes=&quot;(max-width: 600px) 100vw, 600px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/2aa4615de54421722c82a8c2d468f2fa/09b79/releaseit.jpg 240w,
/static/2aa4615de54421722c82a8c2d468f2fa/7cc5e/releaseit.jpg 480w,
/static/2aa4615de54421722c82a8c2d468f2fa/b4294/releaseit.jpg 600w&quot;
            sizes=&quot;(max-width: 600px) 100vw, 600px&quot;
            type=&quot;image/jpeg&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/2aa4615de54421722c82a8c2d468f2fa/b4294/releaseit.jpg&quot;
            alt=&quot;release it cover&quot;
            title=&quot;release it cover&quot;
            loading=&quot;lazy&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Have you ever heard a dreadful story about a software system bringing a major enterprise to its knees?
Have you ever wondered what it takes for software to be mature and reliable? If so you’ll love
this piece. With a mixture of technical insights and best practices coloured with production stories,
this book reads like a novel. It explains in-depth multiple techniques that improve the resilience of
software systems. Circuit breaker, bulkhead and redundancy will be your bread and butter after you
get yourself familiar with what Michael T. Nygard describes.&lt;/p&gt;
&lt;p&gt;What are the books that you think are worth reading? Please post comments with your recommendations!&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Autoscaling AWS EKS cluster with custom Gitlab runner configuration]]></title><description><![CDATA[Gitlab offers a robust CI/CD solution suitable for most projects.
The documentation depicts the easiest way to connect your Kubernetes cluster to Gitlab.
Once connected Gitlab can install and configure Gitlab runner. However, such approach does not allow for many adjustments to Gitlab runner configuration.
For example…]]></description><link>undefined/gitlab-ci-kubernetes-cluster/</link><guid isPermaLink="false">undefined/gitlab-ci-kubernetes-cluster/</guid><pubDate>Wed, 17 Jun 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Gitlab offers a robust CI/CD solution suitable for most projects.
The &lt;a href=&quot;https://docs.gitlab.com/ee/user/project/clusters/add_remove_clusters.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;documentation&lt;/a&gt; depicts the easiest way to connect your Kubernetes cluster to Gitlab.
Once connected Gitlab can install and configure Gitlab runner.&lt;/p&gt;
&lt;p&gt;However, such approach does not allow for many adjustments to Gitlab runner configuration.
For example when using Kubernetes executor providing build level &lt;a href=&quot;https://docs.gitlab.com/runner/executors/kubernetes.html#overwriting-build-resources&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;resource requests and limits&lt;/a&gt; does not work.&lt;/p&gt;
&lt;p&gt;In this post we’ll use aws-cdk to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;provision an AWS EKS cluster&lt;/li&gt;
&lt;li&gt;install &lt;a href=&quot;https://docs.aws.amazon.com/eks/latest/userguide/cluster-autoscaler.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;cluster autoscaler&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;install Gitlab runner using &lt;a href=&quot;https://docs.gitlab.com/runner/install/kubernetes.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Helm chart&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 638px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/5d04332d8cb4704165b142f664c853bb/41be6/gitlab-aws.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: 39.166666666666664%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABJ0lEQVQoz41SPU/DMBD1xMbUiYnfV4mO/AM21N8AjB2KhIqQANGRgYGBAVGSkuaj0KRpQ1MlckjuHnKSBlCJlCedzmc/353fWTAzExGISC2hoDyn6Y+puIEpCHUfBXiTrBHqEurjCV5eNdb0MfQ3M98kKbE6Osayc5h7ThLQVwZKCZQyWCY1NRhicHXLZ70B+pdDvru5BgHIZi6snRYMIWDv7iHzP5F5I6y6bay7bQTP99BsF6blYLEMMNIMhOG66DCdPwHeA9h/RGIPwanMD6JeH05rH/H5RVk+QnzSgTw9gJQBLMfF3F/gfebBtKaIonijIYNDAxxOtp6QTT8qvZrJyhCKy+VECmFLkYkKElGerxCeypjqp1wRf5Gqr0P0Z+pb5/90/g3PYWEh6pTlKAAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/5d04332d8cb4704165b142f664c853bb/8ac56/gitlab-aws.webp 240w,
/static/5d04332d8cb4704165b142f664c853bb/d3be9/gitlab-aws.webp 480w,
/static/5d04332d8cb4704165b142f664c853bb/a2d8a/gitlab-aws.webp 638w&quot;
              sizes=&quot;(max-width: 638px) 100vw, 638px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/5d04332d8cb4704165b142f664c853bb/8ff5a/gitlab-aws.png 240w,
/static/5d04332d8cb4704165b142f664c853bb/e85cb/gitlab-aws.png 480w,
/static/5d04332d8cb4704165b142f664c853bb/41be6/gitlab-aws.png 638w&quot;
            sizes=&quot;(max-width: 638px) 100vw, 638px&quot;
            type=&quot;image/png&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/5d04332d8cb4704165b142f664c853bb/41be6/gitlab-aws.png&quot;
            alt=&quot;gitlab aws&quot;
            title=&quot;gitlab aws&quot;
            loading=&quot;lazy&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;prerequisite&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#prerequisite&quot; aria-label=&quot;prerequisite permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Prerequisite&lt;/h2&gt;
&lt;p&gt;Create an aws-cdk typescript project with necessary dependencies using&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;shell&quot;&gt;&lt;pre class=&quot;language-shell&quot;&gt;&lt;code class=&quot;language-shell&quot;&gt;&lt;span class=&quot;token function&quot;&gt;mkdir&lt;/span&gt; cicd &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; cicd
npx cdk init --language typescript
&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; i --save @aws-cdk/aws-eks&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;create-eks-cluster-with-aws-cdk&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#create-eks-cluster-with-aws-cdk&quot; aria-label=&quot;create eks cluster with aws cdk permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Create EKS Cluster with aws-cdk&lt;/h2&gt;
&lt;p&gt;First we add an AWS EKS cluster with a managed node group.
&lt;a href=&quot;https://docs.aws.amazon.com/eks/latest/userguide/managed-node-groups.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;A managed node group&lt;/a&gt; provides a convenient way to provision and manage nodes.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CICDStack&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;cdk&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Stack &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;scope&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; cdk&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Construct&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; props&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; cdk&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;StackProps&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;scope&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; props&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; clusterAdmin &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;iam&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Role&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Cluster Master Role&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      assumedBy&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;iam&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;AccountRootPrincipal&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; clusterName &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;cicd&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; cluster &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;eks&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Cluster&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;CICD Cluster&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      mastersRole&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; clusterAdmin&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      clusterName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; clusterName&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      defaultCapacity&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; mainNodeGroup &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; cluster&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addNodegroup&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;main&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      desiredSize&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      instanceType&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; ec2&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;InstanceType&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;of&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;InstanceClass&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;M5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; InstanceSize&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;XLARGE2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      nodegroupName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;main&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      maxSize&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;

  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;clusterAdmin&lt;/code&gt; IAM Role is going to be use to manage the cluster with &lt;a href=&quot;https://kubernetes.io/docs/tasks/tools/install-kubectl/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;kubectl&lt;/a&gt;.
We do not need it to install and configure Gitlab runner. However, it is essential for debugging purposes.&lt;/p&gt;
&lt;h2 id=&quot;install-gitlab-runner-using-helm-chart&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#install-gitlab-runner-using-helm-chart&quot; aria-label=&quot;install gitlab runner using helm chart permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Install Gitlab runner using Helm chart&lt;/h2&gt;
&lt;p&gt;For our EKS cluster to perform any CI work we need to install &lt;a href=&quot;https://docs.gitlab.com/runner/install/kubernetes.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Gitlab runner&lt;/a&gt;.
Thankfully Gitlab provides &lt;a href=&quot;https://charts.gitlab.io/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;an official Helm chart&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;cluster&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addChart&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;gitlab-runner&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  chart&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;gitlab-runner&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  repository&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://charts.gitlab.io/&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  version&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;v0.17.1&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  wait&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  values&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    gitlabUrl&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://gitlab.com/&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    runnerRegistrationToken&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&amp;lt;runner registration token&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    rbac&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      create&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    runners&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// https://gitlab.com/gitlab-org/charts/gitlab-runner/blob/master/values.yaml&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// required for dind&lt;/span&gt;
      privileged&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      builds&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        cpuRequests&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;1&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        cpuRequestsOverwriteMaxAllowed&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;16&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        cpuLimitOverwriteMaxAllowed&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;16&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        memoryRequests&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;4Gi&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        memoryLimitOverwriteMaxAllowed&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;16Gi&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        memoryRequestsOverwriteMaxAllowed&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;16Gi&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;For the Gitlab runner to register in Gitlab server we need to get a runner registration token.
You can find the runner registration token on a project or group CI/CD settings page.
In the above example I passed the value as is to the &lt;code class=&quot;language-text&quot;&gt;runnerRegistrationToken&lt;/code&gt; setting.
However, you should not commit that into source control and instead use an environment variable,
or &lt;a href=&quot;https://docs.aws.amazon.com/cdk/latest/guide/get_ssm_value.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;a parameter store reference&lt;/a&gt;.&lt;/p&gt;
&lt;p&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/286824caf48bfb1988fdbe1d37644e39/3ceac/registration-token.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: 104.58333333333334%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAVCAYAAABG1c6oAAAACXBIWXMAABYlAAAWJQFJUiTwAAADNklEQVQ4y41U2YoTURDt31FnVMQNEZ/FP/BBYRhRcQF/QF/EBfEHRBxQ/ANRGRCcFxEUZhQT0uklvSXdSXpJL+klneVIVaZDZtTBC4e70H3uqapTV7h44jIuXbiJc+fv4fix6zh75i5WV67hzOk7OLp6DadO3sLKkXUcPrT2XxC+fv+Bn78kiKKFWk2DKJo8Nxom6nUd9bqGnR0J29vNfZD4fGdbWuxpFgajAhPMcNDIsiEjz1OkacJIkmgxR9EAcRwiDAMIwzjGqCgwm80wnU73gM6yLEMQBPA8H77vYzCgn+N/Xi5EcYyiKHhDBNWo1vSzKIrQNA2maUJRFF5PJpPFxbSuIERRhNFo9E9C+si2bRi6zlCJsKVCajaZvCmKfGGtVoPneRCGwyHKslyQLIPGeDxGx+lB1S0omslQ9Tasjo1er4dOp4NutwvHcZDnOQQK6SCFRBgmGfpBjH6Q8Ox4EaIkQ55lTEKiCJQ6IUkSlOVoH9FeheVoBMexocgSZElCS1XQbM5DlWWZFZLaNE3nhHRLEJAl5sRVhSvCLM/RlBXU6g0YZhu6YcIwLbTbbS5Uv99nQkodh5xlOXw/RpoWi0IsE2JWYug78B0DkdtB2G8zTMOA67psJwKljotCXvN9D2k6/EPhZDzG5i8fL7faeLVlMV580rHxWUcQxhiPS76UU0MKyTZE6Loe3zab7Rp7ifDNlx4evuvgyQcbj9/bePrRxvNNB8O8xHQ6YTJSt1BIOXTdPqIo/GsOyyzBpEgwLRKMs4hRptRyEcIw5O4hDiakHMZxAsfpcYuRbMIyoWGYkGQVotxCvSFBlFQoaosLQl0jSRLbhjuFFoNBCF0no7qoUlANzk9ZomU5EDUbkuFA0m24ns8CSB2B0kWOEagQVVHiOPpryAX5sNOGocowWsp81jS2CpFWxNwpltXlB4AO2SL7CKu2/Ph6A/fXruDR7Rt4sH4Vb589htvvMRH1MNmGO+XbtyYnlkKlw+oVWRDuWiLwPLRUFZZp8gNh6Bp8z+Po6PuFbYiVNtWDUJEthzx3wdxWFGay+6AQGf1fWYarTH1Mqg56HOhDIiUQCe2XzbyM36qMECxPI8sqAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/286824caf48bfb1988fdbe1d37644e39/8ac56/registration-token.webp 240w,
/static/286824caf48bfb1988fdbe1d37644e39/d3be9/registration-token.webp 480w,
/static/286824caf48bfb1988fdbe1d37644e39/e46b2/registration-token.webp 960w,
/static/286824caf48bfb1988fdbe1d37644e39/f992d/registration-token.webp 1440w,
/static/286824caf48bfb1988fdbe1d37644e39/5377c/registration-token.webp 1456w&quot;
              sizes=&quot;(max-width: 960px) 100vw, 960px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/286824caf48bfb1988fdbe1d37644e39/8ff5a/registration-token.png 240w,
/static/286824caf48bfb1988fdbe1d37644e39/e85cb/registration-token.png 480w,
/static/286824caf48bfb1988fdbe1d37644e39/d9199/registration-token.png 960w,
/static/286824caf48bfb1988fdbe1d37644e39/07a9c/registration-token.png 1440w,
/static/286824caf48bfb1988fdbe1d37644e39/3ceac/registration-token.png 1456w&quot;
            sizes=&quot;(max-width: 960px) 100vw, 960px&quot;
            type=&quot;image/png&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/286824caf48bfb1988fdbe1d37644e39/d9199/registration-token.png&quot;
            alt=&quot;runner registration token&quot;
            title=&quot;runner registration token&quot;
            loading=&quot;lazy&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Note that we have configured a couple of values defined in &lt;a href=&quot;https://gitlab.com/gitlab-org/charts/gitlab-runner/blob/master/values.yaml&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;the Helm chart&lt;/a&gt;.
Most notably we set the required &lt;code class=&quot;language-text&quot;&gt;cpu*OverwriteMaxAllowed&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;memory*OverwriteMaxAllowed&lt;/code&gt; options.
We have to configure them otherwise it will not be possible to set Kubernetes CPU and memory allocations for requests and limits on the &lt;code class=&quot;language-text&quot;&gt;.gitlab-ci.yml&lt;/code&gt;.
With the above set we can request a certain amount of CPU and memory for build:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;yaml&quot;&gt;&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt; &lt;span class=&quot;token key atrule&quot;&gt;variables&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
   &lt;span class=&quot;token key atrule&quot;&gt;KUBERNETES_CPU_REQUEST&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;
   &lt;span class=&quot;token key atrule&quot;&gt;KUBERNETES_CPU_LIMIT&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;
   &lt;span class=&quot;token key atrule&quot;&gt;KUBERNETES_MEMORY_REQUEST&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 2Gi
   &lt;span class=&quot;token key atrule&quot;&gt;KUBERNETES_MEMORY_LIMIT&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 4Gi&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;install-cluster-autoscaler-using-aws-cdk-construct&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#install-cluster-autoscaler-using-aws-cdk-construct&quot; aria-label=&quot;install cluster autoscaler using aws cdk construct permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Install Cluster autoscaler using aws-cdk construct&lt;/h2&gt;
&lt;p&gt;In order for our AWS EKS cluster to scale dynamically we need to install &lt;a href=&quot;https://docs.aws.amazon.com/eks/latest/userguide/cluster-autoscaler.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Cluster autoscaler&lt;/a&gt;.
With autoscaler installed, whenever the amount of &lt;strong&gt;declared requested&lt;/strong&gt; CPU or memory resources exceeds those available on nodes, a new node will be added to the cluster.&lt;/p&gt;
&lt;p&gt;I’ve wrapped the Cluster autoscaler setup &lt;a href=&quot;https://github.com/miensol/miensol.github.io/blob/develop/content/posts/gitlab-ci-kubernetes-cluster/cicd/lib/cluster-autoscaler.ts&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;into aws-cdk construct&lt;/a&gt;
With the &lt;code class=&quot;language-text&quot;&gt;ClusterAutoscaler&lt;/code&gt; construct we can simply enhance our EKS Cluster by adding the following to the &lt;code class=&quot;language-text&quot;&gt;CICDStack&lt;/code&gt; definition:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ClusterAutoscaler&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;cluster-autoscaler&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  cluster&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; cluster&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  nodeGroups&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;mainNodeGroup&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  clusterName&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;connect-to-the-cluster-with-kubectl&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#connect-to-the-cluster-with-kubectl&quot; aria-label=&quot;connect to the cluster with kubectl permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Connect to the cluster with kubectl&lt;/h2&gt;
&lt;p&gt;After a deployment the new Gitlab runner becomes available for a project or Gitlab group.
The &lt;code class=&quot;language-text&quot;&gt;cdk deploy&lt;/code&gt; command will also output a hint on how to configure &lt;code class=&quot;language-text&quot;&gt;kubectl&lt;/code&gt; to connect to the cluster.
It will look somewhat similar to the example below:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;shell&quot;&gt;&lt;pre class=&quot;language-shell&quot;&gt;&lt;code class=&quot;language-shell&quot;&gt;aws eks update-kubeconfig --name cicd --region eu-west-1 &lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;
  --role-arn arn:aws:iam::XXXXXXXXXXX:role/CICD-ClusterMasterRoleXXXX-XXXX&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You only need to execute the above command once. It will store the configuration for &lt;code class=&quot;language-text&quot;&gt;kubectl&lt;/code&gt; on your local disk.
Afterwards you can inspect the EKS Kubernetes cluster with &lt;code class=&quot;language-text&quot;&gt;kubectl&lt;/code&gt; e.g:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;shell&quot;&gt;&lt;pre class=&quot;language-shell&quot;&gt;&lt;code class=&quot;language-shell&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; kubectl get pods 
NAME                                                              READY   STATUS    RESTARTS   AGE
cicdcicdclusterchartgitlabrunnerdXXXXX-gitlab-runner-XXXXXXXXXX   &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;/1     Running   &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;          26h&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You can find full working example &lt;a href=&quot;http://github.com/miensol/miensol.github.io/blob/develop/content/posts/gitlab-ci-kubernetes-cluster/cicd&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;under the github repository&lt;/a&gt;.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Deploy aws-cdk app to different environments]]></title><description><![CDATA[Infrastructure as a code greatly improves traceability, repeatability and thus overall quality of the software systems built with it.
With a correct setup development teams can now more easily spin up short-lived clones of systems or their parts.
This gives a profound boost in both productivity but also ability to run…]]></description><link>undefined/deploying-aws-cdk-app-to-different-environments/</link><guid isPermaLink="false">undefined/deploying-aws-cdk-app-to-different-environments/</guid><pubDate>Sun, 31 May 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Infrastructure as a code greatly improves traceability, repeatability and thus overall quality of the software systems built with it.
With a correct setup development teams can now more easily spin up short-lived clones of systems or their parts.
This gives a profound boost in both productivity but also ability to run automated regression or performance tests.&lt;/p&gt;
&lt;p&gt;In this post I will show how to use aws-cdk to deploy multiple copies of the same application:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;#using-multiple-aws-accounts-to-deploy-copies-of-the-same-aws-cdk-application&quot;&gt;&lt;strong&gt;1. Using multiple AWS accounts.&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;#using-single-aws-account-to-deploy-copies-of-the-same-aws-cdk-application&quot;&gt;&lt;strong&gt;2. Using a single AWS account.&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&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/87c5eda5dd66a76407be65ab9cfdbc55/0f98f/dna.jpg&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: 50%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAKABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAIDAQX/xAAWAQEBAQAAAAAAAAAAAAAAAAADAgT/2gAMAwEAAhADEAAAAee+TbOhEhP/xAAbEAACAQUAAAAAAAAAAAAAAAAAAQIDESIxMv/aAAgBAQABBQKMbIxH1U2f/8QAFhEBAQEAAAAAAAAAAAAAAAAAABEx/9oACAEDAQE/AdR//8QAFREBAQAAAAAAAAAAAAAAAAAAABH/2gAIAQIBAT8BV//EABgQAQADAQAAAAAAAAAAAAAAAAAQQYHB/9oACAEBAAY/AnVtn//EABsQAQACAwEBAAAAAAAAAAAAAAEAESExQVGh/9oACAEBAAE/IQs+scaqjpi3yJ9mVXXETc5Hc//aAAwDAQACAAMAAAAQ9x//xAAXEQEAAwAAAAAAAAAAAAAAAAAAATFh/9oACAEDAQE/ELI0/8QAFhEAAwAAAAAAAAAAAAAAAAAAARAx/9oACAECAQE/EIE//8QAHhABAAICAQUAAAAAAAAAAAAAAREhADEQUWGRwdH/2gAIAQEAAT8QMJCt0T2PuQFZElBfeT9yvqfONFlDhaKy5GDRNFcH/9k=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/87c5eda5dd66a76407be65ab9cfdbc55/8ac56/dna.webp 240w,
/static/87c5eda5dd66a76407be65ab9cfdbc55/d3be9/dna.webp 480w,
/static/87c5eda5dd66a76407be65ab9cfdbc55/e46b2/dna.webp 960w,
/static/87c5eda5dd66a76407be65ab9cfdbc55/f992d/dna.webp 1440w,
/static/87c5eda5dd66a76407be65ab9cfdbc55/882b9/dna.webp 1920w&quot;
              sizes=&quot;(max-width: 960px) 100vw, 960px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/87c5eda5dd66a76407be65ab9cfdbc55/09b79/dna.jpg 240w,
/static/87c5eda5dd66a76407be65ab9cfdbc55/7cc5e/dna.jpg 480w,
/static/87c5eda5dd66a76407be65ab9cfdbc55/6a068/dna.jpg 960w,
/static/87c5eda5dd66a76407be65ab9cfdbc55/644c5/dna.jpg 1440w,
/static/87c5eda5dd66a76407be65ab9cfdbc55/0f98f/dna.jpg 1920w&quot;
            sizes=&quot;(max-width: 960px) 100vw, 960px&quot;
            type=&quot;image/jpeg&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/87c5eda5dd66a76407be65ab9cfdbc55/6a068/dna.jpg&quot;
            alt=&quot;dna clone&quot;
            title=&quot;dna clone&quot;
            loading=&quot;lazy&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;using-multiple-aws-accounts-to-deploy-copies-of-the-same-aws-cdk-application&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#using-multiple-aws-accounts-to-deploy-copies-of-the-same-aws-cdk-application&quot; aria-label=&quot;using multiple aws accounts to deploy copies of the same aws cdk application permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Using multiple AWS accounts to deploy copies of the same aws-cdk application&lt;/h2&gt;
&lt;p&gt;By default, every aws-cdk &lt;code class=&quot;language-text&quot;&gt;Stack&lt;/code&gt; you create is environment-agnostic.
You can deploy an environment-agnostic stack with any AWS account granted you have enough entitlements.
Note that AWS account does not mean IAM user. A single AWS account can have multiple IAM users.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 446px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/0a9234622592231b093515ded26f1dd1/6244b/iam-user-vs-account.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: 54.166666666666664%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAABYlAAAWJQFJUiTwAAABeUlEQVQoz5WSy07CQBiFeWFlI7I27HwEwwOYGDUuiTsxRiWBEC9Jo7UXxFILUrXQdjrTz3QEjRe8THIymfnPf+abdkp5nlOMYv6s+f5/Rumnpu8OWaS5XwcGQYBpmnr2PA/XdZlMJv8inPt0YJqmRFFEHMdEz8+EYYgQglypNwKlFFLKL2Rq5vlI6PvYjoN3H+APR/QHvpbl9rj1PGzbxry+xjAMTe84Dr1ej8FgoNcFyIfADPTpKhyhwgfkeET2MCQbBVpCSmRxEyFIkphMSrIs0z1z6vdAkSK6LdJWk7h1yPS0SXRyQNY51lLdEyhknIGSf/iG7SMejQv6tsVUKlRR/OwWCdxa5O0j8jTV9cV/+aLNOIdwGrNRr7NULrNarVKpVFhaLrO9s8tTIkiKju4pud+fIakF7/DqnGFjj+Csw2Z9g1q1wnptTau2ukJje4vxeYekuQ83xiv9D0+ppEvxBCwDbAN8B+4s8CzwXTAvwbnSnt/CisAXsdtGZHMObRIAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/0a9234622592231b093515ded26f1dd1/8ac56/iam-user-vs-account.webp 240w,
/static/0a9234622592231b093515ded26f1dd1/5021b/iam-user-vs-account.webp 446w&quot;
              sizes=&quot;(max-width: 446px) 100vw, 446px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/0a9234622592231b093515ded26f1dd1/8ff5a/iam-user-vs-account.png 240w,
/static/0a9234622592231b093515ded26f1dd1/6244b/iam-user-vs-account.png 446w&quot;
            sizes=&quot;(max-width: 446px) 100vw, 446px&quot;
            type=&quot;image/png&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/0a9234622592231b093515ded26f1dd1/6244b/iam-user-vs-account.png&quot;
            alt=&quot;iam user vs account&quot;
            title=&quot;iam user vs account&quot;
            loading=&quot;lazy&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;cdk deploy&lt;/code&gt; command uses specified AWS profile or a default one.&lt;/p&gt;
&lt;p&gt;Let us start with a bare bone app &lt;code class=&quot;language-text&quot;&gt;multiple-accounts&lt;/code&gt; generated with:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;shell&quot;&gt;&lt;pre class=&quot;language-shell&quot;&gt;&lt;code class=&quot;language-shell&quot;&gt;&lt;span class=&quot;token function&quot;&gt;mkdir&lt;/span&gt; multiple-accounts &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; multiple-accounts
npx cdk init --language typescript&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;To make our example more entertaining I added a single S3 Bucket to the &lt;code class=&quot;language-text&quot;&gt;MultipleAccountsStack&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; cdk &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;@aws-cdk/core&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; s3 &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;@aws-cdk/aws-s3&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;MultipleAccountsStack&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;cdk&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Stack &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;scope&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; cdk&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Construct&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; props&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; cdk&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;StackProps&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;scope&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; props&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;s3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Bucket&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;MyBucket&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I also created 2 AWS profiles for 2 AWS accounts, using &lt;code class=&quot;language-text&quot;&gt;aws configure&lt;/code&gt;, named &lt;code class=&quot;language-text&quot;&gt;blog-staging&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;blog-production&lt;/code&gt; for demonstration.&lt;/p&gt;
&lt;h3 id=&quot;deploy-aws-cdk-app-using-explicitly-specified-profile&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#deploy-aws-cdk-app-using-explicitly-specified-profile&quot; aria-label=&quot;deploy aws cdk app using explicitly specified profile permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Deploy aws-cdk app using explicitly specified profile&lt;/h3&gt;
&lt;p&gt;For start let’s use &lt;code class=&quot;language-text&quot;&gt;--profile&lt;/code&gt; parameter to deploy our stacks:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;shell&quot;&gt;&lt;pre class=&quot;language-shell&quot;&gt;&lt;code class=&quot;language-shell&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; npx cdk deploy --profile blog-staging

MultipleAccountsStack: deploying&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.
MultipleAccountsStack: creating CloudFormation changeset&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.
 &lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.

 ✅  MultipleAccountsStack

Stack ARN:
arn:aws:cloudformation:eu-central-1:XXXXXXXXXX:stack/MultipleAccountsStack/0d3c7530-a318-11ea-ab8d-02b8022d5b40

&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; npx cdk deploy --profile blog-production

MultipleAccountsStack: deploying&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.
MultipleAccountsStack: creating CloudFormation changeset&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.
&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.

 ✅  MultipleAccountsStack

Stack ARN:
arn:aws:cloudformation:eu-central-1:YYYYYYYYYY:stack/MultipleAccountsStack/3a5cc690-a319-11ea-b00b-023cc2de05b4&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Note how &lt;code class=&quot;language-text&quot;&gt;XXXXXXXXXX&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;YYYYYYYYYY&lt;/code&gt; identifies, which AWS account deployed the stack.
The stack has the same &lt;strong&gt;name&lt;/strong&gt; in both cases: &lt;code class=&quot;language-text&quot;&gt;MultipleAccountsStack&lt;/code&gt;&lt;/p&gt;
&lt;p&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/553f0381ba311293df5c447f8744b70d/8ae78/stack-name.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: 44.583333333333336%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAABYlAAAWJQFJUiTwAAABTUlEQVQoz5XP647bIBSFUb//83UsTTXppHF8d2zjA5ib81VhRu206p8gLaED0mZTnNob3y4DZTXyep2Y15Vr01DVDZsIatueUtyUoIzLVm0RrVnWNdPGoLV+SqHUSvnyQlmWnM8/2fedlBIxRkIITytENNe6oW5a+nHEGJtDH7z3/+W++PeusPvOohTaWoy1bFqjRPIe/moZP+ePPX79RYy/FdZaQkr5NTEGMRazO3yMuBAy/+Dcn4bOISK5gPucs0fD3XuiFuwycz2daN6+M/x44y6KZIQgG14LPqYc/Gi0252qalgWxZHupJg44pHbF+7yThpbwjwxtz3zcGObFcswMdVdPr+PHam5kGLkOO644BilZ5KB2dwYZWDceqy3FL6rOcaOOHR054r6dKE/V1n7XuGHDqY+h96Pg8fy0dFtDf3WctNjDh+kw4WdX6fztDxAwNMsAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/553f0381ba311293df5c447f8744b70d/8ac56/stack-name.webp 240w,
/static/553f0381ba311293df5c447f8744b70d/d3be9/stack-name.webp 480w,
/static/553f0381ba311293df5c447f8744b70d/e46b2/stack-name.webp 960w,
/static/553f0381ba311293df5c447f8744b70d/7f3f2/stack-name.webp 1096w&quot;
              sizes=&quot;(max-width: 960px) 100vw, 960px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/553f0381ba311293df5c447f8744b70d/8ff5a/stack-name.png 240w,
/static/553f0381ba311293df5c447f8744b70d/e85cb/stack-name.png 480w,
/static/553f0381ba311293df5c447f8744b70d/d9199/stack-name.png 960w,
/static/553f0381ba311293df5c447f8744b70d/8ae78/stack-name.png 1096w&quot;
            sizes=&quot;(max-width: 960px) 100vw, 960px&quot;
            type=&quot;image/png&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/553f0381ba311293df5c447f8744b70d/d9199/stack-name.png&quot;
            alt=&quot;stack name&quot;
            title=&quot;stack name&quot;
            loading=&quot;lazy&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;You can specify the AWS profile to use with &lt;code class=&quot;language-text&quot;&gt;AWS_PROFILE&lt;/code&gt; environment variable:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;shell&quot;&gt;&lt;pre class=&quot;language-shell&quot;&gt;&lt;code class=&quot;language-shell&quot;&gt;&lt;span class=&quot;token assign-left variable&quot;&gt;AWS_PROFILE&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;blog-production npx cdk deploy&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Last but not least the standard AWS CLI environment variables work as well:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;shell&quot;&gt;&lt;pre class=&quot;language-shell&quot;&gt;&lt;code class=&quot;language-shell&quot;&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;AWS_ACCESS_KEY_ID&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;xxxx
&lt;span class=&quot;token builtin class-name&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;AWS_SECRET_ACCESS_KEY&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;yyy
&lt;span class=&quot;token builtin class-name&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;AWS_DEFAULT_REGION&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;eu-central-1
npx cdk deploy&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Please refer to &lt;a href=&quot;https://docs.aws.amazon.com/cdk/latest/guide/environments.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;the documentation&lt;/a&gt; for further details.&lt;/p&gt;
&lt;h3 id=&quot;benefits-of-using-multiple-aws-accounts-to-deploy-aws-cdk-app&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#benefits-of-using-multiple-aws-accounts-to-deploy-aws-cdk-app&quot; aria-label=&quot;benefits of using multiple aws accounts to deploy aws cdk app permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Benefits of using multiple AWS accounts to deploy aws-cdk app&lt;/h3&gt;
&lt;p&gt;The first advantage is how using multiple AWS accounts keeps aws-cdk code simple.
The infrastructure code ignores details of the environment it runs in. This makes it possible to re-use it in other contexts.
This approach also improves security.
With multiple AWS accounts we minimise risk of aws-cdk installations affecting each other.&lt;/p&gt;
&lt;h3 id=&quot;downsides-of-using-multiple-aws-accounts-to-deploy-aws-cdk-app&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#downsides-of-using-multiple-aws-accounts-to-deploy-aws-cdk-app&quot; aria-label=&quot;downsides of using multiple aws accounts to deploy aws cdk app permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Downsides of using multiple AWS accounts to deploy aws-cdk app&lt;/h3&gt;
&lt;p&gt;The following example presents a first downside, or in reality a gotcha easy to miss.
Say someone not well versed in AWS services decided to name the bucket:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;s3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Bucket&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;MyBucket&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  bucketName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;important-assets&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;It will work fine when deployed for the first time. However, as soon as we try to deploy it to a second AWS account we get:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;shell&quot;&gt;&lt;pre class=&quot;language-shell&quot;&gt;&lt;code class=&quot;language-shell&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; npx cdk deploy --profile blog-production
&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;node:61539&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; ExperimentalWarning: Conditional exports is an experimental feature. This feature could change at any &lt;span class=&quot;token function&quot;&gt;time&lt;/span&gt;
MultipleAccountsStack: deploying&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.
MultipleAccountsStack: creating CloudFormation changeset&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.
 &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/3 &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;:56:27 AM &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; CREATE_IN_PROGRESS   &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; AWS::S3::Bucket    &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; MyBucket &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;MyBucketF68F3FF0&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
 &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;/3 &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;:56:27 AM &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; CREATE_IN_PROGRESS   &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; AWS::CDK::Metadata &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; CDKMetadata
 &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;/3 &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;:56:27 AM &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; CREATE_FAILED        &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; AWS::S3::Bucket    &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; MyBucket &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;MyBucketF68F3FF0&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; important-assets already exists&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Some AWS resources names need a unique name in a given region across all AWS accounts.&lt;/p&gt;
&lt;p&gt;The difficulty to create AWS accounts on a developer whim is the second downside.
Remember that want to re-create environments with changed parts.
Forcing a new AWS account may turn out problematic and create a management headache too big to ignore.&lt;/p&gt;
&lt;h2 id=&quot;using-single-aws-account-to-deploy-copies-of-the-same-aws-cdk-application&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#using-single-aws-account-to-deploy-copies-of-the-same-aws-cdk-application&quot; aria-label=&quot;using single aws account to deploy copies of the same aws cdk application permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Using single AWS account to deploy copies of the same aws-cdk application&lt;/h2&gt;
&lt;p&gt;As we saw above by default the Stack name gets derived from the class name.
Thankfully one can easily override that behaviour.
In my projects I prefer using a &lt;code class=&quot;language-text&quot;&gt;DEPLOY_ENV&lt;/code&gt; environment variable to specify the deployment target.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;shell&quot;&gt;&lt;pre class=&quot;language-shell&quot;&gt;&lt;code class=&quot;language-shell&quot;&gt;&lt;span class=&quot;token assign-left variable&quot;&gt;DEPLOY_ENV&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;staging npx cdk deploy&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We need to adjust our app definition so that &lt;code class=&quot;language-text&quot;&gt;DEPLOY_ENV&lt;/code&gt; is recognized.&lt;/p&gt;
&lt;h3 id=&quot;using-deploy_env-variable-inside-aws-cdk-entry-point&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#using-deploy_env-variable-inside-aws-cdk-entry-point&quot; aria-label=&quot;using deploy_env variable inside aws cdk entry point permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Using DEPLOY_ENV variable inside aws-cdk entry point&lt;/h3&gt;
&lt;p&gt;The aws-cdk app typically resided as &lt;code class=&quot;language-text&quot;&gt;bin&lt;/code&gt; folder. In our example it is the &lt;code class=&quot;language-text&quot;&gt;bin/multiple-accounts.ts&lt;/code&gt; file.
With the following adjustment we can deploy our app to many targets:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;#&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;usr&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;bin&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;env node
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;source-map-support/register&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; cdk &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;@aws-cdk/core&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; MultipleAccountsStack &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../lib/multiple-accounts-stack&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; deployEnv &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; process&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;env&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;DEPLOY_ENV&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;dev&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; app &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;cdk&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;App&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;MultipleAccountsStack&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;app&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; deployEnv &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;-MultipleAccountsStack&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;During deployment aws-cdk will create a CloudFormation stack named &lt;code class=&quot;language-text&quot;&gt;${process.env.DEPLOY_ENV}-MultipleAccountsStack&lt;/code&gt;:&lt;/p&gt;
&lt;p&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/3857fb883c0ea14e06f45a9fab168e36/c1b63/deploy-env-stack-name.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: 41.25%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAABYlAAAWJQFJUiTwAAABJUlEQVQoz5WQ226DMBBE+f9/bAPBDRAUzMXGxmtzKrtpq0pVpT4caS/SzOxWw7Rw04Z+tgx6Y15XhvvIQ2s2Y1i3je0fVNYaVHvl2jT0XYf3nihCCIHjOP5NZaylbq68Xmr64V4EyzKEIvobf+0ru+9knPe4w5MNlm0rM3km/SL3IqQzITH+mH1SGWOKo/We+2NinDTzZvBBcCF844+Sfneu/Dj/K/fOuY8wTyqTkxwHXk+M9aWw3hRJP5DMPCGzJri9JMjmwzBijCU+U0r4vqTad0tSNdIp3rqJ26Bph5lrr+n6iVqNLOoN2heIESeOdr5wW1q6RdE8XrivPed5Fqp8At6R1oVDNYS2LkhGfdRp0Zy75UyJlBJePDEKIQZiikiUL8F30rxpejAtlXcAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/3857fb883c0ea14e06f45a9fab168e36/8ac56/deploy-env-stack-name.webp 240w,
/static/3857fb883c0ea14e06f45a9fab168e36/d3be9/deploy-env-stack-name.webp 480w,
/static/3857fb883c0ea14e06f45a9fab168e36/e46b2/deploy-env-stack-name.webp 960w,
/static/3857fb883c0ea14e06f45a9fab168e36/92f8c/deploy-env-stack-name.webp 1200w&quot;
              sizes=&quot;(max-width: 960px) 100vw, 960px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/3857fb883c0ea14e06f45a9fab168e36/8ff5a/deploy-env-stack-name.png 240w,
/static/3857fb883c0ea14e06f45a9fab168e36/e85cb/deploy-env-stack-name.png 480w,
/static/3857fb883c0ea14e06f45a9fab168e36/d9199/deploy-env-stack-name.png 960w,
/static/3857fb883c0ea14e06f45a9fab168e36/c1b63/deploy-env-stack-name.png 1200w&quot;
            sizes=&quot;(max-width: 960px) 100vw, 960px&quot;
            type=&quot;image/png&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/3857fb883c0ea14e06f45a9fab168e36/d9199/deploy-env-stack-name.png&quot;
            alt=&quot;deploy env stack name&quot;
            title=&quot;deploy env stack name&quot;
            loading=&quot;lazy&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h3 id=&quot;using-deploy_env-consistently-inside-aws-cdk-application&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#using-deploy_env-consistently-inside-aws-cdk-application&quot; aria-label=&quot;using deploy_env consistently inside aws cdk application permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Using DEPLOY_ENV consistently inside aws-cdk application&lt;/h3&gt;
&lt;p&gt;As I mentioned above one can easily fall into unique name traps.
In order to avoid naming conflicts and to apply consistent naming scheme I often define a helper similar to the following.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;deployEnv&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; process&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;env&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;DEPLOY_ENV&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;dev&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;envSpecific&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;logicalName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; suffix &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;typeof&lt;/span&gt; logicalName &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;function&quot;&lt;/span&gt; 
    &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; logicalName&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name 
    &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; logicalName&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;deployEnv&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;suffix&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;MultipleAccountsStack&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;cdk&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Stack &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;scope&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; cdk&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Construct&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; props&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; cdk&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;StackProps&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;scope&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;envSpecific&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;MultipleAccountsStack&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; props&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;s3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Bucket&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;MyBucket&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      bucketName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;envSpecific&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;important-assets&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;With the above change our cdk app entry point no longer decides how to name the stack.
Note however, that you can still allow passing the name through constructor &lt;strong&gt;when&lt;/strong&gt; you need it.&lt;/p&gt;
&lt;p&gt;Using &lt;code class=&quot;language-text&quot;&gt;envSpecific&lt;/code&gt; helper keeps important resource names consistent.
More importantly it allows deploying as many copies of aws-cdk app as we like.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Combine AWS Step Functions with CloudWatch Events using aws-cdk]]></title><description><![CDATA[AWS Step Functions allow one to execute & coordinate long-running processes.
Step Functions fall into serverless AWS services, and the platform manages the function execution state completely. In the example below we will use the following AWS services: aws-cdk Step Function Lambda The example demonstrates how Step…]]></description><link>undefined/aws-step-function-with-cloudwatch-events/</link><guid isPermaLink="false">undefined/aws-step-function-with-cloudwatch-events/</guid><pubDate>Wed, 20 May 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://aws.amazon.com/step-functions/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;AWS Step Functions&lt;/a&gt; allow one to execute &amp;#x26; coordinate &lt;strong&gt;long-running&lt;/strong&gt; processes.
Step Functions fall into serverless AWS services, and the platform manages the function execution state completely.&lt;/p&gt;
&lt;p&gt;In the example below we will use the following AWS services:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;aws-cdk&lt;/li&gt;
&lt;li&gt;Step Function&lt;/li&gt;
&lt;li&gt;Lambda&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The example demonstrates how Step Functions manage execution of a process, which involves external events e.g. human interaction.&lt;/p&gt;
&lt;p&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/cff04c8299ebc81b26306fd7358cf68c/29ea0/steps.jpg&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: 45.833333333333336%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAJABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAAQBBf/EABUBAQEAAAAAAAAAAAAAAAAAAAEC/9oADAMBAAIQAxAAAAHuS2pTVH//xAAYEAEBAAMAAAAAAAAAAAAAAAACAQMSIP/aAAgBAQABBQJrWBZHeP/EABURAQEAAAAAAAAAAAAAAAAAABAR/9oACAEDAQE/Aaf/xAAVEQEBAAAAAAAAAAAAAAAAAAAQEf/aAAgBAgEBPwGH/8QAGBAAAgMAAAAAAAAAAAAAAAAAAAERIFH/2gAIAQEABj8CkxV//8QAGxAAAQQDAAAAAAAAAAAAAAAAAQARICExUXH/2gAIAQEAAT8hC+vQWbjjH//aAAwDAQACAAMAAAAQOw//xAAWEQEBAQAAAAAAAAAAAAAAAAABEDH/2gAIAQMBAT8QAGT/xAAWEQEBAQAAAAAAAAAAAAAAAAABERD/2gAIAQIBAT8QUtuf/8QAGhABAAMAAwAAAAAAAAAAAAAAAQAQITFBkf/aAAgBAQABPxBGCujlY1Up3PhTCv/Z&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/cff04c8299ebc81b26306fd7358cf68c/8ac56/steps.webp 240w,
/static/cff04c8299ebc81b26306fd7358cf68c/d3be9/steps.webp 480w,
/static/cff04c8299ebc81b26306fd7358cf68c/e46b2/steps.webp 960w,
/static/cff04c8299ebc81b26306fd7358cf68c/f992d/steps.webp 1440w,
/static/cff04c8299ebc81b26306fd7358cf68c/882b9/steps.webp 1920w,
/static/cff04c8299ebc81b26306fd7358cf68c/dc968/steps.webp 4966w&quot;
              sizes=&quot;(max-width: 960px) 100vw, 960px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/cff04c8299ebc81b26306fd7358cf68c/09b79/steps.jpg 240w,
/static/cff04c8299ebc81b26306fd7358cf68c/7cc5e/steps.jpg 480w,
/static/cff04c8299ebc81b26306fd7358cf68c/6a068/steps.jpg 960w,
/static/cff04c8299ebc81b26306fd7358cf68c/644c5/steps.jpg 1440w,
/static/cff04c8299ebc81b26306fd7358cf68c/0f98f/steps.jpg 1920w,
/static/cff04c8299ebc81b26306fd7358cf68c/29ea0/steps.jpg 4966w&quot;
            sizes=&quot;(max-width: 960px) 100vw, 960px&quot;
            type=&quot;image/jpeg&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/cff04c8299ebc81b26306fd7358cf68c/6a068/steps.jpg&quot;
            alt=&quot;steps&quot;
            title=&quot;steps&quot;
            loading=&quot;lazy&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;define-step-function&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#define-step-function&quot; aria-label=&quot;define step function permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Define step function&lt;/h2&gt;
&lt;p&gt;I will use blank infrastructure project created with&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;shellscript&quot;&gt;&lt;pre class=&quot;language-shellscript&quot;&gt;&lt;code class=&quot;language-shellscript&quot;&gt;&lt;span class=&quot;token function&quot;&gt;mkdir&lt;/span&gt; step-function &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; step-function
npx cdk init --language typescript&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Next we need to add required packages:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;shellscript&quot;&gt;&lt;pre class=&quot;language-shellscript&quot;&gt;&lt;code class=&quot;language-shellscript&quot;&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; step-function
&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; i --save @aws-cdk/aws-stepfunctions &lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;
  @aws-cdk/aws-stepfunctions-tasks &lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;
  @aws-cdk/aws-lambda-nodejs &lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;
  @aws-cdk/aws-dynamodb&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We start with a state machine that contains a single &lt;code class=&quot;language-text&quot;&gt;Wait&lt;/code&gt; step as follows.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; WaitTime &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;@aws-cdk/aws-stepfunctions&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Duration &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;@aws-cdk/core&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; cdk &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;@aws-cdk/core&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; sfn &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;@aws-cdk/aws-stepfunctions&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;StepFunctionStack&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;cdk&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Stack &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;scope&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; cdk&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Construct&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; props&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; cdk&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;StackProps&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;scope&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; props&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; wait &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;sfn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Wait&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Wait for Event&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      time&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; WaitTime&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;duration&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Duration&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;seconds&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;sfn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;StateMachine&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Step Function&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      definition&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; wait&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We deploy it with the usual aws-cdk deploy invocation&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;shellscript&quot;&gt;&lt;pre class=&quot;language-shellscript&quot;&gt;&lt;code class=&quot;language-shellscript&quot;&gt;&lt;span class=&quot;token assign-left variable&quot;&gt;AWS_PROFILE&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;my-aws-profile &lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; run cdk deploy&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;After a few moments we can find our brand new AWS Step Function visual representation in AWS Web Console:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 914px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/84cbfb256f6a2747437ccead794b8e32/076ca/step-wait.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: 116.25000000000001%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAXCAYAAAALHW+jAAAACXBIWXMAABYlAAAWJQFJUiTwAAACVklEQVQ4y5WVWW4TQRCGfYm85AAR3IkjcAGIACFeQEK5DMoDQiyCRFEsAyERkQIoOME4tmfGnqX36Z4fVXscPB6P45RU6v2rqt6qxThHnufIrYXxZe7b1lpIpSCEgJCyqkKAMQ4pJTjVOQfnHBljaCmlcHx8gsN2B1+PvqHd7mBv/wAfP+0jSVIPNsZUVGuNySRG9+ISw1GAMIy8AYK2yEocJxgOR4iiMcIw9BNGo8B74AEzUFmSE7Tm8k8PQRghSdP/QKU1mqQoipU6E+ecb9N2tMgiWRhP4sYFNxmcCUXUov2gUMhTVw5WwWio142LGZBgUqoacFaf92hZXwVIIcdJGXLTQidROFODNQLTjHloOaMyycgRgs8PEZ++hHXGG12MoAKkC90fDNHrXy3sn5saECMM9u5j8uUJHed6IVOFc1HxkERZibhguBqfIGTnSFwGY01tW6qHYkzNmi2sb+90d7DxagNbb+5i6+0dbL7exG6068fyIl8NnLfoynDfRx+wfbaNp2fP8ezXCzz68Rjf2en0nAq3HnDxingZdIDkfOnYWh5eKwCtE/x+dw+9wwe+7T1bdcorgSVUjY+gk5+18VuFvLSvNLDyYs8Dm9WVus5bXgu4BHAT8LZS1PenfHpGI8sdQq6gypzRl30IKcCVggxDCFKl/U/tX5VUsOkFJM0Rwuce+mQ90OYGzAKRUJCCI+Mcf1UfjDNkQkKGAUQYeDgBKSExIeGyLjKWIqNkpZQPm77Alu+Q4to7Ui2n75t+YKH1VOfGfbZTOYRU0zll9qOs9w/4JftwVoEq2AAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/84cbfb256f6a2747437ccead794b8e32/8ac56/step-wait.webp 240w,
/static/84cbfb256f6a2747437ccead794b8e32/d3be9/step-wait.webp 480w,
/static/84cbfb256f6a2747437ccead794b8e32/38f11/step-wait.webp 914w&quot;
              sizes=&quot;(max-width: 914px) 100vw, 914px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/84cbfb256f6a2747437ccead794b8e32/8ff5a/step-wait.png 240w,
/static/84cbfb256f6a2747437ccead794b8e32/e85cb/step-wait.png 480w,
/static/84cbfb256f6a2747437ccead794b8e32/076ca/step-wait.png 914w&quot;
            sizes=&quot;(max-width: 914px) 100vw, 914px&quot;
            type=&quot;image/png&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/84cbfb256f6a2747437ccead794b8e32/076ca/step-wait.png&quot;
            alt=&quot;step-wait&quot;
            title=&quot;step-wait&quot;
            loading=&quot;lazy&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;define-workflow-in-aws-step-function&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#define-workflow-in-aws-step-function&quot; aria-label=&quot;define workflow in aws step function permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Define workflow in AWS Step Function&lt;/h2&gt;
&lt;p&gt;In order to make our example more interesting let’s add a bit complexity to it.
Imagine we handle a document flow, which requires two separate actors to sign it off.&lt;/p&gt;
&lt;p&gt;The actors act independently. The first signer, Alice, signs documents quickly.
The other, Bob, can take a couple of days to process a document.&lt;/p&gt;
&lt;p&gt;Once both actors sign the document our flow succeeds. However, if we do not collect the signatures
until some time elapses the flow fails.&lt;/p&gt;
&lt;p class=&quot;note&quot;&gt;
In order for the `@aws-cdk/aws-lambda-nodejs` to work properly you need to have Docker running
&lt;/p&gt;
&lt;p&gt;Alice’s part consists of a single task along with a lambda function.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; signDocument &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;lambda&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;NodejsFunction&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Sign Document&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  entry&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; __dirname &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;/sign-document.ts&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  handler&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;signDocument&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; aliceSignature &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;sfn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Task&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Alice Signature&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  task&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;tasks&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;RunLambdaTask&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;signDocument&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    payload&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; sfn&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;TaskInput&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fromObject&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      signer&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Alice&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      documentId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;stringAt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;$.documentId&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;signDocument&lt;/code&gt; lambda function handler defined in &lt;code class=&quot;language-text&quot;&gt;step-function/lib/sign-document.ts&lt;/code&gt; looks as follows:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Handler &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;aws-lambda&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;delay&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;millis&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;resolve&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;setTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;resolve&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; millis&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; signDocument&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Handler&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  documentId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  signer&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;event&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;delay&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Sign document&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; event&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    result&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;event&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;signer&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; signed &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;event&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;documentId&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Please note that the lambda function can be async as long as it completes within the regular AWS Lambda function rules.&lt;/p&gt;
&lt;p&gt;Bob’s signature is a more complex job. Since Bob can take several days to process a request to sign a document we cannot simply use lambda.&lt;/p&gt;
&lt;p&gt;In order to solve that we will split the processing into 2 lambda functions using &lt;code class=&quot;language-text&quot;&gt;ServiceIntegrationPattern.WAIT_FOR_TASK_TOKEN&lt;/code&gt;.
The first one will receive step function token and store it in a DynamoDb table. That simulates reaching out to Bob e.g. through email.&lt;/p&gt;
&lt;p&gt;The second one will retrieve the token from the DynamoDb table and mark the Step function task as complete.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; signRequestsTable &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;dynamodb&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Table&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Signature Requests&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  billingMode&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; BillingMode&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;PAY_PER_REQUEST&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  partitionKey&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;documentId&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; AttributeType&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;STRING&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; requestDocumentSignature &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;lambda&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;NodejsFunction&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token string&quot;&gt;&quot;Request Document Signature&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    entry&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; __dirname &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;/sign-document.ts&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    handler&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;requestDocumentSignature&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    environment&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      signRequestsTableName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; signRequestsTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;tableName&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; completeSignatureRequest &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;lambda&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;NodejsFunction&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token string&quot;&gt;&quot;Complete Document Signature&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    entry&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; __dirname &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;/sign-document.ts&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    handler&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;completeSignatureRequest&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    environment&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      signRequestsTableName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; signRequestsTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;tableName&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

signRequestsTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;grantReadWriteData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;requestDocumentSignature&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
signRequestsTable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;grantReadWriteData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;completeSignatureRequest&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; bobSignature &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;sfn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Task&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Bob Signature&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  task&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;tasks&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;RunLambdaTask&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;requestDocumentSignature&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    integrationPattern&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; ServiceIntegrationPattern&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;WAIT_FOR_TASK_TOKEN&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    payload&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; sfn&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;TaskInput&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fromObject&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      stepFunctionToken&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; sfn&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Context&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;taskToken&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      signer&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Bob&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      documentId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;stringAt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;$.documentId&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Last but not least we need to allow the &lt;code class=&quot;language-text&quot;&gt;completeSignatureRequest&lt;/code&gt; to adjust step function state through IAM Policy Statement.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; waitForSignaturesTimeout &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Duration&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;seconds&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;60&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; stateMachine &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;sfn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;StateMachine&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Step Function&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  definition&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; flow&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  timeout&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; waitForSignaturesTimeout&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

completeSignatureRequest&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addToRolePolicy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;iam&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;PolicyStatement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    actions&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;states:SendTaskSuccess&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;states:SendTaskFailure&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    resources&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;stateMachine&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;stateMachineArn&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;After we deploy our updated stack the function definition should look as follows:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 309px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/67aa9c51e6fbd011319137b00e3606db/532e8/signatures.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: 82.91666666666667%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAARCAYAAADdRIy+AAAACXBIWXMAAAsTAAALEwEAmpwYAAADCElEQVQ4y41Uz2sTQRR+WT14Uw/iQT2IJ9GjNxE8etCziAoKIsVimzVpbakUQcX/QEREETy0iFRNsUWkgrTmR5NgW5pakiXZZrfZuPnRdrMzk87uPpntD22NxQcfb2a+7307zOwbgBZRHO+EsYFbcL+3DbDWDZVk6EwpGjyL2A9vnt6E2FA7lKJB+O/IfLoNzlxIsqdlKMeDNxtTMvK5MFaTsuzNhwFzXVJ2rKN1MWMMFEUBXddB07Q15L4BLjyQMNsOS2l5NDV0FSffXsWltDyB822A+YeSnvv6W69pkMvlABEByuVyABElMUHEwCa8T7vM8UvwMxG+0JwNUzYb4j8ToYuV8UsguC3atVqpXq8HoFQqwfpCayx/gRePzx199uj8cdf8vKO2Wq0CFAqFg7Ztv2SMjVBKP1BKI4yxSLPZjDDWHHYcHtF0YySvaqOu6whueI1jEaEVNYyxj4SQ14ZhHIbl5eV23Bau66Jt29hoNPwsQIi9uUYIQc/ztpehZVm90Gg05HWSISIXIIRwx3H88Xp2PM9zXNf111ZXV33Nht7zPCY8bNvuF4adYrK4uMh1XfdKpRJqmoaGYfi5Vquh4zjIGBMa1HUdTdNEVVVRaIvFolepVDjnXBjeA8uyZLE9RVFYLBbjmUyGi5xKpXgymeSapnGxs2az6XPpdJoXCgUejUb9cTwe5wsLC0x81N/hyspKu5i0OpON8/Txh2a7VvDCw7KsHvFTHqCUPhe3RykdopS++xOM+bf4nhASYZR82M6vaViEEPJKVdVDYBjGjv9WTR0TDbUHAPaVc6M7aoUXmKa50SmBrZiWvj47CerE3SNL6TtRayqc1qPdx6YHTwNiatffepSEF9Trdchms34/FotFH/m8AmyubzfPBKGalLtmhq9hZuQ61pLyA5yXwc3e251XfmzqRa3w8Hu5VfQEL0NlMiiZCRm0ieCJSqJDMeMdRW2i81RlMgi1pCwNPLnx/89Xr3wFMBsSz1TAng6BmerbW//et5/OhADVrgAa3TD4D8NfWI+jWrxnHVMAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/67aa9c51e6fbd011319137b00e3606db/8ac56/signatures.webp 240w,
/static/67aa9c51e6fbd011319137b00e3606db/451be/signatures.webp 309w&quot;
              sizes=&quot;(max-width: 309px) 100vw, 309px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/67aa9c51e6fbd011319137b00e3606db/8ff5a/signatures.png 240w,
/static/67aa9c51e6fbd011319137b00e3606db/532e8/signatures.png 309w&quot;
            sizes=&quot;(max-width: 309px) 100vw, 309px&quot;
            type=&quot;image/png&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/67aa9c51e6fbd011319137b00e3606db/532e8/signatures.png&quot;
            alt=&quot;alice and bob signatures&quot;
            title=&quot;alice and bob signatures&quot;
            loading=&quot;lazy&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;call-step-function-callback-from-aws-lambda&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#call-step-function-callback-from-aws-lambda&quot; aria-label=&quot;call step function callback from aws lambda permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Call Step Function callback from AWS Lambda&lt;/h2&gt;
&lt;p&gt;For our workflow to complete we need to implement Bob’s lambda part.
Let’s start with a function that simulates starting a long-running business process.
The important bit in &lt;code class=&quot;language-text&quot;&gt;sendSignatureRequest&lt;/code&gt; is that it stores state function task token.
We will use the token later on to call AWS Step Function back.
The callback will include result. In our case a fake signature of a document.&lt;/p&gt;
&lt;p&gt;First add 2 more packages to our project:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;shellscript&quot;&gt;&lt;pre class=&quot;language-shellscript&quot;&gt;&lt;code class=&quot;language-shellscript&quot;&gt;&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; i --save @types/aws-lambda aws-sdk&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Then update the AWS Lambda &lt;code class=&quot;language-text&quot;&gt;sendSignatureRequest&lt;/code&gt; definition:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Handler &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;aws-lambda&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; DynamoDb &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;aws-sdk/clients/dynamodb&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;SignDocumentEvent&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  documentId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  signer&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  stepFunctionToken&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; documentClient &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;DynamoDb&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;DocumentClient&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; signRequestsTableName &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; process&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;env&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;signRequestsTableName&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; requestDocumentSignature&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Handler&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;SignDocumentEvent&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
  event
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Request signature for&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; event&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; documentClient
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;put&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      TableName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; signRequestsTableName&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      Item&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; event&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;promise&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The last missing piece is to implement the &lt;code class=&quot;language-text&quot;&gt;completeSignatureRequest&lt;/code&gt; lambda function.
The important bit is to call &lt;code class=&quot;language-text&quot;&gt;sendTaskSuccess&lt;/code&gt; to indicate that processing completed successfully.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Handler &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;aws-lambda&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; StepFunctions &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;aws-sdk/clients/stepfunctions&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; DynamoDb &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;aws-sdk/clients/dynamodb&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; documentClient &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;DynamoDb&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;DocumentClient&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; signRequestsTableName &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; process&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;env&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;signRequestsTableName&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; stepFunctions &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;StepFunctions&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; completeSignatureRequest&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Handler&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; documentId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
  event
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; tableItem &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; documentClient
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      TableName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; signRequestsTableName&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      Key&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; documentId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; event&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;documentId &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;promise&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; signRequest&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; SignDocumentEvent &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; tableItem&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Item&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Received signature for&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; signRequest&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; output &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;stringify&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    signature&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;signRequest&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;signer&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; signed &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;signRequest&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;documentId&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; stepFunctions
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;sendTaskSuccess&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      output&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; output&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      taskToken&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; signRequest&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;stepFunctionToken&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;promise&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Let’s test the execution by requesting a document with id equal to 3.
As expected Alice signs the document after couple of seconds.
However, for in order to get Bob’s signature we invoke complete signature lambda.
This simulates an action that involves human interaction.
Note that the whole process could take months to complete!&lt;/p&gt;
&lt;p&gt;The AWS Step Function console depicts the current phase of processing pretty neatly.
&lt;div class=&quot;gatsby-resp-iframe-wrapper&quot; style=&quot;padding-bottom: 56.49999999999999%; position: relative; height: 0; overflow: hidden; margin-bottom: 1.0725rem&quot; &gt; &lt;div class=&quot;embedVideo-container&quot;&gt; &lt;iframe title=&quot;&quot; src=&quot;https://player.vimeo.com/video/420803128&quot; class=&quot;embedVideo-iframe&quot; style=&quot;border:0; position: absolute; top: 0; left: 0; width: 100%; height: 100%; &quot; loading=&quot;eager&quot; allowfullscreen=&quot;&quot; sandbox=&quot;allow-same-origin allow-scripts allow-popups&quot;&gt;&lt;/iframe&gt; &lt;/div&gt; &lt;/div&gt;&lt;/p&gt;
&lt;p&gt;You can find &lt;a href=&quot;https://github.com/miensol/miensol.github.io/tree/develop/content/posts/aws-step-function-with-cloudwatch-events/step-function&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;full working example in Github repository&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Leave a comment if you like the article and would like to see more!&lt;/p&gt;</content:encoded></item><item><title><![CDATA[HTTPs on CloudFront using Certificate Manager and aws-cdk]]></title><description><![CDATA[The static website deployed with aws-cdk to CloudFront post
shows how to deploy static content with aws-cdk. We still miss a custom domain configuration for
our website though. The following example shows how to: setup a custom domain name for a CloudFront distribution enable https using AWS issued trusted certificate…]]></description><link>undefined/cloudfront-custom-domain-https/</link><guid isPermaLink="false">undefined/cloudfront-custom-domain-https/</guid><pubDate>Tue, 05 May 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;../fast-static-website-with-aws-cdk&quot;&gt;The static website deployed with aws-cdk to CloudFront post&lt;/a&gt;
shows how to deploy static content with aws-cdk. We still miss a custom domain configuration for
our website though. The following example shows how to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;setup a custom domain name for a CloudFront distribution&lt;/li&gt;
&lt;li&gt;enable https using AWS issued trusted certificate&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;get-a-trusted-certificate-from-aws-certificate-manager-using-aws-cdk&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#get-a-trusted-certificate-from-aws-certificate-manager-using-aws-cdk&quot; aria-label=&quot;get a trusted certificate from aws certificate manager using aws cdk permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Get a trusted certificate from AWS Certificate Manager using aws-cdk&lt;/h2&gt;
&lt;p&gt;Using the &lt;a href=&quot;https://github.com/miensol/miensol.github.io/tree/develop/content/posts/cloudfront-custom-domain-https&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;example from previous post as a base&lt;/a&gt;, inside &lt;code class=&quot;language-text&quot;&gt;infrastructure&lt;/code&gt; directory, let’s add
additional package:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;shellscript&quot;&gt;&lt;pre class=&quot;language-shellscript&quot;&gt;&lt;code class=&quot;language-shellscript&quot;&gt;&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; i --save @aws-cdk/aws-certificatemanager&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;CloudFront can only use AWS Certificate Manager issued certificates inside us-east-1 region (N. Virginia).
We can create our &lt;code class=&quot;language-text&quot;&gt;FrontendStack&lt;/code&gt; in us-east-1 region. Alternatively we can create another stack with the certificate only.
Below I show how to use the second option.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; ValidationMethod &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;@aws-cdk/aws-certificatemanager&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; cm &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;@aws-cdk/aws-certificatemanager&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; domainName &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;fast-static-website.miensol.pl&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CertificateStack&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;cdk&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Stack &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;scope&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; cdk&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Construct&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;scope&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;CertificateStack&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      env&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; region&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;us-east-1&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; certificate &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;cm&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Certificate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;CustomDomainCertificate&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      domainName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; domainName&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      validationMethod&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; ValidationMethod&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;DNS&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; certificateArn &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; certificate&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;certificateArn&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CfnOutput&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;CertificateArn&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      value&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; certificateArn&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We request a certificate for a given domain name in us-east-1 region.
Before AWS Certificate Manager issues a trusted TLS certificate it needs to verify that you own
the domain. The validation happens using either:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;email: AWS CM sends a message to &lt;em&gt;admin&lt;/em&gt; email addresses for the domain&lt;/li&gt;
&lt;li&gt;DNS: AWS CM requests a particular DNS record configuration&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In the example above I use &lt;code class=&quot;language-text&quot;&gt;fast-static-website.miensol.pl&lt;/code&gt; with DNS validation method. Since I own
the domain I can prove that to AWS Certificate Manager.&lt;/p&gt;
&lt;p&gt;We also update the &lt;code class=&quot;language-text&quot;&gt;bin/infrastructure.ts&lt;/code&gt; file to include our new stack:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;#&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;usr&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;bin&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;env node
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;source-map-support/register&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; cdk &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;@aws-cdk/core&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; CertificateStack&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; FrontendStack &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../lib/frontend-stack&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; app &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;cdk&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;App&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CertificateStack&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;app&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;FrontendStack&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;app&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Let’s trigger next deployment with:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;shellscript&quot;&gt;&lt;pre class=&quot;language-shellscript&quot;&gt;&lt;code class=&quot;language-shellscript&quot;&gt;&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; run cdk deploy &lt;span class=&quot;token string&quot;&gt;&apos;*&apos;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The process will wait for a certificate request validation. The requested DNS
record will show up in the deployment command output:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;shellscript&quot;&gt;&lt;pre class=&quot;language-shellscript&quot;&gt;&lt;code class=&quot;language-shellscript&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; run cdk deploy
&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.
&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;/5 &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;6&lt;/span&gt;:03:37 PM &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; CREATE_IN_PROGRESS   &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; AWS::CertificateManager::Certificate
 &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; CustomDomainCertificate &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;CustomDomainCertificateXXXXX&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; Content of DNS Record is: &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;Name: XXXXXX.fast-static-website.miensol.pl.,Type: CNAME,Value: XXXXX.auiqqraehs.acm-validations.aws.&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;/5 Currently &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; progress: CustomDomainCertificateXXXXX
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You can also find the request in &lt;a href=&quot;https://eu-central-1.console.aws.amazon.com/acm/home?region=eu-central-1#/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Certificate Manager&lt;/a&gt; inside AWS Web console. After
you configure the DNS record, the process will continue. In the command output you should see a message similar to:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;shellscript&quot;&gt;&lt;pre class=&quot;language-shellscript&quot;&gt;&lt;code class=&quot;language-shellscript&quot;&gt;CertificateStack.CertificateArn &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; arn:aws:acm:us-east-1:XXXXXXX:certificate/XXXXX-XXXXX-XXXX-XXXX-XXXXXXXX&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Please note the above value, we will need it in the following step.&lt;/p&gt;
&lt;h2 id=&quot;attach-a-certificate-to-cloudfront-distribution-using-aws-cdk&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#attach-a-certificate-to-cloudfront-distribution-using-aws-cdk&quot; aria-label=&quot;attach a certificate to cloudfront distribution using aws cdk permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Attach a certificate to CloudFront distribution using aws-cdk&lt;/h2&gt;
&lt;p&gt;We need to tell the CloudFront distribution to use the new certificate. Let’s modify the &lt;code class=&quot;language-text&quot;&gt;FrontendStack&lt;/code&gt;
to accept parameters:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;
&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;FrontendProps&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  certificateArn&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;FrontendStack&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;cdk&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Stack &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;scope&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; cdk&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Construct&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; props&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; FrontendProps&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;scope&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;FrontendStack&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; frontBucket &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;s3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Bucket&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;FrontendBucket&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      websiteIndexDocument&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;index.html&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      publicReadAccess&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; distribution &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;cloudfront&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;CloudFrontWebDistribution&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token string&quot;&gt;&quot;Distribution&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        viewerCertificate&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          aliases&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;domainName&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          props&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            acmCertificateArn&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; props&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;certificateArn&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            sslSupportMethod&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;sni-only&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In the &lt;code class=&quot;language-text&quot;&gt;viewerCertificate&lt;/code&gt; section we specify domain name as well as certificate CloudFront distribution should use.
Next we pass CertificateStack.CertificateArn value noted above as a parameter:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; app &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;cdk&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;App&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CertificateStack&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;app&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;FrontendStack&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;app&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  certificateArn&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&quot;arn:aws:acm:us-east-1:XXXXXXX:certificate/XXXXX-XXXXX-XXXX-XXXX-XXXXXXXX&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The deployment will take a while to complete since the CF distribution has to update.
We can use that time to configure &lt;code class=&quot;language-text&quot;&gt;fast-static-website.miensol.pl&lt;/code&gt; DNS record.
The record needs to point to &lt;code class=&quot;language-text&quot;&gt;FrontendStack.DistributionDomainName&lt;/code&gt;.
I use CloudFlare so in my case this means creating a CNAME record:
&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/99ad63bc35281463c74de3c1f9ddf8cd/a4f52/cloudflare-dns-entry.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: 28.750000000000004%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAYAAADDl76dAAAACXBIWXMAABYlAAAWJQFJUiTwAAAA+ElEQVQY05WR0U7FIBBE+/+v/oAf4pM/oS/eGJNrK/SyUKBYWjgG9EZj4oObTGYngdlZGMQY5nlGRLDWYozhOA5qrZRSKOWTm/4LP2uQuOHWjRgjKaXO+77zu9q1ZtyGdbS+68I4jjydTmg9M5wnxaQ04zShtO4JvQ89tVIKrXXnptvAq3HNmbpnynEQ14RzC2tKDCKG4D2zUsQQOt5T6uu3AS2x975zzpk1eIp3ePWGvJ7JVmDP3ysvy8K2bXgRghUWYwjO9TTOuW7WDUMk7wfRCvtF93PWGLaLhhSpXw8z8I+6fkAtBbYE+R0nwsvzidv7R27uHvgAWIzQtLuEyRMAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/99ad63bc35281463c74de3c1f9ddf8cd/8ac56/cloudflare-dns-entry.webp 240w,
/static/99ad63bc35281463c74de3c1f9ddf8cd/d3be9/cloudflare-dns-entry.webp 480w,
/static/99ad63bc35281463c74de3c1f9ddf8cd/e46b2/cloudflare-dns-entry.webp 960w,
/static/99ad63bc35281463c74de3c1f9ddf8cd/f992d/cloudflare-dns-entry.webp 1440w,
/static/99ad63bc35281463c74de3c1f9ddf8cd/882b9/cloudflare-dns-entry.webp 1920w,
/static/99ad63bc35281463c74de3c1f9ddf8cd/f2636/cloudflare-dns-entry.webp 2024w&quot;
              sizes=&quot;(max-width: 960px) 100vw, 960px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/99ad63bc35281463c74de3c1f9ddf8cd/8ff5a/cloudflare-dns-entry.png 240w,
/static/99ad63bc35281463c74de3c1f9ddf8cd/e85cb/cloudflare-dns-entry.png 480w,
/static/99ad63bc35281463c74de3c1f9ddf8cd/d9199/cloudflare-dns-entry.png 960w,
/static/99ad63bc35281463c74de3c1f9ddf8cd/07a9c/cloudflare-dns-entry.png 1440w,
/static/99ad63bc35281463c74de3c1f9ddf8cd/29114/cloudflare-dns-entry.png 1920w,
/static/99ad63bc35281463c74de3c1f9ddf8cd/a4f52/cloudflare-dns-entry.png 2024w&quot;
            sizes=&quot;(max-width: 960px) 100vw, 960px&quot;
            type=&quot;image/png&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/99ad63bc35281463c74de3c1f9ddf8cd/d9199/cloudflare-dns-entry.png&quot;
            alt=&quot;cloudflare cname entry&quot;
            title=&quot;cloudflare cname entry&quot;
            loading=&quot;lazy&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;We can now load our static website using HTTPS!&lt;/p&gt;
&lt;p&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/4fd2271fa5155b57a072b2e79721396b/0ef7e/certificate.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: 89.58333333333334%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAYAAABb0P4QAAAACXBIWXMAABYlAAAWJQFJUiTwAAAC6ElEQVQ4y42TS28cRRRG/R/wIlE8bU97+lXVXdM9Pd3TPe/peedhhEkWQEQIXsRhcHhkkUW8iASSN4AiYMECFogFgh0rEH/uoG4/MmNPIhafbpWq6tR3763a8Gsx9bhJGKVEcbMY1+oJpi2pmA6GJbEcd0Xmkoq5JTFMgatCNiwZYorakgIsL6Y7e4fWZJ9qc4qu2mhOA00k7IjGqmSCCLvYbogl62zYbp0VyRoiaHGt+Yjy8Ah3/iUyWxQSwyM20wVvJQs200+L8WbzM8xkD0f4WG4BDHmlHBph2Iq7Hz/m2YsTZt0+o96AcT9j1OkxaXVwVEjZEOimRLckUp2aybO9cJhPcqijYrZ1m+Ovv+Hvf/7iVr/DtN2inySkUtBwbIRwEY7AlS67+i62UNhetB6YR+HV0Ss25YqD6UqU9JCmRWXXoKTtoG2Xz6QXcmTweofnwErFQC/rlLY0btwosVXaplTS0ErbaEXcQdu6jnZ9EyG9olRrgKdRqgjlR7jVOl6Y4qV9ZDND9ueI9hi3NcQNGzjpu8jhIbKeYcvgvClXgblDFTRQQYLfm1HNblO//xh//wH1D49Q0338/gxvcoDMDhHhGqAtwxVo/iYNS+HUWky//Y3xyc+MvvqJ8ckvpA+/IP7gE7x2hlEuY509GXsl5UtOi645Psn9Bc2Dpwxf/MjNH/4kO37J3q//0njvEMPwsFXyytDllJcd5tG0fZIHTwro/Ps/GDz/jvnL36ndeZ/0o8+L9ctnr/yUC4fnG50ANbhNe3FMdO+gcJrDorsPMe1q0d3lcxvrYOc35n8zT93YFQTze7QePbtwnsOsNZm90eFyfU3Hx7TU6boX8bpSXQHm3fWClOF0j1ZvQncwYzTdo92b0O6O6XTHDEa36GVzesObjOdvU4s7xbk31lBWGwgVF1K1Jn5rjN+e4PfmqLiLVHGxxwsSnLN//D9qGGKJGlYOze4UzfEn+4ioh+kEF+91OeX/AKz0RQnEs9mOAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/4fd2271fa5155b57a072b2e79721396b/8ac56/certificate.webp 240w,
/static/4fd2271fa5155b57a072b2e79721396b/d3be9/certificate.webp 480w,
/static/4fd2271fa5155b57a072b2e79721396b/e46b2/certificate.webp 960w,
/static/4fd2271fa5155b57a072b2e79721396b/f992d/certificate.webp 1440w,
/static/4fd2271fa5155b57a072b2e79721396b/f4029/certificate.webp 1594w&quot;
              sizes=&quot;(max-width: 960px) 100vw, 960px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/4fd2271fa5155b57a072b2e79721396b/8ff5a/certificate.png 240w,
/static/4fd2271fa5155b57a072b2e79721396b/e85cb/certificate.png 480w,
/static/4fd2271fa5155b57a072b2e79721396b/d9199/certificate.png 960w,
/static/4fd2271fa5155b57a072b2e79721396b/07a9c/certificate.png 1440w,
/static/4fd2271fa5155b57a072b2e79721396b/0ef7e/certificate.png 1594w&quot;
            sizes=&quot;(max-width: 960px) 100vw, 960px&quot;
            type=&quot;image/png&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/4fd2271fa5155b57a072b2e79721396b/d9199/certificate.png&quot;
            alt=&quot;certificate&quot;
            title=&quot;certificate&quot;
            loading=&quot;lazy&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;It is a shame that it is not possible to create &lt;a href=&quot;https://github.com/aws/aws-cdk/issues/49#issuecomment-454800305&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;cross region references using aws-cdk&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;There is not, unfortunately. You’re going to have to thread the API URL across regions manually. That means:&lt;/p&gt;
&lt;p&gt;Deploy the ApiStackIreland first. Note the API URL (maybe make it an Output so that it’s easy to get to).
Deploy the EdgeStack and plug in the value of API URL from the first step.
There are a number of ways you could do this, and honestly I’m not sure which one to recommend.&lt;/p&gt;
&lt;p&gt;I guess a pragmatic one would be to use &lt;code class=&quot;language-text&quot;&gt;this.node.getContext()&lt;/code&gt; and pass the value on the command-line when deploying the second stack (using the &lt;code class=&quot;language-text&quot;&gt;-c KEY=VALUE fflag&lt;/code&gt;), or put it into cdk.json under the context: {} section.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The full working example is available &lt;a href=&quot;https://github.com/miensol/miensol.github.io/tree/develop/content/posts/cloudfront-custom-domain-https&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;in the github repository&lt;/a&gt;.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Deploy fast, static website to AWS like a pro]]></title><description><![CDATA[In this post we’ll see how to create and deploy a static website using IaC using the following technologies: aws-cdk AWS CloudFormation AWS Lambda AWS S3 Have a static website For the sake of simplicity we’ll use Create React App in a directory called : Create the static website content inside  directory with: Add aws…]]></description><link>undefined/fast-static-website-with-aws-cdk/</link><guid isPermaLink="false">undefined/fast-static-website-with-aws-cdk/</guid><pubDate>Sun, 03 May 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;In this post we’ll see how to create and deploy a static website using IaC using the following technologies:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;aws-cdk&lt;/li&gt;
&lt;li&gt;AWS CloudFormation&lt;/li&gt;
&lt;li&gt;AWS Lambda&lt;/li&gt;
&lt;li&gt;AWS S3&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;have-a-static-website&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#have-a-static-website&quot; aria-label=&quot;have a static website permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Have a static website&lt;/h2&gt;
&lt;p&gt;For the sake of simplicity we’ll use &lt;a href=&quot;https://create-react-app.dev/docs/adding-typescript/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Create React App&lt;/a&gt; in a directory called &lt;code class=&quot;language-text&quot;&gt;my-project&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;shellscript&quot;&gt;&lt;pre class=&quot;language-shellscript&quot;&gt;&lt;code class=&quot;language-shellscript&quot;&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; my-project
npx create-react-app frontend --template typescript&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Create the static website content inside &lt;code class=&quot;language-text&quot;&gt;frontend/build&lt;/code&gt; directory with:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;shellscript&quot;&gt;&lt;pre class=&quot;language-shellscript&quot;&gt;&lt;code class=&quot;language-shellscript&quot;&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; frontend &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;yarn&lt;/span&gt; build&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;add-aws-cdk-to-the-project&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#add-aws-cdk-to-the-project&quot; aria-label=&quot;add aws cdk to the project permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Add aws-cdk to the project&lt;/h2&gt;
&lt;p&gt;Create infrastructure project with &lt;a href=&quot;https://docs.aws.amazon.com/cdk/latest/guide/home.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;aws-cdk&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;shellscript&quot;&gt;&lt;pre class=&quot;language-shellscript&quot;&gt;&lt;code class=&quot;language-shellscript&quot;&gt;&lt;span class=&quot;token function&quot;&gt;mkdir&lt;/span&gt; infrastructure &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; infrastructure
npx cdk init --language typescript&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Note that in order to deploy you need to have AWS API credentials configured.
I prefer using AWS profiles, which you can set up using AWS CLI:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;shellscript&quot;&gt;&lt;pre class=&quot;language-shellscript&quot;&gt;&lt;code class=&quot;language-shellscript&quot;&gt;aws configure --profile my-profile-name&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The command will ask you couple of questions.
Please find the AWS Access Key Id and AWS Secret Access Key for your AWS account in &lt;a href=&quot;https://console.aws.amazon.com/iam/home?region=eu-central-1&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;AWS Web Console IAM section&lt;/a&gt;.
The AWS CLI stores configuration under &lt;code class=&quot;language-text&quot;&gt;~/.aws&lt;/code&gt; (Linux or Mac) or &lt;code class=&quot;language-text&quot;&gt;%USERPROFILE%\.aws&lt;/code&gt; (Windows).&lt;/p&gt;
&lt;p&gt;Please follow aws-cdk &lt;a href=&quot;https://docs.aws.amazon.com/cdk/latest/guide/getting_started.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Getting Started&lt;/a&gt; to get more details.&lt;/p&gt;
&lt;h2 id=&quot;deploy-static-content-deployment-to-s3-website&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#deploy-static-content-deployment-to-s3-website&quot; aria-label=&quot;deploy static content deployment to s3 website permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Deploy static content deployment to S3 website&lt;/h2&gt;
&lt;p&gt;We will deploy static content to AWS using &lt;code class=&quot;language-text&quot;&gt;@aws-cdk/aws-s3-deployment&lt;/code&gt; package. We need to add it to our project:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;shellscript&quot;&gt;&lt;pre class=&quot;language-shellscript&quot;&gt;&lt;code class=&quot;language-shellscript&quot;&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; infrastructure
&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; i --save @aws-cdk/aws-s3-deployment&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Next, let’s tell aws-cdk to deploy contents of &lt;code class=&quot;language-text&quot;&gt;frontend/build&lt;/code&gt; directory to AWS.
In our template we have &lt;code class=&quot;language-text&quot;&gt;InfrastructureStack&lt;/code&gt; available under &lt;code class=&quot;language-text&quot;&gt;lib/infrastructure-stack.ts&lt;/code&gt;.
Since it makes sense to have more focused CloudFormation stacks let’s rename it to &lt;code class=&quot;language-text&quot;&gt;FrontendStackStack&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; cdk &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;@aws-cdk/core&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; s3 &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;@aws-cdk/aws-s3&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; s3deploy &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;@aws-cdk/aws-s3-deployment&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; cloudfront &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;@aws-cdk/aws-cloudfront&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; path &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;path&apos;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;FrontendStack&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;cdk&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Stack &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;constructor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;scope&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; cdk&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Construct&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;scope&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;FrontendStack&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;All files, which our static content consists of, will be stored on S3, so we need to create a bucket there:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;scope&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;FrontendStack&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; frontBucket &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;s3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Bucket&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;FrontendBucket&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  websiteIndexDocument&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;index.html&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  publicReadAccess&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Next, we need to tell &lt;code class=&quot;language-text&quot;&gt;@aws-cdk/aws-s3-deployment&lt;/code&gt; to push contents of &lt;code class=&quot;language-text&quot;&gt;frontent/build&lt;/code&gt; to the bucket created above:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;s3deploy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;BucketDeployment&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;DeployWebsite&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  sources&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;s3deploy&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Source&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;asset&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    path&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;__dirname&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;..&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;..&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;frontend&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;build&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  destinationBucket&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; frontBucket
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Since our aws-cdk stack uses assets we need to bootstrap our AWS account before &lt;strong&gt;first&lt;/strong&gt; deployment:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;shellscript&quot;&gt;&lt;pre class=&quot;language-shellscript&quot;&gt;&lt;code class=&quot;language-shellscript&quot;&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; infrastructure
&lt;span class=&quot;token assign-left variable&quot;&gt;AWS_PROFILE&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;my-profile-name npx cdk bootstrap&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Once the above command completes we can now finally deploy our website:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;shellscript&quot;&gt;&lt;pre class=&quot;language-shellscript&quot;&gt;&lt;code class=&quot;language-shellscript&quot;&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; infrastructure
&lt;span class=&quot;token assign-left variable&quot;&gt;AWS_PROFILE&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;my-profile-name &lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; run cdk deploy &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The command will prompt for confirmation before it creates the necessary security rules.
You will see what resources get created or modified while the command runs.
Afterwards all resources created are part of AWS CloudFormation &lt;code class=&quot;language-text&quot;&gt;FrontendStack&lt;/code&gt; stack.
Most importantly the command copied all files to S3 Bucket, which in turn can host the website.&lt;/p&gt;
&lt;p&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/5d2071c2f494ad61978f230e6640431c/3707e/s3-contents.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: 76.66666666666666%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAYAAADkmO9VAAAACXBIWXMAABYlAAAWJQFJUiTwAAACAUlEQVQ4y4VT227TQBT0RyPaPCLeKFSg0lBUVLWfwhsICakoaRJIL4lz8d2O7+tLBs1pjEJaKyuNj312d86cWa82XyzwMJlgfHuHweg3+oMhboYjXPcG+NUfYvRnLLle/waz5RKO58NyXIlJmiLNsv+gBWEIPwjwszfEi+PP6Hy8xMujLt6cn+HtlzMcHHVxeHKBzuklOu+6OHx/joOTC7z+dCXEuVKI01TICU0lEYo0wsr3oE+n0HUd43vGe8z0O9w+TDE3LcwIw8TMsAQL0xaCLM+RZdk/aGM7BqEHGcZuhomfo6prrNdrlNVaYtuo6/oJtONvJk5/2Li6dvDq6xwfvptw4wylyhFkJYyogCofC+yiGds5rS4VVJoIwbpU4HfONvYgThJ4vo8wiuSbB8KoMaHP51iFEVRZ7iUiWDAMQ1i2LYRFUUAVhRyQppSC7/tYrVaINpO7bTwHriMx9/MwkiSRnMYHyWzbRhAEktxHRsRxDMuyRAz3GoYhOVHoui6WyyXKsmw9vW2QkN2w5SeE7Nv1PJimKbLbCHcVci2F0EuSOo7z+GPnuYLneVKFXrSNNkLaxf1Uy5x4yAq8IfSEC3gV6SffGamiqiohatTKKW88NC1LLKMN4iErUDIV0gdOEM07KzeEzQ/9bMtU2Pw2THCy7art3pDtlhntTct/AYHKdZNNTiG4AAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/5d2071c2f494ad61978f230e6640431c/8ac56/s3-contents.webp 240w,
/static/5d2071c2f494ad61978f230e6640431c/d3be9/s3-contents.webp 480w,
/static/5d2071c2f494ad61978f230e6640431c/e46b2/s3-contents.webp 960w,
/static/5d2071c2f494ad61978f230e6640431c/f992d/s3-contents.webp 1440w,
/static/5d2071c2f494ad61978f230e6640431c/6c20f/s3-contents.webp 1878w&quot;
              sizes=&quot;(max-width: 960px) 100vw, 960px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/5d2071c2f494ad61978f230e6640431c/8ff5a/s3-contents.png 240w,
/static/5d2071c2f494ad61978f230e6640431c/e85cb/s3-contents.png 480w,
/static/5d2071c2f494ad61978f230e6640431c/d9199/s3-contents.png 960w,
/static/5d2071c2f494ad61978f230e6640431c/07a9c/s3-contents.png 1440w,
/static/5d2071c2f494ad61978f230e6640431c/3707e/s3-contents.png 1878w&quot;
            sizes=&quot;(max-width: 960px) 100vw, 960px&quot;
            type=&quot;image/png&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/5d2071c2f494ad61978f230e6640431c/d9199/s3-contents.png&quot;
            alt=&quot;s3 bucket contents&quot;
            title=&quot;s3 bucket contents&quot;
            loading=&quot;lazy&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;One you find the S3 bucket created in the AWS CloudFormation stack:&lt;/p&gt;
&lt;p&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/2c5687577f9d8e771102d31cda02673b/eb1d2/cloudformation-stack.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: 85%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAARCAYAAADdRIy+AAAACXBIWXMAABYlAAAWJQFJUiTwAAAC5ElEQVQ4y3WUCW/bOBCF/f9/WNEc3W3TTRM7h+UjvnTykHiJ+hakHQPdYgUMOKTHT08z73G23myYL144Hk845/DO5fUz/P+c/VHjfc5nSml03+cwxpx/8J4QwrUoh/d5fz271PkQzvkFdNYJQd20GXAYhgxqrCW9KOUZOASstfTDwGBMBkj7FOl/n3mKWVXVnE6nK6MEqnXPZvtBVddorZFKYZ3LawIYxzHX9kNPWVd4HxjDeAaUUlFWVd58Pn3f8/b6ynq1QogOrdT1vK4bTmWJFAofHTuxoelrSnVkjCOzxGK5LChWa5bFiqZpsCHyepS8lRppR5Qd8eOUXyqlREjJMBjC6OmdJsSQ82mamG23Hzz+emKxeOHpeZE/X/vI16LLsawHpAmEOCGEpO26DGoGgxsdH92aui8p1eHMMDEqVqvM7n1ZUNc1xkeeDorHveIoLS5Ewhj575MAwhiYJjK7zPD19Y1v3/7OWnyeL9jvdmgXuSk6blcdq8bQ9B43Tiilsl5Tm5jABsumLWj66vcefnzscnEKZy1+jFTaUfeOdvBnOhcGfwa/7WdpIDe399zd/8Xt3T3vyyUxjkghEF1H27bUTUOMU5ZTUkRqSxwjNhh2You2EmFa4hSZpU8oihVv70tWqzWDsYzTdNVfGkQaQrLXmWXq50jqaAJIUx58n9crYOrj4XDIjpFVxVAemd/d8OvrF5YP3xHbNbGr81r8/MFuMafb77HecFKHDKasOAMmKwkhMNYRtQQlsFpT7Ct2ZZv7OV2mmnSYNBisgUHju4pan9BOIY0gxsgsqT9Jp2k7qrcXgunpJ/h+MDwcBjado/dnyfSDoekErZB575sjx3aNsF2edGaotKZpWtpO0DUN5rinPx15fvjJ4mlO8rqW4nxFpQukKlGpZrfFDRLlVHaJ/3RKWVa56f3lCvPJ5EpSzJ9Zz5/YPP5Dt10zNhW+a9B1jSjLXOtGn72cnHK6OOVfGPQWGPoEGDsAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/2c5687577f9d8e771102d31cda02673b/8ac56/cloudformation-stack.webp 240w,
/static/2c5687577f9d8e771102d31cda02673b/d3be9/cloudformation-stack.webp 480w,
/static/2c5687577f9d8e771102d31cda02673b/e46b2/cloudformation-stack.webp 960w,
/static/2c5687577f9d8e771102d31cda02673b/f992d/cloudformation-stack.webp 1440w,
/static/2c5687577f9d8e771102d31cda02673b/b3a72/cloudformation-stack.webp 1622w&quot;
              sizes=&quot;(max-width: 960px) 100vw, 960px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/2c5687577f9d8e771102d31cda02673b/8ff5a/cloudformation-stack.png 240w,
/static/2c5687577f9d8e771102d31cda02673b/e85cb/cloudformation-stack.png 480w,
/static/2c5687577f9d8e771102d31cda02673b/d9199/cloudformation-stack.png 960w,
/static/2c5687577f9d8e771102d31cda02673b/07a9c/cloudformation-stack.png 1440w,
/static/2c5687577f9d8e771102d31cda02673b/eb1d2/cloudformation-stack.png 1622w&quot;
            sizes=&quot;(max-width: 960px) 100vw, 960px&quot;
            type=&quot;image/png&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/2c5687577f9d8e771102d31cda02673b/d9199/cloudformation-stack.png&quot;
            alt=&quot;cloudformation stack&quot;
            title=&quot;cloudformation stack&quot;
            loading=&quot;lazy&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Your website is now available under a URL similar to:&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;http://frontendstack-frontendbucketefe2e19c-ixsoxq891rl1.s3-website.eu-central-1.amazonaws.com/&lt;/code&gt;&lt;/p&gt;
&lt;h2 id=&quot;improve-performance-of-static-website-with-cloudfront&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#improve-performance-of-static-website-with-cloudfront&quot; aria-label=&quot;improve performance of static website with cloudfront permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Improve performance of static website with CloudFront&lt;/h2&gt;
&lt;p&gt;The website loads files directly from S3 bucket. The S3 bucket, by default, lives inside a single AWS Region,
which means that visitors from far away may suffer from subpar loading speeds.&lt;/p&gt;
&lt;p&gt;For production setup we can use AWS CloudFront CDN, which distributes our content across over 100 locations around the globe.
Using this solution with &lt;code class=&quot;language-text&quot;&gt;@aws-cdk/aws-s3-deployment&lt;/code&gt; is a piece of cake:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; distribution &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;cloudfront&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;CloudFrontWebDistribution&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Distribution&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  originConfigs&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    s3OriginSource&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      s3BucketSource&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; frontBucket
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    behaviors &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;isDefaultBehavior&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;cdk&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;CfnOutput&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;DistributionDomainName&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  value&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; distribution&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;domainName
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;s3deploy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;BucketDeployment&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;DeployWebsite&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  sources&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;s3deploy&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Source&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;asset&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
      path&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;__dirname&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;..&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;..&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;frontend&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;build&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  destinationBucket&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; frontBucket&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  distribution&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; distribution&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;After you update the stack with &lt;code class=&quot;language-text&quot;&gt;AWS_PROFILE=my-profile-name npm run cdk deploy&lt;/code&gt; you will find a new CloudFront distribution created.
Note that it make take few minutes to complete.
We added &lt;code class=&quot;language-text&quot;&gt;CfnOutput&lt;/code&gt; to make it easier to find the CloudFront distribution autogenerated domain name.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;log&quot;&gt;&lt;pre class=&quot;language-log&quot;&gt;&lt;code class=&quot;language-log&quot;&gt;Outputs:
FrontendStack.DistributionDomainName = d3a9wcc4fxw2d.cloudfront.net&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now the static website uses global content delivery network!&lt;/p&gt;
&lt;p&gt;You can find full example used in this post &lt;a href=&quot;https://github.com/miensol/miensol.github.io/tree/develop/content/posts/fast-static-website-with-aws-cdk&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;in the Github repository&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[How to convert an express app to AWS Lambda?]]></title><description><![CDATA[In this post we will see how to convert an existing express application to AWS Lambda. This can help reduce AWS bill even by an order of magnitude. We will also use cloudform to describe the CloudFormation stack.  An express app For our example to be complete we need an express application. Let’s use a single  file to…]]></description><link>undefined/how-to-convert-an-express-app-to-aws-lambda/</link><guid isPermaLink="false">undefined/how-to-convert-an-express-app-to-aws-lambda/</guid><pubDate>Tue, 29 May 2018 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;In this post we will see how to convert an existing &lt;a href=&quot;https://expressjs.com/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;express&lt;/a&gt; application to AWS Lambda. This can help reduce AWS bill even by an order of magnitude. We will also use &lt;a href=&quot;https://github.com/bright/cloudform&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;cloudform&lt;/a&gt; to describe the &lt;a href=&quot;https://aws.amazon.com/cloudformation/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;CloudFormation&lt;/a&gt; stack.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 465px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/46bc2ff2509d5263f6fb5067702578ae/51ce3/express-js.webp&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: 30.41666666666667%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/webp;base64,UklGRj4AAABXRUJQVlA4IDIAAAAQAwCdASoUAAYAPtFUo0uoJKMhsAgBABoJaQAAex/+iAAA/vILCdwCVLhodOVQAAAAAA==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/46bc2ff2509d5263f6fb5067702578ae/8ac56/express-js.webp 240w,
/static/46bc2ff2509d5263f6fb5067702578ae/51ce3/express-js.webp 465w&quot;
              sizes=&quot;(max-width: 465px) 100vw, 465px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/46bc2ff2509d5263f6fb5067702578ae/8ac56/express-js.webp 240w,
/static/46bc2ff2509d5263f6fb5067702578ae/51ce3/express-js.webp 465w&quot;
            sizes=&quot;(max-width: 465px) 100vw, 465px&quot;
            type=&quot;image/webp&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/46bc2ff2509d5263f6fb5067702578ae/51ce3/express-js.webp&quot;
            alt=&quot;lambda&quot;
            title=&quot;lambda&quot;
            loading=&quot;lazy&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;an-express-app&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#an-express-app&quot; aria-label=&quot;an express app permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;An express app&lt;/h2&gt;
&lt;p&gt;For our example to be complete we need an express application. Let’s use a single &lt;code class=&quot;language-text&quot;&gt;index.js&lt;/code&gt; file to define it:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; express &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;express&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;apiRoutes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; routes &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;express&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Router&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    routes&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;/v1/version&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;req&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; res&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; res&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;version&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;1&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    routes&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;/v1/echo&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;req&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; res&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; res&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;req&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;body&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; routes&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;


&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; app &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;express&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;express&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;apiRoutes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

app&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;listen&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Listening on 3000&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The above application has only 2 endpoints:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;GET /v1/version&lt;/code&gt; returns API version&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;POST /v1/echo&lt;/code&gt; sends back the request body&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We start the application as any other node app with &lt;code class=&quot;language-text&quot;&gt;node index.js&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;convert-the-express-app-to-aws-lambda&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#convert-the-express-app-to-aws-lambda&quot; aria-label=&quot;convert the express app to aws lambda permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Convert the express app to AWS Lambda&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-model-handler.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;The AWS Lambda Node.js&lt;/a&gt; runtime model differs from a simple &lt;code class=&quot;language-text&quot;&gt;node fileName.js&lt;/code&gt; invocation. For the AWS Lambda to invoke our application code we need to structure it appropriately. Thankfully the &lt;a href=&quot;https://github.com/awslabs/aws-serverless-express&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;aws-serverless-express&lt;/a&gt; module adapts express to AWS Lambda Node.js runtime model.&lt;/p&gt;
&lt;p&gt;Let’s adapt our &lt;code class=&quot;language-text&quot;&gt;index.js&lt;/code&gt; file to support &lt;code class=&quot;language-text&quot;&gt;aws-serverless-express&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; isInLambda &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;process&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;env&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;LAMBDA_TASK_ROOT&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;isInLambda&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; serverlessExpress &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;aws-serverless-express&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; server &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; serverlessExpress&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createServer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;app&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    exports&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;main&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;event&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; context&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; serverlessExpress&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;proxy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;server&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; event&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; context&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    app&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;listen&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Listening on 3000&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;main&lt;/code&gt; function is called by the AWS Lambda Node.js runtime. Note that we’ve used &lt;a href=&quot;https://docs.aws.amazon.com/lambda/latest/dg/current-supported-versions.html#lambda-environment-variables&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;LAMBDA_TASK_ROOT&lt;/code&gt;&lt;/a&gt; environment variable to detect if the app is running inside AWS Lambda. It is better to split the express application setup and &lt;code class=&quot;language-text&quot;&gt;listen&lt;/code&gt; call into separate files and use 2 different &lt;em&gt;main&lt;/em&gt; files e.g. &lt;code class=&quot;language-text&quot;&gt;development.js&lt;/code&gt; calling &lt;code class=&quot;language-text&quot;&gt;listen(port)&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;lambda.js&lt;/code&gt; using &lt;code class=&quot;language-text&quot;&gt;aws-serverless-express&lt;/code&gt;. However, this would complicate our example unnecessarily.&lt;/p&gt;
&lt;h2 id=&quot;deploy-the-express-app-to-aws-lambda&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#deploy-the-express-app-to-aws-lambda&quot; aria-label=&quot;deploy the express app to aws lambda permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Deploy the express app to AWS Lambda&lt;/h2&gt;
&lt;p&gt;I already showed &lt;a href=&quot;/deploy-lambda-with-cloudformation&quot;&gt;how we can deploy lambda with cloudform&lt;/a&gt;. We will use the previous example as a base:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; cloudform&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Lambda&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;IAM&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Fn&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ApiGateway&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Refs&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;cloudform&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; FunctionProperties &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;cloudform/types/lambda/function&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; readFileSync &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;fs&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt;
    LambdaExecutionRole &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;LambdaExecutionRole&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    ExpressMain &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;ExpressMain&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    RestApi &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;RestApi&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    RestApiMainResource &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;RestApiMainResource&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    PackageKey &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;PackageKey&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    RestApiDeployment &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;RestApiDeployment&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    RestApiMethod &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;RestApiMethod&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;cloudform&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    Parameters&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        PackageKey&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            Type&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;String&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            Default&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;express-lambda.zip&apos;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    Resources&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;ExpressMain&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Lambda&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            Code&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; S3Bucket&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;bright-tmp&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; S3Key&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Fn&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Ref&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;PackageKey&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            Handler&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;index.main&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            Role&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Fn&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;GetAtt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;LambdaExecutionRole&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Arn&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            Runtime&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;nodejs6.10&quot;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;LambdaExecutionRole&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token constant&quot;&gt;IAM&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Role&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            AssumeRolePolicyDocument&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                Statement&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                    Effect&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Allow&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                    Principal&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Service&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;lambda.amazonaws.com&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                    Action&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;sts:AssumeRole&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            ManagedPolicyArns&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        PermissionToInvokeLambda&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Lambda&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Permission&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            Action&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;lambda:InvokeFunction&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            FunctionName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Fn&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;GetAtt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ExpressMain&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Arn&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            Principal&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;apigateway.amazonaws.com&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            SourceArn&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Fn&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Join&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
                &lt;span class=&quot;token string&quot;&gt;&apos;arn:aws:execute-api:&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Refs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Region&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;:&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Refs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;AccountId&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;:&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Fn&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Ref&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;RestApi&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;/*&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Rest Api Gateway see below&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;For the AWS Lambda function source we use a zip file hosted in a S3 Bucket named &lt;code class=&quot;language-text&quot;&gt;packages&lt;/code&gt; at key specified in the template parameter &lt;code class=&quot;language-text&quot;&gt;PackageKey&lt;/code&gt;. The package zip file must contain all application source code including &lt;code class=&quot;language-text&quot;&gt;node_modules&lt;/code&gt;. We also define &lt;code class=&quot;language-text&quot;&gt;PermissionToInvokeLambda&lt;/code&gt; so that API Gateway can invoke the lambda function.&lt;/p&gt;
&lt;h2 id=&quot;add-api-gateway-to-call-aws-lambda&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#add-api-gateway-to-call-aws-lambda&quot; aria-label=&quot;add api gateway to call aws lambda permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Add API Gateway to call AWS Lambda&lt;/h2&gt;
&lt;p&gt;To be able to invoke the AWS Lambda function using HTTP protocol we will use &lt;a href=&quot;https://aws.amazon.com/api-gateway/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;API Gateway&lt;/a&gt;. There are multiple ways of setting up the API gateway but we will use an appoach that is simplest in my opinion.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;RestApi&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ApiGateway&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;RestApi&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Express API&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;RestApiMainResource&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ApiGateway&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Resource&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    RestApiId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Fn&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Ref&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;RestApi&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    ParentId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Fn&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;GetAtt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;RestApi&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;RootResourceId&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    PathPart&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;{proxy+}&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;RestApiMethod&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ApiGateway&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Method&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    HttpMethod&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;ANY&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    ResourceId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Fn&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Ref&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;RestApiMainResource&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    RestApiId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Fn&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Ref&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;RestApi&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    AuthorizationType&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;NONE&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    Integration&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        Type&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;AWS_PROXY&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        IntegrationHttpMethod&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;POST&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        Uri&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Fn&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Sub&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${ExpressMain.Arn}/invocations&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;RestApiDeployment&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ApiGateway&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Deployment&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    RestApiId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Fn&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Ref&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;RestApi&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    StageName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;test&apos;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We first define a &lt;a href=&quot;https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigateway-restapi.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;RestApi&lt;/code&gt;&lt;/a&gt; which is a collection of resources with various configuration options describing the API. Next is the &lt;a href=&quot;https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigateway-resource.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;RestApiMainResource&lt;/code&gt;&lt;/a&gt; which depicts a single REST resource. However, in our case we use wildcard &lt;code class=&quot;language-text&quot;&gt;PathPart&lt;/code&gt; to match &lt;strong&gt;all&lt;/strong&gt; paths. This way we can have a single resource encompassing all API endpoints. For the &lt;code class=&quot;language-text&quot;&gt;RestApiMainResource&lt;/code&gt; we also need to define a single &lt;a href=&quot;https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigateway-method.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;RestApiMethod&lt;/code&gt;&lt;/a&gt;. Note that the &lt;code class=&quot;language-text&quot;&gt;HttpMethod&lt;/code&gt; is set to &lt;code class=&quot;language-text&quot;&gt;ANY&lt;/code&gt; which matches all verbs. The &lt;code class=&quot;language-text&quot;&gt;Integration&lt;/code&gt; specifies that we would like to proxy requests to the &lt;code class=&quot;language-text&quot;&gt;ExpressMain&lt;/code&gt; AWS Lambda function. Last but not least we define a &lt;a href=&quot;https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigateway-deployment.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;RestApiDeployment&lt;/code&gt;&lt;/a&gt; so that we have an URL to call the API.&lt;/p&gt;
&lt;p&gt;It is handy to define &lt;code class=&quot;language-text&quot;&gt;Outputs&lt;/code&gt; in our template so that we can easily access the API url:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;Outputs&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    RestApiUrl&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        Value&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Fn&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Join&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Fn&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Ref&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;RestApi&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;.execute-api.&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Refs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Region&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;.amazonaws.com/test&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;test-api-gateway-calling-aws-lambda&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#test-api-gateway-calling-aws-lambda&quot; aria-label=&quot;test api gateway calling aws lambda permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Test API Gateway calling AWS Lambda&lt;/h2&gt;
&lt;p&gt;With our cloudform template deployed with a single command:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;aws cloudformation update-stack &lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;
  --stack-name lambda-example &lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;
  --capabilities CAPABILITY_IAM &lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;
  --template-body file://&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;./node_modules/.bin/cloudform aws-template.ts&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We can also fetch the API url:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token assign-left variable&quot;&gt;API_URL&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$(&lt;/span&gt;aws cloudformation describe-stacks &lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;
  --stack-name lambda-example &lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;
  --query &lt;span class=&quot;token string&quot;&gt;&apos;Stacks[0].Outputs[?OutputKey==&lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;`&lt;/span&gt;RestApiUrl&lt;span class=&quot;token variable&quot;&gt;`&lt;/span&gt;&lt;/span&gt;].OutputValue&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;
  --output text&lt;span class=&quot;token variable&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Finally, with the help of &lt;a href=&quot;https://httpie.org/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;httpie&lt;/code&gt;&lt;/a&gt; we can test our API:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; http https://&lt;span class=&quot;token variable&quot;&gt;${API_URL}&lt;/span&gt;/v1/version

HTTP/1.1 &lt;span class=&quot;token number&quot;&gt;200&lt;/span&gt; OK
Connection: keep-alive
Content-Length: &lt;span class=&quot;token number&quot;&gt;15&lt;/span&gt;
Content-Type: application/json&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;charset&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;utf-8
Date: Mon, &lt;span class=&quot;token number&quot;&gt;28&lt;/span&gt; May &lt;span class=&quot;token number&quot;&gt;2018&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;19&lt;/span&gt;:58:13 GMT
Via: &lt;span class=&quot;token number&quot;&gt;1.1&lt;/span&gt; XXXXXXXXXXXXX.cloudfront.net &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;CloudFront&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
X-Amz-Cf-Id: &lt;span class=&quot;token assign-left variable&quot;&gt;XXXXXXXXXXXXX&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt;
X-Amzn-Trace-Id: &lt;span class=&quot;token assign-left variable&quot;&gt;Root&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;-5b0c5f54-806e190d437c7d31a4a0d4ba
X-Cache: Miss from cloudfront
etag: W/&lt;span class=&quot;token string&quot;&gt;&quot;f-sHigu4BMVa0IJ0LR3NDJ5y8l4sc&quot;&lt;/span&gt;
x-amz-apigw-id: HnPVQH4yjoEF8-w&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
x-amzn-Remapped-connection: close
x-amzn-Remapped-content-length: &lt;span class=&quot;token number&quot;&gt;15&lt;/span&gt;
x-amzn-Remapped-date: Mon, &lt;span class=&quot;token number&quot;&gt;28&lt;/span&gt; May &lt;span class=&quot;token number&quot;&gt;2018&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;19&lt;/span&gt;:58:13 GMT
x-amzn-RequestId: 73eff8a6-62b1-11e8-907c-79117668835e
x-powered-by: Express

&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&quot;version&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;1&quot;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And a &lt;code class=&quot;language-text&quot;&gt;POST&lt;/code&gt; to the echo endpoint:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;http https://&lt;span class=&quot;token variable&quot;&gt;${API_URL}&lt;/span&gt;/v1/echo &lt;span class=&quot;token assign-left variable&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Hello 👋 My name is Piotr&quot;&lt;/span&gt;

HTTP/1.1 &lt;span class=&quot;token number&quot;&gt;200&lt;/span&gt; OK
Connection: keep-alive
Content-Length: &lt;span class=&quot;token number&quot;&gt;41&lt;/span&gt;
Content-Type: application/json&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;charset&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;utf-8
Date: Mon, &lt;span class=&quot;token number&quot;&gt;28&lt;/span&gt; May &lt;span class=&quot;token number&quot;&gt;2018&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;20&lt;/span&gt;:00:31 GMT
Via: &lt;span class=&quot;token number&quot;&gt;1.1&lt;/span&gt; XXXXXXXXXXXXX.cloudfront.net &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;CloudFront&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
X-Amz-Cf-Id: &lt;span class=&quot;token assign-left variable&quot;&gt;XXXXXXXXXXXXX&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt;
X-Amzn-Trace-Id: &lt;span class=&quot;token assign-left variable&quot;&gt;Root&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;-5b0c5fdf-802178cceb5160684ef2cc34
X-Cache: Miss from cloudfront
etag: W/&lt;span class=&quot;token string&quot;&gt;&quot;29-SKqhJThIfjmVId6IIeTilD7Mkk0&quot;&lt;/span&gt;
x-amz-apigw-id: &lt;span class=&quot;token assign-left variable&quot;&gt;HnPq5HeJjoEFuRQ&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
x-amzn-Remapped-connection: close
x-amzn-Remapped-content-length: &lt;span class=&quot;token number&quot;&gt;41&lt;/span&gt;
x-amzn-Remapped-date: Mon, &lt;span class=&quot;token number&quot;&gt;28&lt;/span&gt; May &lt;span class=&quot;token number&quot;&gt;2018&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;20&lt;/span&gt;:00:31 GMT
x-amzn-RequestId: c67b41c0-62b1-11e8-a23f-c7cbebde15f2
x-powered-by: Express

&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&quot;message&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Hello 👋 My name is Piotr&quot;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;reduced-infrastructure-cost&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#reduced-infrastructure-cost&quot; aria-label=&quot;reduced infrastructure cost permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Reduced infrastructure cost&lt;/h2&gt;
&lt;p&gt;With the above setup we no longer have to pay for an always running EC2 instance. Our monthly bill depends on the number of requests that are executed against the exposed API. More than that, we get much better scalability characteristics, especially when we have nonlinear request rates.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[TypeScript tips from Kotlin developer - const]]></title><description><![CDATA[Nowadays I mostly code in Kotlin programming language. I got interested in it when I started working on a Java 7 codebase and quickly got fed up with the language. At Bright Inventions we often use TypeScript for both back-end, front-end and mobile development so I thought I would share some thoughts and tips for…]]></description><link>undefined/typescript-tips-from-kotlin-developer-const/</link><guid isPermaLink="false">undefined/typescript-tips-from-kotlin-developer-const/</guid><pubDate>Wed, 11 Apr 2018 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Nowadays I mostly code in &lt;a href=&quot;https://kotlinlang.org/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Kotlin programming language&lt;/a&gt;. I got interested in it when I started working on a Java 7 codebase and quickly got fed up with the language. At &lt;a href=&quot;https://brightinventions.pl&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Bright Inventions&lt;/a&gt; we often use TypeScript for both back-end, front-end and mobile development so I thought I would share some thoughts and tips for TypeScript learned while using Kotlin. In particular this post is about constant variables.&lt;/p&gt;
&lt;h2 id=&quot;use-const-whenever-possible&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#use-const-whenever-possible&quot; aria-label=&quot;use const whenever possible permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Use &lt;code class=&quot;language-text&quot;&gt;const&lt;/code&gt; whenever possible&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://hackernoon.com/5-benefits-of-immutable-objects-worth-considering-for-your-next-project-f98e7e85b6ac&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Using immutable variables&lt;/a&gt; aids reasoning about the flow and state of a program. It helps compiler to provide more intelligent hints especially while dealing with nullable types.&lt;/p&gt;
&lt;p&gt;In Kotlin a &lt;code class=&quot;language-text&quot;&gt;val&lt;/code&gt; keyword denotes a variable which value does not change after initialization e.g.:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;kotlin&quot;&gt;&lt;pre class=&quot;language-kotlin&quot;&gt;&lt;code class=&quot;language-kotlin&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; x&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Int
&lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; y &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;
x &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;
x &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;20&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Error: Val cannot be reassigned&lt;/span&gt;
y &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;30&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Error: Val cannot be reassigned&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In &lt;a href=&quot;https://www.typescriptlang.org/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;TypeScript&lt;/a&gt; such a situation is handled with &lt;code class=&quot;language-text&quot;&gt;const&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; x&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Error: &apos;const&apos; declarations must be initialized&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; y&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;

y &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;30&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Error: Cannot assign to &apos;y&apos; because it is constant or read-only property&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;compilers-love-const&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#compilers-love-const&quot; aria-label=&quot;compilers love const permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Compilers love &lt;code class=&quot;language-text&quot;&gt;const&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;The first way in which the compiler gets smarter when we use &lt;code class=&quot;language-text&quot;&gt;const&lt;/code&gt; are null checks. When you enable &lt;a href=&quot;https://www.typescriptlang.org/docs/handbook/compiler-options.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;strictNullChecks&lt;/code&gt;&lt;/a&gt;, which you should, both Kotlin and TypeScript compiler understand if something can or cannot be null.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; firstName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getFirstName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; lastName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getLastName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;firstName &lt;span class=&quot;token operator&quot;&gt;!==&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; lastName &lt;span class=&quot;token operator&quot;&gt;!==&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;setTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;firstName&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;lastName&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Error: Object is possibly &apos;null&apos;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In the first 2 lines we declare &lt;code class=&quot;language-text&quot;&gt;firstName&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;lastName&lt;/code&gt; as holding &lt;code class=&quot;language-text&quot;&gt;string&lt;/code&gt; or &lt;code class=&quot;language-text&quot;&gt;null&lt;/code&gt;. The variables are initialized with the helper functions &lt;code class=&quot;language-text&quot;&gt;getFirstName&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;getLastName&lt;/code&gt;. After we check that &lt;code class=&quot;language-text&quot;&gt;firstName&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;lastName&lt;/code&gt; are &lt;strong&gt;definitely not null&lt;/strong&gt; we fire some async function. We can safely use &lt;code class=&quot;language-text&quot;&gt;firstName.length&lt;/code&gt;. However, when we use &lt;code class=&quot;language-text&quot;&gt;lastName.length&lt;/code&gt; the compiler complains with &lt;code class=&quot;language-text&quot;&gt;Object is possibly &amp;#39;null&amp;#39;&lt;/code&gt; error. This is because it is possible that in between the null check and the &lt;code class=&quot;language-text&quot;&gt;console.log&lt;/code&gt; statement &lt;em&gt;something&lt;/em&gt; could change the &lt;code class=&quot;language-text&quot;&gt;lastName&lt;/code&gt; value. We might know that this is not true just by looking at the code. The compiler however, cannot be 100% sure in all cases. Thankfully we have &lt;code class=&quot;language-text&quot;&gt;const&lt;/code&gt; and we can share our knowledge with the compiler.&lt;/p&gt;
&lt;h2 id=&quot;compilers-catch-bugs-with-const&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#compilers-catch-bugs-with-const&quot; aria-label=&quot;compilers catch bugs with const permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Compilers catch bugs with &lt;code class=&quot;language-text&quot;&gt;const&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Because &lt;code class=&quot;language-text&quot;&gt;const&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;val&lt;/code&gt; can only be assigned once, compilers can prevent another class of bugs. Take a look at the code example blow. There is a bug 🐛 that could easily be avoided had we used &lt;code class=&quot;language-text&quot;&gt;const&lt;/code&gt; instead of &lt;code class=&quot;language-text&quot;&gt;let&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; firstName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; person&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;firstName
&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; lastName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; person&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;lastName

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; parsed &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;parseFormData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;data&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; first&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; last&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; parts &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos; &apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    lastName &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; parts&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    firstName &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; parts&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; firstName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; first&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; lastName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; last &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;parsed&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;firstName &lt;span class=&quot;token operator&quot;&gt;!==&lt;/span&gt; firstName &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; parsed&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;lastName &lt;span class=&quot;token operator&quot;&gt;!==&lt;/span&gt; lastName&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
    &lt;span class=&quot;token comment&quot;&gt;// submit changes&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You may have spotted the bug. Chances are though, especially if you are like me, that after long hours when the coffee level in your blood drops substantially below the required level, it will take long minutes to figure out the cause. There is a very easy remedy though. With &lt;code class=&quot;language-text&quot;&gt;firstName&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;lastName&lt;/code&gt; declared as constant variables the compiler catches bugs for us:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;lastName &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; parts&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Error: Cannot assign &apos;lastName&apos; because it is a constant or a read-only property&lt;/span&gt;
firstName &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; parts&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Error: Cannot assign &apos;firstName&apos; because it is a constant or a read-only property&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content:encoded></item><item><title><![CDATA[How to deploy Lambda function with CloudFormation?]]></title><description><![CDATA[Serverless deployments are popular these days. With a minimal cost you can have your own code wait and respond to various events. AWS Lambda, Azure Functions are just 2 examples of serverless offering from the biggest cloud providers. For a long time I had thought about them only in the context of ad-hoc setups not…]]></description><link>undefined/deploy-lambda-with-cloudformation/</link><guid isPermaLink="false">undefined/deploy-lambda-with-cloudformation/</guid><pubDate>Sun, 11 Mar 2018 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Serverless deployments are popular these days. With a minimal cost you can have your own code wait and respond to various events. AWS Lambda, Azure Functions are just 2 examples of serverless offering from the biggest cloud providers. For a long time I had thought about them only in the context of ad-hoc setups not suitable for a long term development. This was until I found out that you can, with a little effort, version and deploy the serverless API just as a traditional back-end. In this post I am going to show how to deploy AWS Lambda functions with the help of the tool &lt;a href=&quot;https://adambar.pl/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Adam&lt;/a&gt; created at &lt;a href=&quot;https://brightinventions.pl/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Bright Inventions&lt;/a&gt; called &lt;a href=&quot;https://github.com/bright/cloudform&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;cloudform&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;..//images/lambda/lambda.png&quot; alt=&quot;Lambda function&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;step-1-define-a-template&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#step-1-define-a-template&quot; aria-label=&quot;step 1 define a template permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Step 1: Define a template&lt;/h2&gt;
&lt;p&gt;Let’s install the &lt;a href=&quot;https://github.com/bright/cloudform&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;cloudform&lt;/a&gt; &lt;code class=&quot;language-text&quot;&gt;npm i --save-dev cloudform&lt;/code&gt; and define a minimal template:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; cloudform&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Lambda&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;IAM&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Fn &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;cloudform&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; LambdaExecutionRole &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;LambdaExecutionRole&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;cloudform&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    Resources&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        HelloWorld&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Lambda&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            Code&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                ZipFile&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;exports.wrtiteToConsole = function (event, context, callback){ console.log(&apos;Hello&apos;); callback(null); }&quot;&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            Handler&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;index.wrtiteToConsole&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            Role&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Fn&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;GetAtt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;LambdaExecutionRole&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Arn&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            Runtime&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;nodejs6.10&quot;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;LambdaExecutionRole&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token constant&quot;&gt;IAM&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Role&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            AssumeRolePolicyDocument&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                Statement&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                    Effect&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Allow&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                    Principal&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Service&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;lambda.amazonaws.com&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                    Action&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;sts:AssumeRole&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            Path&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;/&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            ManagedPolicyArns&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;There are only 2 resources defined in the template.  &lt;code class=&quot;language-text&quot;&gt;HelloWorld&lt;/code&gt; is the AWS Lambda function definition. We have set the &lt;code class=&quot;language-text&quot;&gt;Runtime&lt;/code&gt; property to use &lt;code class=&quot;language-text&quot;&gt;nodejs6.10&lt;/code&gt; hence the &lt;code class=&quot;language-text&quot;&gt;Code.ZipFile&lt;/code&gt; contains a JavaScript code. Despite the name &lt;a href=&quot;https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lambda-function-code.html#cfn-lambda-function-code-zipfile&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;ZipFile&lt;/code&gt;&lt;/a&gt; should contain application source code in plain text. Obviously the &lt;a href=&quot;https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lambda-function-code.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;ZipFile&lt;/code&gt;&lt;/a&gt; may only be used for the most simple functions. The &lt;code class=&quot;language-text&quot;&gt;S3Bucket&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;S3Key&lt;/code&gt; properties can be used to deploy a more involved function implementation. The &lt;code class=&quot;language-text&quot;&gt;Handler&lt;/code&gt; defines which function from &lt;code class=&quot;language-text&quot;&gt;Code&lt;/code&gt; the Lambda runtime should invoke. In case of &lt;code class=&quot;language-text&quot;&gt;ZipFile&lt;/code&gt; the first part is always &lt;code class=&quot;language-text&quot;&gt;index&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;Role&lt;/code&gt; is a required setting for every AWS Lambda function. It defines what entitlements the code invoked by the Lambda runtime has. In the above template we define a policy which can be assumed by &lt;code class=&quot;language-text&quot;&gt;lambda.amazonaws.com&lt;/code&gt; and references a pre-defined AWS managed policy &lt;a href=&quot;https://docs.aws.amazon.com/lambda/latest/dg/intro-permission-model.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;AWSLambdaBasicExecutionRole&lt;/code&gt;&lt;/a&gt;. The &lt;code class=&quot;language-text&quot;&gt;AWSLambdaBasicExecutionRole&lt;/code&gt; makes it possible for the Lambda function logs to be pushed to Cloud Watch.&lt;/p&gt;
&lt;h2 id=&quot;step-2-create-the-aws-lambda-function&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#step-2-create-the-aws-lambda-function&quot; aria-label=&quot;step 2 create the aws lambda function permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Step 2: Create the AWS Lambda function&lt;/h2&gt;
&lt;p&gt;Deploying our Lambda function using CloudFormation requires a single command:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;aws cloudformation create-stack &lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;
    --capabilities CAPABILITY_IAM &lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;
    --stack-name lambda-example &lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;
    --template-body file://&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;node_modules/.bin/cloudform aws-template.ts&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;--capabilities CAPABILITY_IAM&lt;/code&gt; is required whenever the CloudFormation has to define Roles, Policies or related resources. The &lt;code class=&quot;language-text&quot;&gt;--template-body file://&amp;lt;(node_modules/.bin/cloudform aws-template.ts)&lt;/code&gt; instructs CloudFormation to use a template defined in a file. The &lt;code class=&quot;language-text&quot;&gt;&amp;lt;(...)&lt;/code&gt; is &lt;a href=&quot;https://superuser.com/questions/1059781/what-exactly-is-in-bash-and-in-zsh&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;bash and zsh way to pass an output of a command&lt;/a&gt; to other program as if the output was a file. After waiting a bit for the invocation to complete we will see the following in the AWS Console:&lt;/p&gt;
&lt;p&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/db231600f8b624947a1b37ee4784ae95/ca3c3/aws-console.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: 78.33333333333333%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAQCAYAAAAWGF8bAAAACXBIWXMAABYlAAAWJQFJUiTwAAACmklEQVQ4y4VUyZKkNhDlk/1HvvonfPLJPjh6HDG9uaq7qCoaAZKQEJIQAt5EZtE9y2EmI15IKFO5PlF8vn/A/cMjHp+ecffpPzw8PsFYi/PlivJyge4NqrcatWh4r/oeUmv01sKNI7qug1AG/V+/o//jNxRSKfx/OEA0DUIIGL1HjBHTNH0gvu9jZF2c4nc2rA8jgjMovA9QSrMzkmVZeJ+mhDll5HlHmpFXYFmBdVmxrRvWZbvZkG5ekFJGobRGeb5ANC1HWtcVhkrTPXLKWNJyWxegLQ94fTniWHV4PlU4XASMn7HOC5aUMU8zCipxcCNGH+C8R84Zgx2wkNG3yBtkK3D3+R5//n2HT4cz7ssamhzmmw0FLvq+R9t2nBnJtm2wxiLF9AMmSL/gqCOexICjntD4DO0i5pgwxYQY4s2hlArjOHJ25NA5h8E6KKnRa/MBOsvTzNlMIeLx9O9t8kqhaVp0nURh7QAhBDopeSDkkIbAJezrt+B+7quUElr30NrAmoEDFsPguOSUEt5lyZkv/Aq9MhB1g66V8M7DjwEFkbjvDewwwHuPECOMsUxYKuFnoFKJcpTlOHrmcFELgcPxBa+nExrVs0PiYdhJzN8x7OtXxN3Ok20IH98FKTmzEDDvQ6FeEuY58/R/BOtyxrpt3KL3MxpqQRHeasFv9eZk/uglDYoITxfImECS0ozztULdKRBLMrF+lyJyzwwraOLUU6bNMKA39GI0nBtBw6NzqoYoZq3d7xkMzvHESV/QH6PtOpyubzifzyjLEtfrlalUnl7Rtg0GZzH6mzM/jozAbdrhA5qm4aQKjmQtpHGoqoqjOjegqlv886xxOHV4OdZ4LQWEVKilglAaVdvh2lq8NQpVe0XT3hx+Af0EydywnS8HAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/db231600f8b624947a1b37ee4784ae95/8ac56/aws-console.webp 240w,
/static/db231600f8b624947a1b37ee4784ae95/d3be9/aws-console.webp 480w,
/static/db231600f8b624947a1b37ee4784ae95/e46b2/aws-console.webp 960w,
/static/db231600f8b624947a1b37ee4784ae95/f992d/aws-console.webp 1440w,
/static/db231600f8b624947a1b37ee4784ae95/62ac3/aws-console.webp 1850w&quot;
              sizes=&quot;(max-width: 960px) 100vw, 960px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/db231600f8b624947a1b37ee4784ae95/8ff5a/aws-console.png 240w,
/static/db231600f8b624947a1b37ee4784ae95/e85cb/aws-console.png 480w,
/static/db231600f8b624947a1b37ee4784ae95/d9199/aws-console.png 960w,
/static/db231600f8b624947a1b37ee4784ae95/07a9c/aws-console.png 1440w,
/static/db231600f8b624947a1b37ee4784ae95/ca3c3/aws-console.png 1850w&quot;
            sizes=&quot;(max-width: 960px) 100vw, 960px&quot;
            type=&quot;image/png&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/db231600f8b624947a1b37ee4784ae95/d9199/aws-console.png&quot;
            alt=&quot;AWS Lambda Screen&quot;
            title=&quot;AWS Lambda Screen&quot;
            loading=&quot;lazy&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;It is possible to use the AWS Console editor to test and change the function. However, if we are to treat the serverless approach seriously we should not forget about the standard practices like versioning of our source code.&lt;/p&gt;
&lt;h2 id=&quot;step-3-update-and-version-aws-lambda-function&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#step-3-update-and-version-aws-lambda-function&quot; aria-label=&quot;step 3 update and version aws lambda function permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Step 3: Update and version AWS Lambda function&lt;/h2&gt;
&lt;p&gt;Since we have defined the AWS Lambda function using a cloudform template we can version it as any other code. The whole serverless infrastructure we use and configure is treated as a source code allowing for an easy replication of deployment environments, audit trail and change management. Let’s see how we can use cloudform to add another function that will be called by the first one.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; cloudform&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Lambda&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;IAM&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Fn &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;cloudform&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; FunctionProperties &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;cloudform/types/lambda/function&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; readFileSync &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;fs&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt;
    LambdaExecutionRole &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;LambdaExecutionRole&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    Alice &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Alice&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    Bob &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Bob&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;lambdaFunction&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    functionCode&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    options&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Partial&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;FunctionProperties&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Lambda&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        Code&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; ZipFile&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; functionCode &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        Handler&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;index.main&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        Role&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Fn&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;GetAtt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;LambdaExecutionRole&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Arn&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        Runtime&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;nodejs6.10&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;options
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;cloudform&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    Resources&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Alice&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;lambdaFunction&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;readFileSync&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Alice.js&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;utf-8&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            Environment&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                Variables&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                    BobFunction&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Fn&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;GetAtt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Bob&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Arn&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Bob&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;lambdaFunction&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;readFileSync&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Bob.js&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;utf-8&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// LambdaExecutionRole see below&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;As you can see above, we’ve extracted a function &lt;code class=&quot;language-text&quot;&gt;lambdaFunction&lt;/code&gt; to simplify Lambda function declaration. Both &lt;code class=&quot;language-text&quot;&gt;Alice&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;Bob&lt;/code&gt; function’s bodies are defined in separate files. Interestingly  &lt;code class=&quot;language-text&quot;&gt;Alice&lt;/code&gt; function, during the invocation, will have access to &lt;code class=&quot;language-text&quot;&gt;BobFunction&lt;/code&gt; environment variable pointing to &lt;code class=&quot;language-text&quot;&gt;Bob&lt;/code&gt; function &lt;a href=&quot;https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;ARN&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Our &lt;code class=&quot;language-text&quot;&gt;LambdaExecutionRole&lt;/code&gt; lacks a permission to invoke another Lambda function. Let’s fix that:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;    &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;LambdaExecutionRole&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token constant&quot;&gt;IAM&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Role&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        AssumeRolePolicyDocument&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            Statement&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                Effect&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Allow&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                Principal&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Service&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;lambda.amazonaws.com&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                Action&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;sts:AssumeRole&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        Path&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;/&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        ManagedPolicyArns&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        Policies&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            PolicyName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;AllowCallingOtherLambda&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            PolicyDocument&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                Version&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;2012-10-17&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                Statement&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                    Sid&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;InvokeLambdaPermission&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                    Effect&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Allow&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                    Action&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;lambda:InvokeFunction&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                    Resource&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;*&quot;&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;Alice&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;Bob&lt;/code&gt; sources export &lt;code class=&quot;language-text&quot;&gt;main&lt;/code&gt; functions invoked by AWS Lambda runtime:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Alice.ts&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; aws &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;aws-sdk&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;event&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; context&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; callback&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;aws&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Lambda&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;invoke&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        FunctionName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; process&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;env&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;BobFunction&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        Payload&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;stringify&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;message&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Hi!. I&apos;m Alice.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Error&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; data&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; response &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;parse&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Payload&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;FromBob&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; error &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; response&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;callback&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Bob.ts&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;event&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; context&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; callback&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;FromAlice&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; event&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;callback&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;message&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Hi! I&apos;m Bob. Nice to meet you!&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Since we now use TypeScript for &lt;code class=&quot;language-text&quot;&gt;Alice&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;Bob&lt;/code&gt; source we need to install the compiler &lt;code class=&quot;language-text&quot;&gt;npm i --save-dev typescript @types/node aws-sdk&lt;/code&gt;. Unfortunately currently in &lt;a href=&quot;https://github.com/bright/cloudform&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;cloudform&lt;/a&gt; it is not possible to use custom &lt;code class=&quot;language-text&quot;&gt;tsconfig.json&lt;/code&gt; for the compilation. Fortunately we can invoke the compiler manually and use its outputs as any other Node.js source code. With a &lt;code class=&quot;language-text&quot;&gt;tsconfig.json&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;compilerOptions&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;module&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;commonjs&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;target&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;es6&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;strict&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
    &lt;span class=&quot;token property&quot;&gt;&quot;strictPropertyInitialization&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;esModuleInterop&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;exclude&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;node_modules&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;compileOnSave&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;we can use the following commands to compile and deploy Lambda functions:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;./node_modules/.bin/tsc

aws cloudformation update-stack &lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;
    --capabilities CAPABILITY_IAM &lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;
    --stack-name lambda-example &lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;
    --template-body file://&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;node -e &lt;span class=&quot;token string&quot;&gt;&quot;console.log&lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;((&lt;/span&gt;require&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&apos;.&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;aws&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;template&apos;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;.default&lt;span class=&quot;token punctuation&quot;&gt;))&lt;/span&gt;&lt;/span&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;After the stack update completes we now should have 2 Lambda functions available. When we invoke the &lt;code class=&quot;language-text&quot;&gt;Alice&lt;/code&gt; function, we’ll see that the 2 AWS Lambda functions communicate:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;START RequestId: 6a87c764-251e-11e8-b921-f9ca7649c7d7 Version: $LATEST
2018-03-11T11:22:00.615Z	6a87c764-251e-11e8-b921-f9ca7649c7d7	Alice says: Hi!. I&amp;#39;m Alice.
2018-03-11T11:22:01.676Z	6a87c764-251e-11e8-b921-f9ca7649c7d7	Bob says: Hi! I&amp;#39;m Bob. Nice to meet you!
END RequestId: 6a87c764-251e-11e8-b921-f9ca7649c7d7
REPORT RequestId: 6a87c764-251e-11e8-b921-f9ca7649c7d7	Duration: 1110.68 ms	Billed Duration: 1200 ms 	Memory Size: 128 MB	Max Memory Used: 34 MB	&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Serverless infrastructure offers endless possibilities. With &lt;a href=&quot;https://github.com/bright/cloudform&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;cloudform&lt;/a&gt; we can take AWS Lambda development, change management and deployment to the next level.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[How to call a load balanced ECS service?]]></title><description><![CDATA[A service running ECS can call plethora of AWS APIs. It can read messages from queues, publish messages to SNS topics, query a database. These are all valid ways to communicate with the service. However, often the most appropriate way is to call the service by an HTTP API. In this post I’ll describe how to configure an…]]></description><link>undefined/how-to-call-a-load-balanced-ecs-service/</link><guid isPermaLink="false">undefined/how-to-call-a-load-balanced-ecs-service/</guid><pubDate>Tue, 06 Mar 2018 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;A service running &lt;a href=&quot;https://aws.amazon.com/ecs/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;ECS&lt;/a&gt; can call plethora of AWS APIs. It can read messages from queues, publish messages to &lt;a href=&quot;https://aws.amazon.com/sns/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;SNS&lt;/a&gt; topics, query a database. These are all valid ways to communicate with the service. However, often the most appropriate way is to call the service by an HTTP API. In this post I’ll describe how to configure an ECS service running inside VPC so that other services can call its API.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/ec257d456bb857219a90eb6a0e5b6758/c08c5/containers.jpg&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: 66.66666666666666%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAMEAv/EABUBAQEAAAAAAAAAAAAAAAAAAAEC/9oADAMBAAIQAxAAAAGWhG6hQkX/xAAZEAEBAQEBAQAAAAAAAAAAAAABAAISESH/2gAIAQEAAQUC7yXYSlkvlp8f/8QAFhEAAwAAAAAAAAAAAAAAAAAAAAES/9oACAEDAQE/AYRKP//EABcRAAMBAAAAAAAAAAAAAAAAAAABEgL/2gAIAQIBAT8BvRbP/8QAGhAAAgIDAAAAAAAAAAAAAAAAADEBERAS4f/aAAgBAQAGPwJF6xRzCEf/xAAbEAEAAgMBAQAAAAAAAAAAAAABACERUXExQf/aAAgBAQABPyESinkqBnuLbwOoyHx7LHmoGCP/2gAMAwEAAgADAAAAEMTP/8QAFhEAAwAAAAAAAAAAAAAAAAAAARBR/9oACAEDAQE/EBFX/8QAFREBAQAAAAAAAAAAAAAAAAAAEGH/2gAIAQIBAT8QsP8A/8QAGxABAQADAQEBAAAAAAAAAAAAAREAITFBYaH/2gAIAQEAAT8Qi3HSumUWoL387rHtepXP3AFTRwXFQR8y4lAz/9k=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/ec257d456bb857219a90eb6a0e5b6758/8ac56/containers.webp 240w,
/static/ec257d456bb857219a90eb6a0e5b6758/d3be9/containers.webp 480w,
/static/ec257d456bb857219a90eb6a0e5b6758/0ba47/containers.webp 640w&quot;
              sizes=&quot;(max-width: 640px) 100vw, 640px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/ec257d456bb857219a90eb6a0e5b6758/09b79/containers.jpg 240w,
/static/ec257d456bb857219a90eb6a0e5b6758/7cc5e/containers.jpg 480w,
/static/ec257d456bb857219a90eb6a0e5b6758/c08c5/containers.jpg 640w&quot;
            sizes=&quot;(max-width: 640px) 100vw, 640px&quot;
            type=&quot;image/jpeg&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/ec257d456bb857219a90eb6a0e5b6758/c08c5/containers.jpg&quot;
            alt=&quot;containers&quot;
            title=&quot;containers&quot;
            loading=&quot;lazy&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;deploy-an-ecs-service-to-multiple-hosts&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#deploy-an-ecs-service-to-multiple-hosts&quot; aria-label=&quot;deploy an ecs service to multiple hosts permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Deploy an ECS service to multiple hosts&lt;/h2&gt;
&lt;p&gt;Whenever we care about availability of a service running inside AWS, we need to have it running in at least 2 availability zones. For that reason when defining the ECS Cluster Auto Scaling Group we need to specify at least 2 VPC Subnets running in different availability zones.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token property&quot;&gt;&quot;ECSMainCluster&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;Type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;AWS::ECS::Cluster&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;Properties&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;&quot;ClusterName&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Main Cluster&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token property&quot;&gt;&quot;ECSAutoScalingGroup&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;Type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;AWS::AutoScaling::AutoScalingGroup&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;Properties&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;VPCZoneIdentifier&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;&quot;Ref&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;PrivateASubnet&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;&quot;Ref&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;PrivateBSubnet&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;LaunchConfigurationName&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;&quot;Ref&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;ContainerHostInstances&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;MinSize&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;2&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;MaxSize&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;6&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;DesiredCapacity&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;2&quot;&lt;/span&gt;                
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token property&quot;&gt;&quot;ServiceA&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;Type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;AWS::ECS::Service&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;Properties&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;Cluster&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;&quot;Ref&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;ECSMainCluster&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;DesiredCount&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;LoadBalancers&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;ContainerName&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;serviceA&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;ContainerPort&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;8080&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;TargetGroupArn&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;&quot;Ref&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;ServiceAAlbTargetGroup&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;DeploymentConfiguration&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;&quot;MinimumHealthyPercent&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;50&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;Role&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;&quot;Ref&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;ECSServiceRole&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;TaskDefinition&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;&quot;Ref&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;ServiceATask&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Notice how we are using 2 private subnets as &lt;code class=&quot;language-text&quot;&gt;VPCZoneIdentifier&lt;/code&gt;. The &lt;code class=&quot;language-text&quot;&gt;MinSize&lt;/code&gt; is also set to 2 which will cause both availability zones to have at least 1 instance running. For brevity subnets and VPC definitions are not included. You can find more details about how to configure the EC2 instances inside ECS cluster &lt;a href=&quot;/how-to-deploy-a-service-to-amazon-elastic-container-service-with-cloud-formation&quot;&gt;in my previous post&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;ServiceA&lt;/code&gt; deployed in &lt;code class=&quot;language-text&quot;&gt;ECSMainCluster&lt;/code&gt; is also specifying that at it has &lt;a href=&quot;https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs_services.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;DesiredCount&lt;/code&gt;&lt;/a&gt; of 2 which instructs ECS to have at least 2 instances of the service running. The &lt;a href=&quot;https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ecs-service.html#cfn-ecs-service-loadbalancers&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;LoadBalancers&lt;/code&gt;&lt;/a&gt; and &lt;a href=&quot;https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ecs-service.html#cfn-ecs-service-role&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Role&lt;/code&gt;&lt;/a&gt; attributes are required for the load balanced setup. The &lt;code class=&quot;language-text&quot;&gt;ECSServiceRole&lt;/code&gt; must allow the ECS agent to make calls to the load balancer API. The &lt;code class=&quot;language-text&quot;&gt;LoadBalancers&lt;/code&gt; reference &lt;a href=&quot;https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-target-groups.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;an ALB target group&lt;/a&gt; to which the running ECS task should be added.&lt;/p&gt;
&lt;h2 id=&quot;a-private-load-balancer&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#a-private-load-balancer&quot; aria-label=&quot;a private load balancer permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;A private load balancer&lt;/h2&gt;
&lt;p&gt;In order for us to be able to call an API exposed by ECS service running on multiple instances we will use &lt;a href=&quot;https://docs.aws.amazon.com/AmazonECS/latest/developerguide/service-load-balancing.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;an internal Application Load Balancer&lt;/a&gt;. By internal, I mean that the load balancer will not be accessible outside of the VPC.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token property&quot;&gt;&quot;PrivateApiLoadBalancer&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;Type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;AWS::ElasticLoadBalancingV2::LoadBalancer&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;Properties&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;Subnets&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;&quot;Ref&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;PrivateASubnet&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;&quot;Ref&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;PrivateBSubnet&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;Name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;PrivateApiLoadBalancer&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;Scheme&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;internal&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;SecurityGroups&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;Ref&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;HttpHttpsProxySecurityGroup&quot;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token property&quot;&gt;&quot;HttpHttpsProxySecurityGroup&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;Type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;AWS::EC2::SecurityGroup&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;Properties&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;GroupDescription&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Enable http and https access&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;VpcId&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;&quot;Ref&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;VPC&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;SecurityGroupIngress&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;IpProtocol&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;tcp&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;&quot;FromPort&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;80&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;&quot;ToPort&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;80&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;CidrIp&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;&quot;Ref&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;VPCCidr&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;IpProtocol&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;tcp&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;&quot;FromPort&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;443&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;&quot;ToPort&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;443&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;CidrIp&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;&quot;Ref&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;VPCCidr&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;SecurityGroupEgress&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;IpProtocol&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;-1&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;CidrIp&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;&quot;Ref&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;VPCCidr&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;There are only 2 important aspects to the &lt;code class=&quot;language-text&quot;&gt;PrivateApiLoadBalancer&lt;/code&gt;. First, it is attached to the same subnets as our ECS task definition. Secondly, it has a security group configured which allows for incoming HTTP/HTTPS traffic and outgoing traffic to any IP in the VPC CIDR address. The egress rule is required for the load balancer to be able to check the health of its targets.&lt;/p&gt;
&lt;p&gt;For the load balancer to perform some actions we need to configure listeners that define its behavior in response to incoming traffic.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token property&quot;&gt;&quot;PrivateApiLoadBalancerHttpListener&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;Type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;AWS::ElasticLoadBalancingV2::Listener&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;Properties&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;Port&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;80&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;Protocol&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;HTTP&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;LoadBalancerArn&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;&quot;Ref&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;PrivateApiLoadBalancer&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;DefaultActions&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;Type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;forward&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;TargetGroupArn&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;token property&quot;&gt;&quot;Ref&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;PrivateApiLoadBalancerInvalidHostGroup&quot;&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token property&quot;&gt;&quot;PrivateApiLoadBalancerInvalidHostGroup&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;Type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;AWS::ElasticLoadBalancingV2::TargetGroup&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;Properties&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;Protocol&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;HTTP&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;Port&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;80&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;VpcId&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;&quot;Ref&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;VPC&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;Name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;invalid-target-group&quot;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;PrivateApiLoadBalancerHttpListener&lt;/code&gt; specifies that the HTTP request to &lt;code class=&quot;language-text&quot;&gt;PrivateApiLoadBalancer&lt;/code&gt; on port 80 should be routed to &lt;code class=&quot;language-text&quot;&gt;PrivateApiLoadBalancerInvalidHostGroup&lt;/code&gt;. The &lt;code class=&quot;language-text&quot;&gt;AWS::ElasticLoadBalancingV2::Listener&lt;/code&gt; requires us to set the &lt;code class=&quot;language-text&quot;&gt;DefaultActions&lt;/code&gt;. The above setup allows us to fail in a consistent manner. Unless there are &lt;code class=&quot;language-text&quot;&gt;AWS::ElasticLoadBalancingV2::ListenerRule&lt;/code&gt; which match an incoming the HTTP request it will be routed to an empty &lt;code class=&quot;language-text&quot;&gt;AWS::ElasticLoadBalancingV2::TargetGroup&lt;/code&gt; which in turn will result in 502 Bad Gateway. This allows us to effectively decouple the &lt;code class=&quot;language-text&quot;&gt;DefaultActions&lt;/code&gt; of the load balancer listener from a specific ECS service instance.&lt;/p&gt;
&lt;h2 id=&quot;attach-ecs-service-to-an-application-load-balancer&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#attach-ecs-service-to-an-application-load-balancer&quot; aria-label=&quot;attach ecs service to an application load balancer permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Attach ECS service to an Application Load Balancer&lt;/h2&gt;
&lt;p&gt;It is time to route a request from the Application Load Balancer to the ECS service instances. The &lt;a href=&quot;https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-elasticloadbalancingv2-listenerrule.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;AWS::ElasticLoadBalancingV2::ListenerRule&lt;/code&gt;&lt;/a&gt; allows us to configure such behavior:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token property&quot;&gt;&quot;ServiceAAlbHttpListenerRule&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;Type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;AWS::ElasticLoadBalancingV2::ListenerRule&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;Properties&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;Actions&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;Type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;forward&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;TargetGroupArn&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;&quot;Ref&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;ServiceAAlbTargetGroup&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;Priority&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;Conditions&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;Field&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;host-header&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;Values&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;service-a.in.example.com&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;ListenerArn&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;Ref&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;PrivateApiLoadBalancerHttpListener&quot;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token property&quot;&gt;&quot;ServiceAAlbTargetGroup&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;Type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;AWS::ElasticLoadBalancingV2::TargetGroup&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;Properties&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;Protocol&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;HTTP&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;Port&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;8080&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;HealthCheckPath&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;/application-status/health&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;HealthyThresholdCount&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;UnhealthyThresholdCount&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;HealthCheckIntervalSeconds&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;HealthCheckTimeoutSeconds&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;VpcId&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;&quot;Ref&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;VPC&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;Name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;service-a-target-group&quot;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;ServiceAAlbHttpListenerRule&lt;/code&gt; states that any request with a &lt;code class=&quot;language-text&quot;&gt;Host&lt;/code&gt; equal to &lt;code class=&quot;language-text&quot;&gt;service-a.in.example.com&lt;/code&gt; should be routed to an instance from the &lt;code class=&quot;language-text&quot;&gt;ServiceAAlbTargetGroup&lt;/code&gt;. The &lt;code class=&quot;language-text&quot;&gt;ServiceAAlbTargetGroup&lt;/code&gt; group is referenced from the &lt;code class=&quot;language-text&quot;&gt;ServiceA&lt;/code&gt; definition and contains all running and healthy instances of our task. This means that in order to call the HTTP API exposed by &lt;code class=&quot;language-text&quot;&gt;ServiceA&lt;/code&gt; we will simply use the &lt;code class=&quot;language-text&quot;&gt;service-a.in.example.com&lt;/code&gt; domain name.&lt;/p&gt;
&lt;h2 id=&quot;a-private-dns-record&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#a-private-dns-record&quot; aria-label=&quot;a private dns record permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;A private DNS record&lt;/h2&gt;
&lt;p&gt;The last part is to define a &lt;a href=&quot;https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/hosted-zone-private-creating.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Private Hosted Zone&lt;/a&gt; and &lt;a href=&quot;https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-route53-recordset.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;a DNS Record Set&lt;/a&gt; so that a DNS look up, happening inside the VPC, for &lt;code class=&quot;language-text&quot;&gt;service-a.in.example.com&lt;/code&gt; results in an IP address of the &lt;code class=&quot;language-text&quot;&gt;PrivateApiLoadBalancer&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token property&quot;&gt;&quot;PrivateHostedZone&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;Type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;AWS::Route53::HostedZone&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;Properties&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;VPCs&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;VPCId&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;&quot;Ref&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;VPC&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;VPCRegion&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;&quot;Ref&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;AWS::Region&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;Name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;in.example.com&quot;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
 &lt;span class=&quot;token property&quot;&gt;&quot;ServiceALoadBalancerDNSRecord&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;Type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;AWS::Route53::RecordSet&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;Properties&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;Name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;service-a.in.example.com&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;HostedZoneId&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;&quot;Ref&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;PrivateHostedZone&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;ResourceRecords&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;Fn::GetAtt&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;PrivateApiLoadBalancer&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;DNSName&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;TTL&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;60&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;Type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;CNAME&quot;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;PrivateHostedZone&lt;/code&gt; merely defines the name of the domain which we will use for addressing ECS services running inside our VPC. It is recommended to use a domain name that you control so that a mistake in the DNS configuration will not cause your services to call an address that you do not own. The &lt;code class=&quot;language-text&quot;&gt;ServiceALoadBalancerDNSRecord&lt;/code&gt; defines a CNAME that uses &lt;code class=&quot;language-text&quot;&gt;PrivateApiLoadBalancer&lt;/code&gt; AWS assigned DNS name. This way the lookup for &lt;code class=&quot;language-text&quot;&gt;service-a.in.example.com&lt;/code&gt; will effectively resolve to multiple IPs in different availability zones.&lt;/p&gt;
&lt;p&gt;With the above configuration in place we can call an HTTP API exposed privately by a load balanced service running inside VPC on ECS cluster using the most natural way i.e. a DNS name.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[How to deploy a service to Amazon Elastic Container Service with CloudFormation?]]></title><description><![CDATA[Containers are becoming the standard way of deploying software. Every cloud vendor now offers one or multiple ways to run containers on their platform. Most of our clients uses AWS to host their SaaS solution. As part of a new development for one of our clients we have decided to move away from Elastic Beanstalk and…]]></description><link>undefined/how-to-deploy-a-service-to-amazon-elastic-container-service-with-cloud-formation/</link><guid isPermaLink="false">undefined/how-to-deploy-a-service-to-amazon-elastic-container-service-with-cloud-formation/</guid><pubDate>Mon, 19 Feb 2018 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Containers are becoming the standard way of deploying software. Every cloud vendor now offers one or multiple ways to run containers on their platform. Most of our clients uses AWS to host their SaaS solution. As part of a new development for one of our clients we have decided to move away from &lt;a href=&quot;https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/Welcome.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Elastic Beanstalk&lt;/a&gt; and embrace containers. Amazon &lt;a href=&quot;https://aws.amazon.com/ecs/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Elastic Container Service&lt;/a&gt; is an orchestration service that supports Docker containers and is generally available for over a year. Given our small development team it seemed like the best choice since it takes away most of the cluster management headaches. In this post I will describe how we deploy a container to ECS using &lt;a href=&quot;https://aws.amazon.com/cloudformation/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;CloudFormation&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/ec257d456bb857219a90eb6a0e5b6758/c08c5/containers.jpg&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: 66.66666666666666%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAMEAv/EABUBAQEAAAAAAAAAAAAAAAAAAAEC/9oADAMBAAIQAxAAAAGWhG6hQkX/xAAZEAEBAQEBAQAAAAAAAAAAAAABAAISESH/2gAIAQEAAQUC7yXYSlkvlp8f/8QAFhEAAwAAAAAAAAAAAAAAAAAAAAES/9oACAEDAQE/AYRKP//EABcRAAMBAAAAAAAAAAAAAAAAAAABEgL/2gAIAQIBAT8BvRbP/8QAGhAAAgIDAAAAAAAAAAAAAAAAADEBERAS4f/aAAgBAQAGPwJF6xRzCEf/xAAbEAEAAgMBAQAAAAAAAAAAAAABACERUXExQf/aAAgBAQABPyESinkqBnuLbwOoyHx7LHmoGCP/2gAMAwEAAgADAAAAEMTP/8QAFhEAAwAAAAAAAAAAAAAAAAAAARBR/9oACAEDAQE/EBFX/8QAFREBAQAAAAAAAAAAAAAAAAAAEGH/2gAIAQIBAT8QsP8A/8QAGxABAQADAQEBAAAAAAAAAAAAAREAITFBYaH/2gAIAQEAAT8Qi3HSumUWoL387rHtepXP3AFTRwXFQR8y4lAz/9k=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/ec257d456bb857219a90eb6a0e5b6758/8ac56/containers.webp 240w,
/static/ec257d456bb857219a90eb6a0e5b6758/d3be9/containers.webp 480w,
/static/ec257d456bb857219a90eb6a0e5b6758/0ba47/containers.webp 640w&quot;
              sizes=&quot;(max-width: 640px) 100vw, 640px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/ec257d456bb857219a90eb6a0e5b6758/09b79/containers.jpg 240w,
/static/ec257d456bb857219a90eb6a0e5b6758/7cc5e/containers.jpg 480w,
/static/ec257d456bb857219a90eb6a0e5b6758/c08c5/containers.jpg 640w&quot;
            sizes=&quot;(max-width: 640px) 100vw, 640px&quot;
            type=&quot;image/jpeg&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/ec257d456bb857219a90eb6a0e5b6758/c08c5/containers.jpg&quot;
            alt=&quot;containers&quot;
            title=&quot;containers&quot;
            loading=&quot;lazy&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;ecs-cluster-definition&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#ecs-cluster-definition&quot; aria-label=&quot;ecs cluster definition permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;ECS Cluster definition&lt;/h2&gt;
&lt;p&gt;At &lt;a href=&quot;https://brightinventions.pl/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Bright Inventions&lt;/a&gt; we often use CloudFormation for infrastructure configuration since it allows us to version and track changes easily. The first piece of infrastructure we need is an &lt;a href=&quot;https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ECS_clusters.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;ECS cluster&lt;/a&gt;. A cluster is a logical group of tasks/containers running inside ECS. In particular, since we will be using &lt;a href=&quot;https://docs.aws.amazon.com/AmazonECS/latest/developerguide/launch_types.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;EC2 Launch Type&lt;/a&gt;, a cluster can also be though of as a group of EC2 instances with an ECS Agent installed.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token property&quot;&gt;&quot;ECSMainCluster&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;Type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;AWS::ECS::Cluster&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;Properties&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;ClusterName&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;app-stack-main&quot;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token property&quot;&gt;&quot;ECSAutoScalingGroup&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;Type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;AWS::AutoScaling::AutoScalingGroup&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;Properties&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;VPCZoneIdentifier&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;&quot;Ref&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;PrivateASubnet&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;&quot;Ref&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;PrivateBSubnet&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;LaunchConfigurationName&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;Ref&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;ContainerHostInstances&quot;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;MinSize&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;1&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;MaxSize&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;6&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;DesiredCapacity&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;1&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;Tags&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;token property&quot;&gt;&quot;Key&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Name&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;token property&quot;&gt;&quot;Value&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;app-stack-ecs&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;token property&quot;&gt;&quot;PropagateAtLaunch&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;CreationPolicy&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;ResourceSignal&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;Timeout&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;PT5M&quot;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;UpdatePolicy&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;AutoScalingReplacingUpdate&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;WillReplace&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;true&quot;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;As you can see above, the &lt;code class=&quot;language-text&quot;&gt;ECSMainCluster&lt;/code&gt; is mostly a declaration. What follows is an auto scaling group that will launch and manage EC2 instances. The &lt;code class=&quot;language-text&quot;&gt;VPCZoneIdentifier&lt;/code&gt; lists 2 VPC subnets created in separate availability zones. This is vital for availability as it causes the EC2 instances to run on physically separate hardware. For brevity, I’ve omitted their configuration from this post. However, if you are interested in this topic head over &lt;a href=&quot;https://sookocheff.com/post/aws/how-to-create-a-vpc-using-cloudformation/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;to this post&lt;/a&gt;. The specified &lt;code class=&quot;language-text&quot;&gt;LaunchConfigurationName&lt;/code&gt; named &lt;code class=&quot;language-text&quot;&gt;ContainerHostInstances&lt;/code&gt; details how the EC2 instance should look like.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token property&quot;&gt;&quot;ContainerHostInstances&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;Type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;AWS::AutoScaling::LaunchConfiguration&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;Properties&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;ImageId&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;ami-880d64f1&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;SecurityGroups&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;&quot;Ref&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;ECSSecurityGroup&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;InstanceType&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;t2.medium&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;IamInstanceProfile&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;&quot;Ref&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;ECSHostEC2InstanceProfile&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;KeyName&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;private-key-pair&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;UserData&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;Fn::Base64&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;token property&quot;&gt;&quot;Fn::Join&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
                    &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                    &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
                        &lt;span class=&quot;token string&quot;&gt;&quot;#!/bin/bash -xe\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                        &lt;span class=&quot;token string&quot;&gt;&quot;echo ECS_CLUSTER=&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                            &lt;span class=&quot;token property&quot;&gt;&quot;Ref&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;ECSMainCluster&quot;&lt;/span&gt;
                        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                        &lt;span class=&quot;token string&quot;&gt;&quot; &gt;&gt; /etc/ecs/ecs.config\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                        &lt;span class=&quot;token string&quot;&gt;&quot;yum install -y aws-cfn-bootstrap\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                        &lt;span class=&quot;token string&quot;&gt;&quot;/opt/aws/bin/cfn-signal -e $? &quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                        &lt;span class=&quot;token string&quot;&gt;&quot;         --stack &quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                            &lt;span class=&quot;token property&quot;&gt;&quot;Ref&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;AWS::StackName&quot;&lt;/span&gt;
                        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                        &lt;span class=&quot;token string&quot;&gt;&quot;         --resource ECSAutoScalingGroup &quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                        &lt;span class=&quot;token string&quot;&gt;&quot;         --region &quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                            &lt;span class=&quot;token property&quot;&gt;&quot;Ref&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;AWS::Region&quot;&lt;/span&gt;
                        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                        &lt;span class=&quot;token string&quot;&gt;&quot;\n&quot;&lt;/span&gt;
                    &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token property&quot;&gt;&quot;ECSHostEC2InstanceProfile&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;Type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;AWS::IAM::InstanceProfile&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;Properties&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;Path&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;/&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;Roles&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;token property&quot;&gt;&quot;Ref&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;ECSHostEC2Role&quot;&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The first important property is the &lt;code class=&quot;language-text&quot;&gt;ImageId&lt;/code&gt; which uses &lt;a href=&quot;https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-optimized_AMI.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Amazon ECS-optimized Linux AMI ID&lt;/a&gt;. Next we have a security group that adds rules for incoming traffic on application ports. Next we have &lt;code class=&quot;language-text&quot;&gt;IamInstanceProfile&lt;/code&gt; which references an instance profile &lt;code class=&quot;language-text&quot;&gt;ECSHostEC2InstanceProfile&lt;/code&gt; that in turn &lt;a href=&quot;https://docs.aws.amazon.com/AmazonECS/latest/developerguide/instance_IAM_role.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;assumes a role policy required by the ECS Agent&lt;/a&gt; to deploy and configure containers.
Inside &lt;code class=&quot;language-text&quot;&gt;UserData&lt;/code&gt; we define a shell script that informs ECS Agent about the cluster it is running in. I will omit &lt;code class=&quot;language-text&quot;&gt;ECSHostEC2Role&lt;/code&gt; definition since &lt;a href=&quot;https://docs.aws.amazon.com/AmazonECS/latest/developerguide/instance_IAM_role.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;it is well described in the documentation&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;With the above we are now ready to deploy an ECS Cluster through CloudFormation template. However, a cluster without containers is pretty meaningless.&lt;/p&gt;
&lt;h2 id=&quot;ecs-service-and-task-definition&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#ecs-service-and-task-definition&quot; aria-label=&quot;ecs service and task definition permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;ECS Service and Task definition&lt;/h2&gt;
&lt;p&gt;In AWS lingo &lt;a href=&quot;https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs_services.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;an ECS Service&lt;/a&gt; describes a minimal configuration required to deploy and run a Task Definition. A &lt;a href=&quot;https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definitions.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Task Definition&lt;/a&gt; in turn describes how to configure and run a set of containers that form a single logical component.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token property&quot;&gt;&quot;EmailSenderService&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;Type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;AWS::ECS::Service&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;Properties&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;Cluster&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;&quot;Ref&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;ECSMainCluster&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;DesiredCount&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;DeploymentConfiguration&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;&quot;MinimumHealthyPercent&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;50&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;Role&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;&quot;Ref&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;ECSServiceRole&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;TaskDefinition&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;&quot;Ref&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;EmailSenderTask&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token property&quot;&gt;&quot;EmailSenderTask&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;Type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;AWS::ECS::TaskDefinition&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;Properties&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;Family&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;app-stack-email-sender&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;ContainerDefinitions&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;Name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;app-stack-email-sender&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;Essential&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;true&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;Image&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;&quot;Ref&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;EmailSenderTaskDockerImage&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;LogConfiguration&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;token property&quot;&gt;&quot;LogDriver&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;awslogs&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;token property&quot;&gt;&quot;Options&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                    &lt;span class=&quot;token property&quot;&gt;&quot;awslogs-group&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;&quot;Ref&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;EmailSenderLogsGroup&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                    &lt;span class=&quot;token property&quot;&gt;&quot;awslogs-region&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;&quot;Ref&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;AWS::Region&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                    &lt;span class=&quot;token property&quot;&gt;&quot;awslogs-stream-prefix&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;email-sender&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                    &lt;span class=&quot;token property&quot;&gt;&quot;awslogs-datetime-format&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;%Y-%m-%d %H:%M:%S.%L&quot;&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;PortMappings&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;&quot;ContainerPort&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;8080&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;Environment&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;token property&quot;&gt;&quot;Name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;DEPLOY_ENV&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;token property&quot;&gt;&quot;Value&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;&quot;Ref&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;DeployEnv&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token property&quot;&gt;&quot;EmailSenderLogsGroup&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;Type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;AWS::Logs::LogGroup&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;Properties&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;LogGroupName&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;app-stack-email-sender&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;RetentionInDays&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;14&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;EmailSenderService&lt;/code&gt; is pretty straightforward to understand. The &lt;code class=&quot;language-text&quot;&gt;EmailSenderTask&lt;/code&gt; defines a single container. The &lt;code class=&quot;language-text&quot;&gt;app-stack-email-sender&lt;/code&gt; task definition states that the &lt;code class=&quot;language-text&quot;&gt;Image&lt;/code&gt; is a reference to a parameter passed in to the CloudFormation template when creating or updating the stack. Its value must &lt;a href=&quot;https://docs.docker.com/engine/reference/commandline/pull/#pull-from-a-different-registry&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;be a name of a Docker image&lt;/a&gt; that can be pulled by the ECS Agent. The repository can either be &lt;a href=&quot;https://hub.docker.com/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;public&lt;/a&gt; or private. When hosting your own, private Docker image repository you need to make sure the ECS Agent &lt;a href=&quot;https://docs.aws.amazon.com/AmazonECS/latest/developerguide/private-auth.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;has the correct credentials configured&lt;/a&gt;. Thankfully there is &lt;a href=&quot;https://aws.amazon.com/ecr/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Elastic Container Registry&lt;/a&gt; which offers private repositories that are automatically configured when using ECS as long as &lt;code class=&quot;language-text&quot;&gt;ECSHostEC2Role&lt;/code&gt; policy &lt;a href=&quot;https://docs.aws.amazon.com/AmazonECS/latest/developerguide/instance_IAM_role.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;allows ECR related actions&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Next we have the &lt;code class=&quot;language-text&quot;&gt;LogConfiguration&lt;/code&gt; that pushes containers logs to the &lt;code class=&quot;language-text&quot;&gt;EmailSenderLogsGroup&lt;/code&gt; CloudWatch Log Group so that we can can inspect them through AWS Console. The &lt;code class=&quot;language-text&quot;&gt;PortMappings&lt;/code&gt; lists ports exposed by a running container. Note that we have not defined the host port and it will get assigned automatically. This is important when running multiple instances of the same container. I’ll describe it in a bit more detail in the next post. Last but not least the &lt;code class=&quot;language-text&quot;&gt;Environment&lt;/code&gt; section lists environment variables passed to the container instances on startup. Here we are referencing a &lt;code class=&quot;language-text&quot;&gt;DeployEnv&lt;/code&gt; stack parameter that allows us to inform the application running inside the container about the current deployment environment e.g. staging vs production.&lt;/p&gt;
&lt;p&gt;As you can see above it takes couple of steps to use CloudFormation to deploy a container to ECS. It is true that it requires more configuration than Elastic Beanstalk. However, it allows for better utilization of EC2 instances and an uniform approach to deployment and configuration regardless of the application technology used inside the container. Moreover it is more future proof as with few adjustments it should be possible to switch to &lt;a href=&quot;https://docs.aws.amazon.com/AmazonECS/latest/developerguide/launch_types.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Fargate Launch Mode&lt;/a&gt;. Using this mode releases us from the burden of EC2 ECS cluster management tasks. Deploying more services and tasks will require separate CloudFormation resource definitions. However, with the help of &lt;a href=&quot;https://brightinventions.pl/blog/introducing-cloudform-tame-aws-cloudformation-templates/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;cloudform&lt;/a&gt; it easy keep the CloudFormation template DRY.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[In-memory database tests with Querydsl]]></title><description><![CDATA[Writing tests is an important skill of a software engineer. I used to write lots of very focused, narrow unit tests. However, I often found such tests to hinder refactoring and barely help in catching regressions. Whether such issues were caused by my poor design choices or are intrinsic to unit tests is not the focus…]]></description><link>undefined/in-memory-database-tests-with-querydsl/</link><guid isPermaLink="false">undefined/in-memory-database-tests-with-querydsl/</guid><pubDate>Mon, 12 Feb 2018 22:14:00 GMT</pubDate><content:encoded>&lt;p&gt;Writing tests is an important skill of a software engineer. I used to write lots of very focused, narrow unit tests. However, I often found such tests to hinder refactoring and barely help in catching regressions. Whether such issues were caused by my poor design choices or are intrinsic to unit tests is not the focus of this post. However, the fact is that nowadays I tend to write more coarse-grained, integration style tests. There is one downside to such approach: speed. For instance, using Hibernate with a full fledged database is relatively slow compared to using a fake repository implementation. Today I write about abstracting the database access using &lt;a href=&quot;http://www.querydsl.com/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Querydsl&lt;/a&gt; in a way that aids testing.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/ccacd62b2cb75489034f561354f95cc2/c08c5/test.jpg&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: 72.5%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAOABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAEEAgP/xAAVAQEBAAAAAAAAAAAAAAAAAAACA//aAAwDAQACEAMQAAABXWRTdRgFP//EABkQAQEAAwEAAAAAAAAAAAAAAAECAAMREv/aAAgBAQABBQKWnCVzXXZ5QvtZ18P/xAAWEQEBAQAAAAAAAAAAAAAAAAABABH/2gAIAQMBAT8BdYW//8QAFhEBAQEAAAAAAAAAAAAAAAAAAQAS/9oACAECAQE/ATMl/8QAGxAAAgIDAQAAAAAAAAAAAAAAAAECERAhIjH/2gAIAQEABj8C5KcsaaKcz1n/xAAbEAACAgMBAAAAAAAAAAAAAAAAAREhMUFRcf/aAAgBAQABPyGVgoQ6oPi0IyPJaISh5S8Fdiz/2gAMAwEAAgADAAAAEJ/P/8QAFhEBAQEAAAAAAAAAAAAAAAAAAQAR/9oACAEDAQE/ENSDCAv/xAAWEQEBAQAAAAAAAAAAAAAAAAABABH/2gAIAQIBAT8QwDSFVv/EAB0QAQACAgIDAAAAAAAAAAAAAAEAESExQWGRwdH/2gAIAQEAAT8QZo9tpjzEaQy5fSIlRGK7nCo1rY4eOosZFyCiUlZWifJ//9k=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/ccacd62b2cb75489034f561354f95cc2/8ac56/test.webp 240w,
/static/ccacd62b2cb75489034f561354f95cc2/d3be9/test.webp 480w,
/static/ccacd62b2cb75489034f561354f95cc2/0ba47/test.webp 640w&quot;
              sizes=&quot;(max-width: 640px) 100vw, 640px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/ccacd62b2cb75489034f561354f95cc2/09b79/test.jpg 240w,
/static/ccacd62b2cb75489034f561354f95cc2/7cc5e/test.jpg 480w,
/static/ccacd62b2cb75489034f561354f95cc2/c08c5/test.jpg 640w&quot;
            sizes=&quot;(max-width: 640px) 100vw, 640px&quot;
            type=&quot;image/jpeg&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/ccacd62b2cb75489034f561354f95cc2/c08c5/test.jpg&quot;
            alt=&quot;test&quot;
            title=&quot;test&quot;
            loading=&quot;lazy&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;querydsl-is-awesome&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#querydsl-is-awesome&quot; aria-label=&quot;querydsl is awesome permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Querydsl is awesome&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;http://www.querydsl.com/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Querydsl&lt;/a&gt; is a set of libraries that, as the name implies, provides strongly typed Domain Specific Language to execute queries. &lt;a href=&quot;http://www.querydsl.com/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Querydsl&lt;/a&gt; supports many data access technologies e.g. JDBC, Hibernate, JDO.
The following example in Kotlin illustrates how a DSL generated based on entity class can be used to find some entities through JPA interface:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;kotlin&quot;&gt;&lt;pre class=&quot;language-kotlin&quot;&gt;&lt;code class=&quot;language-kotlin&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; queryFactory&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; JPAQueryFactory &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; userEmailToSearch &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;alamakota@gmail.com&quot;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; user &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; queryFactory&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;query&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;QUser&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;where&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;QUser&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;eq&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;userEmailToSearch&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;select&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;QUser&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fetchOne&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;One important option available is the &lt;a href=&quot;https://github.com/querydsl/querydsl/tree/master/querydsl-collections&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Collections&lt;/a&gt; module that offers an integration to POJO collections and beans. The following example in Kotlin shows how a list of users can be queried:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;kotlin&quot;&gt;&lt;pre class=&quot;language-kotlin&quot;&gt;&lt;code class=&quot;language-kotlin&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; users &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;listOf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;userAlan&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; userBob&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; userAlice&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; user &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; CollQuery&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Nothing&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;QUser&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; users&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;where&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;QUser&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;eq&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;userEmailToSearch&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;select&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;QUser&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fetchOne&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;abstract-the-complex-away&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#abstract-the-complex-away&quot; aria-label=&quot;abstract the complex away permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Abstract the complex away&lt;/h2&gt;
&lt;p&gt;The above examples look similar thanks to common interface provided by Querydsl. However, while the default DSL is very capable I found it a bit verbose in the most common cases. For that matter let us define a bit simpler interface that will allow for finding entities given some criteria&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;kotlin&quot;&gt;&lt;pre class=&quot;language-kotlin&quot;&gt;&lt;code class=&quot;language-kotlin&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; EntityQueries &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;TQEntity &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; EntityPath&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;TEntity&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; TEntity &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Any&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;findFirst&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
        qEntity&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; TQEntity&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
        &lt;span class=&quot;token keyword&quot;&gt;where&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;TQEntity&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; Predicate&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
        orderBy&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;TQEntity&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; OrderSpecifier&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; TEntity&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; 
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; queries&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;EntityQueries &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;..&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; ala &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; queries&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;findFirst&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;QUser&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;where&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; it&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;eq&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;ala@gmail.com&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; latestUser &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; queries&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;findFirst&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;QUser&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; orderBy &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; it&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;created&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;desc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The above interface allows us to express commonly used queries in a more succinct fashion.&lt;/p&gt;
&lt;h2 id=&quot;define-production-implementation&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#define-production-implementation&quot; aria-label=&quot;define production implementation permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Define production implementation&lt;/h2&gt;
&lt;p&gt;With Querydsl it is easy enough to implement the &lt;code class=&quot;language-text&quot;&gt;EntityQueries&lt;/code&gt; interface. First the production implementation delegating to JPA for actual data access technology:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;kotlin&quot;&gt;&lt;pre class=&quot;language-kotlin&quot;&gt;&lt;code class=&quot;language-kotlin&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;QueryDslDomainQueryFactory&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; queryFactory&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; JPAQueryFactory&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; EntityQueries &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;TQEntity &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; EntityPath&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;TEntity&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; TEntity &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Any&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;findFirst&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;qEntity&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; TQEntity&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;where&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;TQEntity&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; Predicate&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; orderBy&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;TQEntity&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; OrderSpecifier&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; TEntity&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; queryFactory&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;query&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;qEntity&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;where&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;where&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;qEntity&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;apply&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;orderBy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;qEntity&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;orderBy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;it&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;select&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;qEntity&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fetchFirst&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The above lets us use the &lt;code class=&quot;language-text&quot;&gt;EntityQueries&lt;/code&gt; interface instead of JPA in e.g. Spring controllers like so:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;kotlin&quot;&gt;&lt;pre class=&quot;language-kotlin&quot;&gt;&lt;code class=&quot;language-kotlin&quot;&gt;&lt;span class=&quot;token annotation builtin&quot;&gt;@RestController&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;UsersController&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; queries&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; EntityQueries&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token annotation builtin&quot;&gt;@GetMapping&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;/users&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getByEmail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token annotation builtin&quot;&gt;@RequestParam&lt;/span&gt; email&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; queries&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;findFirst&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;QUser&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;where&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; it&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;eq&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;One of the Spring recommended ways to abstract the specifics of query technology is to use &lt;a href=&quot;https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.query-methods&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;repository interfaces&lt;/a&gt; e.g:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;kotlin&quot;&gt;&lt;pre class=&quot;language-kotlin&quot;&gt;&lt;code class=&quot;language-kotlin&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; UserRepository &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Repository&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;User&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Long&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;findByEmail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;String email&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; User&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Such interface would be &lt;em&gt;magically&lt;/em&gt; implemented by Spring runtime and put in the application context. The approach may seem appealing at first since we do not have to implement the interface. There are however, multiple issues:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;an application context is required which in turn is slow to bootstrap&lt;/li&gt;
&lt;li&gt;there is no compile time checks&lt;/li&gt;
&lt;li&gt;the refactoring is harder without a special support from IDE&lt;/li&gt;
&lt;li&gt;the actual behavior is hard to figure out without a careful documentation lecture (what will happen if e.g. there are multiple users with the same email?)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;EntityQueries&lt;/code&gt; invocation to find users by email is almost as readable as &lt;code class=&quot;language-text&quot;&gt;findByEmail&lt;/code&gt; but does not suffer from any of downsides listed above. Encapsulating more complex filtering logic can be done with a simple extension method or a more elaborate &lt;a href=&quot;https://en.wikipedia.org/wiki/Specification_pattern&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Specification pattern&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;using-in-memory-database-in-tests&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#using-in-memory-database-in-tests&quot; aria-label=&quot;using in memory database in tests permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Using in-memory database in tests&lt;/h2&gt;
&lt;p&gt;We can use Spring test helpers to ease writing tests involving an application context that lets us inject e.g. &lt;code class=&quot;language-text&quot;&gt;UsersController&lt;/code&gt; instance to invoke its methods. However, such tests are, comparatively, very slow to run and thus cause the feedback loop to be much slower. Fortunately the &lt;code class=&quot;language-text&quot;&gt;EntityQueries&lt;/code&gt; abstraction is very easy to implement using POJO in-memory collections.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;kotlin&quot;&gt;&lt;pre class=&quot;language-kotlin&quot;&gt;&lt;code class=&quot;language-kotlin&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; InMemoryEntityQueries &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;QueriesBase&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; EntityQueries &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; entities &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; mutableMapOf&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Class&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; MutableList&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;TQEntity &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; EntityPath&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;TEntity&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; TEntity &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Any&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;findFirst&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;qEntity&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; TQEntity&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;where&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;TQEntity&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; Predicate&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; orderBy&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;TQEntity&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; OrderSpecifier&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; TEntity&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; entities &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; entities&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getOrPut&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;qEntity&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;type&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; mutableListOf&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;TEntity&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; List&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;TEntity&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; CollQuery&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Nothing&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;qEntity&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; entities&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;where&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;where&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;qEntity&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;apply&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;orderBy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;qEntity&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;orderBy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;it&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;select&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;qEntity&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fetchFirst&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The above implementation looks almost exactly the same as the production one. We can of course try to extract the common code to make things more DRY. However, the most important observation is that we delegate to Querydsl implementation for the important filtering and ordering logic. This can increase our confidence that the fake implementation behaves the same as production one with only difference being the actual entity storage.&lt;/p&gt;
&lt;p&gt;Given the above implementation we can now easily replace the &lt;code class=&quot;language-text&quot;&gt;UsersController&lt;/code&gt; dependency and instantiate it as a regular POJO:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;kotlin&quot;&gt;&lt;pre class=&quot;language-kotlin&quot;&gt;&lt;code class=&quot;language-kotlin&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; UsersControllerTests &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; db &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;InMemoryEntityQueries&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; controller &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;UsersController&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;db&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token annotation builtin&quot;&gt;@Test&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;canFindByEmail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        db&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;entities&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;User&lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;java&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;  &lt;span class=&quot;token function&quot;&gt;listOf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;email &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;ala@gmail.com&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;email &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;ola@gmail.com&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

        controller&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getByEmail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;ola@gmail.com&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;shouldEqual&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;ola@gmail.com&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        controller&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getByEmail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;peter@gmail.com&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;shouldEqual&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;notes-on-in-memory-implementation&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#notes-on-in-memory-implementation&quot; aria-label=&quot;notes on in memory implementation permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Notes on in-memory implementation&lt;/h2&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;EntityQueries&lt;/code&gt; interface above is obviously a simplified version. The most important missing piece is the ability to save entities. However, this is not a hard thing to implement given the in-memory implementation. We can, for instance, make use of the fact that all of our entities are marked JPA Persistence annotations to find a field marked with &lt;code class=&quot;language-text&quot;&gt;@Id&lt;/code&gt;, generate the id and assign it based on the contents of the &lt;code class=&quot;language-text&quot;&gt;entities&lt;/code&gt; variable. Another approach is to mark all entities with a dedicated interface e.g.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;kotlin&quot;&gt;&lt;pre class=&quot;language-kotlin&quot;&gt;&lt;code class=&quot;language-kotlin&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; HasId&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;TId&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; TId
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;An entity implementing &lt;code class=&quot;language-text&quot;&gt;HasId&lt;/code&gt; could be checked in the &lt;code class=&quot;language-text&quot;&gt;save&lt;/code&gt; method of the in-memory implementation and assigned with a unique identifier e.g.:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;kotlin&quot;&gt;&lt;pre class=&quot;language-kotlin&quot;&gt;&lt;code class=&quot;language-kotlin&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;TEntity&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; HasId&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Long&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;entity&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; TEntity&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; entities &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; entities&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getOrPut&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;entity&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;javaClass&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; mutableListOf&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;TEntity&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; List&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;TEntity&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;entity&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        entity&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;entities&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; it&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;?:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    entities &lt;span class=&quot;token operator&quot;&gt;+=&lt;/span&gt; entity
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Following the above approach we can easily add missing operations e.g. to remove an entity and that in turn allows us to write even more tests that run fully in-memory. It is worth noting that using an in-memory database implementation works best for queries that fetch, save or update one or multiple instances. As soon as we need to use a features natural to a database technology e.g. joins in SQL, we are better of connecting to a real database. While Querydsl collections module supports both join and group operations the in-memory implementation is often not equivalent to the database one especially around &lt;code class=&quot;language-text&quot;&gt;null&lt;/code&gt; values handling.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[How to publish a library to a Maven repository with the maven-publish plugin]]></title><description><![CDATA[A seasoned developer now and then creates a piece of code that he or she would like to reuse in a different project. When such time comes it is useful to know how to publish a library so that it can easily be incorporated into a different project. In this post I will describe how to publish a Kotlin library to JCenter…]]></description><link>undefined/how-to-publish-a-library-to-a-maven-repository/</link><guid isPermaLink="false">undefined/how-to-publish-a-library-to-a-maven-repository/</guid><pubDate>Tue, 06 Feb 2018 22:14:00 GMT</pubDate><content:encoded>&lt;p&gt;A seasoned developer now and then creates a piece of code that he or she would like to &lt;em&gt;reuse&lt;/em&gt; in a different project. When such time comes it is useful to know how to publish a library so that it can easily be incorporated into a different project. In this post I will describe how to publish a Kotlin library to &lt;a href=&quot;https://bintray.com/bintray/jcenter&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;JCenter&lt;/a&gt; with &lt;code class=&quot;language-text&quot;&gt;maven-publish&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;com.jfrog.bintray&lt;/code&gt; Gradle plugins.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 660px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/16e745eae6d08f788652ae956f75239c/ee745/announce.jpg&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: 90.83333333333333%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAASABQDASIAAhEBAxEB/8QAGAABAAMBAAAAAAAAAAAAAAAAAAECBQP/xAAWAQEBAQAAAAAAAAAAAAAAAAABAgD/2gAMAwEAAhADEAAAAdjpfPidBVTeBZG3/8QAGxAAAQQDAAAAAAAAAAAAAAAAAQIEEBESEyL/2gAIAQEAAQUCpe7ICXA6TYE//8QAFxEBAAMAAAAAAAAAAAAAAAAAAQIRIP/aAAgBAwEBPwGTRj//xAAXEQEAAwAAAAAAAAAAAAAAAAABAhEg/9oACAECAQE/AZNGP//EABwQAAEDBQAAAAAAAAAAAAAAAAACEjEQESAhIv/aAAgBAQAGPwJzuLQTVJvD/8QAGxAAAgIDAQAAAAAAAAAAAAAAAREAIRAgMXH/2gAIAQEAAT8hvWUe4e5MlcGnBBBM6f/aAAwDAQACAAMAAAAQfzcA/8QAFxEBAQEBAAAAAAAAAAAAAAAAAREAEP/aAAgBAwEBPxBaBhp3/8QAFxEBAQEBAAAAAAAAAAAAAAAAAREAEP/aAAgBAgEBPxBrGGl7/8QAGxABAAIDAQEAAAAAAAAAAAAAAREhABAxYYH/2gAIAQEAAT8QTgIA5fU40BJqHu5ZpBSopuMtJLf2tIPQdf/Z&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/16e745eae6d08f788652ae956f75239c/8ac56/announce.webp 240w,
/static/16e745eae6d08f788652ae956f75239c/d3be9/announce.webp 480w,
/static/16e745eae6d08f788652ae956f75239c/cc661/announce.webp 660w&quot;
              sizes=&quot;(max-width: 660px) 100vw, 660px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/16e745eae6d08f788652ae956f75239c/09b79/announce.jpg 240w,
/static/16e745eae6d08f788652ae956f75239c/7cc5e/announce.jpg 480w,
/static/16e745eae6d08f788652ae956f75239c/ee745/announce.jpg 660w&quot;
            sizes=&quot;(max-width: 660px) 100vw, 660px&quot;
            type=&quot;image/jpeg&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/16e745eae6d08f788652ae956f75239c/ee745/announce.jpg&quot;
            alt=&quot;publish&quot;
            title=&quot;publish&quot;
            loading=&quot;lazy&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;gradle-maven-plugins&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#gradle-maven-plugins&quot; aria-label=&quot;gradle maven plugins permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Gradle Maven plugins&lt;/h2&gt;
&lt;p&gt;The first step is to apply &lt;a href=&quot;https://docs.gradle.org/current/userguide/maven_plugin.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Maven plugin&lt;/a&gt;. The plugin adds support for deploying artifacts to Maven repositories. Note that in case of multi-project build e.g. &lt;a href=&quot;https://github.com/bright/shouldko&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;ShouldKO&lt;/a&gt; the Maven plugin should be applied to every project that defines some artifact to be published. You can use &lt;code class=&quot;language-text&quot;&gt;allprojects&lt;/code&gt; to get rid of duplication e.g.:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;groovy&quot;&gt;&lt;pre class=&quot;language-groovy&quot;&gt;&lt;code class=&quot;language-groovy&quot;&gt;allprojects &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    repositories &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;jcenter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    apply plugin&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;kotlin&apos;&lt;/span&gt;
    apply plugin&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;maven&apos;&lt;/span&gt;

    group &lt;span class=&quot;token string gstring&quot;&gt;&quot;pl.miensol.shouldko&quot;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;For the &lt;a href=&quot;https://github.com/bintray/gradle-bintray-plugin&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;com.jfrog.bintray&lt;/code&gt;&lt;/a&gt; plugin, used later on, to work nicely with Maven artifacts we need to apply additional Gradle plugin. This additional piece is the &lt;a href=&quot;https://docs.gradle.org/current/userguide/publishing_maven.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;maven-publish&lt;/code&gt;&lt;/a&gt; plugin which provides ability to publish artifacts in Maven format. All we need to do is to &lt;code class=&quot;language-text&quot;&gt;apply plugin: &amp;#39;maven-publish&amp;#39;&lt;/code&gt; in the main project.&lt;/p&gt;
&lt;h2 id=&quot;define-maven-publishing&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#define-maven-publishing&quot; aria-label=&quot;define maven publishing permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Define Maven publishing&lt;/h2&gt;
&lt;p&gt;The &lt;a href=&quot;https://github.com/bintray/gradle-bintray-plugin#step-7-define-artifacts-to-be-uploaded-to-bintray&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;com.jfrog.bintray&lt;/code&gt;&lt;/a&gt; plugin relies on properly defined &lt;a href=&quot;https://docs.gradle.org/current/userguide/publishing_maven.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Maven Publications&lt;/a&gt;. The Gradle DSL allows us to define them easily basing on project properties e.g.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;groovy&quot;&gt;&lt;pre class=&quot;language-groovy&quot;&gt;&lt;code class=&quot;language-groovy&quot;&gt;publishing &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    publications &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;hamcrest&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;MavenPublication&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; project &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;project&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;:hamcrest&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            from project&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;components&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;java
            artifact project&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;sourcesJar &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// not required, includes sourcesJar with correct classifer&lt;/span&gt;
                classifier &lt;span class=&quot;token string gstring&quot;&gt;&quot;sources&quot;&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
            groupId group
            artifactId project&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name
            version project&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;version
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

        &lt;span class=&quot;token function&quot;&gt;core&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;MavenPublication&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; project &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;project&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;:core&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            from project&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;components&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;java
            artifact project&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;sourcesJar &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                classifier &lt;span class=&quot;token string gstring&quot;&gt;&quot;sources&quot;&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
            groupId group
            artifactId project&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name
            version project&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;version
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The above Maven Publications include sources artifact. Publishing additional classifiers for artifacts is important since &lt;a href=&quot;https://stackoverflow.com/a/20909695/155213&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;it allows for IDE to show a documentation popup or debug through the library source code&lt;/a&gt;.  However, one needs to define it first as it is not included by default when applying &lt;code class=&quot;language-text&quot;&gt;java&lt;/code&gt; or &lt;code class=&quot;language-text&quot;&gt;kotlin&lt;/code&gt; plugins to a Gradle project. This is easily done as follows:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;groovy&quot;&gt;&lt;pre class=&quot;language-groovy&quot;&gt;&lt;code class=&quot;language-groovy&quot;&gt;allprojects &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    task &lt;span class=&quot;token function&quot;&gt;sourcesJar&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;type&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Jar&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; dependsOn&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; classes&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        from sourceSets&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;main&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;allSource
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;project-versioning&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#project-versioning&quot; aria-label=&quot;project versioning permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Project versioning&lt;/h2&gt;
&lt;p&gt;As you saw above, we have used &lt;code class=&quot;language-text&quot;&gt;project.version&lt;/code&gt; to indicate a version to &lt;code class=&quot;language-text&quot;&gt;MavenPublication&lt;/code&gt;. There are multiple strategies to version software but the &lt;a href=&quot;https://semver.org/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Semantic Versioning&lt;/a&gt; scheme is widely accepted as a standard when it comes to libraries. If you wish to use it then there are plugins available for Gradle to simplify the mundane tasks of maintaining pre-release and patch versions. I like the set of plugin from &lt;a href=&quot;https://github.com/ajoberstar/gradle-git/wiki&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;ajoberstar&lt;/code&gt;&lt;/a&gt; that provide an opinionated way to version your project based on git tags. Applying them is easy:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;groovy&quot;&gt;&lt;pre class=&quot;language-groovy&quot;&gt;&lt;code class=&quot;language-groovy&quot;&gt;plugins &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    id &lt;span class=&quot;token string gstring&quot;&gt;&quot;org.ajoberstar.grgit&quot;&lt;/span&gt; version &lt;span class=&quot;token string gstring&quot;&gt;&quot;1.7.2&quot;&lt;/span&gt;
    id &lt;span class=&quot;token string gstring&quot;&gt;&quot;org.ajoberstar.release-opinion&quot;&lt;/span&gt; version &lt;span class=&quot;token string gstring&quot;&gt;&quot;1.7.2&quot;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now when you issue e.g. &lt;code class=&quot;language-text&quot;&gt;gradle build&lt;/code&gt; the plugin will &lt;a href=&quot;https://github.com/ajoberstar/gradle-git/wiki/Release%20Plugins#how-do-i-use-the-opinion-plugin&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;infer a next version based on your git repository state&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&amp;gt; Configure project : 
Inferred project: shouldko, version: 0.1.5-dev.0.uncommitted+4f71d34&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;bintray-upload&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#bintray-upload&quot; aria-label=&quot;bintray upload permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Bintray upload&lt;/h2&gt;
&lt;p&gt;Finally, when we are ready to upload our library and make it available for everyone we need to set up a &lt;a href=&quot;https://bintray.com/signup/oss&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Bintray account&lt;/a&gt;. Once we have it, on the &lt;a href=&quot;https://bintray.com/profile/edit&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;profile&lt;/a&gt; page we can access API key required to configure &lt;a href=&quot;https://github.com/bintray/gradle-bintray-plugin&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;the Bintray&lt;/a&gt; Gradle plugin.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;groovy&quot;&gt;&lt;pre class=&quot;language-groovy&quot;&gt;&lt;code class=&quot;language-groovy&quot;&gt;bintray &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    user &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; project&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;hasProperty&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;bintrayUser&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; project&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;property&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;bintrayUser&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; System&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getenv&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;BINTRAY_USER&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    key &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; project&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;hasProperty&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;bintrayApiKey&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; project&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;property&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;bintrayApiKey&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; System&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getenv&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;BINTRAY_API_KEY&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    publications &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;core&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;hamcrest&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    pkg &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        repo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;maven&apos;&lt;/span&gt;
        name &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;shouldko&apos;&lt;/span&gt;
        desc &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Adds source line to tests assertion messages&apos;&lt;/span&gt;
        userOrg &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;brightinventions&apos;&lt;/span&gt;
        licenses &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;MIT&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
        vcsUrl &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;https://github.com/bright/shouldko.git&apos;&lt;/span&gt;
        labels &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;tests&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;hamcrest&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;junit&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;The Bintray API key should be kept private and by no means included in the source code repository.&lt;/strong&gt;
We can configure &lt;code class=&quot;language-text&quot;&gt;user&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;key&lt;/code&gt; by looking at project properties and if not available using environment variables. This way there is no need to expose them publicly.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;gradle build bintrayUpload -PbintrayUser&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;apiUser&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; -PbintrayApiKey&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;apikKey&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;repo&lt;/code&gt; is the name of the Bintray repository. You can use the same Bintray repository to host multiple projects.&lt;/p&gt;
&lt;p&gt;The Bintray plugin is very taciturn thus I like to add some log message to see when the &lt;code class=&quot;language-text&quot;&gt;bintrayUpload&lt;/code&gt; completes:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;groovy&quot;&gt;&lt;pre class=&quot;language-groovy&quot;&gt;&lt;code class=&quot;language-groovy&quot;&gt;afterEvaluate &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    tasks&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;bintrayUpload&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;doLast &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        logger&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;lifecycle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string gstring&quot;&gt;&quot;Uploaded artifacts to bintray at version &lt;span class=&quot;token expression&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;$&lt;/span&gt;version&lt;/span&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;travis-build&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#travis-build&quot; aria-label=&quot;travis build permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Travis build&lt;/h2&gt;
&lt;p&gt;Every project should have at least some form of &lt;a href=&quot;https://en.wikipedia.org/wiki/Continuous_integration&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;continuous integration&lt;/a&gt;. For open source software there are at least couple of free build servers available. &lt;a href=&quot;https://travis-ci.org&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Travis&lt;/a&gt; is probably the most popular one. For gradle project Travis will by default call &lt;code class=&quot;language-text&quot;&gt;build&lt;/code&gt;. If you would like to upload the build artifacts to Bintray whenever successful build completes you need to add a line to &lt;code class=&quot;language-text&quot;&gt;script&lt;/code&gt; section of the &lt;code class=&quot;language-text&quot;&gt;.travis.yml&lt;/code&gt; like so:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;yaml&quot;&gt;&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; ./gradlew build
  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; ./gradlew bintrayUpload&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Obviously the Bintray credentials need to be configured as well which can be done through a project configuration page:&lt;/p&gt;
&lt;p&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/96afd411d895c62e67a335a9b7b4fbb5/ce0a7/travis-configure.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: 36.66666666666667%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAIAAACHqfpvAAAACXBIWXMAAAsTAAALEwEAmpwYAAAA20lEQVQY05XQy46EIBAFUP7/70wvHUdcoGQG5FFQUjxkEjsm3b2bs7qpu7rFUq2xFKwVSsmt9f9gFqOCoEP48d4jUkpElC5ElHMut5xzetFaY87aXWuz7wEgADjn/M05J6UUQqzrum2bUurZWmuNMUTErLW/SmmtIYT4DgCWZfm+cM63bQsXuBzHwYwxUkqtdYwx3J7Ze885/7rM8yylTCkhonMuhFBKYYhIROUFESHix8ic877vwzAIIXrv4zg+Hg9Wa23vTz7Ps9b6cem9a62naQKA3jsAWGv/AJtLkLZtQlrlAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/96afd411d895c62e67a335a9b7b4fbb5/8ac56/travis-configure.webp 240w,
/static/96afd411d895c62e67a335a9b7b4fbb5/d3be9/travis-configure.webp 480w,
/static/96afd411d895c62e67a335a9b7b4fbb5/e46b2/travis-configure.webp 960w,
/static/96afd411d895c62e67a335a9b7b4fbb5/f992d/travis-configure.webp 1440w,
/static/96afd411d895c62e67a335a9b7b4fbb5/d90b2/travis-configure.webp 1590w&quot;
              sizes=&quot;(max-width: 960px) 100vw, 960px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/96afd411d895c62e67a335a9b7b4fbb5/8ff5a/travis-configure.png 240w,
/static/96afd411d895c62e67a335a9b7b4fbb5/e85cb/travis-configure.png 480w,
/static/96afd411d895c62e67a335a9b7b4fbb5/d9199/travis-configure.png 960w,
/static/96afd411d895c62e67a335a9b7b4fbb5/07a9c/travis-configure.png 1440w,
/static/96afd411d895c62e67a335a9b7b4fbb5/ce0a7/travis-configure.png 1590w&quot;
            sizes=&quot;(max-width: 960px) 100vw, 960px&quot;
            type=&quot;image/png&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/96afd411d895c62e67a335a9b7b4fbb5/d9199/travis-configure.png&quot;
            alt=&quot;TravisCI environment configuration&quot;
            title=&quot;TravisCI environment configuration&quot;
            loading=&quot;lazy&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Now, the Gradle git plugin will create a development version and publish it to Bintray on every Travis build.&lt;/p&gt;
&lt;h2 id=&quot;tag-to-release&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#tag-to-release&quot; aria-label=&quot;tag to release permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Tag to release&lt;/h2&gt;
&lt;p&gt;Whenever you want to release a new version of the library you now can simply tag a particular version e.g.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; tag &lt;span class=&quot;token number&quot;&gt;0.1&lt;/span&gt;.4
&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; push origin &lt;span class=&quot;token number&quot;&gt;0.1&lt;/span&gt;.4&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;After a local or continuos integration build completes you should see a new version in the Bintray web application. From there you need &lt;a href=&quot;https://bintray.com/docs/usermanual/starting/starting_tutorial2uploading.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;to publish the version&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;use-the-new-library&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#use-the-new-library&quot; aria-label=&quot;use the new library permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Use the new library&lt;/h2&gt;
&lt;p&gt;Once a version is published, you can consume it from a maven or gradle project easily. Until you &lt;a href=&quot;https://bintray.com/bintray/jcenter&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;link your package to JCenter&lt;/a&gt;, you need to inform your build system about a new maven repository location e.g.:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;groovy&quot;&gt;&lt;pre class=&quot;language-groovy&quot;&gt;&lt;code class=&quot;language-groovy&quot;&gt;repositories &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;jcenter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    maven &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; url &lt;span class=&quot;token string&quot;&gt;&apos;https://dl.bintray.com/brightinventions/maven&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Note that &lt;code class=&quot;language-text&quot;&gt;brightinventions&lt;/code&gt; is the organization user name and &lt;code class=&quot;language-text&quot;&gt;maven&lt;/code&gt; is the repository name mentioned above. You are now, finally able to consume your library 🎉:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;groovy&quot;&gt;&lt;pre class=&quot;language-groovy&quot;&gt;&lt;code class=&quot;language-groovy&quot;&gt;compile &lt;span class=&quot;token string&quot;&gt;&apos;pl.miensol.shouldko:hamcrest:0.1.4&apos;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Enjoy!&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Use ShouldKO for better assertion messages]]></title><description><![CDATA[Most of us write tests these days. Whether they are unit, integration, end-to-end or performance tests once written we often do not go back to them until they fail. It is thus vital to have a clear assertion message when a test fails.  Hamcrest I think Hamcrest is the most popular assertion library available in Java…]]></description><link>undefined/shouldko-for-better-assertion-messages/</link><guid isPermaLink="false">undefined/shouldko-for-better-assertion-messages/</guid><pubDate>Wed, 17 Jan 2018 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Most of us write tests these days. Whether they are unit, integration, end-to-end or performance tests once written we often do not go back to them until they fail. It is thus vital to have a clear assertion message when a test fails.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/485a23c6db6fa5273fbf6fd1bee9ad06/c08c5/search.jpg&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: 100%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAUABQDASIAAhEBAxEB/8QAGQABAAMBAQAAAAAAAAAAAAAAAAIDBAEF/8QAFAEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEAMQAAAB92E85rcCsLAf/8QAGxABAAICAwAAAAAAAAAAAAAAAQIQABESISP/2gAIAQEAAQUCXRCfKpGyJ60Hef/EABQRAQAAAAAAAAAAAAAAAAAAACD/2gAIAQMBAT8BH//EABQRAQAAAAAAAAAAAAAAAAAAACD/2gAIAQIBAT8BH//EABkQAAEFAAAAAAAAAAAAAAAAAAABEBEgYf/aAAgBAQAGPwJ4Fyv/xAAaEAEAAwEBAQAAAAAAAAAAAAABABARQSEx/9oACAEBAAE/Idh7CLWvrN7MwPCjBEn1r//aAAwDAQACAAMAAAAQoMc8/8QAFBEBAAAAAAAAAAAAAAAAAAAAIP/aAAgBAwEBPxAf/8QAFBEBAAAAAAAAAAAAAAAAAAAAIP/aAAgBAgEBPxAf/8QAHBABAAICAwEAAAAAAAAAAAAAAREhABAxQVHh/9oACAEBAAE/EIsuFHuMElMB3onlBEOTDWFgA9PuuGD09mv/2Q==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/485a23c6db6fa5273fbf6fd1bee9ad06/8ac56/search.webp 240w,
/static/485a23c6db6fa5273fbf6fd1bee9ad06/d3be9/search.webp 480w,
/static/485a23c6db6fa5273fbf6fd1bee9ad06/0ba47/search.webp 640w&quot;
              sizes=&quot;(max-width: 640px) 100vw, 640px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/485a23c6db6fa5273fbf6fd1bee9ad06/09b79/search.jpg 240w,
/static/485a23c6db6fa5273fbf6fd1bee9ad06/7cc5e/search.jpg 480w,
/static/485a23c6db6fa5273fbf6fd1bee9ad06/c08c5/search.jpg 640w&quot;
            sizes=&quot;(max-width: 640px) 100vw, 640px&quot;
            type=&quot;image/jpeg&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/485a23c6db6fa5273fbf6fd1bee9ad06/c08c5/search.jpg&quot;
            alt=&quot;search&quot;
            title=&quot;search&quot;
            loading=&quot;lazy&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;hamcrest&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#hamcrest&quot; aria-label=&quot;hamcrest permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Hamcrest&lt;/h2&gt;
&lt;p&gt;I think &lt;a href=&quot;http://hamcrest.org/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Hamcrest&lt;/a&gt; is the most popular assertion library available in Java and Kotlin ecosystem. Let us look at an oversimplified example of &lt;a href=&quot;https://martinfowler.com/bliki/ValueObject.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Money&lt;/code&gt;&lt;/a&gt; class:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;kotlin&quot;&gt;&lt;pre class=&quot;language-kotlin&quot;&gt;&lt;code class=&quot;language-kotlin&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; java&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;math&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;BigDecimal
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; java&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;util&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Money&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; amount&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; BigDecimal&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; currency&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Currency&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;operator&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;plus&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;other&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Money&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Money &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;currency &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; other&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;currency&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;IllegalArgumentException&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Cannot add &lt;span class=&quot;token interpolation variable&quot;&gt;$this&lt;/span&gt; to &lt;span class=&quot;token interpolation variable&quot;&gt;$other&lt;/span&gt;. Currencies must match.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

        &lt;span class=&quot;token comment&quot;&gt;// an accidentally introduced bug 😈&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; newAmount &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; amount &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; other&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;amount &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10.0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toBigDecimal&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;copy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;amount &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; newAmount&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Imagine we write a test for the &lt;a href=&quot;https://kotlinlang.org/docs/reference/operator-overloading.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;plus&lt;/code&gt;&lt;/a&gt; operator using &lt;a href=&quot;http://junit.org/junit5/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;JUnit&lt;/a&gt; and &lt;a href=&quot;http://hamcrest.org/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Hamcrest&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;class MoneyTests {
    val usd = Currency.getInstance(&amp;quot;USD&amp;quot;)

    @Test
    fun can_add() {
        val usd100 = Money(100.toBigDecimal(), usd)
        val usd50 = Money(50.toBigDecimal(), usd)

        assertThat((usd100 + usd50).amount, equalTo(150.toBigDecimal()))
    }
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The test will fail with the following message:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;java.lang.AssertionError: 
Expected: &amp;lt;150&amp;gt;
     but: was &amp;lt;160&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Let’s see how we can improve on that.&lt;/p&gt;
&lt;h2 id=&quot;shouldko-better-assertion-messages-for-kotlin&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#shouldko-better-assertion-messages-for-kotlin&quot; aria-label=&quot;shouldko better assertion messages for kotlin permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;ShouldKO: better assertion messages for Kotlin&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/miensol/shouldko&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;ShouldKO&lt;/a&gt; is a simple library I’ve come up with that improves the assertion messages. Its idea is based on assertion libraries available in .NET e.g. &lt;a href=&quot;https://github.com/shouldly/shouldly&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Shouldly&lt;/a&gt;. Let us see how the tests looks like using &lt;a href=&quot;https://github.com/miensol/shouldko&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;ShouldKO&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;kotlin&quot;&gt;&lt;pre class=&quot;language-kotlin&quot;&gt;&lt;code class=&quot;language-kotlin&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; MoneyTests &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; usd &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Currency&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getInstance&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;USD&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token annotation builtin&quot;&gt;@Test&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;can_add&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; usd100 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Money&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toBigDecimal&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; usd&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; usd50 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Money&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;50&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toBigDecimal&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; usd&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;usd100 &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; usd50&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;amount&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;shouldEqual&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;150&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toBigDecimal&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In my opinion &lt;a href=&quot;https://github.com/miensol/shouldko&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;ShouldKO’s&lt;/a&gt; assertion syntax improves readability. However, this is not where &lt;a href=&quot;https://github.com/miensol/shouldko&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;ShouldKO&lt;/a&gt; main improvement is. Follow the improved assertion message:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;java.lang.AssertionError: (usd100 + usd50).amount 
Expected: &amp;lt;150&amp;gt;
     but: was &amp;lt;160&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/miensol/shouldko&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;ShouldKO&lt;/a&gt; incorporates a source code line with the assertion into the assertion message itself. This comes really handy when we have multiple lines with assertions that form one logical condition. This is a small thing, but can greatly improve debugging test issues especially when all we have is a log file produced by a test run.&lt;/p&gt;
&lt;h2 id=&quot;installation-of-shouldko&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#installation-of-shouldko&quot; aria-label=&quot;installation of shouldko permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Installation of ShouldKO&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/miensol/shouldko&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;ShouldKO&lt;/a&gt; is currently available on &lt;a href=&quot;https://jitpack.io/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Jitpack&lt;/a&gt;. You need to first add Jitpack to your repositories:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;groovy&quot;&gt;&lt;pre class=&quot;language-groovy&quot;&gt;&lt;code class=&quot;language-groovy&quot;&gt;repositories &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    maven &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; url &lt;span class=&quot;token string&quot;&gt;&apos;https://jitpack.io&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;mavenCentral&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And include the library in your tests e.g.:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;groovy&quot;&gt;&lt;pre class=&quot;language-groovy&quot;&gt;&lt;code class=&quot;language-groovy&quot;&gt;testImplementation &lt;span class=&quot;token string&quot;&gt;&apos;com.github.miensol.shouldko:hamcrest:v0.1.0&apos;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/miensol/shouldko&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;ShouldKO’s&lt;/a&gt; Hamcrest library allows for using any Hamcrest matcher.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Multi tenancy task scheduler]]></title><description><![CDATA[Last time I showed how to extend Spring default request handler adapter so that we are able to schedule or reject incoming requests. The goal of the  is to: queue requests for processing limit the maximum number of concurrently processed requests reject requests after the maximum queue size is reached interrupt…]]></description><link>undefined/multi-tenancy-task-scheduler/</link><guid isPermaLink="false">undefined/multi-tenancy-task-scheduler/</guid><pubDate>Thu, 04 Jan 2018 22:14:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;/spring-mvc-multi-tenacy&quot;&gt;Last time I showed&lt;/a&gt; how to extend Spring default request handler adapter so that we are able to schedule or reject incoming requests. The goal of the &lt;code class=&quot;language-text&quot;&gt;TenantTaskCoordinator&lt;/code&gt; is to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;queue requests for processing&lt;/li&gt;
&lt;li&gt;limit the maximum number of concurrently processed requests&lt;/li&gt;
&lt;li&gt;reject requests after the maximum queue size is reached&lt;/li&gt;
&lt;li&gt;interrupt processing of a request upon an upstream subscription disposal&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/84438e01403d72940530a0f6a1e38c27/c08c5/sorting.jpg&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: 66.66666666666666%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAMBBAX/xAAVAQEBAAAAAAAAAAAAAAAAAAACAf/aAAwDAQACEAMQAAABsQlIWmJFP//EABoQAQADAAMAAAAAAAAAAAAAAAEAAgMREiH/2gAIAQEAAQUCtomndmfppXm4MzUr/8QAGREAAgMBAAAAAAAAAAAAAAAAAAIBETFB/9oACAEDAQE/AVeuE6f/xAAVEQEBAAAAAAAAAAAAAAAAAAABAP/aAAgBAgEBPwFIv//EAB0QAAICAQUAAAAAAAAAAAAAAAABESEQEjJRYYH/2gAIAQEABj8Canw3Msd9kanxj//EABsQAAMBAAMBAAAAAAAAAAAAAAERIQAxQWHB/9oACAEBAAE/IRMPmNghU9yNq8nNhjovMKoj8ZbJd3//2gAMAwEAAgADAAAAEJvv/8QAFxEBAQEBAAAAAAAAAAAAAAAAAQARIf/aAAgBAwEBPxDR2PUl/8QAFxEBAQEBAAAAAAAAAAAAAAAAAQAhQf/aAAgBAgEBPxB+MMv/xAAbEAEBAAMBAQEAAAAAAAAAAAABEQAhMUFh8P/aAAgBAQABPxBE1eLNAupcdZQ19foZT2amzXmN3w0qP3dcxIKPSqQIm8iI+mS5/9k=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/84438e01403d72940530a0f6a1e38c27/8ac56/sorting.webp 240w,
/static/84438e01403d72940530a0f6a1e38c27/d3be9/sorting.webp 480w,
/static/84438e01403d72940530a0f6a1e38c27/0ba47/sorting.webp 640w&quot;
              sizes=&quot;(max-width: 640px) 100vw, 640px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/84438e01403d72940530a0f6a1e38c27/09b79/sorting.jpg 240w,
/static/84438e01403d72940530a0f6a1e38c27/7cc5e/sorting.jpg 480w,
/static/84438e01403d72940530a0f6a1e38c27/c08c5/sorting.jpg 640w&quot;
            sizes=&quot;(max-width: 640px) 100vw, 640px&quot;
            type=&quot;image/jpeg&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/84438e01403d72940530a0f6a1e38c27/c08c5/sorting.jpg&quot;
            alt=&quot;Assigning resources&quot;
            title=&quot;Assigning resources&quot;
            loading=&quot;lazy&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;tenant-task-coordinator-execute-method&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#tenant-task-coordinator-execute-method&quot; aria-label=&quot;tenant task coordinator execute method permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Tenant task coordinator execute method&lt;/h2&gt;
&lt;p&gt;Our entry point into &lt;code class=&quot;language-text&quot;&gt;TenantTaskCoordinator&lt;/code&gt; is a single method &lt;code class=&quot;language-text&quot;&gt;fun &amp;lt;T : Any&amp;gt; execute(job: Callable&amp;lt;T&amp;gt;): Mono&amp;lt;T&amp;gt;&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;kotlin&quot;&gt;&lt;pre class=&quot;language-kotlin&quot;&gt;&lt;code class=&quot;language-kotlin&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;T &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Any&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;execute&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;job&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Callable&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;T&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Mono&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;T&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Mono&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; outsideSink &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; _workInProgressWasDecremented &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;AtomicBoolean&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;decrementOnce&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;_workInProgressWasDecremented&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;compareAndSet&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                    currentWorkInProgressCounter&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;decrementAndGet&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

            &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; workInProgress &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; currentWorkInProgressCounter&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;incrementAndGet&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;workInProgress &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; maximumWorkInProgress&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                outsideSink&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;TooManyTasks&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Work in progress &lt;span class=&quot;token interpolation variable&quot;&gt;$workInProgress&lt;/span&gt; exceeds &lt;span class=&quot;token interpolation variable&quot;&gt;$maximumWorkInProgress&lt;/span&gt; jobs in &lt;span class=&quot;token interpolation variable&quot;&gt;$name&lt;/span&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;token function&quot;&gt;decrementOnce&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; singleJob &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Mono&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fromCallable&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;job&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;doAfterTerminate&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                    &lt;span class=&quot;token function&quot;&gt;decrementOnce&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

                &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; delayedTask &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Task&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; singleJob &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; Mono&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Any&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; outsideSink &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; MonoSink&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Any&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

                outsideSink&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;onCancel&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                    delayedTask&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;outsideCancel&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                    &lt;span class=&quot;token function&quot;&gt;decrementOnce&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
                
                taskSink&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;delayedTask&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The first step is to return &lt;code class=&quot;language-text&quot;&gt;Mono&amp;lt;T&amp;gt;&lt;/code&gt; which is simply done with &lt;a href=&quot;https://projectreactor.io/docs/core/release/api/reactor/core/publisher/Mono.html#create-java.util.function.Consumer-&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Mono.create&lt;/code&gt;&lt;/a&gt;. The &lt;code class=&quot;language-text&quot;&gt;sink&lt;/code&gt; we get passed is used to control the outcome observed from outside. It also allows for registering an &lt;a href=&quot;https://projectreactor.io/docs/core/release/api/reactor/core/publisher/MonoSink.html#onCancel-reactor.core.Disposable-&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;onCancel&lt;/code&gt;&lt;/a&gt; callback invoked when the upstream cancels its subscription.&lt;/p&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;_workInProgressWasDecremented&lt;/code&gt; is used to guard and decrement the &lt;code class=&quot;language-text&quot;&gt;currentWorkInProgressCounter&lt;/code&gt; in a thread safe fashion. We first check whether we have immediately exceeded the maximum number of queued jobs. If the threshold is reached, we notify the observer about the error with &lt;a href=&quot;https://projectreactor.io/docs/core/release/api/reactor/core/publisher/MonoSink.html#error-java.lang.Throwable-&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;outsideSink.error&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If we have enough capacity to a perform &lt;code class=&quot;language-text&quot;&gt;job&lt;/code&gt;, we convert it to a reactive world with &lt;a href=&quot;https://projectreactor.io/docs/core/release/api/reactor/core/publisher/Mono.html#fromCallable-java.util.concurrent.Callable-&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Mono.fromCallable&lt;/code&gt;&lt;/a&gt; and attach a &lt;a href=&quot;https://projectreactor.io/docs/core/release/api/reactor/core/publisher/Mono.html#doAfterTerminate-java.lang.Runnable-&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;doAfterTerminate&lt;/code&gt;&lt;/a&gt; callback that decrements the work in progress counter. The &lt;code class=&quot;language-text&quot;&gt;Task&lt;/code&gt; class links &lt;code class=&quot;language-text&quot;&gt;singleJob&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;outsideSink&lt;/code&gt; so that they are both accessible while processing. Finally, we schedule the &lt;code class=&quot;language-text&quot;&gt;task&lt;/code&gt; through &lt;code class=&quot;language-text&quot;&gt;taskSink.next(delayedTask)&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;task-coordinator-state&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#task-coordinator-state&quot; aria-label=&quot;task coordinator state permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Task coordinator state&lt;/h2&gt;
&lt;p&gt;Let’s have a look at the task coordinator state variables and how they are initialized:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;kotlin&quot;&gt;&lt;pre class=&quot;language-kotlin&quot;&gt;&lt;code class=&quot;language-kotlin&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;TenantTaskCoordinator&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; scheduler&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Scheduler&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                            &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; maximumConcurrency&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Int &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                            &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; maximumQueueSize&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Int &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;50&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                            &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; String &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; AutoCloseable &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; maximumWorkInProgress &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; maximumQueueSize &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; maximumConcurrency

    &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; maxBufferSize &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; maximumWorkInProgress &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; currentWorkInProgressCounter &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;AtomicInteger&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;lateinit&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; taskSink&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; FluxSink&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Task&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; taskSource &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Flux&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;create&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Task&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; taskSink &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; it &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; FluxSink&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;OverflowStrategy&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;BUFFER&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; processSinkOnErrorResume &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;processSinkWithLimitedConcurrency&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;onErrorResume&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; error&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Throwable&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
            LOG&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;warn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;name={} Error processing sink with limited concurrency&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;processSinkWithLimitedConcurrency&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The first interesting part is how we setup &lt;code class=&quot;language-text&quot;&gt;taskSink&lt;/code&gt; by using &lt;a href=&quot;https://projectreactor.io/docs/core/release/api/reactor/core/publisher/Flux.html#create-java.util.function.Consumer-reactor.core.publisher.FluxSink.OverflowStrategy-&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Flux.create&lt;/code&gt;&lt;/a&gt;. For clarity, we explicitly pass &lt;code class=&quot;language-text&quot;&gt;FluxSink.OverflowStrategy.BUFFER&lt;/code&gt; so that tasks are buffered in case they outpace the processor. The &lt;code class=&quot;language-text&quot;&gt;name&lt;/code&gt; is used to get better log messages. Finally, we call &lt;code class=&quot;language-text&quot;&gt;processSinkWithLimitedConcurrency&lt;/code&gt; to start task processing using the given &lt;code class=&quot;language-text&quot;&gt;scheduler&lt;/code&gt;. Interestingly the &lt;code class=&quot;language-text&quot;&gt;onErrorResume&lt;/code&gt; restarts the processing in case we have a bug.&lt;/p&gt;
&lt;h2 id=&quot;task-coordinator-concurrent-processing&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#task-coordinator-concurrent-processing&quot; aria-label=&quot;task coordinator concurrent processing permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Task coordinator concurrent processing&lt;/h2&gt;
&lt;p&gt;The most important and tricky to figure out part is to correctly process jobs. It took me several back and forth steps until I got the order of reactive API calls right.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;kotlin&quot;&gt;&lt;pre class=&quot;language-kotlin&quot;&gt;&lt;code class=&quot;language-kotlin&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;processSinkWithLimitedConcurrency&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Flux&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Any&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; taskSource
            &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;filter&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;it&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isCancelled &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;flatMap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; task &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
                task&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;work
                    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;doOnError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;task&lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt;onError&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;doOnSuccess&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;task&lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt;onSuccess&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;subscribeOn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;scheduler&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;timeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;task&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;outsideTimeout&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;onErrorReturn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;task&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; maximumConcurrency&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; maxBufferSize&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;First, we filter out tasks that are already cancelled. Then, we use &lt;a href=&quot;https://projectreactor.io/docs/core/release/api/reactor/core/publisher/Flux.html#flatMap-java.util.function.Function-int-int-&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;flatMap&lt;/code&gt;&lt;/a&gt; overload to process tasks with given maximum concurrency. The &lt;code class=&quot;language-text&quot;&gt;flatMap&lt;/code&gt; callback delegates most of the work to the mentioned &lt;code class=&quot;language-text&quot;&gt;Task&lt;/code&gt; instance. The &lt;code class=&quot;language-text&quot;&gt;onErrorReturn&lt;/code&gt; effectively suppresses any errors that might occur during &lt;code class=&quot;language-text&quot;&gt;task&lt;/code&gt; execution. Let’s see how the inner &lt;code class=&quot;language-text&quot;&gt;Task&lt;/code&gt; class looks like:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;kotlin&quot;&gt;&lt;pre class=&quot;language-kotlin&quot;&gt;&lt;code class=&quot;language-kotlin&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Task&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                            &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; job&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Mono&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Any&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                            &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; outsideSink&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; MonoSink&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Any&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                            &lt;span class=&quot;token annotation builtin&quot;&gt;@field:Volatile&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; isCancelled&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Boolean &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; work&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Mono&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Any&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;isCancelled&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; Mono&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;empty&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; job

        &lt;span class=&quot;token keyword&quot;&gt;lateinit&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; outsideTimeoutSink&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; MonoSink&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Task&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; outsideTimeout &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Mono&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;create&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Task&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; outsideTimeoutSink &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; it &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;outsideCancel&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            isCancelled &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;
            outsideTimeoutSink&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;success&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;onSuccess&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Any&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            outsideSink&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;success&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        
        &lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;onError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Throwable&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            LOG&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;warn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Task.onError {}&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            outsideSink&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;job&lt;/code&gt; argument is the &lt;code class=&quot;language-text&quot;&gt;Callable&lt;/code&gt; passed to the &lt;code class=&quot;language-text&quot;&gt;execute&lt;/code&gt; method. The &lt;code class=&quot;language-text&quot;&gt;outsideTimeout&lt;/code&gt; signals when the &lt;code class=&quot;language-text&quot;&gt;task&lt;/code&gt; instance subscription is cancelled. The signal is propagated inside &lt;code class=&quot;language-text&quot;&gt;processSinkWithLimitedConcurrency&lt;/code&gt; with a &lt;a href=&quot;https://projectreactor.io/docs/core/release/api/reactor/core/publisher/Mono.html#timeout-org.reactivestreams.Publisher-&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Mono.timeout&lt;/code&gt;&lt;/a&gt; call and breaks the &lt;code class=&quot;language-text&quot;&gt;task&lt;/code&gt; processing. Last but not least the &lt;code class=&quot;language-text&quot;&gt;onSuccess&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;onError&lt;/code&gt; simply push the result or error to the &lt;code class=&quot;language-text&quot;&gt;outsideSink&lt;/code&gt; effectively notifying the observer of the result.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://gist.github.com/miensol/1e2b203a128cdc428f3b0c598e515bd6&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;TenantTaskCoordinator&lt;/code&gt;&lt;/a&gt; was not simple to figure out given the requirements mentioned at the begging of the post. I’m pleased with the final result although I must say it was not intuitive to figure out how to combine all the nuts and bolts of &lt;a href=&quot;https://projectreactor.io/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Reactor&lt;/a&gt; library to achieve the desired outcome.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Multi tenancy in Spring MVC]]></title><description><![CDATA[One of our clients aimed to replace old, often DOS based, point of sale systems with a cloud based, SaaS modeled solution. [At Bright Inventions]({{ site.url }}) we have developed all required components including AWS based back-end processing requests originating from multiple clients. Each business that uses the SaaS…]]></description><link>undefined/spring-mvc-multi-tenacy/</link><guid isPermaLink="false">undefined/spring-mvc-multi-tenacy/</guid><pubDate>Tue, 12 Dec 2017 22:14:00 GMT</pubDate><content:encoded>&lt;p&gt;One of our clients aimed to replace old, often DOS based, point of sale systems with a cloud based, SaaS modeled solution. [At Bright Inventions]({{ site.url }}) we have developed all required components including AWS based back-end processing requests originating from multiple clients. Each business that uses the SaaS point of sale can be considered a tenant in a multi-tenant environment. There many aspects involved when developing multi-tenant application with &lt;a href=&quot;http://blog.memsql.com/database-multi-tenancy-in-the-cloud-and-beyond/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;data isolation and partitioning being the most discussed topic&lt;/a&gt;. However, today I would like to focus on computational and resource isolation aspect.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/65e9deab4d4cfc809010da9861f98e48/c08c5/feeding-animals.jpg&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(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAPABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAMEAQL/xAAVAQEBAAAAAAAAAAAAAAAAAAAAAf/aAAwDAQACEAMQAAABYvucvMLP/8QAGBABAQEBAQAAAAAAAAAAAAAAAQIAAwT/2gAIAQEAAQUCZgBhxG6cqrT5kxKb/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAGxAAAQQDAAAAAAAAAAAAAAAAAAERITICMXH/2gAIAQEABj8CkVlbpYjIsbP/xAAaEAADAAMBAAAAAAAAAAAAAAAAAREhQYFx/9oACAEBAAE/Ibd2ntM1ZOei6xXTJs6NAklH/9oADAMBAAIAAwAAABDYL//EABURAQEAAAAAAAAAAAAAAAAAABAh/9oACAEDAQE/EIf/xAAVEQEBAAAAAAAAAAAAAAAAAAAQIf/aAAgBAgEBPxCn/8QAHBABAAMAAgMAAAAAAAAAAAAAAQARITFBUWGB/9oACAEBAAE/EDwXoLQeMlmYEuEWyoGrGSw1OlkQX7J5hFfKf//Z&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/65e9deab4d4cfc809010da9861f98e48/8ac56/feeding-animals.webp 240w,
/static/65e9deab4d4cfc809010da9861f98e48/d3be9/feeding-animals.webp 480w,
/static/65e9deab4d4cfc809010da9861f98e48/0ba47/feeding-animals.webp 640w&quot;
              sizes=&quot;(max-width: 640px) 100vw, 640px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/65e9deab4d4cfc809010da9861f98e48/09b79/feeding-animals.jpg 240w,
/static/65e9deab4d4cfc809010da9861f98e48/7cc5e/feeding-animals.jpg 480w,
/static/65e9deab4d4cfc809010da9861f98e48/c08c5/feeding-animals.jpg 640w&quot;
            sizes=&quot;(max-width: 640px) 100vw, 640px&quot;
            type=&quot;image/jpeg&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/65e9deab4d4cfc809010da9861f98e48/c08c5/feeding-animals.jpg&quot;
            alt=&quot;Multiple consumers&quot;
            title=&quot;Multiple consumers&quot;
            loading=&quot;lazy&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;controlled-resource-usage&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#controlled-resource-usage&quot; aria-label=&quot;controlled resource usage permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Controlled resource usage&lt;/h2&gt;
&lt;p&gt;In the discussed case each tenant would have multiple iOS based API clients. The exact number varies from 1 to couple of dozens. Each iOS application would be open constantly throughout a sales day and execute frequent requests against the back-end API. In the iOS application there was a code that polls the server for data changes in frequent and regular intervals. Unfortunately a bug slipped through a code review and caused the app to ask the server for changes around 50 times per second instead of once in half of a minute. The bug caused an explosion of API requests issued by a single API client with a throughput 10 to 100 times bigger than expected. To make things worse the rate at which the bug increased polling frequency exceeded back-end the scaling out policy. Soon all request processing threads were busy processing requests issued by only a small percentile of API clients.&lt;/p&gt;
&lt;p&gt;In a multi-tenant application one needs to take special care to prevent tenant “A” from affecting, even indirectly, tenant “B” operations. We have failed that requirement on the CPU/thread pool level and that caused the support lines to be hot.&lt;/p&gt;
&lt;h2 id=&quot;reverse-proxy-request-rate-limit&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#reverse-proxy-request-rate-limit&quot; aria-label=&quot;reverse proxy request rate limit permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Reverse proxy request rate limit&lt;/h2&gt;
&lt;p&gt;The first solution that comes to mind is to apply a per API client request rate limiting. In fact this solution is so common that it is available as a configuration opt-in in many servers. For instance &lt;a href=&quot;https://www.nginx.com/blog/rate-limiting-nginx/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;in NGINX you could do&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;limit_req_zone $binary_remote_addr zone=mylimit:10m rate=10r/s;

server {
    location /login/ {
        limit_req zone=mylimit burst=20;

        proxy_pass http://my_upstream;
    }
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The above would only allow up to 10 request per second from the same IP address. Any request that comes in at higher rate would be queued up to specified capacity (&lt;code class=&quot;language-text&quot;&gt;burst=20&lt;/code&gt;). Any request above the limit would get rejected with 503 status code.&lt;/p&gt;
&lt;p&gt;The nginx approach is battle tested and fairly easy to apply. Instead of using IP address it would be better to group requests by a tenant identifier. However, it may not be easy to determine exactly which tenant is making the request unless the information is easily available in the request headers. For that matter it is good to consider sending the API client identification using a custom HTTP header. For instance if the API client provides &lt;code class=&quot;language-text&quot;&gt;X-Tenant-Id: tenant.1&lt;/code&gt; you can use it as &lt;code class=&quot;language-text&quot;&gt;limit_req_zone $http_x_tenant_id zone=mylimit:10m rate=10r/s;&lt;/code&gt;. When using JWT, you often can determine &lt;em&gt;who&lt;/em&gt; is making the request by parsing the &lt;code class=&quot;language-text&quot;&gt;Authorization&lt;/code&gt; header value.&lt;/p&gt;
&lt;h2 id=&quot;spring-mvc-request-rate-limit&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#spring-mvc-request-rate-limit&quot; aria-label=&quot;spring mvc request rate limit permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Spring MVC request rate limit&lt;/h2&gt;
&lt;p&gt;It is often not feasible to apply the request rate limit at the reverse proxy level. In such scenario we can apply the limit inside Spring MVC application. For start one can try suing &lt;a href=&quot;http://www.oracle.com/technetwork/java/filters-137243.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Servlet Filter&lt;/a&gt;. &lt;a href=&quot;https://stackoverflow.com/questions/10127472/servlet-filter-very-simple-rate-limiting-filter-allowing-bursts&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;There are several solutions&lt;/a&gt; available including a &lt;a href=&quot;https://www.eclipse.org/jetty/javadoc/9.4.7.v20170914/org/eclipse/jetty/servlets/DoSFilter.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;DoSFilter that is part of Jetty project&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Using a ready-made Servlet Filter is often sufficient especially when the available customization options suit our needs. In case of our client however, we wanted the limits to depend on the &lt;em&gt;size&lt;/em&gt; of the client. In other words the more service you buy, the more resources are available to you. Moreover, I wanted to have a have fine-grained control at &lt;strong&gt;a controller action&lt;/strong&gt; level. To my surprise such behavior was not easy to accomplish using &lt;a href=&quot;https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/servlet/AsyncHandlerInterceptor.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;AsyncHandlerInterceptor&lt;/a&gt;. Fortunately I did find a way to achieve a desired result using a mix of extensibility points and hacks.&lt;/p&gt;
&lt;p&gt;The first step is to customize &lt;a href=&quot;https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerAdapter.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;RequestMappingHandlerAdapter&lt;/code&gt;&lt;/a&gt; used by Spring MVC to transform &lt;code class=&quot;language-text&quot;&gt;@RequestMapping&lt;/code&gt; annotation into handler classes. The following configuration class in Kotlin achieves just that:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;kotlin&quot;&gt;&lt;pre class=&quot;language-kotlin&quot;&gt;&lt;code class=&quot;language-kotlin&quot;&gt;&lt;span class=&quot;token annotation builtin&quot;&gt;@Configuration&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; WebMvcConfiguration &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;DelegatingWebMvcConfiguration&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;token annotation builtin&quot;&gt;@Autowired&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;required &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; mvcProperties&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; WebMvcProperties&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;

    &lt;span class=&quot;token annotation builtin&quot;&gt;@Inject&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;lateinit&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; reactiveRequestCommandFactory&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; ReactiveRequestCommandFactory
    &lt;span class=&quot;token annotation builtin&quot;&gt;@Inject&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;lateinit&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; reactiveRequestsProperties&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; ReactiveRequestsConfiguration&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;RequestsProperties

    &lt;span class=&quot;token annotation builtin&quot;&gt;@Bean&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;requestMappingHandlerAdapter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; RequestMappingHandlerAdapter &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;//copy pasted from WebMvcConfigurationSupport&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; argumentResolvers &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ArrayList&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;HandlerMethodArgumentResolver&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;addArgumentResolvers&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;argumentResolvers&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; returnValueHandlers &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ArrayList&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;HandlerMethodReturnValueHandler&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;addReturnValueHandlers&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;returnValueHandlers&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; adapter &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;RateLimitingRequestMappingHandlerAdapter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;reactiveRequestCommandFactory&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; reactiveRequestsProperties&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

        adapter&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setContentNegotiationManager&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;mvcContentNegotiationManager&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        adapter&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;messageConverters &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; messageConverters
        adapter&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;webBindingInitializer &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; configurableWebBindingInitializer
        adapter&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;customArgumentResolvers &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; argumentResolvers

        adapter&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;customReturnValueHandlers &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; returnValueHandlers

        &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; requestBodyAdvices &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ArrayList&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;RequestBodyAdvice&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        requestBodyAdvices&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;JsonViewRequestBodyAdvice&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        adapter&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setRequestBodyAdvice&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;requestBodyAdvices&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; responseBodyAdvices &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ArrayList&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;ResponseBodyAdvice&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        responseBodyAdvices&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;JsonViewResponseBodyAdvice&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        adapter&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setResponseBodyAdvice&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;responseBodyAdvices&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;token function&quot;&gt;configureAsync&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;adapter&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;


        adapter&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setIgnoreDefaultModelOnRedirect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;mvcProperties&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isIgnoreDefaultModelOnRedirect &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; adapter
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;configureAsync&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;adapter&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; RequestMappingHandlerAdapter&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;//expose field publicly&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; configurer &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;AsyncSupportConfigurer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getTaskExecutor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getTaskExecutor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getCallableInterceptors&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getCallableInterceptors&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getDeferredResultInterceptors&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getDeferredResultInterceptors&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

        &lt;span class=&quot;token function&quot;&gt;configureAsyncSupport&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;configurer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;configurer&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;taskExecutor &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            adapter&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setTaskExecutor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;configurer&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;taskExecutor&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;configurer&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;timeout &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            adapter&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setAsyncRequestTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;configurer&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;timeout&lt;span class=&quot;token operator&quot;&gt;!!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

        adapter&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setCallableInterceptors&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;configurer&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;callableInterceptors&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        adapter&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setDeferredResultInterceptors&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;configurer&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;deferredResultInterceptors&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Note that we are injecting &lt;code class=&quot;language-text&quot;&gt;reactiveRequestCommandFactory&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;reactiveRequestsProperties&lt;/code&gt; and pass them into our core &lt;code class=&quot;language-text&quot;&gt;RateLimitingRequestMappingHandlerAdapter&lt;/code&gt;. All other code is a mostly a copy-paste from &lt;code class=&quot;language-text&quot;&gt;DelegatingWebMvcConfiguration&lt;/code&gt; base class.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;kotlin&quot;&gt;&lt;pre class=&quot;language-kotlin&quot;&gt;&lt;code class=&quot;language-kotlin&quot;&gt;&lt;span class=&quot;token annotation builtin&quot;&gt;@Target&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;AnnotationTarget&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;CLASS&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; AnnotationTarget&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;FUNCTION&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;annotation&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;RequestCommand&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; enabled&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Boolean &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; timeoutInMillis&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Int &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;60_000&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;RateLimitingRequestMappingHandlerAdapter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; reactiveRequestCommandFactory&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; ReactiveRequestCommandFactory&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                                               &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; reactiveRequestProperties&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; ReactiveRequestsConfiguration&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;RequestsProperties&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;RequestMappingHandlerAdapter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; handlerMethodConfigurationsCache &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ConcurrentHashMap&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;HandlerMethod&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; RequestCommandConfiguration&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createInvocableHandlerMethod&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;handlerMethod&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; HandlerMethod&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; ServletInvocableHandlerMethod&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; configuration &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;requestCommandConfigurationFor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;handlerMethod&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;when&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            configuration&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;enabled &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; reactiveRequestProperties&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;enabled &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;CommandInvocableHandlerMethod&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;handlerMethod&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; reactiveRequestCommandFactory&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; configuration&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createInvocableHandlerMethod&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;handlerMethod&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;requestCommandConfigurationFor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;handlerMethod&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; HandlerMethod&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; RequestCommandConfiguration &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; handlerMethodConfigurationsCache&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getOrPut&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;handlerMethod&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; method &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; handlerMethod&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getMethodAnnotation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;RequestCommand&lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;java&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; methodOrController &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; method &lt;span class=&quot;token operator&quot;&gt;?:&lt;/span&gt; AnnotatedElementUtils&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;findMergedAnnotation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;handlerMethod&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;beanType&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; RequestCommand&lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;java&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            methodOrController&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;RequestCommandConfiguration&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;it&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;?:&lt;/span&gt; RequestCommandConfiguration&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Default
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Inside of &lt;code class=&quot;language-text&quot;&gt;createInvocableHandlerMethod&lt;/code&gt; we get the configuration for the &lt;code class=&quot;language-text&quot;&gt;handlerMethod&lt;/code&gt; determined by Spring MVC. The &lt;code class=&quot;language-text&quot;&gt;handlerMethod&lt;/code&gt; denotes a controller action. Then we decide if we should use the rate limiting handler or fallback to the default one. In case we need to apply rate limiting we switch the invocation to use custom &lt;code class=&quot;language-text&quot;&gt;CommandInvocableHandlerMethod&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;kotlin&quot;&gt;&lt;pre class=&quot;language-kotlin&quot;&gt;&lt;code class=&quot;language-kotlin&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;CommandInvocableHandlerMethod&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; handlerMethod&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; HandlerMethod&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                                    &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; requestCommandFactory&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; RequestCommandFactory&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                                    &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; configuration&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; RequestCommandConfiguration&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;ServletInvocableHandlerMethod&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;handlerMethod&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;lateinit&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; returnValueHandlers&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; HandlerMethodReturnValueHandlerComposite

    &lt;span class=&quot;token keyword&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;invokeForRequest&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; NativeWebRequest&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; mavContainer&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; ModelAndViewContainer&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;vararg&lt;/span&gt; providedArgs&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Any&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Any &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// same as super.invokeForRequest(request, mavContainer, *providedArgs)&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// but with request passed to do invoke&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; args &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;getMethodArgumentValuesCallable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;invoke&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; mavContainer&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; providedArgs&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;doInvokeWithRequest&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; args&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; result
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;doInvokeWithRequest&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; NativeWebRequest&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; args&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Array&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;out&lt;/span&gt; Any&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Any &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; nativeRequest &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; request&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getNativeRequest&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;HttpServletRequest&lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;java&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;token comment&quot;&gt;// If the response has already set error status code tomcat will not wait for async result&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;nativeRequest &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; nativeRequest&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;dispatcherType &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; DispatcherType&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;REQUEST&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; callSuper &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Callable &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;doInvoke&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;args &lt;span class=&quot;token operator&quot;&gt;?:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;emptyArray&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

            &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; job &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; callSuper

            &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; context &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;RequestCommandContext&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;configuration&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; handlerMethod&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; SecurityContextHolder&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getContext&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; job&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

            &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; requestCommandFactory&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createSingle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;context&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

            &lt;span class=&quot;token function&quot;&gt;MonoDeferredResult&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;doInvoke&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;args &lt;span class=&quot;token operator&quot;&gt;?:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;emptyArray&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;setHandlerMethodReturnValueHandlers&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;returnValueHandlers&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; HandlerMethodReturnValueHandlerComposite&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;returnValueHandlers &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; returnValueHandlers&lt;span class=&quot;token operator&quot;&gt;!!&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setHandlerMethodReturnValueHandlers&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;returnValueHandlers&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;wrapConcurrentResult&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Any&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; ServletInvocableHandlerMethod &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;ConcurrentResultHandlerMethod&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;ConcurrentResultMethodParameter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token operator&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The above code is using &lt;em&gt;private&lt;/em&gt; &lt;a href=&quot;https://github.com/spring-projects/spring-framework/blob/cc74a28/spring-web/src/main/java/org/springframework/web/method/support/InvocableHandlerMethod.java#L147&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;getMethodArgumentValues&lt;/code&gt;&lt;/a&gt; API to achieve the desired behavior‼ The &lt;code class=&quot;language-text&quot;&gt;doInvokeWithRequest&lt;/code&gt; checks if an asynchronous dispatch should be performed and if so creates a &lt;a href=&quot;https://projectreactor.io/docs/core/release/api/reactor/core/publisher/Mono.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Mono&lt;/code&gt;&lt;/a&gt; that denotes the result of the controller action method invocation. &lt;code class=&quot;language-text&quot;&gt;RequestCommandContext&lt;/code&gt; stores the information about target controller action method and current security context. The security context needs to be preserved when invoking the controller action on a different thread. The &lt;a href=&quot;https://gist.github.com/miensol/cca73d158ce8e7664ed653a30fc8dc70&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;ConcurrentResultHandlerMethod&lt;/code&gt;&lt;/a&gt; extends &lt;code class=&quot;language-text&quot;&gt;ServletInvocableHandlerMethod&lt;/code&gt; to add support for using &lt;code class=&quot;language-text&quot;&gt;Mono&lt;/code&gt; on regular, synchronous controller action. The core logic of rate limiting is delegated to &lt;code class=&quot;language-text&quot;&gt;ReactiveRequestCommandFactory&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;kotlin&quot;&gt;&lt;pre class=&quot;language-kotlin&quot;&gt;&lt;code class=&quot;language-kotlin&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; ReactiveRequestCommandFactory &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createSingle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;context&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; RequestCommandContext&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Mono&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Optional&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Any&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The factory responsibilty it to convert a request context into an async result. Spring MVC 5 &lt;a href=&quot;https://docs.spring.io/spring-framework/docs/5.0.0.BUILD-SNAPSHOT/spring-framework-reference/html/web-reactive.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;has built in support for Reactor&lt;/a&gt; hence we decided to use this implementation of &lt;a href=&quot;http://www.reactive-streams.org/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Reactive Streams specification&lt;/a&gt;. The &lt;code class=&quot;language-text&quot;&gt;ReactiveRequestCommandFactory&lt;/code&gt; looks as follows:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;kotlin&quot;&gt;&lt;pre class=&quot;language-kotlin&quot;&gt;&lt;code class=&quot;language-kotlin&quot;&gt;&lt;span class=&quot;token annotation builtin&quot;&gt;@Component&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;ReactorRequestCommandFactory&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    threadPoolPropertiesCalculator&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; ThreadPoolPropertiesCalculator&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token annotation builtin&quot;&gt;@param:Named&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;reactiveRequestsScheduler&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; reactiveRequestsScheduler&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Schedule
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; ReactiveRequestCommandFactory &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; threadPoolPropertiesCalculator &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;HystrixConfigurationAwarePropertiesCalculator&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;threadPoolPropertiesCalculator&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; tenants &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ConcurrentHashMap&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;String&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; TenantTaskCoordinator&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createSingle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;context&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; RequestCommandContext&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Mono&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Optional&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Any&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; properties &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; threadPoolPropertiesCalculator&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;newThreadPoolProperties&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;context&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; taskCoordinator &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; tenants&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;computeIfAbsent&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;properties&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;threadPoolName&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;TenantTaskCoordinator&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;reactiveRequestsScheduler&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                maximumConcurrency &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; properties&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;maximumThreads&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                maximumQueueSize &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; properties&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;maximumQueueSize&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                name &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; properties&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;threadPoolName
            &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; optionalCallable &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;OptionalCallable&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;context&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;job&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; configureRequestAttributes &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;SpringServletRequestAttributesCallable&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;optionalCallable&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; configureLocale &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;SpringLocaleContextCallable&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;configureRequestAttributes&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; securityCallable &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;DelegatingSecurityContextCallable&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;configureLocale&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; context&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;securityContext&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; taskCoordinator&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;execute&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;securityCallable&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;timeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Duration&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;ofMillis&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;context&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;configuration&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;timeoutInMillis&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toLong&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;OptionalCallable&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;inner&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; RequestHandlerJob&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Callable&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Optional&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Any&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Optional&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Any&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Optional&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;ofNullable&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;inner&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;ThreadPoolPropertiesCalculator&lt;/code&gt; calculates how concurrent threads and how big the requests queue should be for particular tenant or tenants group. Then for each tenant group, in particular a single tenant, we create a &lt;code class=&quot;language-text&quot;&gt;TenantTaskCoordinator&lt;/code&gt; responsible for calculating and enforcing limits on concurrently handled requests. Further down we decorate the &lt;code class=&quot;language-text&quot;&gt;Callable&lt;/code&gt; representing the actual request handling with security delegation, locale configuration and request attributes setup. Finally, we ask the &lt;code class=&quot;language-text&quot;&gt;TenantTaskCoordinator&lt;/code&gt; to execute the decorated job with a configured timeout.&lt;/p&gt;
&lt;p&gt;The last piece of the puzzle, namely &lt;code class=&quot;language-text&quot;&gt;TenantTaskCoordinator&lt;/code&gt; requires a separate blog post so stay tuned.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Request timeouts in Spring MVC]]></title><description><![CDATA[As we saw previously, we only have limited options to configure maximum time a request processing can take in Spring MVC. In this post I will show how to enforce such timeout through a custom Servlet Filter.  Request timeout Servlet Filter Without further ado let us dive right into a sample filter implementation in…]]></description><link>undefined/spring-mvc-request-timeout/</link><guid isPermaLink="false">undefined/spring-mvc-request-timeout/</guid><pubDate>Tue, 28 Nov 2017 22:14:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;/spring-mvc-thread-pool-timeouts&quot;&gt;As we saw previously&lt;/a&gt;, we only have limited options to configure maximum time a request processing can take in Spring MVC. In this post I will show how to enforce such timeout through a custom &lt;a href=&quot;https://docs.oracle.com/cd/B14099_19/web.1012/b14017/filters.htm&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Servlet Filter&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 427px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/260dee5aa067d3fe9b30ade1867b6a4e/141dd/late.jpg&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: 150%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAeABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAQFAgP/xAAVAQEBAAAAAAAAAAAAAAAAAAACAf/aAAwDAQACEAMQAAABqJNrl1TAhzUpKRMGyn//xAAdEAACAgIDAQAAAAAAAAAAAAACAwABBBEQEyIy/9oACAEBAAEFAskyFSbYlkevtm62Hw2vFEJGNaGXjhfH/8QAGBEAAwEBAAAAAAAAAAAAAAAAAQIQESH/2gAIAQMBAT8BCwNzJ//EABYRAQEBAAAAAAAAAAAAAAAAAAEQEf/aAAgBAgEBPwFZk//EACAQAAEEAgEFAAAAAAAAAAAAAAIAARARITESAyJBYaH/2gAIAQEABj8C7dk9IR6hcmL5FaZvKxZe00MN5dVA1jjqo//EABwQAQEAAgMBAQAAAAAAAAAAAAERABAhMaFBUf/aAAgBAQABPyGScIX8udNW92tIczKaQ5iGeHLr3BOUFMnL5o6Fqpdc3X//2gAMAwEAAgADAAAAEGfeff/EABYRAQEBAAAAAAAAAAAAAAAAAAERAP/aAAgBAwEBPxCxkjMpha3f/8QAGBEBAQADAAAAAAAAAAAAAAAAAQAQESH/2gAIAQIBAT8Q0PIkLj//xAAgEAEBAAICAgIDAAAAAAAAAAABEQAhMUFRYRBxgaGx/9oACAEBAAE/ECQrry+36xo7nZKFGu44IlGmWVNmuR9YWKMWLcZ0/jPADTjAa8Hl13kpwy2gfzGeCjrEpHLy12CGh9c69/H/2Q==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/260dee5aa067d3fe9b30ade1867b6a4e/8ac56/late.webp 240w,
/static/260dee5aa067d3fe9b30ade1867b6a4e/b957b/late.webp 427w&quot;
              sizes=&quot;(max-width: 427px) 100vw, 427px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/260dee5aa067d3fe9b30ade1867b6a4e/09b79/late.jpg 240w,
/static/260dee5aa067d3fe9b30ade1867b6a4e/141dd/late.jpg 427w&quot;
            sizes=&quot;(max-width: 427px) 100vw, 427px&quot;
            type=&quot;image/jpeg&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/260dee5aa067d3fe9b30ade1867b6a4e/141dd/late.jpg&quot;
            alt=&quot;Late request&quot;
            title=&quot;Late request&quot;
            loading=&quot;lazy&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;request-timeout-servlet-filter&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#request-timeout-servlet-filter&quot; aria-label=&quot;request timeout servlet filter permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Request timeout Servlet Filter&lt;/h2&gt;
&lt;p&gt;Without further ado let us dive right into a sample filter implementation in Kotlin:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;kotlin&quot;&gt;&lt;pre class=&quot;language-kotlin&quot;&gt;&lt;code class=&quot;language-kotlin&quot;&gt;&lt;span class=&quot;token annotation builtin&quot;&gt;@Component&lt;/span&gt;
&lt;span class=&quot;token annotation builtin&quot;&gt;@Order&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Ordered&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;HIGHEST_PRECEDENCE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; TimeoutFilter &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;OncePerRequestFilter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;doFilterInternal&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; HttpServletRequest&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; response&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; HttpServletResponse&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; filterChain&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; FilterChain&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; completed &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;AtomicBoolean&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; requestHandlingThread &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Thread&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;currentThread&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; timeout &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; timeoutsPool&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;schedule&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;completed&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;compareAndSet&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                requestHandlingThread&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;interrupt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; TimeUnit&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;SECONDS&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            filterChain&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;doFilter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; response&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            timeout&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;cancel&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;finally&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            completed&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;companion&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; timeoutsPool &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Executors&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;newScheduledThreadPool&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token annotation builtin&quot;&gt;@ResponseStatus&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;HttpStatus&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;INTERNAL_SERVER_ERROR&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;TimeoutException&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;message&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; java&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;util&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;concurrent&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;TimeoutException&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;message&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The above code declares a Servlet Filter that will interrupt thread processing a request after 5 seconds. There are couple of interesting points about how it works.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;@Order(Ordered.HIGHEST_PRECEDENCE)&lt;/code&gt; puts the Filter at the beginning of filter chain&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;val completed = AtomicBoolean(false)&lt;/code&gt; denotes whether the request processing completed.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;val timeoutsPool = Executors.newScheduledThreadPool(10)&lt;/code&gt; creates a thread pool responsible for running timeouts. The &lt;code class=&quot;language-text&quot;&gt;newScheduledThreadPool&lt;/code&gt; creates a thread pool that is efficient at running delayed tasks.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;timeoutsPool.schedule({ ... })&lt;/code&gt; schedules a code that will interrupt &lt;code class=&quot;language-text&quot;&gt;requestHandlingThread&lt;/code&gt; after 5 seconds&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;completed.compareAndSet(false, true)&lt;/code&gt; updates the &lt;code class=&quot;language-text&quot;&gt;completed&lt;/code&gt; flag in a thread safe fashion&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;testing-request-timeout-servlet-filter&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#testing-request-timeout-servlet-filter&quot; aria-label=&quot;testing request timeout servlet filter permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Testing request timeout Servlet Filter&lt;/h2&gt;
&lt;p&gt;For the test purposes let us create a simple Spring Boot MVC application written in Kotlin:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;kotlin&quot;&gt;&lt;pre class=&quot;language-kotlin&quot;&gt;&lt;code class=&quot;language-kotlin&quot;&gt;&lt;span class=&quot;token annotation builtin&quot;&gt;@SpringBootApplication&lt;/span&gt;
&lt;span class=&quot;token annotation builtin&quot;&gt;@EnableWebMvc&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; Application &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;companion&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token annotation builtin&quot;&gt;@JvmStatic&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;args&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Array&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;String&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            SpringApplication&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Application&lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;java&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token annotation builtin&quot;&gt;@RestController&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; TimeoutController &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token annotation builtin&quot;&gt;@GetMapping&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;/timeout&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;timeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token annotation builtin&quot;&gt;@RequestParam&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;required &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; timeoutInMillis&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Long&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; ResponseEntity&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        Thread&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;sleep&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;timeoutInMillis &lt;span class=&quot;token operator&quot;&gt;?:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; ResponseEntity&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;ok&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;completed&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;TimeoutController&lt;/code&gt; will sleep for an amount of time given in a parameter. Let’s simulate a short request with &lt;a href=&quot;https://httpie.org/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;httpie&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;http :8080/timeout &lt;span class=&quot;token assign-left variable&quot;&gt;timeoutInMillis&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2000&lt;/span&gt;

HTTP/1.1 &lt;span class=&quot;token number&quot;&gt;200&lt;/span&gt; 
Content-Length: &lt;span class=&quot;token number&quot;&gt;9&lt;/span&gt;
Content-Type: text/plain&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;token assign-left variable&quot;&gt;charset&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;ISO-8859-1
Date: Mon, &lt;span class=&quot;token number&quot;&gt;27&lt;/span&gt; Nov &lt;span class=&quot;token number&quot;&gt;2017&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;12&lt;/span&gt;:19:03 GMT

completed
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This was the happy path. Now let’s try a timeout path:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;http  :8080/timeout &lt;span class=&quot;token assign-left variable&quot;&gt;timeoutInMillis&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;6000&lt;/span&gt;       

HTTP/1.1 &lt;span class=&quot;token number&quot;&gt;500&lt;/span&gt; 
Connection: close
Content-Type: application/json&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;token assign-left variable&quot;&gt;charset&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;UTF-8
Date: Mon, &lt;span class=&quot;token number&quot;&gt;27&lt;/span&gt; Nov &lt;span class=&quot;token number&quot;&gt;2017&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;12&lt;/span&gt;:21:30 GMT
Transfer-Encoding: chunked

&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&quot;error&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Internal Server Error&quot;&lt;/span&gt;,
    &lt;span class=&quot;token string&quot;&gt;&quot;exception&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;java.lang.InterruptedException&quot;&lt;/span&gt;,
    &lt;span class=&quot;token string&quot;&gt;&quot;message&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;sleep interrupted&quot;&lt;/span&gt;,
    &lt;span class=&quot;token string&quot;&gt;&quot;path&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;/timeout&quot;&lt;/span&gt;,
    &lt;span class=&quot;token string&quot;&gt;&quot;status&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;500&lt;/span&gt;,
    &lt;span class=&quot;token string&quot;&gt;&quot;timestamp&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1511785290518&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;As you can see in the exception message, we see that the &lt;code class=&quot;language-text&quot;&gt;Thread.sleep&lt;/code&gt; in the controller action has been interrupted 🎉&lt;/p&gt;
&lt;h2 id=&quot;a-word-of-warning&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#a-word-of-warning&quot; aria-label=&quot;a word of warning permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;A word of warning&lt;/h2&gt;
&lt;p&gt;The above Servlet Filter will not work if we use &lt;a href=&quot;https://docs.oracle.com/javaee/7/tutorial/servlets012.htm&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Async Servlet Filters&lt;/a&gt;. When using Async Servlet Filter there is typically &lt;strong&gt;more than 1&lt;/strong&gt; thread that handles a request hence the above approach will not work. Having said that if you use Async Servlet Filter there already is a way to apply a timeout that &lt;a href=&quot;https://docs.oracle.com/javaee/6/api/javax/servlet/AsyncContext.html#setTimeout(long)&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;is defined by the API&lt;/a&gt;. Another important point is to check how the request processing thread pool handles interrupted threads. &lt;a href=&quot;/spring-mvc-thread-pool-timeouts&quot;&gt;As we have discussed earlier&lt;/a&gt;, the concrete implementation of thread pool used to process request depends on servlet container and configured used in the application. We should make sure that the interrupted thread is eventually replaced with a new thread by the pool so that timeouts do not change the effective thread pool size.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Request timeouts in Spring MVC]]></title><description><![CDATA[Last time we reviewed how to configure HTTP client timeouts. This time let us focus on the other side of the HTTP request i.e. server. There is pretty much always a thread pool involved when we write a Spring MVC application. The thread pool configuration will vary depending on particular servlet container (Tomcat…]]></description><link>undefined/spring-mvc-thread-pool-timeouts/</link><guid isPermaLink="false">undefined/spring-mvc-thread-pool-timeouts/</guid><pubDate>Tue, 21 Nov 2017 22:14:00 GMT</pubDate><content:encoded>&lt;p&gt;Last time we reviewed &lt;a href=&quot;/http-client-timeouts&quot;&gt;how to configure HTTP client timeouts&lt;/a&gt;. This time let us focus on the other side of the HTTP request i.e. server. There is pretty much always a thread pool involved when we write a Spring MVC application. The thread pool configuration will vary depending on particular servlet container (Tomcat, Undertow, Jetty) so we have to watch out for subtle differences. However, most if not all of them will use a thread pool with fixed maximum size. As we already know, a pool of resources might get exhausted. In particular, a thread pool is more likely to get exhausted if we do not control timeouts diligently.&lt;/p&gt;
&lt;h2 id=&quot;threads-involved-in-a-spring-mvc-request-handling&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#threads-involved-in-a-spring-mvc-request-handling&quot; aria-label=&quot;threads involved in a spring mvc request handling permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Threads involved in a Spring MVC request handling&lt;/h2&gt;
&lt;p&gt;A typical servlet container will use one or more thread pools to handle a request. In particular one of the thread pools is used to execute the Spring MVC part of request handling. Let us call this thread pool the request worker thread pool. The request worker thread pool will have a default maximum size:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Tomcat: &lt;code class=&quot;language-text&quot;&gt;server.tomcat.max-threads&lt;/code&gt; controlling &lt;a href=&quot;https://tomcat.apache.org/tomcat-8.5-doc/config/http.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;maxThreads&lt;/code&gt;&lt;/a&gt; with a default of 200&lt;/li&gt;
&lt;li&gt;Undertow: &lt;code class=&quot;language-text&quot;&gt;server.undertow.worker-threads&lt;/code&gt; controlling &lt;a href=&quot;http://undertow.io/undertow-docs/undertow-docs-1.2.0/listeners.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;WORKER_TASK_CORE_THREADS&lt;/code&gt;&lt;/a&gt; with a default of &lt;a href=&quot;https://github.com/undertow-io/undertow/blob/b6a87a4b4a467b297363c46747c344faaee15ded/core/src/main/java/io/undertow/Undertow.java#L419&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;availableProcessors() * 8&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Jetty: There is no Spring configuration property available currently. One can customize the Jetty Thread Pool through code and jetty specific configuration though. The default maximum number of worker threads is 200.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&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/f95db4989dadc903421245f5abdd40c3/c5fc9/thread-pool.jpg&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: 66.66666666666666%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAIEBf/EABUBAQEAAAAAAAAAAAAAAAAAAAAB/9oADAMBAAIQAxAAAAGJ5WsuMgP/xAAbEAACAgMBAAAAAAAAAAAAAAABAgADERITIv/aAAgBAQABBQLZAelU61weqkXDE5P/xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/AT//xAAaEAACAgMAAAAAAAAAAAAAAAAAARAhESKh/9oACAEBAAY/AhadHmLuP//EABkQAQEBAQEBAAAAAAAAAAAAAAERACExQf/aAAgBAQABPyFiROQjiignc7JxW+byPp9xp8C6gu//2gAMAwEAAgADAAAAEJsv/8QAFhEAAwAAAAAAAAAAAAAAAAAAARAR/9oACAEDAQE/EIF//8QAFhEBAQEAAAAAAAAAAAAAAAAAAAER/9oACAECAQE/EG1//8QAGxABAQEAAgMAAAAAAAAAAAAAAREAIUExUWH/2gAIAQEAAT8QRmNpDhV9d2YhKYCoz5MdEaU5EEqB3yWPHXjnKTqu/9k=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/f95db4989dadc903421245f5abdd40c3/8ac56/thread-pool.webp 240w,
/static/f95db4989dadc903421245f5abdd40c3/d3be9/thread-pool.webp 480w,
/static/f95db4989dadc903421245f5abdd40c3/e46b2/thread-pool.webp 960w,
/static/f95db4989dadc903421245f5abdd40c3/34186/thread-pool.webp 1118w&quot;
              sizes=&quot;(max-width: 960px) 100vw, 960px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/f95db4989dadc903421245f5abdd40c3/09b79/thread-pool.jpg 240w,
/static/f95db4989dadc903421245f5abdd40c3/7cc5e/thread-pool.jpg 480w,
/static/f95db4989dadc903421245f5abdd40c3/6a068/thread-pool.jpg 960w,
/static/f95db4989dadc903421245f5abdd40c3/c5fc9/thread-pool.jpg 1118w&quot;
            sizes=&quot;(max-width: 960px) 100vw, 960px&quot;
            type=&quot;image/jpeg&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/f95db4989dadc903421245f5abdd40c3/6a068/thread-pool.jpg&quot;
            alt=&quot;Thread pool&quot;
            title=&quot;Thread pool&quot;
            loading=&quot;lazy&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;what-happens-when-the-request-processing-thread-pool-is-empty&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#what-happens-when-the-request-processing-thread-pool-is-empty&quot; aria-label=&quot;what happens when the request processing thread pool is empty permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;What happens when the request processing thread pool is empty?&lt;/h2&gt;
&lt;p&gt;Once the request processing thread pool is empty, the servlet container will typically queue the requests. The queue is processed by the request processing thread pool. Queueing up requests is consuming server memory and sockets thus there typically is a limit after which a new incoming request is going to be immediately rejected.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Tomcat: &lt;code class=&quot;language-text&quot;&gt;server.tomcat.accept-count&lt;/code&gt; Maximum queue length for incoming connection requests when all possible request processing threads are in use. &lt;a href=&quot;https://tomcat.apache.org/tomcat-8.5-doc/config/http.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;The default value is 100&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Undertow: As far as I can tell by default the requests will be queued and the only bound is system capacity. There is &lt;a href=&quot;http://undertow.io/undertow-docs/undertow-docs-1.2.0/#built-in-handlers&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Request Limiting Handler&lt;/a&gt; available though that allows configuring maximum concurrent requests as well as maximum queue size.&lt;/li&gt;
&lt;li&gt;Jetty: By default will queue requests using unbounded queue. You can configure it though &lt;a href=&quot;https://wiki.eclipse.org/Jetty/Howto/High_Load&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;as documented&lt;/a&gt;:&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;xml&quot;&gt;&lt;pre class=&quot;language-xml&quot;&gt;&lt;code class=&quot;language-xml&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;Configure&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Server&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;org.eclipse.jetty.server.Server&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;Set&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;ThreadPool&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;New&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;org.eclipse.jetty.util.thread.QueuedThreadPool&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- specify a bounded queue --&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;Arg&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
           &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;New&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;java.util.concurrent.ArrayBlockingQueue&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
              &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;Arg&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;int&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;6000&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;Arg&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
           &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;New&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;Arg&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;Set&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;minThreads&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;10&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;Set&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;Set&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;maxThreads&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;200&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;Set&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;Set&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;detailedDump&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;false&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;Set&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;New&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;Set&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;Configure&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Queuing requests is necessary in the most commons scenarios to handle temporary spikes in load. For example, if your application can handle 100 requests per second, and if you can allow it to recover from one minute of excessive high load, you can set the queue capacity to 60*100=6000.&lt;/p&gt;
&lt;h2 id=&quot;how-is-the-request-processing-thread-pool-related-to-timeouts&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#how-is-the-request-processing-thread-pool-related-to-timeouts&quot; aria-label=&quot;how is the request processing thread pool related to timeouts permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;How is the request processing thread pool related to timeouts?&lt;/h2&gt;
&lt;p&gt;Let us assume that the thread pool (max) size is 100 and that on average a request takes 1 second to process. In such server we can thus handle 100 requests per second (rps). Any requests over the rps limit is going to be queued. Now imagine we have a single type of request that for some reason takes much longer to process than usual e.g. 120 seconds due to some dependent service issue. When such request is processed, it will first block subsequent requesting processing threads until all of them are &lt;em&gt;busy waiting&lt;/em&gt;. Depending on the limit of queue size and system capacity our server will soon start rejecting &lt;strong&gt;all new requests&lt;/strong&gt;. It is worth noting that the &lt;em&gt;slow&lt;/em&gt; requests are also going to be put in queue after thread pool capacity is reached.&lt;/p&gt;
&lt;p&gt;One of the ways to mitigate the issue and speed up system recovery is &lt;strong&gt;to apply timeouts&lt;/strong&gt;. When a timeout for a particular request elapses ideally few things should happen:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the client should be notified about the error (&lt;a href=&quot;https://en.wikipedia.org/wiki/List_of_HTTP_status_codes&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;503, 504 or 408&lt;/a&gt; depending on the use case)&lt;/li&gt;
&lt;li&gt;the request should be removed from the processing queue&lt;/li&gt;
&lt;li&gt;the thread processing the requests should be interrupted&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let’s review what options are available.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Tomcat has &lt;a href=&quot;http://tomcat.apache.org/tomcat-8.5-doc/config/valve.html#Stuck_Thread_Detection_Valve&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Stuck Thread Detection Valve&lt;/a&gt;:
&lt;blockquote&gt;
&lt;p&gt;This valve allows to detect requests that take a long time to process, which might indicate that the thread that is processing it is stuck. Additionally it can optionally interrupt such threads to try and unblock them.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The valve has 2 configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;threshold&lt;/code&gt;: Minimum duration in seconds after which a thread is considered stuck. Default is 600 seconds.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;interruptThreadThreshold&lt;/code&gt;: Minimum duration in seconds after which a stuck thread should be interrupted to attempt to “free” it.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;AFAIK the valve only applies to requests that did start processing by the thread pool.&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Undertow and Jetty do not allow for setting a request timeout directly. They both do have &lt;em&gt;idle&lt;/em&gt; connection detection and can timeout it accordingly. Unfortunately since HTTP/2 multiplexing the timeouts options may not be suitable to timeout a single request.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;In Spring MVC there is no way to configure a timeout unless you use &lt;a href=&quot;https://spring.io/guides/gs/async-method/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;async method&lt;/a&gt;. With async method one can use &lt;code class=&quot;language-text&quot;&gt;spring.mvc.async.request-timeout=&lt;/code&gt; to set amount of time (in milliseconds) before asynchronous request handling times out. However, using Async Servlet with Spring MVC requires changing the controller methods return types.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;there-is-no-standard-request-timeout-configuration&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#there-is-no-standard-request-timeout-configuration&quot; aria-label=&quot;there is no standard request timeout configuration permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;There is no standard request timeout configuration&lt;/h2&gt;
&lt;p&gt;There are only couple of options available to set encompass request handling with a timeout. This is partially due to historical reasons. The servlet container specification did not consider timeouts until Async Servlet was defined. Another reason is that the there is no way &lt;a href=&quot;https://docs.oracle.com/javase/1.5.0/docs/guide/misc/threadPrimitiveDeprecation.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;to safely &lt;em&gt;stop&lt;/em&gt; a thread&lt;/a&gt; that a framework could use. The application code needs to cooperate to safely terminate the request handling execution. In the next post we will show how to add a request timeout to a Spring MVC application.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[HTTP client timeouts]]></title><description><![CDATA[We have already touched upon the importance of timeouts and described most important related JDBC knobs. The next aspect of timeouts I would like to focus on is using API clients. Specifically HTTP clients which are by far the most popular. We will review couple of popular HTTP client libraries and their configuration…]]></description><link>undefined/http-client-timeouts/</link><guid isPermaLink="false">undefined/http-client-timeouts/</guid><pubDate>Sun, 05 Nov 2017 22:14:00 GMT</pubDate><content:encoded>&lt;p&gt;We have already touched upon &lt;a href=&quot;/the-importance-of-timeouts&quot;&gt;the importance of timeouts&lt;/a&gt; and described most important &lt;a href=&quot;/database-timeouts&quot;&gt;related JDBC knobs&lt;/a&gt;. The next aspect of timeouts I would like to focus on is using API clients. Specifically HTTP clients which are by far the most popular. We will review couple of popular HTTP client libraries and their configuration regarding timeouts.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/7f6c315e16d505fd000775dea314eafa/c08c5/waiting.jpg&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: 66.25%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAMEAf/EABQBAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhADEAAAAbF40qIg/8QAHBAAAgICAwAAAAAAAAAAAAAAAQIAAwQREhMh/9oACAEBAAEFAiHBrVWbkBGyPV1VO3c//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAHBAAAQQDAQAAAAAAAAAAAAAAABEhMaEBECIy/9oACAEBAAY/AucDOmosVJPNn//EABwQAAMBAAIDAAAAAAAAAAAAAAABESExQVFx8P/aAAgBAQABPyG9ohg1TUcDR0+IfDXfRrqvno//2gAMAwEAAgADAAAAEAAP/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPxA//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPxA//8QAHhABAAMAAgIDAAAAAAAAAAAAAQARITFBUWFxobH/2gAIAQEAAT8QaU7ddqderb4+yBc0OMJyHRAv9ZBLLsjG4+PcTGCnQj//2Q==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/7f6c315e16d505fd000775dea314eafa/8ac56/waiting.webp 240w,
/static/7f6c315e16d505fd000775dea314eafa/d3be9/waiting.webp 480w,
/static/7f6c315e16d505fd000775dea314eafa/0ba47/waiting.webp 640w&quot;
              sizes=&quot;(max-width: 640px) 100vw, 640px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/7f6c315e16d505fd000775dea314eafa/09b79/waiting.jpg 240w,
/static/7f6c315e16d505fd000775dea314eafa/7cc5e/waiting.jpg 480w,
/static/7f6c315e16d505fd000775dea314eafa/c08c5/waiting.jpg 640w&quot;
            sizes=&quot;(max-width: 640px) 100vw, 640px&quot;
            type=&quot;image/jpeg&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/7f6c315e16d505fd000775dea314eafa/c08c5/waiting.jpg&quot;
            alt=&quot;Waiting&quot;
            title=&quot;Waiting&quot;
            loading=&quot;lazy&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;httpurlconnection-timeouts&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#httpurlconnection-timeouts&quot; aria-label=&quot;httpurlconnection timeouts permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;HttpURLConnection timeouts&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.oracle.com/javase/7/docs/api/java/net/HttpURLConnection.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;HttpURLConnection&lt;/code&gt;&lt;/a&gt; available since JDK 1.1 has gained the ability to timeout its network communication in version JDK 5. The 2 available timeouts &lt;a href=&quot;https://docs.oracle.com/javase/7/docs/api/java/net/URLConnection.html#setConnectTimeout(int)&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;setConnectionTimeout&lt;/code&gt;&lt;/a&gt;, &lt;a href=&quot;https://docs.oracle.com/javase/7/docs/api/java/net/URLConnection.html#setReadTimeout(int)&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;setReadTimeout&lt;/code&gt;&lt;/a&gt; control how long to wait until connection is established and how long to wait for a data from the server respectively. The default values are &lt;strong&gt;infinite ‼️&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id=&quot;apache-httpclient-timeouts&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#apache-httpclient-timeouts&quot; aria-label=&quot;apache httpclient timeouts permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Apache HttpClient timeouts&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://hc.apache.org/httpcomponents-client-4.5.x/index.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;HttpClient&lt;/a&gt; from Apache HttpComponents suite has been a standard choice for http communication. It is a mature project, with rich API that fills many &lt;code class=&quot;language-text&quot;&gt;HttpURLConnection&lt;/code&gt; shortcomings e.g. connection pooling. Many of the APIs have been deprecated e.g. &lt;code class=&quot;language-text&quot;&gt;DefaultHttpClient&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;org.apache.http.params.CoreConnectionPNames&lt;/code&gt; hence one needs to be careful when setting the timeouts they fallback to system defined socket level defaults.&lt;/p&gt;
&lt;p&gt;There are 3 timeouts settings available:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;kotlin&quot;&gt;&lt;pre class=&quot;language-kotlin&quot;&gt;&lt;code class=&quot;language-kotlin&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; requestConfig &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; RequestConfig&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;custom&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// Determines the timeout in milliseconds until a connection is established.&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setConnectTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;5_000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 
    &lt;span class=&quot;token comment&quot;&gt;// Defines the socket timeout in milliseconds,&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// which is the timeout for waiting for data or, put differently,&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// a maximum period inactivity between two consecutive data packets).&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setSocketTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;5_000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// Returns the timeout in milliseconds used when requesting a connection&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// from the connection manager.&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setConnectionRequestTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2_000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;requestConfig&lt;/code&gt; can be further used as a default for an &lt;code class=&quot;language-text&quot;&gt;HttpClient&lt;/code&gt; instance:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;kotlin&quot;&gt;&lt;pre class=&quot;language-kotlin&quot;&gt;&lt;code class=&quot;language-kotlin&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; httpClient &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; HttpClients&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;custom&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setDefaultRequestConfig&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;requestConfig&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;It is also possible to configure each request separately:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;kotlin&quot;&gt;&lt;pre class=&quot;language-kotlin&quot;&gt;&lt;code class=&quot;language-kotlin&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;HttpGet&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;http://httpbin.org/get&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;apply&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
    config &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; requestConfig
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
httpClient&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;execute&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;okhttp&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#okhttp&quot; aria-label=&quot;okhttp permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;OkHttp&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;http://square.github.io/okhttp/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;OkHttp&lt;/a&gt; is my favorite HTTP &amp;#x26; HTTP/2 client for Android and Java applications. It is efficient and has &lt;strong&gt;good configuration defaults&lt;/strong&gt;. There are 3 timeout settings available:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;kotlin&quot;&gt;&lt;pre class=&quot;language-kotlin&quot;&gt;&lt;code class=&quot;language-kotlin&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; client &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; OkHttpClient&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Builder&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// Sets the default connect timeout for new connections.&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;connectTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; TimeUnit&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;SECONDS&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// Sets the default read timeout for new connections.&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;readTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; TimeUnit&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;SECONDS&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// Sets the default write timeout for new connections.&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;writeTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; TimeUnit&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;SECONDS&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;All &lt;code class=&quot;language-text&quot;&gt;connectTimeout&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;readTimeout&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;writeTimeout&lt;/code&gt; default to &lt;strong&gt;10 seconds&lt;/strong&gt; 👍.&lt;/p&gt;
&lt;h2 id=&quot;xmlhttprequest-and-fetch-api-timeouts&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#xmlhttprequest-and-fetch-api-timeouts&quot; aria-label=&quot;xmlhttprequest and fetch api timeouts permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;XMLHttpRequest and Fetch API timeouts&lt;/h2&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;XMLHttpRequest&lt;/code&gt; is the standard foundation of network communication of Web application for over 10 years now. Nowadays it is being replaced with Fetch API but it still is, and will continue to be, the most popular for couple of years. There is only a single &lt;code class=&quot;language-text&quot;&gt;timeout&lt;/code&gt; configuration available in &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/timeout&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;XMLHttpRequest&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The XMLHttpRequest.timeout property is an unsigned long representing the number of milliseconds a request can take before automatically being terminated. The default value is 0, which means there is no timeout.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Default is infinite ‼️&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Since the default value is not configured we should diligently set the timeout in our code! It may be tempting to think that client side timeout is not so important compared to the one on the server. This is a questionable attitude to say the least. We need to keep in mind that there is a hard limit on the number of connections a browser will make to a single domain which is very important if we use &lt;strong&gt;HTTP 1.&lt;/strong&gt;*. When we reach maximum number of concurrently opened connections, any new &lt;code class=&quot;language-text&quot;&gt;XMLHttpRequest&lt;/code&gt; is going to be queued indefinitely. The limit value varies in browsers and the &lt;a href=&quot;https://tools.ietf.org/html/rfc7230#section-6.4&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;recent RCF&lt;/a&gt; relaxes it. &lt;strong&gt;HTTP/2&lt;/strong&gt; alleviates the issue &lt;a href=&quot;http://qnimate.com/what-is-multiplexing-in-http2/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;with connection multiplexing&lt;/a&gt; nonetheless its adoption is still low. According to w3techs it is &lt;a href=&quot;https://w3techs.com/technologies/details/ce-http2/all/all&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;about 20% as of today&lt;/a&gt;. The timeout value used in &lt;code class=&quot;language-text&quot;&gt;XMLHttpRequest&lt;/code&gt; is even more important in Single Page Applications. In SPAs the &lt;code class=&quot;language-text&quot;&gt;XMLHttpRequest&lt;/code&gt; without a timeout can live for as long as server and intermediate network parties allow effectively blocking all subsequent network calls.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Fetch API&lt;/a&gt; is meant to replace &lt;code class=&quot;language-text&quot;&gt;XMLHttpRequest&lt;/code&gt;. It is thus sad that the ability to timeout a request has not yet made it into &lt;a href=&quot;https://fetch.spec.whatwg.org/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;the standard&lt;/a&gt;. &lt;strong&gt;Currently there is no standard way to enforce a timeout&lt;/strong&gt;. There are couple of GitHub issues active: &lt;a href=&quot;https://github.com/whatwg/fetch/issues/20#issuecomment-323740783&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Add timeout option&lt;/a&gt;, &lt;a href=&quot;https://github.com/whatwg/fetch/issues/179&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Add option to reject the fetch promise automatically after a certain time elapsed&lt;/a&gt; that go over potential solutions. There was a proposal for &lt;a href=&quot;https://github.com/tc39/proposal-cancelable-promises&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;cancelable promises&lt;/a&gt; which had been withdrawn after &lt;a href=&quot;https://github.com/tc39/proposal-cancelable-promises/issues/70&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;lots of discussion and lack of consensus&lt;/a&gt;. A brand new way &lt;a href=&quot;https://developers.google.com/web/updates/2017/09/abortable-fetch&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;has recently been implemented by Edge and Firefox&lt;/a&gt; allows one to timeout a Fetch API call 🎉 through &lt;a href=&quot;https://dom.spec.whatwg.org/#aborting-ongoing-activities&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;the DOM standardized &lt;code class=&quot;language-text&quot;&gt;AbortController&lt;/code&gt;&lt;/a&gt;. Hopefully it will get into the Fetch API standard soon.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; controller &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AbortController&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; signal &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; controller&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;signal&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;setTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; controller&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;abort&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;fetch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;url&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; signal &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;response&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;text&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;urlsession-timeouts&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#urlsession-timeouts&quot; aria-label=&quot;urlsession timeouts permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;URLSession timeouts&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://developer.apple.com/documentation/foundation/urlsession&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;URLSession&lt;/code&gt;&lt;/a&gt; is the successor to &lt;code class=&quot;language-text&quot;&gt;NSURLConnection&lt;/code&gt; that underlays most if not all iOS http clients e.g. Alamofire. There are 2 main timeout values to configure both of which have default values available via &lt;code class=&quot;language-text&quot;&gt;URLSessionConfiguration.default&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;swift&quot;&gt;&lt;pre class=&quot;language-swift&quot;&gt;&lt;code class=&quot;language-swift&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; sessionConfig &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;URLSessionConfiguration&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt;
sessionConfig&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;timeoutIntervalForRequest &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;20.0&lt;/span&gt;
sessionConfig&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;timeoutIntervalForResource &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;40.0&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; session &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;URLSession&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;configuration&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; sessionConfig&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Fortunately there are default values configured:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;timeoutIntervalForRequest&lt;/code&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;This property determines the request timeout interval for all tasks within sessions based on this configuration. The request timeout interval controls how long (in seconds) a task should wait for additional data to arrive before giving up. The timer associated with this value is reset whenever new data arrives.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The default value is 60.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;timeoutIntervalForResource&lt;/code&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;This property determines the resource timeout interval for all tasks within sessions based on this configuration. The resource timeout interval controls how long (in seconds) to wait for an entire resource to transfer before giving up.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The default value is 7 days.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Note that &lt;code class=&quot;language-text&quot;&gt;timeoutIntervalForResource&lt;/code&gt; is a higher level timeout that what we have considered in other HTTP clients. It encompasses retries and or request timeouts hence has a large default.&lt;/p&gt;
&lt;h2 id=&quot;summary&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#summary&quot; aria-label=&quot;summary permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Summary&lt;/h2&gt;
&lt;p&gt;Many of HTTP clients do not have a good default timeout configuration. Hence, if you care about your application resource usage and system stability you have to carefully review and configure timeouts where applicable. It is reassuring to see that modern HTTP clients e.g. OkHttp and URLSession have a short but sane default.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Database timeouts]]></title><description><![CDATA[Last time I have outlined the importance of timeouts. Without a carefully considered timeouts our application can become unresponsive easily. In this post I will focus on configuring various timeouts related to interaction with database. I am going to focus specifically on relational databases. The principles and…]]></description><link>undefined/database-timeouts/</link><guid isPermaLink="false">undefined/database-timeouts/</guid><pubDate>Tue, 31 Oct 2017 22:14:00 GMT</pubDate><content:encoded>&lt;p&gt;Last time I have outlined &lt;a href=&quot;/the-importance-of-timeouts&quot;&gt;the importance of timeouts&lt;/a&gt;. Without a carefully considered timeouts our application can become unresponsive easily. In this post I will focus on configuring various timeouts related to interaction with database. I am going to focus specifically on relational databases. The principles and practices however can be applied equally well to other types of databases.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/f7abe2875ea078ff7e8f6c2905313058/c08c5/database-files.jpg&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: 52.083333333333336%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAKABQDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAUCAwT/xAAWAQEBAQAAAAAAAAAAAAAAAAAEAQL/2gAMAwEAAhADEAAAAWWVsouplANf/8QAGRAAAgMBAAAAAAAAAAAAAAAAAAECAxIx/9oACAEBAAEFAp2SRvTHySSvP//EABcRAQADAAAAAAAAAAAAAAAAAAABAkH/2gAIAQMBAT8BxFX/xAAYEQACAwAAAAAAAAAAAAAAAAAAARJBYf/aAAgBAgEBPwGm8JH/xAAaEAACAgMAAAAAAAAAAAAAAAAAARARMTJR/9oACAEBAAY/AuG6M3Cj/8QAGxABAAICAwAAAAAAAAAAAAAAAQARIWFxocH/2gAIAQEAAT8hdp6wo5Hc5HiC1cqMDDCf/9oADAMBAAIAAwAAABDkH//EABgRAQEAAwAAAAAAAAAAAAAAAAEAITGB/9oACAEDAQE/EMPZCG7/xAAXEQEBAQEAAAAAAAAAAAAAAAABADGB/9oACAECAQE/EDmTLXL/xAAeEAEAAgIBBQAAAAAAAAAAAAABABEhMUFRgbHB8P/aAAgBAQABPxBQNKcr8y1NLi77+yRQDTYp06doQAImmERjgCuIAugLba5Z/9k=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/f7abe2875ea078ff7e8f6c2905313058/8ac56/database-files.webp 240w,
/static/f7abe2875ea078ff7e8f6c2905313058/d3be9/database-files.webp 480w,
/static/f7abe2875ea078ff7e8f6c2905313058/0ba47/database-files.webp 640w&quot;
              sizes=&quot;(max-width: 640px) 100vw, 640px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/f7abe2875ea078ff7e8f6c2905313058/09b79/database-files.jpg 240w,
/static/f7abe2875ea078ff7e8f6c2905313058/7cc5e/database-files.jpg 480w,
/static/f7abe2875ea078ff7e8f6c2905313058/c08c5/database-files.jpg 640w&quot;
            sizes=&quot;(max-width: 640px) 100vw, 640px&quot;
            type=&quot;image/jpeg&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/f7abe2875ea078ff7e8f6c2905313058/c08c5/database-files.jpg&quot;
            alt=&quot;Database&quot;
            title=&quot;Database&quot;
            loading=&quot;lazy&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;different-kinds-of-timeouts&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#different-kinds-of-timeouts&quot; aria-label=&quot;different kinds of timeouts permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Different kinds of timeouts&lt;/h2&gt;
&lt;p&gt;Asking a database for results of a query is one of the most common activities a back end application will do. Let us decompose this simple task into steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;#init&quot;&gt;Establish database connection(s) in pool&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#pool&quot;&gt;Take the connection out of the pool&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#validate&quot;&gt;Validate the acquired connection&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#send&quot;&gt;Send statement(s) to database&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#read&quot;&gt;Read query results&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Each of the above steps can involve a specific timeout configuration. The details depend on particular technology stack and type of database we are querying.&lt;/p&gt;
&lt;h3 id=&quot;a-nameinitestablish-database-connections-in-poola&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#a-nameinitestablish-database-connections-in-poola&quot; aria-label=&quot;a nameinitestablish database connections in poola permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;a name=&quot;init&quot;&gt;Establish database connection(s) in pool&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Dealing with raw database connections is almost always done with the help of connection pool. Establishing a connection to database is very expensive compared to running a simple statement. The pool alleviates this cost by reusing connections for as long as needed.&lt;/p&gt;
&lt;p&gt;The first timeout is the maximum duration until a database connection is established. In JDBC this can be controlled by:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;connectTimeout&lt;/code&gt; in &lt;a href=&quot;https://dev.mysql.com/doc/connector-j/5.1/en/connector-j-reference-configuration-properties.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;MySQL JDBC driver&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Timeout for socket connect (in milliseconds), with 0 being no timeout. Only works on JDK-1.4 or newer. Defaults to ‘0’.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The default is &lt;strong&gt;infinite ‼️&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;socketTimeout&lt;/code&gt; in &lt;a href=&quot;https://dev.mysql.com/doc/connector-j/5.1/en/connector-j-reference-configuration-properties.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;MySQL JDBC driver&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Timeout (in milliseconds) on network socket operations (0, the default means no timeout).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;loginTimeout&lt;/code&gt; in &lt;a href=&quot;https://docs.oracle.com/javase/8/docs/api/java/sql/DriverManager.html#setLoginTimeout-int-&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;MySQL JDBC driver&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Sets the maximum time in seconds that a driver will wait while attempting to connect to a database once the driver has been identified.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The default value 0 means &lt;strong&gt;infinite ‼️&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;loginTimeout&lt;/code&gt; in &lt;a href=&quot;https://jdbc.postgresql.org/documentation/head/connect.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;PostgreSQL JDBC driver&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Specify how long to wait for establishment of a database connection. The timeout is specified in seconds.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Default is infinite ‼️&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;connectTimeout&lt;/code&gt; in &lt;a href=&quot;https://jdbc.postgresql.org/documentation/head/connect.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;PostgreSQL JDBC driver&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The timeout value used for socket connect operations. If connecting to the server takes longer than this value, the connection is broken. The timeout is specified in seconds and a value of zero means that it is disabled.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;socketTimeout&lt;/code&gt; in &lt;a href=&quot;https://jdbc.postgresql.org/documentation/head/connect.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;PostgreSQL JDBC driver&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The timeout value used for socket read operations. If reading from the server takes longer than this value, the connection is closed. This can be used as both a brute force global query timeout and a method of detecting network problems. The timeout is specified in seconds and a value of zero means that it is disabled.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You probably have noticed a recurring theme above: &lt;strong&gt;default timeouts are either infinite or disabled at the driver level&lt;/strong&gt;. &lt;em&gt;In case of &lt;code class=&quot;language-text&quot;&gt;socketTimeout&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;connectTimeout&lt;/code&gt; there can still be a system level timeout involved both on &lt;a href=&quot;https://linux.die.net/man/7/socket&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Linux&lt;/a&gt; and &lt;a href=&quot;https://msdn.microsoft.com/en-us/library/windows/desktop/ms740476(v=vs.85).aspx&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Windows&lt;/a&gt;. However, those only work on blocking send and receive operations and how the JDBC driver interacts with the socket is an implementation detail for the most part.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;In order to demonstrate how the above timeouts work in practice we will use the following test cases:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;kotlin&quot;&gt;&lt;pre class=&quot;language-kotlin&quot;&gt;&lt;code class=&quot;language-kotlin&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; JdbcTimeoutTest &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token annotation builtin&quot;&gt;@Test&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;`mysql getConnection`&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; mysqlDataSource &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;mysqlDataSource&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;token function&quot;&gt;assertTimeoutPreemptively&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Duration&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;ofMinutes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            useResource &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; mysqlDataSource&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;connection &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token annotation builtin&quot;&gt;@Test&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;`postgresql getConnection`&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; mysqlDataSource &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;postgreSQLDataSource&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;token function&quot;&gt;assertTimeoutPreemptively&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Duration&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;ofMinutes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            useResource &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; mysqlDataSource&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;connection &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useResource&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;resourceProvider&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; AutoCloseable&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; start &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Instant&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;now&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;resourceProvider&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;token function&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Completed in &lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token delimiter variable&quot;&gt;${&lt;/span&gt;Duration&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;between&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;start&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Instant&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;now&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token delimiter variable&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;e&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Exception&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Error &lt;span class=&quot;token interpolation variable&quot;&gt;$e&lt;/span&gt; after &lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token delimiter variable&quot;&gt;${&lt;/span&gt;Duration&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;between&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;start&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Instant&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;now&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token delimiter variable&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;mysqlDataSource&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; MysqlDataSource &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;MysqlDataSource&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;apply&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setURL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;jdbc:mysql://localhost:3306/database&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;user &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;user&quot;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setPassword&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;password&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;postgreSQLDataSource&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; PGSimpleDataSource &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;PGSimpleDataSource&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;apply&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;user &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;user&quot;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;password &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;password&quot;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;databaseName &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;database&quot;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;serverName &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;localhost&quot;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;To simulate a misbehaving database server we’ll use &lt;code class=&quot;language-text&quot;&gt;netcat&lt;/code&gt; listening on standard MySQL and PostgreSQL port e.g.:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;nc&lt;/span&gt; -k -l &lt;span class=&quot;token number&quot;&gt;3306&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# listen on MySQL port, PostgreSQL uses 5432 by default&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Both of the above tests will fail due to &lt;code class=&quot;language-text&quot;&gt;assertTimeoutPreemptively&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The most appropriate candidate to use for establishing connection is &lt;code class=&quot;language-text&quot;&gt;loginTimeout&lt;/code&gt;. This works in PostgreSQL but does not with MySQL. Apparently the MySQL JDBC driver in versions 5.1, 6.0 and 8.0 implement the method as &lt;a href=&quot;https://en.wikipedia.org/wiki/Noop&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Noop&lt;/a&gt;. Interestingly it is possible to force MySQL driver to respect the timeout when it is set &lt;strong&gt;globally&lt;/strong&gt; through a static method &lt;code class=&quot;language-text&quot;&gt;java.sql.DriverManager.setLoginTimeout&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;A slightly less correct option is to use &lt;code class=&quot;language-text&quot;&gt;connectTimeout&lt;/code&gt; or &lt;code class=&quot;language-text&quot;&gt;socketTimeout&lt;/code&gt;. The socket level options work oblivious to database protocol hence it is impossible to set the timeout accurately for the whole establish connection operation. Additionally, the &lt;code class=&quot;language-text&quot;&gt;socketTimeout&lt;/code&gt; is applied to socket read operations not only to initial connection handshake. The fake &lt;code class=&quot;language-text&quot;&gt;netcat&lt;/code&gt; server is not suitable for testing the &lt;code class=&quot;language-text&quot;&gt;connectTimeout&lt;/code&gt; however we can use it for &lt;code class=&quot;language-text&quot;&gt;socketTimeout&lt;/code&gt;. The PostgreSQL driver correctly reported error after about 2 seconds after setting &lt;code class=&quot;language-text&quot;&gt;pgSimpleDataSource.socketTimeout = 2&lt;/code&gt;. Unfortunately settings &lt;code class=&quot;language-text&quot;&gt;socketTimeout&lt;/code&gt; in MySQL driver had &lt;strong&gt;no effect&lt;/strong&gt; on the &lt;code class=&quot;language-text&quot;&gt;getConnection&lt;/code&gt; behavior. Interestingly no matter what value I’ve set the &lt;code class=&quot;language-text&quot;&gt;socketTimeout&lt;/code&gt; to, the error was thrown after about 26 seconds. I have no idea why it behaves like that 🤔.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Be aware of the shortcomings of MySQL JDBC Driver.&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id=&quot;a-namepooltake-the-connection-out-of-the-poola&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#a-namepooltake-the-connection-out-of-the-poola&quot; aria-label=&quot;a namepooltake the connection out of the poola permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;a name=&quot;pool&quot;&gt;Take the connection out of the pool&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Reusing database connections gives the application great performance boost. However, writing an efficient and bug free database connection pool is no easy task thus we should all rely on proven solutions. In JVM world there are multiple choices when it comes to JDBC:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://brettwooldridge.github.io/HikariCP/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Hikari&lt;/a&gt; Claims to be the fastest and has limited number of configuration knobs and sane defaults. My favorite by far.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://commons.apache.org/proper/commons-dbcp/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;DBCP 2&lt;/a&gt; A recently resurrected project which has a potential of being applicable to all resources pools with its &lt;code class=&quot;language-text&quot;&gt;commons-pool2&lt;/code&gt; module.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://tomcat.apache.org/tomcat-8.0-doc/jdbc-pool.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Tomcat JDBC Connection Pool&lt;/a&gt; Commonly used with lots of configuration options. Came to be as a replacement of dbcp.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When there are no connections available in the pool, the code asking for it needs to wait until one is available. The amount of time a thread is blocked waiting for a connection needs to be considered carefully. It is important to note that there are 2 situations we need to consider. The first one is when the pool has reached its maximum size and all connections are being used already. This is when there is very little actual work required to acquire a connection. The second case is when all currently opened connections are in use but the pool is allowed to create a new connection because it is not yet full. Here we need to keep in mind that time to establish a connection to the database may easily be around 200ms hence timeout should not be too short. Below you’ll find how to configure the timeout in the mentioned connection pools:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Hikari: &lt;code class=&quot;language-text&quot;&gt;connectionTimeout&lt;/code&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;This property controls the maximum number of milliseconds that a client (that’s you) will wait for a connection from the pool. If this time is exceeded without a connection becoming available, a SQLException will be thrown. Lowest acceptable connection timeout is 250 ms. Default: 30000 (30 seconds)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;DBCP: &lt;code class=&quot;language-text&quot;&gt;maxWaitMillis&lt;/code&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The maximum number of milliseconds that the pool will wait (when there are no available connections) for a connection to be returned before throwing an exception, or -1 to wait indefinitely.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Default is infinite ‼️&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Tomcat: &lt;code class=&quot;language-text&quot;&gt;maxWait&lt;/code&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;(int) The maximum number of milliseconds that the pool will wait (when there are no available connections) for a connection to be returned before throwing an exception. Default value is 30000 (30 seconds)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;My rule of thumb is to set this timeout &lt;strong&gt;be under 5 seconds&lt;/strong&gt;.&lt;/p&gt;
&lt;h3 id=&quot;a-namevalidatevalidate-the-acquired-connectiona&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#a-namevalidatevalidate-the-acquired-connectiona&quot; aria-label=&quot;a namevalidatevalidate the acquired connectiona permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;a name=&quot;validate&quot;&gt;Validate the acquired connection&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;A database connection can be opened for several hours or even days. However, because there is network involved there are numerous cases where a socket that is seemingly open on the client side may in fact be part of a broken connection. A well behaving connection pool should avoid handing such connection to an application code. A common strategy to alleviate the problem is to test the connection just before it is taken out of the pool. In the past the test was performed using a simple SQL query e.g. &lt;code class=&quot;language-text&quot;&gt;SELECT 1&lt;/code&gt;. Nowadays there is a &lt;a href=&quot;https://docs.oracle.com/javase/7/docs/api/java/sql/Connection.html#isValid(int)&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;isValid&lt;/code&gt;&lt;/a&gt; method available on the JDBC &lt;code class=&quot;language-text&quot;&gt;Connection&lt;/code&gt; itself which moves the responsibility to the driver itself:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Returns true if the connection has not been closed and is still valid. The driver shall submit a query on the connection or use some other mechanism that positively verifies the connection is still valid when this method is called.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Hikari: &lt;code class=&quot;language-text&quot;&gt;validationTimeout&lt;/code&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;This property controls the maximum amount of time that a connection will be tested for aliveness. This value must be less than the &lt;code class=&quot;language-text&quot;&gt;connectionTimeout&lt;/code&gt;. Lowest acceptable validation timeout is 250 ms. Default: 5000&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;DBCP: &lt;code class=&quot;language-text&quot;&gt;validationQueryTimeout&lt;/code&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The timeout in seconds before connection validation queries fail. If set to a positive value, this value is passed to the driver via the &lt;code class=&quot;language-text&quot;&gt;setQueryTimeout&lt;/code&gt; method of the &lt;code class=&quot;language-text&quot;&gt;Statement&lt;/code&gt; used to execute the validation query.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Default is infinite ‼️&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Tomcat: &lt;code class=&quot;language-text&quot;&gt;validationQueryTimeout&lt;/code&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;(int) The timeout in seconds before a connection validation queries fail. This works by calling java.sql.Statement.setQueryTimeout(seconds) on the statement that executes the validationQuery. The pool itself doesn’t timeout the query, it is still up to the JDBC driver to enforce query timeouts. A value less than or equal to zero will disable this feature. The default value is -1.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Default is infinite ‼️&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;a-namesendsend-statements-to-databasea-and-a-namereadread-query-resultsa&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#a-namesendsend-statements-to-databasea-and-a-namereadread-query-resultsa&quot; aria-label=&quot;a namesendsend statements to databasea and a namereadread query resultsa permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;a name=&quot;send&quot;&gt;Send statement(s) to database&lt;/a&gt; and &lt;a name=&quot;read&quot;&gt;read query results&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;We have finally arrived at the most common usage. Every query that we send to a database should have a timeout configured either at the statement level or at the transaction level. When it comes to individual statements, there is &lt;a href=&quot;https://docs.oracle.com/javase/7/docs/api/java/sql/Statement.html#setQueryTimeout(int)&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;setQueryTimeout&lt;/code&gt;&lt;/a&gt; available:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Sets the number of seconds the driver will wait for a Statement object to execute to the given number of seconds. By default there is no limit on the amount of time allowed for a running statement to complete. If the limit is exceeded, an SQLTimeoutException is thrown. A JDBC driver must apply this limit to the execute, executeQuery and executeUpdate methods.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Additionally, it’s up to the driver to decide what the above timeout means exactly:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Note: JDBC driver implementations may also apply this limit to ResultSet methods (consult your driver vendor documentation for details).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Note: In the case of Statement batching, it is implementation defined as to whether the time-out is applied to individual SQL commands added via the addBatch method or to the entire batch of SQL commands invoked by the executeBatch method (consult your driver vendor documentation for details).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;A time required for a query to complete is very use case dependent thus we should &lt;strong&gt;not expect a sane default&lt;/strong&gt; to be there. Instead, we need to ask ourself how long we are willing to wait for a query to complete. It is very easy to forget about this rule hence it is very handy to be able to set this timeout globally:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;DBCP: &lt;code class=&quot;language-text&quot;&gt;defaultQueryTimeout&lt;/code&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;defaultQueryTimeout	null	If non-null, the value of this Integer property determines the query timeout that will be used for Statements created from connections managed by the pool. null means that the driver default will be used.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Tomcat: &lt;code class=&quot;language-text&quot;&gt;queryTimeout&lt;/code&gt; available through &lt;a href=&quot;https://tomcat.apache.org/tomcat-8.0-doc/jdbc-pool.html#JDBC_interceptors&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;QueryTimeoutInterceptor&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;(int as String) The number of seconds to set for the query timeout. A value less than or equal to zero will disable this feature. The default value is 1 seconds.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Hikari: Not available but fairly easy to add by wrapping a DataSource e.g.:&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;kotlin&quot;&gt;&lt;pre class=&quot;language-kotlin&quot;&gt;&lt;code class=&quot;language-kotlin&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;CustomTimeoutsDataSource&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; innerDataSource&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; DataSource&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; queryTimeoutProperties&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; DataSourceConfiguration&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;QueryTimeoutProperties&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; DataSource &lt;span class=&quot;token keyword&quot;&gt;by&lt;/span&gt; innerDataSource &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getConnection&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;username&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; password&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;configureTimeouts&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;innerDataSource&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getConnection&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;username&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; password&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getConnection&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;configureTimeouts&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;innerDataSource&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;connection&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;configureTimeouts&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;connection&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Connection&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;Connection &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;CustomTimeoutsConnection&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;connection&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; queryTimeoutProperties&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;CustomTimeoutsConnection&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; innerConnection&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Connection&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; queryTimeoutProperties&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; DataSourceConfiguration&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;QueryTimeoutProperties&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Connection &lt;span class=&quot;token keyword&quot;&gt;by&lt;/span&gt; innerConnection &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;T &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Statement&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;configure&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;prepareStatement&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; T&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; T &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token comment&quot;&gt;//0 means no timeout&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; desiredTimeout &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; queryTimeoutProperties&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;statementQueryTimeoutInSeconds &lt;span class=&quot;token operator&quot;&gt;?:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;
            prepareStatement&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;queryTimeout &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; desiredTimeout
            LOG&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;trace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Configure timeout {} seconds for statement {}&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; desiredTimeout&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; prepareStatement&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; prepareStatement
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;prepareStatement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sql&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; autoGeneratedKeys&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Int&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;configure&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;innerConnection&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;prepareStatement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sql&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; autoGeneratedKeys&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;prepareStatement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sql&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; resultSetType&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Int&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; resultSetConcurrency&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Int&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; resultSetHoldability&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Int&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;configure&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;innerConnection&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;prepareStatement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sql&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; resultSetType&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; resultSetConcurrency&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; resultSetHoldability&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;prepareStatement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sql&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;configure&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;innerConnection&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;prepareStatement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sql&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;prepareStatement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sql&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; columnNames&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Array&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;out&lt;/span&gt; String&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;configure&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;innerConnection&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;prepareStatement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sql&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; columnNames&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;prepareStatement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sql&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; resultSetType&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Int&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; resultSetConcurrency&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Int&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;configure&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;innerConnection&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;prepareStatement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sql&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; resultSetType&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; resultSetConcurrency&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;prepareStatement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sql&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; columnIndexes&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IntArray&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;configure&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;innerConnection&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;prepareStatement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sql&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; columnIndexes&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;prepareCall&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sql&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;configure&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;innerConnection&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;prepareCall&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sql&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;prepareCall&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sql&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; resultSetType&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Int&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; resultSetConcurrency&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Int&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;configure&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;innerConnection&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;prepareCall&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sql&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; resultSetType&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; resultSetConcurrency&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;prepareCall&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sql&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; resultSetType&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Int&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; resultSetConcurrency&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Int&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; resultSetHoldability&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Int&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;configure&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;innerConnection&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;prepareCall&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sql&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; resultSetType&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; resultSetConcurrency&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; resultSetHoldability&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createStatement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;configure&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;innerConnection&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createStatement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createStatement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;resultSetType&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Int&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; resultSetConcurrency&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Int&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;configure&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;innerConnection&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createStatement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;resultSetType&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; resultSetConcurrency&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createStatement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;resultSetType&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Int&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; resultSetConcurrency&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Int&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; resultSetHoldability&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Int&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;configure&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;innerConnection&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createStatement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;resultSetType&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; resultSetConcurrency&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; resultSetHoldability&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; String &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;CustomTimeoutsConnection(innerConnection=&lt;span class=&quot;token interpolation variable&quot;&gt;$innerConnection&lt;/span&gt;)&quot;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;companion&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; LOG &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; LoggerFactory&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getLogger&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;CustomTimeoutsDataSource&lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;java&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The JDBC level &lt;code class=&quot;language-text&quot;&gt;queryTimeout&lt;/code&gt; is enforced at the application code side i.e. there’s a code executed after the timeout elapses which stops the query execution. Recent releases of both MySQL and PostgreSQL offer a database server level statement timeout capabilities.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;MySQL: &lt;a href=&quot;https://dev.mysql.com/doc/refman/5.7/en/optimizer-hints.html#optimizer-hints-execution-time&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;MAX_EXECUTION_TIME&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The MAX_EXECUTION_TIME hint is permitted only for SELECT statements. It places a limit N (a timeout value in milliseconds) on how long a statement is permitted to execute before the server terminates it:&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;PostgreSQL: &lt;a href=&quot;https://www.postgresql.org/docs/9.6/static/runtime-config-client.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;statement_timeout&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Abort any statement that takes more than the specified number of milliseconds, starting from the time the command arrives at the server from the client. If log_min_error_statement is set to ERROR or lower, the statement that timed out will also be logged. A value of zero (the default) turns this off.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Setting statement_timeout in postgresql.conf is not recommended because it would affect all sessions.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you are using a JPA provider like Hibernate, you might be urged to use &lt;a href=&quot;https://docs.jboss.org/hibernate/entitymanager/3.5/reference/en/html/configuration.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;javax.persistence.query.timeout&lt;/code&gt;&lt;/a&gt;. However, from my experience using Hibernate this timeout, when configured globally, is enforced in some uses cases and completely ignored in others. There were multiple bugs reported related to this feature: &lt;a href=&quot;https://bugs.eclipse.org/bugs/show_bug.cgi?id=303360&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Bug 303360&lt;/a&gt;, &lt;a href=&quot;https://hibernate.atlassian.net/browse/HHH-9929&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;HHH-9929&lt;/a&gt;, &lt;a href=&quot;https://forum.hibernate.org/viewtopic.php?p=2466990&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;“Query timeout in persistence.xml doesn’t work”&lt;/a&gt; and some of them are still not addressed.&lt;/p&gt;
&lt;p&gt;There is no transaction scoped timeout available in JDBC. However, one can still apply the timeout in the application code through e.g. &lt;a href=&quot;https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/transaction/annotation/Transactional.html#timeout--&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;@Transactional.timeout&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;keep-all-timeouts-short&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#keep-all-timeouts-short&quot; aria-label=&quot;keep all timeouts short permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Keep all timeouts short&lt;/h3&gt;
&lt;p&gt;The best timeout is a short one. It is often tempting to increase a query or wait timeout in face of performance or throughput problems. However, doing so will increase the amount of resources blocked on the server and is thus a rarely a good choice. Blocking more and more resources on server e.g. threads, may at some point, cause the entire server to &lt;a href=&quot;https://en.wikipedia.org/wiki/Thrashing_(computer_science)&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;collapse abruptly&lt;/a&gt;. I keep the timeouts as short as possible especially when certain API is called often. If you are looking for a good read on the topic I highly recommend &lt;a href=&quot;https://pragprog.com/book/mnee/release-it&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Release It!&lt;/a&gt; by Michael T. Nygard. This books covers many resiliency related topics including timeouts and provides strategies to avoid increasing them.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[The importance of timeouts]]></title><description><![CDATA[Timeouts are not an exciting thing to talk about. They do not add immediately perceivable value. They are difficult to guess get right and force one to consider problems that are hard to solve. In fact, in my experience, the timeout is only ever considered when our software stops working or is about to. That is an…]]></description><link>undefined/the-importance-of-timeouts/</link><guid isPermaLink="false">undefined/the-importance-of-timeouts/</guid><pubDate>Mon, 23 Oct 2017 22:14:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Timeout_(computing)&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Timeouts&lt;/a&gt; are not an exciting thing to talk about. They do not add immediately perceivable value. They are difficult to &lt;del&gt;guess&lt;/del&gt; get right and force one to &lt;a href=&quot;https://en.wikipedia.org/wiki/Byzantine_fault_tolerance#Byzantine_Generals.27_Problem&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;consider problems that are hard to solve&lt;/a&gt;. In fact, in my experience, the timeout is only ever considered when our software stops working or is about to. That is an enormous shame since, in my opinion, carefully applied timeouts can vastly improve software resiliency.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/5a62ff5b481f38c5ffe98957ddf1fbf4/c08c5/man-clock.jpg&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: 73.33333333333334%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAPABQDASIAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAABQAE/8QAFQEBAQAAAAAAAAAAAAAAAAAAAgH/2gAMAwEAAhADEAAAARkM6JoE3I//xAAaEAACAgMAAAAAAAAAAAAAAAABAgATBBIh/9oACAEBAAEFAkKysaRGpIQPGxe//8QAFREBAQAAAAAAAAAAAAAAAAAAABH/2gAIAQMBAT8BV//EABURAQEAAAAAAAAAAAAAAAAAAAEQ/9oACAECAQE/AWf/xAAcEAABBAMBAAAAAAAAAAAAAAABAAIRIRAiQaH/2gAIAQEABj8CuVIc12ATYPEHDWfVRX//xAAcEAEBAAICAwAAAAAAAAAAAAABACFhETFRgdH/2gAIAQEAAT8hE4+kKvAZEeoRITmLtNZj5ZloJu//2gAMAwEAAgADAAAAEETv/8QAFxEBAAMAAAAAAAAAAAAAAAAAARARIf/aAAgBAwEBPxACth//xAAWEQEBAQAAAAAAAAAAAAAAAAARAAH/2gAIAQIBAT8Q1qRf/8QAHBABAAICAwEAAAAAAAAAAAAAAQARITFBUaFh/9oACAEBAAE/EElQ4eLKsQJuOsDEAoZkHgeu/jNQQjaW9b8ItOtlKfJ//9k=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/5a62ff5b481f38c5ffe98957ddf1fbf4/8ac56/man-clock.webp 240w,
/static/5a62ff5b481f38c5ffe98957ddf1fbf4/d3be9/man-clock.webp 480w,
/static/5a62ff5b481f38c5ffe98957ddf1fbf4/0ba47/man-clock.webp 640w&quot;
              sizes=&quot;(max-width: 640px) 100vw, 640px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/5a62ff5b481f38c5ffe98957ddf1fbf4/09b79/man-clock.jpg 240w,
/static/5a62ff5b481f38c5ffe98957ddf1fbf4/7cc5e/man-clock.jpg 480w,
/static/5a62ff5b481f38c5ffe98957ddf1fbf4/c08c5/man-clock.jpg 640w&quot;
            sizes=&quot;(max-width: 640px) 100vw, 640px&quot;
            type=&quot;image/jpeg&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/5a62ff5b481f38c5ffe98957ddf1fbf4/c08c5/man-clock.jpg&quot;
            alt=&quot;Man with a wrist clock&quot;
            title=&quot;Man with a wrist clock&quot;
            loading=&quot;lazy&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;an-example-application&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#an-example-application&quot; aria-label=&quot;an example application permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;An example application&lt;/h2&gt;
&lt;p&gt;Let us consider a simplistic example of a Spring Boot application generated using &lt;a href=&quot;https://start.spring.io/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Spring Initializr&lt;/a&gt;. The application will only expose &lt;a href=&quot;https://spring.io/guides/gs/actuator-service/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;actuator&lt;/a&gt; API which by default define a health check endpoint. Our example will also have a mail module configured.&lt;/p&gt;
&lt;p&gt;The dependencies section of &lt;code class=&quot;language-text&quot;&gt;build.gradle&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;groovy&quot;&gt;&lt;pre class=&quot;language-groovy&quot;&gt;&lt;code class=&quot;language-groovy&quot;&gt;dependencies &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;compile&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;org.springframework.boot:spring-boot-starter-actuator&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;compile&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;org.springframework.boot:spring-boot-starter-mail&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;compile&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;org.springframework.boot:spring-boot-starter-web&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;compile&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string gstring&quot;&gt;&quot;org.jetbrains.kotlin:kotlin-stdlib-jre8:&lt;span class=&quot;token expression&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;kotlinVersion&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;compile&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string gstring&quot;&gt;&quot;org.jetbrains.kotlin:kotlin-reflect:&lt;span class=&quot;token expression&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;kotlinVersion&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;A typical health check endpoint verifies that application integration points work correctly. If the service talks to database then a connection is established and verified. A free disk space is checked. If the service sends emails through SMTP then a connection to a server is established.&lt;/p&gt;
&lt;p&gt;The health checks are auto discovered and enabled when you include Spring Boot Actuator. By default, &lt;code class=&quot;language-text&quot;&gt;/health&lt;/code&gt; path is used for the endpoint. The SMTP server host, port and credentials obviously need to be configured. At minimum host entry is required e.g. &lt;code class=&quot;language-text&quot;&gt;spring.mail.host=localhost&lt;/code&gt;. &lt;em&gt;For the debugging purpose one can disable actuator security with &lt;code class=&quot;language-text&quot;&gt;management.security.enabled=false&lt;/code&gt; to verify what health checks are performed by actuator.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;A last part of our example is the trivial application code:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;kotlin&quot;&gt;&lt;pre class=&quot;language-kotlin&quot;&gt;&lt;code class=&quot;language-kotlin&quot;&gt;&lt;span class=&quot;token annotation builtin&quot;&gt;@SpringBootApplication&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; Application &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;companion&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token annotation builtin&quot;&gt;@JvmStatic&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;args&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Array&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;String&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            SpringApplication&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Application&lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;java&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;args&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;When you request &lt;code class=&quot;language-text&quot;&gt;/health&lt;/code&gt; the API will return response similar to:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;HTTP/1.1 200 
Content-Type: application/vnd.spring-boot.actuator.v1+json;charset=UTF-8
Date: Mon, 23 Oct 2017 08:08:32 GMT
Transfer-Encoding: chunked
X-Application-Context: application

{
    &amp;quot;diskSpace&amp;quot;: {
        &amp;quot;free&amp;quot;: 105755779072,
        &amp;quot;status&amp;quot;: &amp;quot;UP&amp;quot;,
        &amp;quot;threshold&amp;quot;: 10485760,
        &amp;quot;total&amp;quot;: 499046809600
    },
    &amp;quot;mail&amp;quot;: {
        &amp;quot;location&amp;quot;: &amp;quot;localhost:-1&amp;quot;,
        &amp;quot;status&amp;quot;: &amp;quot;UP&amp;quot;
    },
    &amp;quot;status&amp;quot;: &amp;quot;UP&amp;quot;
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;An application health API, like the one in our example, is often hooked into external monitoring software. The monitor asks the target application about its health in regular intervals e.g. every 5 seconds.&lt;/p&gt;
&lt;h2 id=&quot;shooting-yourself-in-the-foot&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#shooting-yourself-in-the-foot&quot; aria-label=&quot;shooting yourself in the foot permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Shooting yourself in the foot&lt;/h2&gt;
&lt;p&gt;The above example has an issue that can kill production server. More importantly, other metrics that are usually monitored e.g. CPU and memory usage will not warn about upcoming, dreadful service stall. The application will also not suffer from an enormous number of requests or emails being sent.&lt;/p&gt;
&lt;p&gt;Imagine that the health endpoint is checked every 5 seconds and that there is &lt;strong&gt;intermittent&lt;/strong&gt; issue with the SMPT server. The health endpoint will &lt;strong&gt;rightfully&lt;/strong&gt; try to connect to the SMTP server and from time to time respond with error. From my experience, when a health check is introduced it typically takes a while to tweak the monitor thresholds so that we get rid of false alarms. It is thus very easy to ignore intermittent errors when we think they are caused by too sensitive thresholds. However, the ignored errors can after a while cause our server to stop responding to &lt;strong&gt;any request&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/9cb8a4fa7b7c9ccb14f866e9d15d8913/c08c5/error.jpg&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(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAALABQDASIAAhEBAxEB/8QAGQAAAgMBAAAAAAAAAAAAAAAAAAIBAwQF/8QAFgEBAQEAAAAAAAAAAAAAAAAAAwEC/9oADAMBAAIQAxAAAAHsLZmOwMFv/8QAGRAAAwEBAQAAAAAAAAAAAAAAAQIRADJB/9oACAEBAAEFAiIZcqMUPHu//8QAFREBAQAAAAAAAAAAAAAAAAAAARD/2gAIAQMBAT8BJ//EABcRAQADAAAAAAAAAAAAAAAAAAACETH/2gAIAQIBAT8Bnin/xAAaEAABBQEAAAAAAAAAAAAAAAARAQIQICEx/9oACAEBAAY/AoapOdp//8QAGxABAQEAAwEBAAAAAAAAAAAAAREAITFBUXH/2gAIAQEAAT8hgQ7+ZrOuKrhBdFD25y/d65cEIUP3f//aAAwDAQACAAMAAAAQHM//xAAXEQADAQAAAAAAAAAAAAAAAAAAARHw/9oACAEDAQE/EJpVkf/EABkRAAIDAQAAAAAAAAAAAAAAAAERACGB4f/aAAgBAgEBPxB0A2EnTG8n/8QAGBABAQEBAQAAAAAAAAAAAAAAAREAIZH/2gAIAQEAAT8QAsjqivr3VZYSVT3FZTESHUmQS8BHdT8FMAIAgCA3/9k=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/9cb8a4fa7b7c9ccb14f866e9d15d8913/8ac56/error.webp 240w,
/static/9cb8a4fa7b7c9ccb14f866e9d15d8913/d3be9/error.webp 480w,
/static/9cb8a4fa7b7c9ccb14f866e9d15d8913/0ba47/error.webp 640w&quot;
              sizes=&quot;(max-width: 640px) 100vw, 640px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/9cb8a4fa7b7c9ccb14f866e9d15d8913/09b79/error.jpg 240w,
/static/9cb8a4fa7b7c9ccb14f866e9d15d8913/7cc5e/error.jpg 480w,
/static/9cb8a4fa7b7c9ccb14f866e9d15d8913/c08c5/error.jpg 640w&quot;
            sizes=&quot;(max-width: 640px) 100vw, 640px&quot;
            type=&quot;image/jpeg&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/9cb8a4fa7b7c9ccb14f866e9d15d8913/c08c5/error.jpg&quot;
            alt=&quot;Man with a wrist clock&quot;
            title=&quot;Man with a wrist clock&quot;
            loading=&quot;lazy&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Why this can happen you ask and I answer. &lt;strong&gt;There is no timeout configured!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The mail server health check uses &lt;a href=&quot;https://docs.oracle.com/javaee/6/api/javax/mail/Service.html#connect(java.lang.String,%20java.lang.String)&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;javax.mail.Service.connect&lt;/code&gt;&lt;/a&gt; under the hood. For a variety of reasons an attempt to establish a TCP connection can take arbitrary longer than usual. Unfortunately &lt;strong&gt;the default&lt;/strong&gt; timeouts used by the &lt;code class=&quot;language-text&quot;&gt;javax.mail.*&lt;/code&gt; &lt;a href=&quot;https://javaee.github.io/javamail/docs/api/com/sun/mail/smtp/package-summary.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;are &lt;strong&gt;infinite&lt;/strong&gt;&lt;/a&gt;. A thread that waits for the connection to be established cannot serve other requests even though it barely uses any CPU. The default maximum thread pool size used by embedded Tomcat in Spring Boot application is 200. Assuming that the blocked connection attempt happens twice an hour our application will stop working after 4 days.&lt;/p&gt;
&lt;h2 id=&quot;never-use-infinite-timeouts&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#never-use-infinite-timeouts&quot; aria-label=&quot;never use infinite timeouts permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Never use infinite timeouts&lt;/h2&gt;
&lt;p&gt;As you can see it is very easy to miss a need for a timeout to be configured. To be fair the &lt;a href=&quot;https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-email.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Spring Boot documentation&lt;/a&gt; states clearly:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;In particular, certain default timeout values are infinite and you may want to change that to avoid having a thread blocked by an unresponsive mail server:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;spring.mail.properties.mail.smtp.connectiontimeout=5000
spring.mail.properties.mail.smtp.timeout=3000
spring.mail.properties.mail.smtp.writetimeout=5000&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/blockquote&gt;
&lt;p&gt;In my option any library or framework should either force the programmer to configure the timeout or have some &lt;strong&gt;sensible default&lt;/strong&gt;. Unfortunately this is not always possible to introduce them later on without breaking changes hence we should &lt;strong&gt;check&lt;/strong&gt; what are the timeouts used when calling any &lt;strong&gt;external service&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id=&quot;timeouts-needed-everywhere&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#timeouts-needed-everywhere&quot; aria-label=&quot;timeouts needed everywhere permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Timeouts needed everywhere&lt;/h2&gt;
&lt;p&gt;Imagine a controller action method that inserts a single row into a database. Let us further assume that the endpoint is called 50 times per second and it typically takes 100ms to complete. Things work well until we encounter an intermittent sloppiness of the database and now the insert takes 2 seconds to complete. The clients calling the API do not slow down. More request threads are blocked and &lt;strong&gt;more database connections&lt;/strong&gt; are taken out of the pool. Soon as all database connections are in use and all other API endpoints start to fail. This is an example of cascading failure i.e. a problem in one component propagating to others. It is easier to avoid such issues when there is a timeout configured on the controller action and the interaction with the database.&lt;/p&gt;
&lt;p&gt;Every API endpoint &lt;strong&gt;should have a timeout configured&lt;/strong&gt; if we want our services to be resilient. Unfortunately this rule is easy to neglect. Moreover, some frameworks do not even expose such ability. Even in the immensely popular Spring Mvc I could not find a way to set such timeout other than using an &lt;a href=&quot;https://spring.io/guides/gs/async-method/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;async method&lt;/a&gt;. Fortunately there are libraries e.g. &lt;a href=&quot;https://github.com/Netflix/Hystrix&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Hystrix&lt;/a&gt; that tackle that problem and can be integrated easily.&lt;/p&gt;
&lt;p&gt;Just to recap here is a short and incomplete list of cases where a timeout should be configured:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;a controller action&lt;/li&gt;
&lt;li&gt;a database query, statement&lt;/li&gt;
&lt;li&gt;a database pool interaction&lt;/li&gt;
&lt;li&gt;a thread pool interaction&lt;/li&gt;
&lt;li&gt;an API client e.g. HTTP, SOAP, SMTP&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I will describe how to deal with the cases in the following posts.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[How to clear database in Spring Boot tests?]]></title><description><![CDATA[Nowadays using a production like database in unit1 tests is a common practice. Calling a real database can increase our confidence that a tested code actually works. Having said that a database, by its very nature, brings external state into a test that will affect its behavior, hence we need to pay special attention…]]></description><link>undefined/clear-database-in-spring-boot-tests/</link><guid isPermaLink="false">undefined/clear-database-in-spring-boot-tests/</guid><pubDate>Fri, 13 Oct 2017 22:14:00 GMT</pubDate><content:encoded>&lt;p&gt;Nowadays using a production like database in &lt;em&gt;unit&lt;/em&gt;&lt;sup&gt;&lt;a href=&quot;#sup-1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; tests is a common practice. Calling a real database can increase our confidence that a tested code actually works. Having said that a database, by its very nature, brings external state into a test that will affect its behavior, hence we need to pay special attention to prepare the test execution. There are couple of ways to handle the database state in tests and I’m going to describe an approach I like most.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/02fae8050074badc44f5ac157c98e966/c08c5/disk.jpg&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: 66.66666666666666%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAIEAQP/xAAUAQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIQAxAAAAHk9k4pgf/EABoQAAICAwAAAAAAAAAAAAAAAAECAxIAEBH/2gAIAQEAAQUCSN+COmo2uhSgz//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EAB4QAAIBAwUAAAAAAAAAAAAAAAECABARIRIiMVGh/9oACAEBAAY/At+S3kvrNA3cZeQ2af/EABoQAAMBAQEBAAAAAAAAAAAAAAABESFBMVH/2gAIAQEAAT8hqpuK6aoa/rG3TBpHgik2Vrgz/9oADAMBAAIAAwAAABCQz//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8QP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8QP//EAB0QAAICAQUAAAAAAAAAAAAAAAERACFREDFBYaH/2gAIAQEAAT8QDTnawOSTm9oACWRWax5pD8ryWaja9D2paHUK5//Z&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/02fae8050074badc44f5ac157c98e966/8ac56/disk.webp 240w,
/static/02fae8050074badc44f5ac157c98e966/d3be9/disk.webp 480w,
/static/02fae8050074badc44f5ac157c98e966/0ba47/disk.webp 640w&quot;
              sizes=&quot;(max-width: 640px) 100vw, 640px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/02fae8050074badc44f5ac157c98e966/09b79/disk.jpg 240w,
/static/02fae8050074badc44f5ac157c98e966/7cc5e/disk.jpg 480w,
/static/02fae8050074badc44f5ac157c98e966/c08c5/disk.jpg 640w&quot;
            sizes=&quot;(max-width: 640px) 100vw, 640px&quot;
            type=&quot;image/jpeg&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/02fae8050074badc44f5ac157c98e966/c08c5/disk.jpg&quot;
            alt=&quot;Database&quot;
            title=&quot;Database&quot;
            loading=&quot;lazy&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;{: .center-image}&lt;/p&gt;
&lt;h2 id=&quot;problems-with-spring-boot-transactional-tests&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#problems-with-spring-boot-transactional-tests&quot; aria-label=&quot;problems with spring boot transactional tests permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Problems with Spring Boot Transactional tests&lt;/h2&gt;
&lt;p&gt;Spring Boot offers many helpers to make testing application easier. Among many you can use a &lt;a href=&quot;https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-testing.html#boot-features-testing-spring-boot-applications-testing-autoconfigured-jpa-test&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;@DataJpaTest&lt;/code&gt;&lt;/a&gt; which by default will configure an in-memory embedded database. You can use a production type database in tests by adding &lt;code class=&quot;language-text&quot;&gt;@AutoConfigureTestDatabase(replace=Replace.NONE)&lt;/code&gt; like so:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;java&quot;&gt;&lt;pre class=&quot;language-java&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;token annotation punctuation&quot;&gt;@RunWith&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;SpringRunner&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token annotation punctuation&quot;&gt;@DataJpaTest&lt;/span&gt;
&lt;span class=&quot;token annotation punctuation&quot;&gt;@AutoConfigureTestDatabase&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;replace&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Replace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;NONE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ExampleRepositoryTests&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;@DataJpaTest&lt;/code&gt; uses &lt;code class=&quot;language-text&quot;&gt;@Transactional&lt;/code&gt; under the hood. A test is wrapped inside a transaction that is rolled back at the end. This means that when using e.g. Hibernate one needs to pay special attention to how the tested code is written. &lt;a href=&quot;https://docs.spring.io/spring/docs/4.3.11.RELEASE/spring-framework-reference/htmlsingle/#testcontext-tx-enabling-transactions&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;As shown in the Java example below&lt;/a&gt;, a manual flush is indeed required:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;java&quot;&gt;&lt;pre class=&quot;language-java&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;token annotation punctuation&quot;&gt;@RunWith&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;SpringRunner&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token annotation punctuation&quot;&gt;@ContextConfiguration&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;classes &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;TestConfig&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token annotation punctuation&quot;&gt;@Transactional&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;HibernateUserRepositoryTests&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
    &lt;span class=&quot;token annotation punctuation&quot;&gt;@Test&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// track initial state in test database:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; count &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;countRowsInTable&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;user&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token class-name&quot;&gt;User&lt;/span&gt; user &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        repository&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token comment&quot;&gt;// Manual flush is required to avoid false positive in test&lt;/span&gt;
        sessionFactory&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getCurrentSession&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;flush&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;assertNumUsers&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;count &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Using &lt;code class=&quot;language-text&quot;&gt;@Transactional&lt;/code&gt; annotation on tests is certainly easy but &lt;strong&gt;I still don’t use it&lt;/strong&gt; for the following reasons:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The production code is using transactions with different scope.&lt;/li&gt;
&lt;li&gt;It is easy to forget about a flush and thus have false positive in test.&lt;/li&gt;
&lt;li&gt;On failure and when debugging it is hard to see what values were actually saved in db.&lt;/li&gt;
&lt;li&gt;It is much harder to write tests of production code that requires a transaction to be committed.&lt;/li&gt;
&lt;li&gt;The test code needs to be more tightly coupled to production code and &lt;a href=&quot;http://blog.cleancoder.com/uncle-bob/2017/10/03/TestContravariance.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;we all know that it hinders refactoring&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;cleaning-database-with-sql&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#cleaning-database-with-sql&quot; aria-label=&quot;cleaning database with sql permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Cleaning database with SQL&lt;/h2&gt;
&lt;p&gt;In tests involving a database I reset its state &lt;strong&gt;before each&lt;/strong&gt; test using plain old SQL. This makes the test code less dependent on how a transaction is scoped inside production code. Furthermore, one can easily review the values saved &lt;strong&gt;after a test failure&lt;/strong&gt;. It turns out it is easy to write a JUnit &lt;code class=&quot;language-text&quot;&gt;@Rule&lt;/code&gt; or &lt;a href=&quot;http://junit.org/junit5/docs/5.0.1/api/org/junit/jupiter/api/extension/BeforeEachCallback.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;BeforeEachCallback&lt;/code&gt;&lt;/a&gt; that will remove all rows from all tables. Moreover, we can do so without hard coding table names which would increase maintenance cost.&lt;/p&gt;
&lt;p&gt;Let’s start with defining a &lt;code class=&quot;language-text&quot;&gt;@Rule&lt;/code&gt; in Kotlin in that will be called before each test:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;kotlin&quot;&gt;&lt;pre class=&quot;language-kotlin&quot;&gt;&lt;code class=&quot;language-kotlin&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; org&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;junit&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;rules&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ExternalResource
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; org&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;springframework&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;stereotype&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Component
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; javax&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;sql&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;DataSource

&lt;span class=&quot;token annotation builtin&quot;&gt;@Component&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;DatabaseCleanerRule&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; dataSource&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; DataSource&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;ExternalResource&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;before&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;databaseCleaner &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token comment&quot;&gt;// Consider inspecting dataSource to check if we are connecting to test database&lt;/span&gt;
            databaseCleaner &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;DatabaseCleaner&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;dataSource&lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt;getConnection&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        databaseCleaner&lt;span class=&quot;token operator&quot;&gt;!!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;reset&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;companion&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;internal&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; databaseCleaner&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; DatabaseCleaner&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Consider inspecting &lt;code class=&quot;language-text&quot;&gt;dataSource&lt;/code&gt; to check if we are about to connect to test database and &lt;strong&gt;not one used for development.&lt;/strong&gt; It is very easy to use incorrect Spring Profile and wipe out your development data. Ask me how I know?&lt;/p&gt;
&lt;p&gt;We can use the &lt;code class=&quot;language-text&quot;&gt;DatabaseCleanerRule&lt;/code&gt; in a spring enabled test as any other JUnit rule e.g. &lt;code class=&quot;language-text&quot;&gt;@Rule @Inject lateinit var cleanerRule: DatabaseCleanerRule&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Notice that we’ve delegated the actual important work to &lt;code class=&quot;language-text&quot;&gt;DatabaseCleaner&lt;/code&gt; class defined in Kotlin below.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;kotlin&quot;&gt;&lt;pre class=&quot;language-kotlin&quot;&gt;&lt;code class=&quot;language-kotlin&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; com&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;practi&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;util&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;iterator
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; org&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;slf4j&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;LoggerFactory
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; java&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;sql&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Connection
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; java&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;sql&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;PreparedStatement
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; java&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;sql&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;SQLException

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;DatabaseCleaner&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; connectionProvider&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; Connection&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; tablesToExclude &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; mutableSetOf&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;String&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; tablesForClearing&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; List&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;TableRef&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;excludeTables&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;vararg&lt;/span&gt; tableNames&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        tablesToExclude &lt;span class=&quot;token operator&quot;&gt;+=&lt;/span&gt; tableNames&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;flatMap&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;listOf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;it&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; it&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toLowerCase&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;reset&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;notPrepared&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;prepare&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;executeReset&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; notPrepared &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; tablesForClearing &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;prepare&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;connectionProvider&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; connection &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; metaData &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; connection&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;metaData
            &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; tableRefs &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; metaData&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getTables&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;connection&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;catalog&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;arrayOf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;TABLE&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; tables &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
                &lt;span class=&quot;token function&quot;&gt;iterator&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;tables&lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt;next&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; tables&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;TABLE_NAME&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
                    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;asSequence&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;filterNot&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;tablesToExclude&lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt;contains&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt;TableRef&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toList&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

            tablesForClearing &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; tableRefs

            LOG&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Prepared clean db command: {}&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; tablesForClearing&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;executeReset&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;connectionProvider&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; connection &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; reset &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;buildClearStatement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;connection&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; reset&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;executeBatch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                result
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;e&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; SQLException&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; status &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;engineInnoDbStatus&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            LOG&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Failed to remove rows because {}. InnoDb status: {}&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; e&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; status&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; e
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;engineInnoDbStatus&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; String &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;buildClearStatement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;connection&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Connection&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; PreparedStatement &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; reset &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; connection&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;prepareStatement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        reset&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addBatch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;SET FOREIGN_KEY_CHECKS = 0&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        tablesForClearing&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;forEach&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; ref &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
            reset&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addBatch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;DELETE FROM `&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token delimiter variable&quot;&gt;${&lt;/span&gt;ref&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token delimiter variable&quot;&gt;}&lt;/span&gt;&lt;/span&gt;`&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        reset&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addBatch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;SET FOREIGN_KEY_CHECKS = 1&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; reset
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;TableRef&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;companion&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; LOG &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; LoggerFactory&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getLogger&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;DatabaseCleaner&lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;java&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!!&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Notice that we’ve defined &lt;code class=&quot;language-text&quot;&gt;tablesToExclude&lt;/code&gt; set that allows us to omit certain tables. This comes in handy when you’re using a database migration tool that stores its state inside some table(s).&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.oracle.com/javase/7/docs/api/java/sql/DatabaseMetaData.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;The JDBC metadata&lt;/a&gt; allows us to introspect schema regardless of the database vendor. The &lt;code class=&quot;language-text&quot;&gt;iterator&lt;/code&gt; is a tiny Kotlin function that aids consuming iterator like objects:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;kotlin&quot;&gt;&lt;pre class=&quot;language-kotlin&quot;&gt;&lt;code class=&quot;language-kotlin&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;inline&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;T&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;iterator&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;crossinline&lt;/span&gt; next&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; Boolean&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;crossinline&lt;/span&gt; value&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; T&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; AbstractIterator&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;out&lt;/span&gt; T&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; AbstractIterator&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;T&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;computeNext&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;setNext&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;done&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;buildClearStatement&lt;/code&gt; constructs a large query that &lt;code class=&quot;language-text&quot;&gt;DELETE&lt;/code&gt;s all rows from each relevant table. The example above uses MySQL where it is very easy to disable foreign key checks. This is important since foreign keys would prevent rows to be removed unless we paid special attention to the order of removal. A more generic example of how to deal with referential integrity when clearing a database can be found in the &lt;a href=&quot;https://github.com/jbogard/Respawn&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Respawn project&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Last but not least, when a &lt;code class=&quot;language-text&quot;&gt;SQLException&lt;/code&gt; is thrown we log the exception accompanied with &lt;a href=&quot;https://dev.mysql.com/doc/refman/5.7/en/show-engine.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;SHOW ENGINE INNODB STATUS&lt;/code&gt;&lt;/a&gt;. The status information can hint us about failure reason e.g. another test process executing against the same database or a rogue, runaway thread that locks some rows.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;kotlin&quot;&gt;&lt;pre class=&quot;language-kotlin&quot;&gt;&lt;code class=&quot;language-kotlin&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;engineInnoDbStatus&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; String &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;connectionProvider&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; connection &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
        connection&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createStatement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;executeQuery&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;SHOW ENGINE INNODB STATUS &quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;iterator&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;it&lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt;next&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; it&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Status&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;asSequence&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toList&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;joinToString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;System&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;lineSeparator&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The above examples show that it is not hard to manually reset the database. I’ve found that using this approach makes my tests more trustworthy and less coupled to the underlying persistence layer. In fact, we can easily switch e.g. from JPA to &lt;code class=&quot;language-text&quot;&gt;JdbcTemplate&lt;/code&gt; in a performance critical code area without a need to change a test.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/em&gt;&lt;a name=&quot;sup-1&quot;&gt;&lt;/a&gt; Whether it is actually unit or integration test is a different topic.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Simple Config Sections 1.2 released]]></title><description><![CDATA[About a week ago I’ve released another version of SimpleConfigSections. It’s marked  and you can install it through . What is SimpleConfigSections? SimpleConfigSections is a little library that simplifies defining .net configuration sections. As you can see in the mentioned msdn documentation the amount of boilerplate…]]></description><link>undefined/simple-config-sections-12-released/</link><guid isPermaLink="false">undefined/simple-config-sections-12-released/</guid><pubDate>Fri, 25 Dec 2015 10:21:00 GMT</pubDate><content:encoded>&lt;p&gt;About a week ago I’ve released another version of &lt;a href=&quot;https://github.com/miensol/SimpleConfigSections&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;&lt;strong&gt;SimpleConfigSections&lt;/strong&gt;&lt;/a&gt;. It’s marked &lt;code class=&quot;language-text&quot;&gt;1.2.0&lt;/code&gt; and you can install it through &lt;code class=&quot;language-text&quot;&gt;Install-Package SimpleConfigSections&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;what-is-simpleconfigsections&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#what-is-simpleconfigsections&quot; aria-label=&quot;what is simpleconfigsections permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;What is SimpleConfigSections?&lt;/h2&gt;
&lt;p&gt;SimpleConfigSections is a little library that simplifies defining &lt;a href=&quot;https://msdn.microsoft.com/pl-pl/library/2tw134k3.aspx&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;.net configuration sections&lt;/a&gt;. As you can see in the mentioned msdn documentation the amount of boilerplate code is substantial. An equivalent example in &lt;strong&gt;SimpleConfigSections&lt;/strong&gt; looks like follows:&lt;/p&gt;
&lt;script src=&quot;https://gist.github.com/miensol/f5801742f7a039c820dc.js?file=MsdnExample.cs&quot;&gt;&lt;/script&gt;
&lt;p&gt;As you can see the &lt;code class=&quot;language-text&quot;&gt;SimpleConfigSection&lt;/code&gt;s version is more concise and a bit easier to write. More examples can be found &lt;a href=&quot;https://github.com/miensol/SimpleConfigSections&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;on project’s github page&lt;/a&gt;.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Android Data Binding Part 2: Observer pattern to the bone]]></title><description><![CDATA[In the previous part I’ve described typical problems we have to face when developing applications on Android. I’ve also highlighted that some of them may be mitigated when data binding API is utilized properly. It’s time to dive into more details of how this promising API works. Observer Pattern At the root of many of…]]></description><link>undefined/android-data-binding-part-2-observer-pattern-to-the-bone/</link><guid isPermaLink="false">undefined/android-data-binding-part-2-observer-pattern-to-the-bone/</guid><pubDate>Mon, 27 Jul 2015 08:45:00 GMT</pubDate><content:encoded>&lt;p&gt;In the &lt;a href=&quot;/android-data-binding-part-1-why-it-is-important&quot;&gt;previous part&lt;/a&gt; I’ve described typical problems we have to face when developing applications on Android. I’ve also highlighted that some of them may be mitigated when &lt;a href=&quot;https://developer.android.com/tools/data-binding/guide.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;data binding API&lt;/a&gt; is utilized properly. It’s time to dive into more details of how this promising API works.&lt;/p&gt;
&lt;h2 id=&quot;observer-pattern&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#observer-pattern&quot; aria-label=&quot;observer pattern permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Observer Pattern&lt;/h2&gt;
&lt;p&gt;At the root of many of solutions we find in today’s APIs is a design pattern. In case of the discussed Android API it is &lt;a href=&quot;https://en.wikipedia.org/wiki/Observer_pattern&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Observer Pattern&lt;/a&gt; applied to the bone. In fact this particular pattern is so common and powerful that some languages and runtimes (C# with .NET, Objective-C and Swift on iOS and Mac) provide neat support for it. You may wonder why it is important in the context of Android data binding? The answer is simple yet easy to ignore - memory management. The following diagram depicts dependencies of an observer pattern’s elements in the context of Android data binding:
&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;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 52.916666666666664%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAAsTAAALEwEAmpwYAAADEklEQVQoz32Rz0/bZhzG3w6kkcRJME0BNbGpQxwn84vzhtWmddmGkyZhJpiyMKFSoaSM2v2JMUFUmuBCBaIZYRX5UdsQEXbYhFTtMqk9bKdeKlXaYef2D5i0Y/+AVMm9O3z06HkOH32lLyiXywO6ro+urq7yhmHE19fXuWKx+KVhGO3tcrFYDDWbzV7Lss4/ebLt2tvbw0qlElav1537+/udvrOzg1mW5TRN0wESiYRLluWLs7OzflmWiVQqxabT6cj09PSlXC5HiqJ4fnt7u3dzc9MnCAKmKAo+OTnZJ0mSP5PJ+GRZxrPZLD41NeU4PT31gng87mYYBqMoysFxXIBhmADLsgSE8AKO410AgK6FhQXy2cFB9HoyeYFlIYkQakMhhIYQQn6EEOZ2u3vOzs4wQJKkk+d5iud5cmRkxD+jKGFJkgiE0EVBEAiapr0rKyv9tWp1IMZxNMdxwxDCQQihj2VZXzQa7YMQegOBgKMjpCjK9dX4uGtsbAxjWdYpSVJAFK8OxGIxjyiKOE3TuK7rg5ZluxRlxrm0tOQpFAod8vl8O/HFxcVeAACwbdsN4jGOHOEgHUNc6IoghCORcBDFOOqKwIdYNjrEhEP9S4U8VS6XvcvLy4SmaRFVVSOapgU1TaNVVYWqqjK7u7vdtm0722LH3Xs6PTe3SAAAPA8eGoySuzUIup3ex4+3hqXZOz037z/qr9Tqns2tLaDrOjAMA6ytrXVo942NDdBoNLo6X/7waAZ/fj8btB+myZYx5z26qwR/vScH/r3zLX6Qz9AnhevE2+Jtf6NW8T2r1Z3VSgWrVCpYtVrt5OHhYRuXaZpey7JcoKzEu4kj6QVxLDVbAADyOHFC2N/owZp4mTpJ/zN49LXRAqC7UUz3rPz15rPjWrV9yac4B9qS0affj48+neeTPzzAuZ/mrqHd+S/GflwIw5+/yw6X5mELB5+3IOh6dzsDSr/9DkzT/CTg/YS/91UieelFJhX6JTcx/OeERP6Rnhhq3shEXl9Nki9TEvnfNU9fiwTnWi4A/l7O/q/wI3taEFv+zNbvAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/ccd052e87f97e39eeef0e6f724a64e42/8ac56/android_data_binding_diagram.webp 240w,
/static/ccd052e87f97e39eeef0e6f724a64e42/d3be9/android_data_binding_diagram.webp 480w,
/static/ccd052e87f97e39eeef0e6f724a64e42/e46b2/android_data_binding_diagram.webp 960w,
/static/ccd052e87f97e39eeef0e6f724a64e42/0b716/android_data_binding_diagram.webp 1296w&quot;
              sizes=&quot;(max-width: 960px) 100vw, 960px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/ccd052e87f97e39eeef0e6f724a64e42/8ff5a/android_data_binding_diagram.png 240w,
/static/ccd052e87f97e39eeef0e6f724a64e42/e85cb/android_data_binding_diagram.png 480w,
/static/ccd052e87f97e39eeef0e6f724a64e42/d9199/android_data_binding_diagram.png 960w,
/static/ccd052e87f97e39eeef0e6f724a64e42/86a1e/android_data_binding_diagram.png 1296w&quot;
            sizes=&quot;(max-width: 960px) 100vw, 960px&quot;
            type=&quot;image/png&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/ccd052e87f97e39eeef0e6f724a64e42/d9199/android_data_binding_diagram.png&quot;
            alt=&quot;Android data binding diagram&quot;
            title=&quot;Android data binding diagram&quot;
            loading=&quot;lazy&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
    &lt;/span&gt;
On the right side we have the &lt;em&gt;observable&lt;/em&gt; part producing notifications about changes - an object implementing &lt;code class=&quot;language-text&quot;&gt;android.databinding.Observable&lt;/code&gt; interface. In the observer pattern &lt;em&gt;events producer&lt;/em&gt; can have many &lt;em&gt;events listeners&lt;/em&gt; - &lt;code class=&quot;language-text&quot;&gt;OnPropertyChangedCallback&lt;/code&gt; implementations. Android data binding provides implementations of &lt;em&gt;events listeners&lt;/em&gt; taking care of property values changes as well as collection elements changes.&lt;/p&gt;
&lt;p&gt;Note that the &lt;code class=&quot;language-text&quot;&gt;Observable&lt;/code&gt; object knows nothing about concrete &lt;code class=&quot;language-text&quot;&gt;OnPropertyChangedCallback&lt;/code&gt; implementations (&lt;a href=&quot;https://en.wikipedia.org/wiki/Dependency_inversion_principle&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Dependency Inversion Principle&lt;/a&gt; at its best). However, at runtime the &lt;code class=&quot;language-text&quot;&gt;Observable&lt;/code&gt; object will hold references to many &lt;code class=&quot;language-text&quot;&gt;OnPropertyChangedCallback&lt;/code&gt;s instances. If you look further down the diagram you’ll see that in order for &lt;code class=&quot;language-text&quot;&gt;OnPropertyChangedCallback&lt;/code&gt; implementations provided by Android data binding library to update the state of the view component a reference to it is required. This means that although the view model knows nothing about the view components at compile time they will reference them at runtime.&lt;/p&gt;
&lt;h2 id=&quot;how-android-data-binding-library-aids-memory-management&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#how-android-data-binding-library-aids-memory-management&quot; aria-label=&quot;how android data binding library aids memory management permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;How Android data binding library aids memory management?&lt;/h2&gt;
&lt;p&gt;As stated above in a simple implementation we would have a lightweight and testable view model retain expensive view widgets - thus making it heavy. In the Android context it means that even though an &lt;code class=&quot;language-text&quot;&gt;Activity&lt;/code&gt; got destroyed we could have other object still retaining its &lt;code class=&quot;language-text&quot;&gt;Views&lt;/code&gt;, trying to update them and preventing them from being garbage collected. Not so nice, huh?&lt;/p&gt;
&lt;p&gt;If you look closer at how Android data binding is implemented you’ll immediately see that its &lt;code class=&quot;language-text&quot;&gt;OnPropertyChangedCallback&lt;/code&gt; holds only &lt;a href=&quot;http://developer.android.com/reference/java/lang/ref/WeakReference.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;weak references&lt;/a&gt; to views.
&lt;code class=&quot;language-text&quot;&gt;WeakPropertyListener&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;WeakListListener&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;WeakMapListener&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;ViewDataBinding.WeakListener&lt;/code&gt; make sure that the &lt;code class=&quot;language-text&quot;&gt;Observable&lt;/code&gt; object is not retaining views. This means that there’s no need for a developer to manually &lt;em&gt;stop&lt;/em&gt; data binding in an activity &lt;code class=&quot;language-text&quot;&gt;onDestroy&lt;/code&gt; or a fragment &lt;code class=&quot;language-text&quot;&gt;onDestroyView&lt;/code&gt; methods. If you use &lt;a href=&quot;https://github.com/ReactiveX/RxJava&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;RxJava&lt;/a&gt; you probably know that this extra step is tedious and requires a great deal of attention and boilerplate code. You can find out more about the problem in at least couple of issues on GitHub: &lt;a href=&quot;https://github.com/ReactiveX/RxJava/issues/386&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;1&lt;/a&gt;, &lt;a href=&quot;https://github.com/ReactiveX/RxAndroid/issues/12&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;2&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Because Android data binding library takes extra steps to make sure a view model will not cause views to be retained we can detach a view model’s lifecycle from that of an activity or a fragment. We now have an easy way to i.e. do a simple in-memory caching via singleton view models. More importantly, we can cross out at least one place when looking for a memory leak cause.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This article is cross-posted with &lt;a href=&quot;http://blog.brightinventions.pl&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;my company blog&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Android Data Binding Part 1: Why it is important]]></title><description><![CDATA[Android application code often suffers from being more verbose than it could be. As libraries such as Android Annotations and ButterKnife have shown that’s only partially due to tediousness of Java. The recently announced Android Data Binding library can remove at least part of the boilerplate code we need to write…]]></description><link>undefined/android-data-binding-part-1-why-it-is-important/</link><guid isPermaLink="false">undefined/android-data-binding-part-1-why-it-is-important/</guid><pubDate>Mon, 20 Jul 2015 08:36:00 GMT</pubDate><content:encoded>&lt;p&gt;Android application code often suffers from being more verbose than it could be. As libraries such as &lt;a href=&quot;http://androidannotations.org/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Android Annotations&lt;/a&gt; and &lt;a href=&quot;http://jakewharton.github.io/butterknife/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;ButterKnife&lt;/a&gt; have shown that’s only partially due to tediousness of Java. The &lt;a href=&quot;https://events.google.com/io2015/schedule?sid=128c9f91-b6d4-e411-b87f-00155d5066d7&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;recently&lt;/a&gt; announced &lt;a href=&quot;https://developer.android.com/tools/data-binding/guide.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Android Data Binding&lt;/a&gt; library can remove at least part of the boilerplate code we need to write. Since I’ve always liked &lt;a href=&quot;http://martinfowler.com/eaaDev/PresentationModel.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Presentation Model pattern (MVVM)&lt;/a&gt; this is very dear to my heart. However just getting rid of a tedious code is not the main reason I’m so happy to see the new API. Let’s recap on common issues developer faces on Android and then I’ll show how using mentioned patterns with new offering from Google can mitigate them.&lt;/p&gt;
&lt;h2 id=&quot;problems-with-classic-approach&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#problems-with-classic-approach&quot; aria-label=&quot;problems with classic approach permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Problems with classic approach&lt;/h2&gt;
&lt;p&gt;I’ll explain that step by step using a registration form screen example. We need couple of fields like first name, last name and an email address. To make the example a bit more interesting and to make UX better we’ll use &lt;a href=&quot;http://mds.is/float-label-demo/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;floating label&lt;/a&gt; pattern. One of the simplest approaches &lt;strong&gt;without data binding&lt;/strong&gt; (for first name only) might look like this:&lt;/p&gt;
&lt;script src=&quot;https://gist.github.com/miensol/52b98f0fcbe89db81441.js?file=RegisterActivityClassic.java&quot;&gt;&lt;/script&gt;
&lt;h3 id=&quot;memory-leaks&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#memory-leaks&quot; aria-label=&quot;memory leaks permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Memory leaks&lt;/h3&gt;
&lt;p&gt;A seasoned Android developer will immediately spot that we’ve a potentially leaked activity here. The culprit is of course the anonymous inner class implementing &lt;code class=&quot;language-text&quot;&gt;RegisterApi&lt;/code&gt; callback (&lt;code class=&quot;language-text&quot;&gt;Action2&lt;/code&gt;), which in turn uses &lt;code class=&quot;language-text&quot;&gt;findViewById&lt;/code&gt;. However it’s not the mentioned method that retains the activity - in Java every non-static inner class will have &lt;em&gt;implicit&lt;/em&gt; reference to the enclosing class instance. While this problem is so common I still haven’t found a concise solution in the Android SDK. There are however community driven libraries i.e. &lt;a href=&quot;http://square.github.io/otto/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Otto&lt;/a&gt; and &lt;a href=&quot;https://github.com/ReactiveX/RxJava&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;RxJava&lt;/a&gt; that can help tackle this problem.&lt;/p&gt;
&lt;h3 id=&quot;to-much-code-in-activity&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#to-much-code-in-activity&quot; aria-label=&quot;to much code in activity permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;To much code in Activity&lt;/h3&gt;
&lt;p&gt;Many of us, me including, are guilt of stuffing too much into &lt;code class=&quot;language-text&quot;&gt;Activity&lt;/code&gt; classes. Writing test and maintaining them can become a nightmare over time. The verbosity of Java only makes the matter worse. One way to slim activities down is to use &lt;a href=&quot;http://martinfowler.com/eaaDev/uiArchs.html#Model-view-presentermvp&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Presenter pattern&lt;/a&gt; written either by hand or with the help of &lt;a href=&quot;https://github.com/square/mortar&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Mortar&lt;/a&gt;. Another solution is to encapsulate more logic into custom view classes used in layouts and using shared static helper methods with common code that calls Android API. Nevertheless, for a programmer that just starts with Android, it’s important that the framework provides guidance and samples that encourage separation of concerns - in my opinion up until now that was rarely the case.&lt;/p&gt;
&lt;h3 id=&quot;maintaining-layout-files&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#maintaining-layout-files&quot; aria-label=&quot;maintaining layout files permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Maintaining layout files&lt;/h3&gt;
&lt;p&gt;Many if not most screens in Android (and other platforms, too) are &lt;em&gt;read-only&lt;/em&gt;. That is they are not forms and fields that user can change. Instead they offer neatly presented content with some way of interacting with it (as opposed to changing it directly). When using Android layout files we’re forced to use references (auto generated in &lt;code class=&quot;language-text&quot;&gt;R&lt;/code&gt; class by aapt) that allow setting view’s properties. This isn’t something necessarily bad especially if you need to heavily interact with a &lt;code class=&quot;language-text&quot;&gt;View&lt;/code&gt;. Having said that, how often you used &lt;code class=&quot;language-text&quot;&gt;findViewById&lt;/code&gt; (or &lt;code class=&quot;language-text&quot;&gt;@InjectView&lt;/code&gt;) just to set the content of &lt;code class=&quot;language-text&quot;&gt;TextView&lt;/code&gt; or had to refactor activity fields type because of a change in a layout definition?&lt;/p&gt;
&lt;h2 id=&quot;android-data-binding-can-help-you&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#android-data-binding-can-help-you&quot; aria-label=&quot;android data binding can help you permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Android Data Binding can help you.&lt;/h2&gt;
&lt;p&gt;The following code illustrates how registration form might look like &lt;strong&gt;with data binding&lt;/strong&gt;:&lt;/p&gt;
&lt;script src=&quot;https://gist.github.com/miensol/44ac5af33a60ad60cab7.js?file=RegisterActivity.java&quot;&gt;&lt;/script&gt;
&lt;p&gt;The new &lt;code class=&quot;language-text&quot;&gt;RegisterActivity&lt;/code&gt; is similar to previous example. We inflate the layout differently to initialize data binding and get an instance of &lt;code class=&quot;language-text&quot;&gt;ActivityRegisterBinding&lt;/code&gt; class. The class, with the name derived from layout name, is generated by data binding and its main purpose is to provide a glue between a view and an observable view model. When using &lt;code class=&quot;language-text&quot;&gt;registerApi.register&lt;/code&gt; we only reference &lt;code class=&quot;language-text&quot;&gt;form&lt;/code&gt; variable thus avoid unnecessarily referencing the activity. The &lt;code class=&quot;language-text&quot;&gt;RegisterForm&lt;/code&gt; class is a &lt;em&gt;view model&lt;/em&gt; for our layout and has all the data that &lt;code class=&quot;language-text&quot;&gt;activity_register&lt;/code&gt; layout requires.&lt;/p&gt;
&lt;script src=&quot;https://gist.github.com/miensol/44ac5af33a60ad60cab7.js?file=RegisterForm.java&quot;&gt;&lt;/script&gt;
&lt;p&gt;The view model has 3 observable attributes marked with &lt;code class=&quot;language-text&quot;&gt;@Bindable&lt;/code&gt; annotation. We don’t strictly need a backing field as the &lt;code class=&quot;language-text&quot;&gt;getFirstNameLabelVisibility&lt;/code&gt; shows. What we do need is to fire change notification events, which is done via &lt;code class=&quot;language-text&quot;&gt;notifyPropertyChanged&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;notifyChange&lt;/code&gt; methods available on &lt;code class=&quot;language-text&quot;&gt;BaseObservable&lt;/code&gt;. The former method accepts a field id that is assigned by data binding processor in generated class &lt;code class=&quot;language-text&quot;&gt;BR&lt;/code&gt; (similarily to &lt;code class=&quot;language-text&quot;&gt;R&lt;/code&gt; class). Deriving from &lt;code class=&quot;language-text&quot;&gt;BaseObservable&lt;/code&gt; is not a must - to make a model bindable it has to implement &lt;code class=&quot;language-text&quot;&gt;android.databinding.Observable&lt;/code&gt;.
Last but not least a layout file:&lt;/p&gt;
&lt;script src=&quot;https://gist.github.com/miensol/44ac5af33a60ad60cab7.js?file=activity_register.xml&quot;&gt;&lt;/script&gt;
&lt;p&gt;The data binding library, while still in beta, provides a nice toolset to remove the boilerplate code and improve Android code (unit) testability by extracting the logic from activity (or fragment). When used properly it can also save you from leaking resources. In the &lt;a href=&quot;/android-data-binding-part-2-observer-pattern-to-the-bone&quot;&gt;next post&lt;/a&gt; I’ll explain in more detail how it happens.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This article is cross-posted with &lt;a href=&quot;http://blog.brightinventions.pl&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;my company blog&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Handling different user types in android application]]></title><description><![CDATA[In the previous post you can read how to use  object to maintain current user information through the application lifecycle. Now we’ll explore different options of implementing varying behavior depending on user type. When an app has only one user type I find it neat when an application allows me to use it before I’m…]]></description><link>undefined/handling-different-user-types-in-android-application/</link><guid isPermaLink="false">undefined/handling-different-user-types-in-android-application/</guid><pubDate>Sun, 12 Jul 2015 23:40:00 GMT</pubDate><content:encoded>&lt;p&gt;In the &lt;a href=&quot;/maintaining-current-user-information-in-android&quot;&gt;previous post&lt;/a&gt; you can read how to use &lt;code class=&quot;language-text&quot;&gt;Session&lt;/code&gt; object to maintain current user information through the application lifecycle. Now we’ll explore different options of implementing varying behavior depending on user type.&lt;/p&gt;
&lt;h2 id=&quot;when-an-app-has-only-one-user-type&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#when-an-app-has-only-one-user-type&quot; aria-label=&quot;when an app has only one user type permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;When an app has only one user type&lt;/h2&gt;
&lt;p&gt;I find it neat when an application allows me to use it before I’m forced to create an account or sign in. In such a case there will be a, potentially very long, time where we have no way of identifying the user. At the same time we’ll want to provide as much features of an identified user as possible. There will however be cases where application behavior will be different depending on whether the user is logged in or not.&lt;/p&gt;
&lt;h3 id=&quot;a-simple-if-will-not-do-any-harm-or-will-it&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#a-simple-if-will-not-do-any-harm-or-will-it&quot; aria-label=&quot;a simple if will not do any harm or will it permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;A simple &lt;code class=&quot;language-text&quot;&gt;if&lt;/code&gt; will not do any harm, or will it?&lt;/h3&gt;
&lt;p&gt;Let’s assume that our application allows changing preferences for both anonymous and authenticated users. When saving or reading user dependent application settings we can write a simple &lt;code class=&quot;language-text&quot;&gt;if&lt;/code&gt; statement to decide which preferences to use.&lt;/p&gt;
&lt;script src=&quot;https://gist.github.com/miensol/4268ec47392ed4ea232e.js?file=CurrentUserProvider.java&quot;&gt;&lt;/script&gt;
&lt;p&gt;Notice how in line &lt;code class=&quot;language-text&quot;&gt;23&lt;/code&gt; we do a check to decide the name of &lt;code class=&quot;language-text&quot;&gt;SharedPreferences&lt;/code&gt; to use. There’s nothing wrong with doing such a check in 1 or 2 places however this type of logic will typically spread over dozens and more places in the various parts of the code base.&lt;/p&gt;
&lt;h3 id=&quot;the-null-object-pattern-to-the-rescue&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#the-null-object-pattern-to-the-rescue&quot; aria-label=&quot;the null object pattern to the rescue permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;The Null Object pattern to the rescue&lt;/h3&gt;
&lt;p&gt;Instead of relying on null checks we can use a simple pattern described in detail by &lt;a href=&quot;http://refactoring.com/catalog/introduceNullObject.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Martin Fowler&lt;/a&gt;. Here’s how it would look like in our case:&lt;/p&gt;
&lt;script src=&quot;https://gist.github.com/miensol/4268ec47392ed4ea232e.js?file=CurrentUserProvider2.java&quot;&gt;&lt;/script&gt;
&lt;p&gt;Now all places where we require an easily substitutable information about the user can be handled with plain old polymorphism.&lt;/p&gt;
&lt;p&gt;The above approach will work whenever we need a default value for the anonymous user - no so much when we need different behavior. It’s tempting to embed various actions into &lt;code class=&quot;language-text&quot;&gt;UserReference&lt;/code&gt; interface implementations (&lt;code class=&quot;language-text&quot;&gt;AnonymousUserReference&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;RegularUserReference&lt;/code&gt;) however this will make the mentioned interface depend on UI concepts which I would like to avoid.&lt;/p&gt;
&lt;h2 id=&quot;when-an-app-has-more-than-one-user-type&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#when-an-app-has-more-than-one-user-type&quot; aria-label=&quot;when an app has more than one user type permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;When an app has more than one user type&lt;/h2&gt;
&lt;p&gt;Before I show how to avoid putting too much weight onto &lt;code class=&quot;language-text&quot;&gt;UserReference&lt;/code&gt; interface, let’s make our situation a bit more complicated. Let’s assume that our app can be used by three types of users: anonymous, regular and premium.
A very common approach is to use an enum to handle that i.e.:&lt;/p&gt;
&lt;script src=&quot;https://gist.github.com/miensol/2c4ffa7ed6fc24b4003c.js&quot;&gt;&lt;/script&gt;
&lt;p&gt;In fact because &lt;code class=&quot;language-text&quot;&gt;case&lt;/code&gt; supports &lt;code class=&quot;language-text&quot;&gt;default&lt;/code&gt; the above implementation works well as long as we have a small number of user types and there’s little shared behavior.&lt;/p&gt;
&lt;p&gt;A slightly different approach is to hide the decision making and expose method(s) that accept different behaviors.
The following code is an example of how we can approach encapsulating differences between user types in by explicitly declaring a behavior:&lt;/p&gt;
&lt;script src=&quot;https://gist.github.com/miensol/363cc59fc5c3b8373a47.js&quot;&gt;&lt;/script&gt;
&lt;p&gt;Note that the above uses &lt;a href=&quot;https://en.wikipedia.org/wiki/Double_dispatch&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;double dispatch&lt;/a&gt; but it could easily be replaced with a &lt;code class=&quot;language-text&quot;&gt;switch&lt;/code&gt; statement. Using separate class to encapsulate differences should make it easier to keep unnecessary logic out of &lt;code class=&quot;language-text&quot;&gt;Activity&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;A curious reader might notice that if we would like to change how we handle only one user type we’re still forced to override all methods. There’s a fairly simple way to improve the above though:&lt;/p&gt;
&lt;script src=&quot;https://gist.github.com/miensol/7872540e0e2d166bc975.js&quot;&gt;&lt;/script&gt;
&lt;p&gt;Now we can implement custom actions as well as indicate a default. As usual whether to go with a simple &lt;code class=&quot;language-text&quot;&gt;if&lt;/code&gt; statement, a &lt;code class=&quot;language-text&quot;&gt;switch&lt;/code&gt; or a double dispatch depends on a use case. However it’s useful to know the different ways of tackling the same problem.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This article is cross-posted with &lt;a href=&quot;http://blog.brightinventions.pl&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;my company blog&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Maintaining current user information in Android]]></title><description><![CDATA[Every but trivial android application needs to maintain information about current user - regardless if he has authenticated or not. While this may sound easy there are still at least handful of ways one can do it - in this article I’m going to explore couple of them. Keeping state in custom  class This technique boils…]]></description><link>undefined/maintaining-current-user-information-in-android/</link><guid isPermaLink="false">undefined/maintaining-current-user-information-in-android/</guid><pubDate>Tue, 30 Jun 2015 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Every but trivial android application needs to maintain information about current user - regardless if he has authenticated or not. While this may sound easy there are still at least handful of ways one can do it - in this article I’m going to explore couple of them.&lt;/p&gt;
&lt;h2 id=&quot;keeping-state-in-custom-application-class&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#keeping-state-in-custom-application-class&quot; aria-label=&quot;keeping state in custom application class permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Keeping state in custom &lt;code class=&quot;language-text&quot;&gt;Application&lt;/code&gt; class&lt;/h2&gt;
&lt;p&gt;This technique boils down to having custom application class like so:&lt;/p&gt;
&lt;script src=&quot;https://gist.github.com/miensol/e7fcce936e0acb3499ec.js?file=MyApplication.java&quot;&gt;&lt;/script&gt;
&lt;p&gt;While the above is both easy to write and understand there are several problems with it. First and foremost if you would like to get some user property you’ll need to reference &lt;code class=&quot;language-text&quot;&gt;MyApplication&lt;/code&gt; i.e.:&lt;/p&gt;
&lt;script src=&quot;https://gist.github.com/miensol/e7fcce936e0acb3499ec.js?file=ActionBar.java&quot;&gt;&lt;/script&gt;
&lt;p&gt;Since data about current user will be used in several places spread through the code each of those places will now be coupled to &lt;code class=&quot;language-text&quot;&gt;MyApplication&lt;/code&gt;. This on the other hand will jeopardize any attempt to break the code base into modules. Furthermore this approach may encourage sharing other global application state through static variables defined on custom &lt;code class=&quot;language-text&quot;&gt;Application&lt;/code&gt; class. In short &lt;strong&gt;don’t do this&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id=&quot;keeping-global-state-in-user-class&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#keeping-global-state-in-user-class&quot; aria-label=&quot;keeping global state in user class permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Keeping global state in &lt;code class=&quot;language-text&quot;&gt;User&lt;/code&gt; class&lt;/h2&gt;
&lt;p&gt;A slightly better idea is to move static variables from &lt;code class=&quot;language-text&quot;&gt;Application&lt;/code&gt; class into &lt;code class=&quot;language-text&quot;&gt;User&lt;/code&gt; class itself:&lt;/p&gt;
&lt;script src=&quot;https://gist.github.com/miensol/e7fcce936e0acb3499ec.js?file=User.java&quot;&gt;&lt;/script&gt;
&lt;p&gt;Now our &lt;code class=&quot;language-text&quot;&gt;Application&lt;/code&gt; class has one less responsibility and we don’t need smelly references spread around the codebase. We may also be able to split the project into modules - as long as we’re not too inclined to separating concerns. Problems arise as soon as you start unit testing though. Remember that good unit test should be as isolated as possible. Using global state through static methods on &lt;code class=&quot;language-text&quot;&gt;User&lt;/code&gt; class forces us to properly &lt;code class=&quot;language-text&quot;&gt;setUp()&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;tearDown()&lt;/code&gt; its state in every test. It would be much easier if we could properly inject information about current user through tested component(s) constructor(s).&lt;/p&gt;
&lt;p&gt;I mentioned &lt;a href=&quot;https://en.wikipedia.org/wiki/Separation_of_concerns&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;separation of concerns&lt;/a&gt; - does a user class have any reason to know whether a user has signed in? I don’t think so.&lt;/p&gt;
&lt;h2 id=&quot;separating-concerns-with-user-session&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#separating-concerns-with-user-session&quot; aria-label=&quot;separating concerns with user session permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Separating concerns with User Session&lt;/h2&gt;
&lt;p&gt;I find it helpful to think about objects lifetimes when designing components. In every application that allows users to sign in there will be a time where we don’t have a &lt;em&gt;user object&lt;/em&gt; to work with. To express that property I usually store the information about current user in a &lt;em&gt;Session&lt;/em&gt; object. There is only one &lt;em&gt;user&lt;/em&gt; session whenever an application is running. After user signs in the session is updated to represent it. After signing out it’s usually a good idea to reset session state. Consider following example:&lt;/p&gt;
&lt;script src=&quot;https://gist.github.com/miensol/e7fcce936e0acb3499ec.js?file=Session.java&quot;&gt;&lt;/script&gt;
&lt;p&gt;Couple of things to note here. First and foremost the &lt;code class=&quot;language-text&quot;&gt;Session&lt;/code&gt; class &lt;strong&gt;is not public&lt;/strong&gt; it’s local to package responsible for maintaining it’s state. Typically it’s a package dealing with user registration, sign in and keeping remote services auth tokens fresh. Secondly &lt;code class=&quot;language-text&quot;&gt;Session&lt;/code&gt; public interface only covers methods defined in &lt;code class=&quot;language-text&quot;&gt;CurrentUserInfo&lt;/code&gt; exposing methods that come handy when getting current user name. The &lt;code class=&quot;language-text&quot;&gt;Session&lt;/code&gt; object is not limited to one interface. Quite opposite it may implement more interfaces depending on different &lt;em&gt;clients&lt;/em&gt; (components requesting various details about current user) needs.&lt;/p&gt;
&lt;p&gt;Since &lt;code class=&quot;language-text&quot;&gt;Session&lt;/code&gt; embraces &lt;a href=&quot;https://en.wikipedia.org/wiki/Interface_segregation_principle&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Interface Segregation Principle&lt;/a&gt; it’s much easier to test code that requests information about current user i.e &lt;code class=&quot;language-text&quot;&gt;AppBeahvior&lt;/code&gt;. A reusable &lt;a href=&quot;http://www.martinfowler.com/bliki/TestDouble.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;fake&lt;/a&gt; can be coded with no effort - it only has to implement very limited set of methods.&lt;/p&gt;
&lt;p&gt;Notice that I’ve not used static methods nor variables in above example. Instead I’ve simply marked the class with &lt;code class=&quot;language-text&quot;&gt;@Singleton&lt;/code&gt; annotation to ensure that there will only be single instance ever created, injected and used. I highly encourage using Dependency Injection frameworks (a.k.a IoC containers) with &lt;a href=&quot;http://square.github.io/dagger/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Dagger&lt;/a&gt; (and &lt;a href=&quot;http://google.github.io/dagger/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Dagger 2&lt;/a&gt;) taking the lead in Android space.&lt;/p&gt;
&lt;p&gt;In the next article I’m going to show a way to deal with application behavior changing depending on user being logged in or not.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This article is cross-posted with &lt;a href=&quot;http://blog.brightinventions.pl&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;my company blog&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Anchor child element click]]></title><description><![CDATA[I had to solve a seemingly trivial bug in an angularjs based application that turned out to be more interesting than usual. The bug The bug report stated that “Clicking on a label causes page reload”. That should be an easy one I thought to myself and openeded chrome inspector to see a structure of DOM. Here’s a…]]></description><link>undefined/anchor-child-element-click/</link><guid isPermaLink="false">undefined/anchor-child-element-click/</guid><pubDate>Sun, 25 Jan 2015 17:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I had to solve a seemingly trivial bug in an angularjs based application that turned out to be more interesting than usual.&lt;/p&gt;
&lt;h2 id=&quot;the-bug&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#the-bug&quot; aria-label=&quot;the bug permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;The bug&lt;/h2&gt;
&lt;p&gt;The bug report stated that &lt;em&gt;“Clicking on a label causes page reload”&lt;/em&gt;. That should be an easy one I thought to myself and openeded chrome inspector to see a structure of DOM. Here’s a simplified version of markup:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;html&quot;&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;a&lt;/span&gt;  &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;ng-click&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;anchorAction($event)&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;ng-controller&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;ActionCtrl&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  Anchor
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;span&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;ng-click&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;childAction($event)&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  A child
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;span&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;module&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;controller&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;ActionCtrl&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;$scope&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  $scope&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;anchorAction&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;$event&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;anchorAction&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  $scope&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;childAction&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;$event&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    $event&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;stopPropagation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;childAction&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;My intention was to have different behaviour when an anchor or a span element is clicked. Just as in the example above when &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt; is clicked &lt;code class=&quot;language-text&quot;&gt;anchorAction&lt;/code&gt; should be printed whereas the same event triggered on &lt;code class=&quot;language-text&quot;&gt;span&lt;/code&gt; should &lt;strong&gt;only&lt;/strong&gt; print &lt;code class=&quot;language-text&quot;&gt;childAction&lt;/code&gt;.
Interestingly the actual behaviour is different.&lt;/p&gt;
&lt;p&gt;When the anchor is clicked indeed a function attached by &lt;code class=&quot;language-text&quot;&gt;ng-click&lt;/code&gt; is executed properly. Note that even though we &lt;strong&gt;did not&lt;/strong&gt; call &lt;code class=&quot;language-text&quot;&gt;$event.preventDefault()&lt;/code&gt; a page reload is not triggered. This is due to &lt;a href=&quot;https://github.com/angular/angular.js/blob/master/src/ng/directive/a.js&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;htmlAnchorDirective&lt;/code&gt;&lt;/a&gt; provided by angularjs which effectively prevents empty &lt;code class=&quot;language-text&quot;&gt;href&lt;/code&gt; attribute from taking action.&lt;/p&gt;
&lt;p&gt;A click on &lt;code class=&quot;language-text&quot;&gt;span&lt;/code&gt; element will stop event from bubbling up document tree - thus preventing &lt;code class=&quot;language-text&quot;&gt;anchorAction&lt;/code&gt; from executing. In addition it will obviously print &lt;code class=&quot;language-text&quot;&gt;childAction&lt;/code&gt; and to my surprise &lt;strong&gt;it will cause a page reload&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Wait a second didn’t we just prevent the event from traveling up to the anchor element? Yes. So why does the page reload anyway?&lt;/p&gt;
&lt;h2 id=&quot;searching-for-a-root-cause&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#searching-for-a-root-cause&quot; aria-label=&quot;searching for a root cause permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Searching for a root cause.&lt;/h2&gt;
&lt;p&gt;Almost immediately I’ve verified that calling &lt;code class=&quot;language-text&quot;&gt;$event.preventDefault()&lt;/code&gt; inside &lt;code class=&quot;language-text&quot;&gt;childAction&lt;/code&gt; fixes the problem. The fix got checked in and will be deployed soon - case closed. I was unhappy though because I didn’t understand this behaviour at all.&lt;/p&gt;
&lt;p&gt;At first I naively thought that it might be a Chrome bug - a quick check in FF and IE diminished this stupid idea.&lt;/p&gt;
&lt;p&gt;Then I thought that it may be related to angularjs in some strange manner so I’ve prepared &lt;a href=&quot;http://jsfiddle.net/83ov5tgm/4/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;an example fiddle&lt;/a&gt; that demonstrates the issue. I’ve searched for and read many answers on &lt;a href=&quot;http://stackoverflow.com/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Stack Overflow&lt;/a&gt; and other forums but none of them gave an in-depth explanation.&lt;/p&gt;
&lt;h2 id=&quot;the-html-spec&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#the-html-spec&quot; aria-label=&quot;the html spec permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;The HTML spec&lt;/h2&gt;
&lt;p&gt;Since the example fiddle demonstrated same behaviour in all major desktop browsers I realised that it must be part of HTML spec - after an hour or so it turned out that it was a good  hunch.&lt;/p&gt;
&lt;p&gt;Up until now I thought that an &lt;code class=&quot;language-text&quot;&gt;event&lt;/code&gt; (and a &lt;code class=&quot;language-text&quot;&gt;click&lt;/code&gt; event in particular) default action is dependent on an element it visits when it is dispatched through a DOM tree. In the above example it would mean that since I’ve stopped &lt;code class=&quot;language-text&quot;&gt;click&lt;/code&gt; from bubbling up it should not reach &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt; element and because of that it &lt;strong&gt;should not&lt;/strong&gt; execute its default action - in our case a page reload.&lt;/p&gt;
&lt;p&gt;It turned out that my assumptions about events dispatching and elements default actions were wrong.&lt;/p&gt;
&lt;p&gt;The relevant part of the specification describes &lt;a href=&quot;http://www.w3.org/html/wg/drafts/html/master/editing.html#activation&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;activation behavior&lt;/a&gt; with an explanation of what I’ve experienced:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;Let target be the element designated by the user (the target of event).&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;If target is a canvas element, run the canvas MouseEvent rerouting steps. If this changes event’s target, then let target be the new target.&lt;/li&gt;
&lt;li&gt;Set the click in progress flag on target to true.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Let e be the nearest activatable element of target (defined below), if any&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;If there is an element e, run pre-click activation steps on it.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Dispatch event (the required click event) at target.&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If there is an element e and the click event is not canceled, run post-click activation steps on element e.
If there is an element e and the event is canceled, run canceled activation steps on element e.
7. Set the click in progress flag on target to false.&lt;/p&gt;
&lt;p&gt;The most relevant steps are &lt;em&gt;4.&lt;/em&gt; and &lt;em&gt;6.&lt;/em&gt; as they clearly indicate that &lt;em&gt;target&lt;/em&gt; and &lt;em&gt;nearest activatable element&lt;/em&gt; that triggers default action can be &lt;strong&gt;separate&lt;/strong&gt;. What’s left to have a complete understanding is how &lt;em&gt;nearest activatable element&lt;/em&gt; is defined:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Given an element target, the nearest activatable element is the element returned by the following algorithm:&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;If target has a defined activation behavior, then return target and abort these steps.&lt;/li&gt;
&lt;li&gt;If target has a parent element, then set target to that parent element and return to the first step.&lt;/li&gt;
&lt;li&gt;Otherwise, there is no nearest activatable element.&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;Now it is obvious why a default action of an &lt;code class=&quot;language-text&quot;&gt;anchor&lt;/code&gt; is executed even though a &lt;code class=&quot;language-text&quot;&gt;click&lt;/code&gt; event did not bubble up from its child.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This article is cross-posted with &lt;a href=&quot;http://blog.brightinventions.pl&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;my company blog&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Lazy Apk - a simple TeamCity artifact downloader]]></title><description><![CDATA[At Bright Inventions we use TeamCity as a continuous integration server. Apart from building, running tests and uploading artifacts we sometimes use it to quickly distribute an android application to clients and test team. However we found using TeamCity UI on a mobile device isn’t as pleasing as it could be. That’s…]]></description><link>undefined/lazy-apk/</link><guid isPermaLink="false">undefined/lazy-apk/</guid><pubDate>Tue, 06 Jan 2015 21:00:00 GMT</pubDate><content:encoded>&lt;p&gt;At &lt;a href=&quot;http://brightinventions.pl&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Bright Inventions&lt;/a&gt; we use &lt;a href=&quot;https://www.jetbrains.com/teamcity/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;TeamCity&lt;/a&gt; as a continuous integration server. Apart from building, running tests and uploading artifacts we sometimes use it to quickly distribute an android application to clients and test team. However we found using TeamCity UI on a mobile device isn’t as pleasing as it could be. That’s why we usually recommend downloading updates through a dedicated application such as &lt;a href=&quot;https://play.google.com/store/apps/details?id=com.raidzero.teamcitydownloader&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;TeamCity Downloader&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;While &lt;em&gt;TeamCity Downloader&lt;/em&gt; is really easy to use I found it lacks a couple of features I need. First of all I would like to be able to use multiple TeamCity servers at once. Moreover it would be nice to see commit messages related to particular build to streamline change communication.&lt;/p&gt;
&lt;h2 id=&quot;lazy-apk---a-simple-apk-downloader&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#lazy-apk---a-simple-apk-downloader&quot; aria-label=&quot;lazy apk   a simple apk downloader permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Lazy Apk - a simple apk downloader&lt;/h2&gt;
&lt;p&gt;Since I wanted to test some of new APIs available in &lt;a href=&quot;https://www.android.com/versions/lollipop-5-0/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Lollipop&lt;/a&gt; I thought it would be a good idea to try them out in an application that could actually be useful. That’s why I’ve build another artifacts downloader - &lt;a href=&quot;https://play.google.com/store/apps/details?id=pl.brightinventions.lazyapk&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Lazy Apk&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The tool allows you to configure multiple TeamCity build servers:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 270px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/f6be68feed3a257359194eca88b67893/01bf6/lazy_apk_sources.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: 177.91666666666669%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAkCAYAAACJ8xqgAAAACXBIWXMAAAsTAAALEwEAmpwYAAAC4ElEQVRIx+2ST0xcVRjFP4FK0hpt1LR14cKkGsHGrSu3SoM0NqEJ1Ligag0CbaxaNiSGAlVr2rS1227LIH9GdGNCorhw57JjCdFIeTPDzHvv3jc8nRk2c465d96bjjCQxpCuWPxyzve9uefe786VyW6pTHY/hqoKqj5GtpDoFtx5W5A8cwS/fNmN6XeexE+jxyvfD7Tjh8FXKpIaEtztF6aGhKlBYeojYWogUtM714Ah4e/nm7k8fJD3LrTyz5FnufTxPi5daIUUJ/Zj4/brLI7tQ/n6SyjfbEP5+lGUbx1D6YunUBxtQvFSSwOa8c/nguJYK4o3Xkbpm3YWv34OUhgWhNdeZOFTQThxmOG1NoZXXmB4tY3rI8LCJ8LCZ2K+N+aiMLx8COFXz3N99AAkSA5AT59hkBxEMHuWwcx7DGber+pcP4PvBs23qjYiOcBg5gPYNXMfQlQJ0GVSlxnrA0oRdV4V8V9KBqKqgPhuDs79v5hx7iObXmXGWeVaxmEum6at06tMr67YnkF5eWrfpfJdai9PpXzq3Ar0bwlqNwtRSsF1Xebz+Vhp1PM8VmuXuVzOeoNWilrriMj7LnTmD2odQHzfh1KKJjjSHfF9fytKwdeB8dUTRjviwc7b03AjraEKf1u1gdGYiMcy48bU94yq+pGtD6i9HPTyr3Z0O7LjOEyn08hms8xkMlxbW7P3FteOk675hoFuBjq1YOpdHllFI0eXi4YXvomGgeaP9T3zhCB1J3uoE25DLUPqnstDPZttqGXs/gn3AvcC9wL3Ah9NoPJcKM9lnf4fahkSlisIyxXWdMP6rWzs2KtlyOJ4BxbHOxgpFsfeRM3XehGb+j9feqO+bzMk0SWY6hIm3hJ+e1L44/lXaesu4dQJ4WSncL7vkMV404t/v3DxNc6cEiY6JV4Dme1trsz2NmO2p6ky19uC+b6nYeuYniYk333CYnx9f77vGcydftyujfqVfwEV4sEhogcn3AAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/f6be68feed3a257359194eca88b67893/8ac56/lazy_apk_sources.webp 240w,
/static/f6be68feed3a257359194eca88b67893/3e767/lazy_apk_sources.webp 270w&quot;
              sizes=&quot;(max-width: 270px) 100vw, 270px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/f6be68feed3a257359194eca88b67893/8ff5a/lazy_apk_sources.png 240w,
/static/f6be68feed3a257359194eca88b67893/01bf6/lazy_apk_sources.png 270w&quot;
            sizes=&quot;(max-width: 270px) 100vw, 270px&quot;
            type=&quot;image/png&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/f6be68feed3a257359194eca88b67893/01bf6/lazy_apk_sources.png&quot;
            alt=&quot;Multiple sources&quot;
            title=&quot;Sources&quot;
            loading=&quot;lazy&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;As I mentioned the commit messages are visible next to each build:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 270px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/3cc2748bd9eb5aa44e69636d9e231372/01bf6/lazy_apk_builds.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: 177.91666666666669%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAkCAIAAAAGkY33AAAACXBIWXMAAAsTAAALEwEAmpwYAAADvklEQVRIx61UXW/bVBg+aTtVkwoIJLRJ3CCtaBratD/AHdroxT40GGgFtIu1gNR2CMG0wg0KIZ0m7aZD67jjEjVSGsJ6N4lS+A2N48Rx7PPh4+OP+Dh13ZStU5F9EidNRsfXo0evHr8+7/FrP68PWL4Mlt8dimMqEu0oRIeXUz9eAsXpo7/feSf/4div355dnT22OjcOpOugNAOkT4E0B6QZIM3GMRYlIebiu9dB+bNh5csX5C9GtfQr1fnnqvPPg3Dh8M4Pb4TZ0da94637r0dx6UQklk60vj/Vun+ytfhqmAZhZiTMDG+lU+E3Q8HXYCud2kqngP/VULA47s+DzdsvB3dfCxbHg3untpZOB4vHgu+OB3fHN28d9W8A/2bKvwn6CPyfZrz8FC/O8JWPeX6ar3zE89NefponLHzCi3O8OOsPEHjhE39nz2/t8Z09v5d/RFEkeSuiFz7pI3BshnSNYEQJIggSHBEjiKEuNNTrBEEDI8di3HO9hpMQ2LataVq1WlUURZKkjY0NRVFkWa52gBBSVbVSqdi2zTn3egAajYZlWbZtm6bp+z6LEQRBs9n0Y3DOhfAGEBUTQnAMM4ZhGIQQy7LEc/h+7Ct2XVesxhgTQowYhBBKqeiIMWZ1wBhzXbe/bcaYaZqU0uThon9KqWEY4hallBDiOE63eLCxA9D35lFx4x9iX9v/Gu22E2P6kHT7dKts267X66qqapqmKIqqqrVaTVGUWq2mqmq9B4l53WLHcSCEmqaJFWKkdF2HEOoxKKUYY13Xe03qvrNw0jRNzrnQfZ3/Zdue5xmGgTFGCBFChOEQQrGXdyDaxQihpN4wjN5JeEax3YHjOCL2mvmM4sFJ8v4e/tuQ/A/FSauJSJKD9nbbtiwrOXdKpZIkSbIsC1Eul2VZrtVqlUqlXC4zxp5+GAirTdMUIyU+u5gcYQRjbNCCqG3xxxNCXNdljAmfRdsHW9CdMHEMWZYlZoYx1vurC33QAWh0YJpmvBcW+4qxwxhTShFCyeSChmsjqOuaCrW6HlHVNRVBDeqRJgjqWp1giKCOoA51LWbdtszo0G9uP7a8gDU2qeObbtMPH/vho5iRaG4nl4/iy93m9q7Ib7Z2wXp2Yi1zZi1zdi1z5pf0m78tTOxjticuTKxn3xJ6PRsR5C6A3EWQOw/yb488/Pxk7mIqylwAy+fAg6kjq1NHls8BkcmdBw9vnF5573CSAYXJkTbfP/Tg2ouFyUPtyyvDxatjxatjhSvDyZqfr71U+GC0MNnO/AnhQuHWwntxSAAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/3cc2748bd9eb5aa44e69636d9e231372/8ac56/lazy_apk_builds.webp 240w,
/static/3cc2748bd9eb5aa44e69636d9e231372/3e767/lazy_apk_builds.webp 270w&quot;
              sizes=&quot;(max-width: 270px) 100vw, 270px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/3cc2748bd9eb5aa44e69636d9e231372/8ff5a/lazy_apk_builds.png 240w,
/static/3cc2748bd9eb5aa44e69636d9e231372/01bf6/lazy_apk_builds.png 270w&quot;
            sizes=&quot;(max-width: 270px) 100vw, 270px&quot;
            type=&quot;image/png&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/3cc2748bd9eb5aa44e69636d9e231372/01bf6/lazy_apk_builds.png&quot;
            alt=&quot;Commit messages&quot;
            title=&quot;Commit messages&quot;
            loading=&quot;lazy&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Downloaded APKs are stored inside android “Downloads” so there is no need to pull the same package twice:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 270px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/4410f90f179191dc8744435f96bbd122/01bf6/lazy_apk_downloads.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: 177.91666666666669%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAkCAIAAAAGkY33AAAACXBIWXMAAAsTAAALEwEAmpwYAAADmUlEQVRIx+1TXWwUVRS+bUFoUh8gRESLChaFammMD7z44BMYgpgQMa0aEmkhsfwkGBQ18YHUBpGNXfpDMCbwQCIlbZfaJib6oolvhvBg6tru0p+duTNzZ+b+zczuzkLANXfu7OxsGzXFV798OTnnzvlyzr3nDBh5E4wcrA9sXYX1FVvltwfARPemXy4cHH330Z/69n7/QdvU8RaQPgF+7wHpkyB9POAxkO4JrHR6quEfJxoyHzbOnKyb/2xD9kxT5kwTKPQ1lq68Uuh9xB/eUex/yh/c5g897w8861/c6l9q84e2+5fb/Ytb/OHWYvIZkTC0vTiwrdD/dL53DeCf1HvJFv4RcM8/7n6xyftqi9e/1RtuEzbZIjjY6iWe9C484X7Z7CWfyw+25pMtXqLZPbsW8Js9dKyLTRxj40fY+FE23s3GugP/iHAEu8IwZHfAo+zm+4AWHvBSmftlVirzkrDS4XfDUDq8VKZ+mRYDK53in8C2kLK4AFVFhwpUclAVVJWcmluUfm5xHio5TVVsEzGKKbEjAsuyFhYWMplMNptNp9PT09PZbHZmZiZTgaIoc3Nzs7OzlmUxxmgMgBBimqZlWYZhcM5RAM/zHMfhARhj0qHLIMQQQjWAEUDTNAihaZqyDqtFjRhjLLNVVYUQagEghLquy44QQmYFCCGM8dK2EUKGYei6HhWX/eu6rmma/KTrOoTQtu2qeHlj/4AlNxdiQgh9KISVH1Js27aqqvFnWIGYEIIQ+rfOGeUu5V6MLmWOEMtNCLMqw2SMkRCU2Ijo80S7Q9RZAjME3iHaHDFVcef4kCJf0zSxjwTT/D326zXnU+CeWy9+2ESzd/4x52PAru2viuVgI7Gu62KkBFOvRH+bYgM72Tevsqt7+dU9/MpultxBJ0+FbcvO5STjIw3axoQ52C1i6mDCMOWCToHwgqgsNyzas8gProupd5fdHnUSm93Lu9yvd7mXXhY2sZmNvSfEcpmjxYwg34rm79Fb13nfOmeo3Rnc6Qy86Ay/5JzbQK93gCVDii9M5bUJxtg2DdtQq0Qatq2l6/k3A5dzriXjgP4H/C9e8S+JrZXQjofA9e/H+KA2XM6aBPDz56/FuKc2XMbe3fEQ3Ngf8HUwemDVD6deuPFGnTwZ2QcmuzZOdW0c2VfN+fF0+/hbjdEJSHWuCvn26snD61Kdq8Owo2HiUNPEoaZUR0OU893h9al31qQ6w5O/AEBJ05TY/PvJAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/4410f90f179191dc8744435f96bbd122/8ac56/lazy_apk_downloads.webp 240w,
/static/4410f90f179191dc8744435f96bbd122/3e767/lazy_apk_downloads.webp 270w&quot;
              sizes=&quot;(max-width: 270px) 100vw, 270px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/4410f90f179191dc8744435f96bbd122/8ff5a/lazy_apk_downloads.png 240w,
/static/4410f90f179191dc8744435f96bbd122/01bf6/lazy_apk_downloads.png 270w&quot;
            sizes=&quot;(max-width: 270px) 100vw, 270px&quot;
            type=&quot;image/png&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/4410f90f179191dc8744435f96bbd122/01bf6/lazy_apk_downloads.png&quot;
            alt=&quot;Downloads&quot;
            title=&quot;Downloads&quot;
            loading=&quot;lazy&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;source-available-on-github&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#source-available-on-github&quot; aria-label=&quot;source available on github permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Source available on Github&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://play.google.com/store/apps/details?id=pl.brightinventions.lazyapk&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Lazy Apk&lt;/a&gt; source code is available on &lt;a href=&quot;https://github.com/bright/lazyapk&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;github&lt;/a&gt;. I’ve tried couple of different techniques to extract code from &lt;a href=&quot;http://developer.android.com/reference/android/app/Activity.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Activity&lt;/a&gt; classes - I’m not yet sure if I like the results though…&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This article is cross-posted with &lt;a href=&quot;http://blog.brightinventions.pl&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;my company blog&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Google Play Services is no longer a giant monolith]]></title><description><![CDATA[Nowadays it’s getting harder and harder to build a meaningful app and not rely on Google Play Services to aid us in some commonly required features such as maps, better location provider, geo fencing and so much more. Unfortunately up until now the library shipped as a giant monolith ripping us from one third of dex…]]></description><link>undefined/google-play-services-is-no-longer-a-monolith/</link><guid isPermaLink="false">undefined/google-play-services-is-no-longer-a-monolith/</guid><pubDate>Tue, 09 Dec 2014 10:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Nowadays it’s getting harder and harder to build a meaningful app and not rely on &lt;a href=&quot;https://developer.android.com/google/play-services/index.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Google Play Services&lt;/a&gt; to aid us in some commonly required features such as &lt;a href=&quot;http://developer.android.com/google/play-services/maps.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;maps&lt;/a&gt;, better &lt;a href=&quot;https://developer.android.com/google/play-services/location.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;location provider&lt;/a&gt;, &lt;a href=&quot;http://developer.android.com/training/location/geofencing.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;geo fencing&lt;/a&gt; and so much more. Unfortunately up until now the library shipped as a giant monolith ripping us from &lt;a href=&quot;http://jakewharton.com/play-services-is-a-monolith/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;one third of dex method limit&lt;/a&gt;. For curious reader here’s are method counts in couple of versions:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&quot;right&quot;&gt;Version&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;Method Count&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&quot;right&quot;&gt;3.2.65&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;6330&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;right&quot;&gt;4.4.52&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;16933&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;right&quot;&gt;5.0.89&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;20312&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;right&quot;&gt;6.1.71&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;23641&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;and &lt;a href=&quot;https://gist.github.com/miensol/c6ac03fa4f6f52441992&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;a full breakdown&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;google-play-services-65-granular-dependency-management&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#google-play-services-65-granular-dependency-management&quot; aria-label=&quot;google play services 65 granular dependency management permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Google Play Services 6.5 granular dependency management&lt;/h2&gt;
&lt;p&gt;Today Google has made the awaited, more than usual, version of their &lt;a href=&quot;https://developer.android.com/google/play-services/index.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;SDK available&lt;/a&gt;. With the update apart from new features you can finally depend only on a subset of enormous API. Here’s a table from documentation along with &lt;a href=&quot;https://github.com/mihaip/dex-method-counts&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;dex method counts&lt;/a&gt;:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;API Name&lt;/th&gt;
&lt;th align=&quot;center&quot;&gt;Gradle depdenency&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;Dex method count&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Google Play Services&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;com.google.android.gms:play-services:6.5.87&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;24525&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Google+&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;com.google.android.gms:play-services-plus:6.5.87&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1525&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Google Account Login&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;com.google.android.gms:play-services-identity:6.5.87&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;181&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Google Activity Recognition&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;com.google.android.gms:play-services-location:6.5.87&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;857&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Google App Indexing&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;com.google.android.gms:play-services-appindexing:6.5.87&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;482&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Google Cast&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;com.google.android.gms:play-services-cast:6.5.87&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;976&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Google Drive&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;com.google.android.gms:play-services-drive:6.5.87&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;2328&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Google Fit&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;com.google.android.gms:play-services-fitness:6.5.87&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1895&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Google Maps&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;com.google.android.gms:play-services-maps:6.5.87&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;2568&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Google Mobile Ads&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;com.google.android.gms:play-services-ads:6.5.87&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;3278&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Google Panorama Viewer&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;com.google.android.gms:play-services-panorama:6.5.87&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;94&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Google Play Game services&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;com.google.android.gms:play-services-games:6.5.87&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;5046&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Google Wallet&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;com.google.android.gms:play-services-wallet:6.5.87&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1116&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Android Wear&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;com.google.android.gms:play-services-wearable:6.5.87&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;1187&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Google Actions&lt;br /&gt; Google Analytics &lt;br /&gt; Google Cloud Messaging&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;com.google.android.gms:play-services-base:6.5.87&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;5212&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&quot;a-small-change-to-improve-build-time&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#a-small-change-to-improve-build-time&quot; aria-label=&quot;a small change to improve build time permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;A small change to improve build time&lt;/h2&gt;
&lt;p&gt;For me the biggest win is that in one of the apps we are actively developing granular dependency declaration means with a simple change from&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;groovy&quot;&gt;&lt;pre class=&quot;language-groovy&quot;&gt;&lt;code class=&quot;language-groovy&quot;&gt;compile &lt;span class=&quot;token string&quot;&gt;&apos;com.google.android.gms:play-services:6.1.71&apos;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;to&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;groovy&quot;&gt;&lt;pre class=&quot;language-groovy&quot;&gt;&lt;code class=&quot;language-groovy&quot;&gt;compile &lt;span class=&quot;token string&quot;&gt;&apos;com.google.android.gms:play-services-maps:6.5.87&apos;&lt;/span&gt;
compile &lt;span class=&quot;token string&quot;&gt;&apos;com.google.android.gms:play-services-location:6.5.87&apos;&lt;/span&gt;
compile &lt;span class=&quot;token string&quot;&gt;&apos;com.google.android.gms:play-services-base:6.5.87&apos;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I no longer have to run &lt;a href=&quot;http://proguard.sourceforge.net/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Proguard&lt;/a&gt; during development. No wonder my build time just improved by 15 seconds.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This article is cross-posted with &lt;a href=&quot;http://blog.brightinventions.pl&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;my company blog&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Integrate slf4j with Crashlytics]]></title><description><![CDATA[As I mentioned in my previous post having meaningful log entries comes handy during development. When an app reaches beta testers as well as goes live it’s equally or even more important to be able to figure out why the app you’ve carefully coded isn’t behaving as it should. Testing the app on all android flavours is…]]></description><link>undefined/integrate-slf4j-with-crashlytics/</link><guid isPermaLink="false">undefined/integrate-slf4j-with-crashlytics/</guid><pubDate>Thu, 20 Nov 2014 21:00:00 GMT</pubDate><content:encoded>&lt;p&gt;As I mentioned in my previous post having meaningful log entries comes handy during development. When an app reaches beta testers as well as goes live it’s equally or even more important to be able to figure out why the app you’ve carefully coded isn’t behaving as it should. Testing the app on all android flavours is literally impossible that’s why getting an insight into what caused a crash is vital.&lt;/p&gt;
&lt;h2 id=&quot;crashlytics&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#crashlytics&quot; aria-label=&quot;crashlytics permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;a href=&quot;https://dev.twitter.com/products/crashlytics&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Crashlytics&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Error reporting providers are getting more and more popular. There are plenty of options to choose from: &lt;a href=&quot;https://raygun.io/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Raygun&lt;/a&gt;, &lt;a href=&quot;https://airbrake.io/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Airbrake&lt;/a&gt; and &lt;a href=&quot;https://dev.twitter.com/products/crashlytics&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Crashlytics&lt;/a&gt; are just frew examples. At &lt;a href=&quot;http://brightinventions.pl/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Bright Inventions&lt;/a&gt; we use the last one and are more and more pleased with it. Setting it up is really easy - if you don’t mind installing an IDE plugin it provides. Frankly I would prefer being able to configure a project with a simple command line tool but I understand a motivation behind it which is making the installation as seamless as possible.&lt;/p&gt;
&lt;p&gt;Crashlytics let’s you not only report &lt;a href=&quot;http://developer.android.com/reference/java/lang/Thread.html#setDefaultUncaughtExceptionHandler(java.lang.Thread.UncaughtExceptionHandler)&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;uncaught exceptions&lt;/a&gt; but also handled errors with additional information provided by log entries:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;java&quot;&gt;&lt;pre class=&quot;language-java&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token class-name&quot;&gt;Crashlytics&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;INFO&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;HomeActivity&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Make request&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;makeRequest&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;RuntimeException&lt;/span&gt; ex&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token class-name&quot;&gt;Crashlytics&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ERROR&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;HomeActivity&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Error making request &quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; ex&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This will print messages to logcat as well as well as well as make them available in Crashlytics dashboard.&lt;/p&gt;
&lt;h2 id=&quot;using-slf4j-with-crashlytics&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#using-slf4j-with-crashlytics&quot; aria-label=&quot;using slf4j with crashlytics permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Using &lt;a href=&quot;https://github.com/bright/slf4android&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;slf4j&lt;/a&gt; with Crashlytics&lt;/h2&gt;
&lt;p&gt;I’ve already explained why &lt;a href=&quot;/introducing-slf4android.html&quot;&gt;I don’t like this approach to logging&lt;/a&gt;. Thankfully with &lt;a href=&quot;https://github.com/bright/slf4android&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;slf4android&lt;/a&gt; it’s really easy to replace a default logcat appender with a &lt;code class=&quot;language-text&quot;&gt;CrashlyticsLoggerHandler&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;java&quot;&gt;&lt;pre class=&quot;language-java&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CrashlyticsLoggerHandler&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Handler&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token class-name&quot;&gt;MessageValueSupplier&lt;/span&gt; messageValueSupplier &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;MessageValueSupplier&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token annotation punctuation&quot;&gt;@Override&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;publish&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token namespace&quot;&gt;java&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;util&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;logging&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;/span&gt;LogRecord&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;record&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;LogRecord&lt;/span&gt; logRecord &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token namespace&quot;&gt;pl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;brightinventions&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;slf4android&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;/span&gt;LogRecord&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fromRecord&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;record&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;StringBuilder&lt;/span&gt; messageBuilder &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;StringBuilder&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    messageValueSupplier&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;logRecord&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; messageBuilder&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;String&lt;/span&gt; tag &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;record&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getLoggerName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; androidLogLevel &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; logRecord&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getLogLevel&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getAndroidLevel&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;Crashlytics&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;androidLogLevel&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; tag&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; messageBuilder&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token annotation punctuation&quot;&gt;@Override&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token annotation punctuation&quot;&gt;@Override&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;flush&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;All that is left is to add the handler to root logger in your custom application &lt;code class=&quot;language-text&quot;&gt;onCreate&lt;/code&gt; method:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;java&quot;&gt;&lt;pre class=&quot;language-java&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;LoggerConfiguration&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;configuration&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;removeRootLogcatHandler&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addHandlerToRootLogger&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CrashlyticsLoggerHandler&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;From now on all log messages will go through Crashlytics API and couple of last log entries will be available next to crash report details in dashboard.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This article is cross-posted &lt;a href=&quot;http://blog.brightinventions.pl/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;my company blog&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Introducing slf4android - a simple slf4j implementation for android]]></title><description><![CDATA[Every now and then you have a bug that is hard to reproduce or only happens on certain phones or android versions. The thing that really comes handy in such case is a detailed application log. That’s why it’s so important to take time to add useful log entries in every non trivial part of the codebase. At the very…]]></description><link>undefined/introducing-slf4android/</link><guid isPermaLink="false">undefined/introducing-slf4android/</guid><pubDate>Sat, 01 Nov 2014 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Every now and then you have a bug that is hard to reproduce or only happens on certain phones or android versions. The thing that really comes handy in such case is a detailed application log. That’s why it’s so important to take time to add useful log entries in every non trivial part of the codebase. At the very minimum you’ll want to log any errors.&lt;/p&gt;
&lt;h2 id=&quot;logging-frameworks&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#logging-frameworks&quot; aria-label=&quot;logging frameworks permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Logging frameworks&lt;/h2&gt;
&lt;p&gt;That’s why it’s so important to create log entries easily. The default solution that comes with Android by means of &lt;a href=&quot;http://developer.android.com/reference/android/util/Log.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Log&lt;/code&gt;&lt;/a&gt; is the most commonly used. However for me it’s really  the least pleasant to use:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;java&quot;&gt;&lt;pre class=&quot;language-java&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;Log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;MyTag&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Failed to download &quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; url &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt;  &lt;span class=&quot;token string&quot;&gt;&quot;due to occurred &quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; ex&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I really don’t like that I have to specify a tag each time I need to log something. Moreover having to concatenate strings seems tedious and error prone.&lt;/p&gt;
&lt;h3 id=&quot;logging-with-javautillogging&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#logging-with-javautillogging&quot; aria-label=&quot;logging with javautillogging permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Logging with &lt;code class=&quot;language-text&quot;&gt;java.util.logging&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;Another alternative that is available by default on android is packaged inside &lt;code class=&quot;language-text&quot;&gt;java.util.logging.*&lt;/code&gt;. And here’s an example of how to use it:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;java&quot;&gt;&lt;pre class=&quot;language-java&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Logger&lt;/span&gt; LOG &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Logger&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getLogger&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;MyActivity&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// and then&lt;/span&gt;
    LOG&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Level&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;FINE&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Starting activity {0} saved instance {1}&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Object&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; savedInstanceState&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You’re able to use &lt;a href=&quot;http://developer.android.com/reference/java/text/MessageFormat.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;MessageFormatter&lt;/code&gt;&lt;/a&gt; style to format log entries. However no variable arguments method overload makes it both harder to read and write. More importantly &lt;strong&gt;by default&lt;/strong&gt; if you use above statement the message &lt;strong&gt;will not be printed anywhere&lt;/strong&gt;. It’s easy to &lt;a href=&quot;http://stackoverflow.com/questions/4561345/how-to-configure-java-util-logging-on-android&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;fix&lt;/a&gt; when you know where to look for.&lt;/p&gt;
&lt;h3 id=&quot;powerful-logback&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#powerful-logback&quot; aria-label=&quot;powerful logback permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Powerful &lt;code class=&quot;language-text&quot;&gt;logback&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;http://logback.qos.ch/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;logback&lt;/a&gt; is probably the most powerful and configurable logging framework. Among many features you can for example send an email with 50 last log entries - I’ve used it in one project, it can be a bit hard to configure but it really comes handy during testing. In order to use it on android one needs to use a ported version &lt;a href=&quot;http://tony19.github.io/logback-android/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;logback-android&lt;/a&gt;. There is one caveat though - this library is costs about 512kB - and takes about 4200 out of &lt;a href=&quot;https://medium.com/@rotxed/dex-skys-the-limit-no-65k-methods-is-28e6cb40cf71&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;dex method limit&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;simple-android-logger&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#simple-android-logger&quot; aria-label=&quot;simple android logger permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Simple &lt;a href=&quot;https://github.com/noveogroup/android-logger&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;android-logger&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;android-logger&lt;/code&gt; is a small (&amp;#x3C;50KB) library that let’s you use slf4j api to print to logcat. It ships with various configuration options that let you change the format of output messages as well as log level based on hierarchical logger names. However you won’t be able to print messages to &lt;a href=&quot;https://github.com/noveogroup/android-logger/issues/25&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;an additional file&lt;/a&gt; and you can only &lt;a href=&quot;https://github.com/noveogroup/android-logger/issues/28&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;configure the logger through properties files&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;slf4android&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#slf4android&quot; aria-label=&quot;slf4android permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;a href=&quot;https://github.com/bright/slf4android&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;slf4android&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Since I wasn’t perfectly happy with above and because some design decisions made in &lt;a href=&quot;https://github.com/noveogroup/android-logger&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;android-logger&lt;/a&gt; make it not so easy to add features like logging to a file, creating custom patterns and configuring it from code I decided to create yet another logging utility.&lt;/p&gt;
&lt;p&gt;It’s a tiny wrapper around &lt;a href=&quot;http://www.slf4j.org/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;slf4j api&lt;/a&gt; baked by the &lt;code class=&quot;language-text&quot;&gt;java.util.logging&lt;/code&gt; logger mechanism. This means you can easily hook in any existing &lt;code class=&quot;language-text&quot;&gt;java.util.logging.Handler&lt;/code&gt; implementations.&lt;/p&gt;
&lt;p&gt;To use this little gem you’ll need to add &lt;a href=&quot;http://bright.github.io/maven-repo/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;http://bright.github.io/maven-repo/&lt;/code&gt;&lt;/a&gt; to repository list:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;groovy&quot;&gt;&lt;pre class=&quot;language-groovy&quot;&gt;&lt;code class=&quot;language-groovy&quot;&gt;repositories &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    maven &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        url &lt;span class=&quot;token string gstring&quot;&gt;&quot;http://bright.github.io/maven-repo/&quot;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;and then declare a dependency inside a module:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;groovy&quot;&gt;&lt;pre class=&quot;language-groovy&quot;&gt;&lt;code class=&quot;language-groovy&quot;&gt;dependencies &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;compile&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;pl.brightinventions:slf4android:0.0.4@aar&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      transitive &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;//other dependencies&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;As with any slf4j compatible implementation using slf4android looks like this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;java&quot;&gt;&lt;pre class=&quot;language-java&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;HomeActivity&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Activity&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Logger&lt;/span&gt; LOG &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;LoggerFactory&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getLogger&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;HomeActivity&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getSimpleName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token annotation punctuation&quot;&gt;@Override&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;onCreate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Bundle&lt;/span&gt; savedInstanceState&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;onCreate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;savedInstanceState&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        LOG&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;debug&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Hello from {} saved instance state {}&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; savedInstanceState&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;logging-to-a-file&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#logging-to-a-file&quot; aria-label=&quot;logging to a file permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Logging to a file&lt;/h3&gt;
&lt;p&gt;To print messages to a separate file just add:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;java&quot;&gt;&lt;pre class=&quot;language-java&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;LoggerConfiguration&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;configuration&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addHandlerToLogger&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;LoggerConfiguration&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fileLogHandler&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;inside your custom &lt;code class=&quot;language-text&quot;&gt;android.app.Application&lt;/code&gt; &lt;code class=&quot;language-text&quot;&gt;onCreate&lt;/code&gt; method. This will create rotated log files inside &lt;code class=&quot;language-text&quot;&gt;context.getApplicationInfo().dataDir&lt;/code&gt; with a name derived from &lt;code class=&quot;language-text&quot;&gt;context.getPackageName()&lt;/code&gt; and a default message pattern &lt;code class=&quot;language-text&quot;&gt;%date %level [%thread] %name - %message%newline&lt;/code&gt;&lt;/p&gt;
&lt;h3 id=&quot;more-features&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#more-features&quot; aria-label=&quot;more features permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;More features&lt;/h3&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;slf4android&lt;/code&gt; let’s you register custom message patterns and configure logging level - although the api for that is still rough around the edges. It also features a simple (and not well tested) mechanism for error reporting that, when enabled, will display a &lt;code class=&quot;language-text&quot;&gt;Dialog&lt;/code&gt; prompting tester to notify developer through email whenever an error is encountered. You can enable it with:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;java&quot;&gt;&lt;pre class=&quot;language-java&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;LoggerConfiguration&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;configuration&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;notifyDeveloperWithLogcatDataHandler&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;applicationContext&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;developer.address@domain.com&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;and receive emails with attached logcat output which comes handy during development.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Guide to javascript generators]]></title><description><![CDATA[For a while now I’ve been hearing and reading about a new exciting features of ES6 like arrow functions, array comprehensions, classes, modules, generators and many more. While many of them are easy to understand generators can take a while to grok. So I thought it would be a good idea to write some samples to master…]]></description><link>undefined/guide-to-javascript-generators/</link><guid isPermaLink="false">undefined/guide-to-javascript-generators/</guid><pubDate>Sun, 15 Jun 2014 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 400px; &quot;
    &gt;
      &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 66.66666666666666%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAIEBf/EABUBAQEAAAAAAAAAAAAAAAAAAAEC/9oADAMBAAIQAxAAAAGpIKkYwiH/xAAYEAADAQEAAAAAAAAAAAAAAAABAgMEMf/aAAgBAQABBQIuUnKtKUrqKvNiHCBZN3//xAAVEQEBAAAAAAAAAAAAAAAAAAAQMf/aAAgBAwEBPwGH/8QAFxEAAwEAAAAAAAAAAAAAAAAAEBESIf/aAAgBAgEBPwF1o//EAB4QAAEEAQUAAAAAAAAAAAAAAAEAAhEhEBIiMVGh/9oACAEBAAY/AiWiSo2xyaUD1Dop2mrOP//EABoQAAMBAAMAAAAAAAAAAAAAAAABESExQVH/2gAIAQEAAT8hTYRsYoXnh0GteLwbhcIWA64GM7rbP//aAAwDAQACAAMAAAAQ8C//xAAWEQEBAQAAAAAAAAAAAAAAAAABEBH/2gAIAQMBAT8QEOM//8QAGBEAAgMAAAAAAAAAAAAAAAAAAAEhMVH/2gAIAQIBAT8QVAnT/8QAHBABAAMAAgMAAAAAAAAAAAAAAQARITFBUYHR/9oACAEBAAE/EBbWWVK747lfoWWzpq8sLUYcLfyM9tBuQd0xhe0Hohbk8s//2Q==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/df05605e171e3486f08fe325ae73d512/8ac56/yield-sign.webp 240w,
/static/df05605e171e3486f08fe325ae73d512/7f61c/yield-sign.webp 400w&quot;
              sizes=&quot;(max-width: 400px) 100vw, 400px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/df05605e171e3486f08fe325ae73d512/09b79/yield-sign.jpg 240w,
/static/df05605e171e3486f08fe325ae73d512/066f9/yield-sign.jpg 400w&quot;
            sizes=&quot;(max-width: 400px) 100vw, 400px&quot;
            type=&quot;image/jpeg&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/df05605e171e3486f08fe325ae73d512/066f9/yield-sign.jpg&quot;
            alt=&quot;Yield sign&quot;
            title=&quot;Yield sign&quot;
            loading=&quot;lazy&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
    &lt;/span&gt;
For a while now I’ve been hearing and reading about a new exciting features of ES6 like arrow functions, array comprehensions, classes, modules, generators and many more. While many of them are easy to understand &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;generators&lt;/a&gt; can take a while to grok. So I thought it would be a good idea to write some samples to master this particular feature.&lt;/p&gt;
&lt;h2 id=&quot;what-are-generators&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#what-are-generators&quot; aria-label=&quot;what are generators permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;What are generators&lt;/h2&gt;
&lt;p&gt;Generators or to be more precise &lt;em&gt;generator functions&lt;/em&gt; are functions which can be exited and then reentered with function execution context (variable binding) preserved - a limited version of &lt;a href=&quot;http://en.wikipedia.org/wiki/Coroutine&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;coroutines&lt;/a&gt; if you will. Traditionally they are used to write iterators more easily but of course they have many more interesting use cases.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;To run following samples your &lt;code class=&quot;language-text&quot;&gt;node&lt;/code&gt; version has to support harmony generators. You can check that with &lt;code class=&quot;language-text&quot;&gt;node --v8-options | grep harmony&lt;/code&gt;. The latest unstable version 0.11.12 supports them.&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&quot;a-simple-generator&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#a-simple-generator&quot; aria-label=&quot;a simple generator permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;A simple generator&lt;/h3&gt;
&lt;p&gt;Here’s a very simple example of generator that yields only two values:
{% gist miensol/9cf18bc90b2021018403 %}
when executed it will output:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;value: &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;, done: false&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;value: &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;, done: false&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;value: undefined, done: true&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;a-fibonacci-generator&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#a-fibonacci-generator&quot; aria-label=&quot;a fibonacci generator permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;A Fibonacci generator&lt;/h3&gt;
&lt;p&gt;Of course since we have an easy way to create iterators we have to have a way to iterate over them. One approach is to just use a while loop:
{% gist miensol/367d27fb1b3f7966e31a %}&lt;/p&gt;
&lt;p&gt;but honestly this would be a step back. Fortunately es6 comes with a new kind of &lt;code class=&quot;language-text&quot;&gt;for-of&lt;/code&gt; loop designed specifically to work with iterators:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; current &lt;span class=&quot;token keyword&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fibo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;current&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;iterators-and-iterables&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#iterators-and-iterables&quot; aria-label=&quot;iterators and iterables permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Iterators and iterables&lt;/h3&gt;
&lt;p&gt;I’ve mentioned couple of times a word iterator, but what exactly is that? In ES6 iterator is an object that has &lt;code class=&quot;language-text&quot;&gt;next&lt;/code&gt; method which when called returns and object having 2 properties:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;value&lt;/code&gt; - which represents value returned by iterator&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;done&lt;/code&gt; - a boolean indicating whether iterator has done it’s job or not&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As we saw in the above generator examples every generator is an implicit iterator thus we can loop through it using new &lt;code class=&quot;language-text&quot;&gt;for-of&lt;/code&gt; syntax.&lt;/p&gt;
&lt;p&gt;There is one more object &lt;em&gt;type&lt;/em&gt; it is good to know of - &lt;code class=&quot;language-text&quot;&gt;iterable&lt;/code&gt;. According to &lt;a href=&quot;http://wiki.ecmascript.org/doku.php?id=harmony:iterators&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;ES6 Wiki&lt;/a&gt; an object is iterable if has a internal property named &lt;code class=&quot;language-text&quot;&gt;iterator&lt;/code&gt; which is a function returning iterator. Unfortunatelly the latests specs aren’t yet implemented in v8 (or incorporated in node.js) so the following example is only my understanding of the specs:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; iterable &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
iterable&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Symbol&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;iterator&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;calling Symbol.iterator&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;yield&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;yield&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; item &lt;span class=&quot;token keyword&quot;&gt;of&lt;/span&gt; iterable&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;item&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;which would print:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;calling Symbol.iterator
&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;passing-values-to-generators&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#passing-values-to-generators&quot; aria-label=&quot;passing values to generators permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Passing values to generators&lt;/h2&gt;
&lt;p&gt;So far we’ve covered the most simplistic usage of generators for those familiar with .NET it reassembles a &lt;code class=&quot;language-text&quot;&gt;yield&lt;/code&gt; keyword introduced in C# 2.0 in 2005. Since ES6 Generators design was influenced a lot by python generators now wonder we can also pass values to generator functions. You do it by passing value to &lt;code class=&quot;language-text&quot;&gt;next&lt;/code&gt; function call:
{% gist miensol/30aa3afe5396bdc6b8c1 %}&lt;/p&gt;
&lt;p&gt;Running it should output something similar to:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;How old are you? oracle says:  &lt;span class=&quot;token number&quot;&gt;0.760754773626104&lt;/span&gt;
Why? oracle says:  &lt;span class=&quot;token number&quot;&gt;0.36784305213950574&lt;/span&gt;
Thank you&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;A careful reader will notice that the first question is silently ignored by our &lt;em&gt;oracle&lt;/em&gt; generator. This is logical although might be strange at first. The generator function body isn’t executed until we call &lt;code class=&quot;language-text&quot;&gt;next&lt;/code&gt; for the &lt;strong&gt;first time&lt;/strong&gt; - which is like &lt;em&gt;starting&lt;/em&gt; the generator. The call to &lt;code class=&quot;language-text&quot;&gt;next&lt;/code&gt; will execute function body until it encounters &lt;code class=&quot;language-text&quot;&gt;yield&lt;/code&gt; - the control flow changes and the function is left to be entered later on - on future &lt;code class=&quot;language-text&quot;&gt;next&lt;/code&gt; call. Notice that we there is no logical place to store/assign the value passed to first &lt;code class=&quot;language-text&quot;&gt;next()&lt;/code&gt; call - &lt;strong&gt;a value that we pass to first &lt;code class=&quot;language-text&quot;&gt;next()&lt;/code&gt; call is ignored.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Thanks to &lt;a href=&quot;http://notherdev.blogspot.com/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;@NOtherDev&lt;/a&gt; for pointing that out&lt;/em&gt;.&lt;/p&gt;
&lt;h3 id=&quot;generators-error-handling&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#generators-error-handling&quot; aria-label=&quot;generators error handling permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Generators error handling&lt;/h3&gt;
&lt;p&gt;Now that we know how to yield values and receive them inside generators. It’s equally important to be able to handle exceptions gracefully. Since generators are executing synchronously semantics of typical &lt;code class=&quot;language-text&quot;&gt;try {} catch {}&lt;/code&gt; should be preseved:
{% gist miensol/f740e31ccc73283809a5 %}
which would output:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;Generator entered, yielding first value
Generator asked &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; second value - will go bum
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Error: You can only call this generator once, sorry&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;It’s important to note however that if you try to call &lt;code class=&quot;language-text&quot;&gt;next&lt;/code&gt; method on a generator that has thrown an exception you’ll get another error:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;throwingGenerator.next&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
                  ^
Error: Generator is already running
    at GeneratorFunctionPrototype.next &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;native&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now this was a case when a generator has thrown exception at caller. What if we would like to tell generator that an error occured at caller’s site. Thanks to generator &lt;code class=&quot;language-text&quot;&gt;throw&lt;/code&gt; function that is easy enough:&lt;/p&gt;
&lt;p&gt;{% gist miensol/d5dd0e6d46c05f51f0ed %}&lt;/p&gt;
&lt;p&gt;This as you may expect will produce:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;I will stop when you tell me about error
Got value from you: I will throw &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; a moment&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;
Got error from you: This is the end. Goodbye&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;practical-generator-usage&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#practical-generator-usage&quot; aria-label=&quot;practical generator usage permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Practical generator usage&lt;/h2&gt;
&lt;p&gt;An obvious use case is of course creating lazy evaluated collections. One can now very easily implement collection operators that are available in LINQ. Consider following examples:
{% gist miensol/e5c8f929e2fcdf0253b2 %}
which when executed will output &lt;em&gt;(note the order or DEBUG calls)&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;DEBUG: concat yielding first generator values
DEBUG: reverse will yield &lt;span class=&quot;token number&quot;&gt;6&lt;/span&gt;
DEBUG: filter predicate value &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; item &lt;span class=&quot;token number&quot;&gt;6&lt;/span&gt;
DEBUG: take will yield  &lt;span class=&quot;token number&quot;&gt;6&lt;/span&gt; counter &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
DEBUG: &lt;span class=&quot;token keyword&quot;&gt;select&lt;/span&gt; will yield Even number &lt;span class=&quot;token number&quot;&gt;6&lt;/span&gt;
Even number &lt;span class=&quot;token number&quot;&gt;6&lt;/span&gt;
DEBUG: reverse will yield &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;
DEBUG: filter predicate value &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; item &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;
DEBUG: reverse will yield &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;
DEBUG: filter predicate value &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; item &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;
DEBUG: take will yield  &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt; counter &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;
DEBUG: &lt;span class=&quot;token keyword&quot;&gt;select&lt;/span&gt; will yield Even number &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;
Even number &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;
DEBUG: concat yielding second generator values
At the end&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Note the &lt;code class=&quot;language-text&quot;&gt;concat&lt;/code&gt; function implementation uses &lt;code class=&quot;language-text&quot;&gt;yield *otherGenerator()&lt;/code&gt; to yield values yielded by other generator which greatly reduces a boilerplate code needed otherwise.&lt;/p&gt;
&lt;h3 id=&quot;simplifying-asynchronous-operations&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#simplifying-asynchronous-operations&quot; aria-label=&quot;simplifying asynchronous operations permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Simplifying asynchronous operations&lt;/h3&gt;
&lt;p&gt;It may as first be a surprise that generators can streamline asynchronous code - how would synchronously executing &lt;code class=&quot;language-text&quot;&gt;yield&lt;/code&gt; help in managing asynchronous calls? If you think of the way we write asynchronous code in most of mainstream languages it typically boils down to either:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;passing a callback function(s) that will be called when the operation completes&lt;/li&gt;
&lt;li&gt;immediately getting back a promise of result from async function&lt;/li&gt;
&lt;li&gt;using a library similar to &lt;a href=&quot;http://msdn.microsoft.com/pl-pl/data/gg577609.aspx&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Reactive Extensions&lt;/a&gt; - that when it comes to asynchronous code somewhat similar in usage to promises but offers very rich API&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now when you look at async code consuming:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;power&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;number&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; exponent&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; deferred &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Q&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;defer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;setTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    deferred&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Math&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;pow&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;number&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; exponent&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;300&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; deferred&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;promise&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;power&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I immediately translate promise calls in my head to a more natural flow:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; _wait_for_async_ &lt;span class=&quot;token function&quot;&gt;power&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now since we don’t have &lt;code class=&quot;language-text&quot;&gt;async&lt;/code&gt; feature like the one C# 5 has (&lt;a href=&quot;http://wiki.ecmascript.org/doku.php?id=strawman:async_functions&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;or rather we don’t yet have it&lt;/a&gt;) it’s not yet possible to achieve this kind of simplification. Still if you think of how the &lt;em&gt;imaginary&lt;/em&gt; &lt;code class=&quot;language-text&quot;&gt;_wait_for_async_&lt;/code&gt; keyword would work it seems that it (in case of promise based implememntation):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;would wait for the promise to complete in a non blocking fashion - possibly leaving function execution context&lt;/li&gt;
&lt;li&gt;when the promise completes it would return to the exact place from where it was &lt;em&gt;called&lt;/em&gt; and return value that it got from promise or throw an exception&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Essentially that’s the way &lt;code class=&quot;language-text&quot;&gt;yield&lt;/code&gt; keyword works - however we still need an umbrella machinery that will  take care of calling generator &lt;code class=&quot;language-text&quot;&gt;next&lt;/code&gt; method so it will return to the original caller as well as it &lt;code class=&quot;language-text&quot;&gt;throw&lt;/code&gt; method to report exceptions.&lt;/p&gt;
&lt;p&gt;As you may have guessed there are already plenty of implementations of this machinery - the one I like most is &lt;a href=&quot;https://github.com/visionmedia/co&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;co&lt;/a&gt;. Take a look at an example from their page and enjoy callback free life!&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Setting up fluentd elasticsearch and Kibana on azure]]></title><description><![CDATA[A decent way too go through log files can come handy in various ways. From debugging bugs, investigating problems on production environment to figuring out where performance bottle necks are.
For simple cases when there is only one log file involved you can go very far with using grep/awk/sed magic or any decent editor…]]></description><link>undefined/setting-up-fluentd-elasticsearch-and-kibana-on-azure/</link><guid isPermaLink="false">undefined/setting-up-fluentd-elasticsearch-and-kibana-on-azure/</guid><pubDate>Sun, 08 Jun 2014 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;A decent way too go through log files can come handy in various ways. From debugging bugs, investigating problems on production environment to figuring out where performance bottle necks are.
For simple cases when there is only one log file involved you can go very far with using grep/awk/sed magic or any decent editor capable of handling regex in large files.&lt;/p&gt;
&lt;p&gt;It becomes tricky however when your logs are scattered through several files, maybe use different log format or stamp entries with different timezones.
Fortunately there are services like &lt;a href=&quot;http://www.splunk.com/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Splunk&lt;/a&gt;, &lt;a href=&quot;https://www.loggly.com/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Loggly&lt;/a&gt; and many others that take away great amount of pain involved in aggregating distributed log entries and searching through them.&lt;/p&gt;
&lt;p&gt;I was searching once for a free alternative that I could quickly get up and running in our test environment where we had 10+ machines running 20+ web sites or services that we’re all part of a single product. That’s when I found out about &lt;a href=&quot;http://www.elasticsearch.org/overview/kibana/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Kibana&lt;/a&gt;, &lt;a href=&quot;http://logstash.net/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;logstash&lt;/a&gt;  and how they make use of &lt;a href=&quot;http://www.elasticsearch.org/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;elasticsearch&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Back then I considered using &lt;a href=&quot;http://fluentd.org/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;fluentd&lt;/a&gt; instead of logstash however most of the machines we were running windows and that is not where fluentd shines. Nowadays I’m using linux vm mostly that’s why I decided to use fluentd.&lt;/p&gt;
&lt;h2 id=&quot;setup-a-vm-for-elasticsearch&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#setup-a-vm-for-elasticsearch&quot; aria-label=&quot;setup a vm for elasticsearch permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Setup a vm for elasticsearch&lt;/h2&gt;
&lt;p&gt;We need a machine that will store our aggregated log entries so let’s create one using &lt;a href=&quot;http://azure.microsoft.com/en-us/documentation/articles/xplat-cli/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Azure Cross-Platform Command-Line interface&lt;/a&gt;. After installing it with &lt;code class=&quot;language-text&quot;&gt;npm install azure-cli -g&lt;/code&gt; we need to introduce ourself to it. The simplest way to do this is to issue &lt;code class=&quot;language-text&quot;&gt;azure account download&lt;/code&gt; which will open a browser to download your profile:
&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;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 57.08333333333333%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAIAAADwazoUAAAACXBIWXMAAAsTAAALEwEAmpwYAAAB6ElEQVQoz42OSY/TMACF8/8PHDiAGGkEgjnMmQMCjRhaShFqp5qme5ZJ0yyOayeOHafxkqWoVSV65NP3jk/vGbd3dx/u729uP756/fbhsed5W8d1bcdZrzeWbbuum5wBAIRRFEZREIYgSR77gzc3743Js/k0mY6eJv3Bb8t2MMZ7hAAAlmUBAOI4zjKSE4pxGsUxAMkpEE7NeW8wNISopqD66lQPThGDJAwj05x5nrcLgl0YY4xzQjDGCCFKaUZIUTDGKEYoS7EB4f7z6OVd7+XTwJkurP5wPJ1bthcn+5QVnLHiUFVCKql0TgsIEeellCrNCITQICQPIuCHURjFa8f/9mM4NtfWFqQ5LyvB+EGoWulW6basJCvK8iCUbnl54LwwtNJaa865ENXG3X35PhiOzJUbpXnRNJ3SjT43lW51fVGpVtfN8Xg0tFJCaUxLelBrN/j559lcewt7hwnTdStULXVzZS11LVR9KUulDmUJIUxTvLK3v8bzydyebXYZLZv2eFqu/23qpmvarus6IaXW2tBnKGUlL/0gmq0sy/Es1/f8HSE5yem1cA+DBC88yAreNI0hpayEyLKMMbb1/eVyaW02AMQIIUIIpfm1GKFkn7ohElKcbiulpJSU0jzPGWPH7sLxP/gLo8pZ04Vbn8QAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source srcset=&quot;/static/3f5ca6d0c36f3df3c2e0d92c7b4a4e71/8ac56/azure_account_download.webp 240w,
/static/3f5ca6d0c36f3df3c2e0d92c7b4a4e71/d3be9/azure_account_download.webp 480w,
/static/3f5ca6d0c36f3df3c2e0d92c7b4a4e71/e46b2/azure_account_download.webp 960w,
/static/3f5ca6d0c36f3df3c2e0d92c7b4a4e71/f992d/azure_account_download.webp 1440w,
/static/3f5ca6d0c36f3df3c2e0d92c7b4a4e71/882b9/azure_account_download.webp 1920w,
/static/3f5ca6d0c36f3df3c2e0d92c7b4a4e71/9bf61/azure_account_download.webp 2030w&quot; sizes=&quot;(max-width: 960px) 100vw, 960px&quot; type=&quot;image/webp&quot;&gt;
          &lt;source srcset=&quot;/static/3f5ca6d0c36f3df3c2e0d92c7b4a4e71/8ff5a/azure_account_download.png 240w,
/static/3f5ca6d0c36f3df3c2e0d92c7b4a4e71/e85cb/azure_account_download.png 480w,
/static/3f5ca6d0c36f3df3c2e0d92c7b4a4e71/d9199/azure_account_download.png 960w,
/static/3f5ca6d0c36f3df3c2e0d92c7b4a4e71/07a9c/azure_account_download.png 1440w,
/static/3f5ca6d0c36f3df3c2e0d92c7b4a4e71/29114/azure_account_download.png 1920w,
/static/3f5ca6d0c36f3df3c2e0d92c7b4a4e71/6052f/azure_account_download.png 2030w&quot; sizes=&quot;(max-width: 960px) 100vw, 960px&quot; type=&quot;image/png&quot;&gt;
          &lt;img class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/3f5ca6d0c36f3df3c2e0d92c7b4a4e71/d9199/azure_account_download.png&quot; alt=&quot;azure account download&quot; title=&quot;azure account download&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;&gt;
        &lt;/picture&gt;
    &lt;/span&gt;
After that you’ll need to import the downloaded file with &lt;code class=&quot;language-text&quot;&gt;npm account import /path/to/your/credentials.publishsettings&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I’m used to ubuntu so let’s find an machine image to use:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;azure vm image list &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;grep&lt;/span&gt; Ubuntu-14
data:    b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu-14_04-LTS-amd64-server-20140122.1-alpha2-en-us-30GB                          Public    Linux  
data:    b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu-14_04-LTS-amd64-server-20140226.1-beta1-en-us-30GB                           Public    Linux  
data:    b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu-14_04-LTS-amd64-server-20140326-beta2-en-us-30GB                             Public    Linux  
data:    b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu-14_04-LTS-amd64-server-20140414-en-us-30GB                                   Public    Linux  
data:    b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu-14_04-LTS-amd64-server-20140416.1-en-us-30GB                                 Public    Linux  
data:    b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu-14_04-LTS-amd64-server-20140528-en-us-30GB                                   Public    Linux  &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The last one looks like most recent so we’ll used that. Next we need to create a virtual machine. We can use either password authentication (which isn’t recommended) or a ssh certificate. To use the latter we need to create a certificate key pair first. Openssl command line tool will do it for us:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;openssl req -x509 -nodes -days &lt;span class=&quot;token number&quot;&gt;730&lt;/span&gt; -newkey rsa:2048 -keyout ~/.ssh/mymachine.key -out ~/.ssh/mymachine.pem&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;It’s now time to issue azure to create a new instance of Ubuntu machine for us:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;azure vm create machine-dns-name b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu-14_04-LTS-amd64-server-20140528-en-us-30GB machineuser &lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;
  --vm-size extrasmall &lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;
  --location &lt;span class=&quot;token string&quot;&gt;&apos;North Europe&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;
  --ssh &lt;span class=&quot;token number&quot;&gt;22&lt;/span&gt; --no-ssh-password --ssh-cert ~/.ssh/mymachine.pem

info:    Executing &lt;span class=&quot;token builtin class-name&quot;&gt;command&lt;/span&gt; vm create
+ Looking up image b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu-14_04-LTS-amd64-server-20140528-en-us-30GB
+ Looking up cloud &lt;span class=&quot;token function&quot;&gt;service&lt;/span&gt;
+ Creating cloud &lt;span class=&quot;token function&quot;&gt;service&lt;/span&gt;
+ Retrieving storage accounts
+ Configuring certificate
+ Creating VM
info:    vm create &lt;span class=&quot;token builtin class-name&quot;&gt;command&lt;/span&gt; OK&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We can find out more details about our newly created machine with: &lt;code class=&quot;language-text&quot;&gt;azure vm list --dns-name machine-dns-name --json&lt;/code&gt;.
Our machine is up and running to so we can log into it using ssh (before you do that be sure to change .key file permission to 0600 so that only you can access it): &lt;code class=&quot;language-text&quot;&gt;ssh -i ~/.ssh/mymachine.key  machineuser@machine-dns-name.cloudapp.net&lt;/code&gt;&lt;/p&gt;
&lt;h2 id=&quot;install-elasticsearch&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#install-elasticsearch&quot; aria-label=&quot;install elasticsearch permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Install elasticsearch&lt;/h2&gt;
&lt;p&gt;First let’s download elasticsearch and extract it to our newly created vm:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; https://download.elasticsearch.org/elasticsearch/elasticsearch/elasticsearch-1.2.0.zip -o elasticsearch-1.2.0.zip
&lt;span class=&quot;token function&quot;&gt;unzip&lt;/span&gt; elasticsearch-1.2.0.zip&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;To run elasticsearch we’ll need java in version at least 1.7:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;apt-get&lt;/span&gt; update
&lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;apt-get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; default-jre&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now we can finally run elasticsearch:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;./elasticsearch-1.2.0/bin/elasticsearch&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If we want to run elasticsearch as a daemon we can pass &lt;code class=&quot;language-text&quot;&gt;-d&lt;/code&gt; to the script. &lt;em&gt;(see below for init.d script)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;We also need to open port for elasticsearch:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;azure vm endpoint create --endpoint-name elasticsearch machine-dns-name &lt;span class=&quot;token number&quot;&gt;9200&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;9200&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We only wan’t our machines to be able to push logs to elasticsearch that’s why we need to add ACL rules to the endpoint we created above. Unfortunately I couldn’t find a way to do this through CLI interface so we need to resort to &lt;a href=&quot;https://manage.windowsazure.com/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;web interface&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;install-kibana&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#install-kibana&quot; aria-label=&quot;install kibana permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Install Kibana&lt;/h2&gt;
&lt;p&gt;Kibana is a web application designed to perform elasticsearch searches and display them using neat interface. It communicates with elasticsearch directly that’s why it’s not really suited to be deployed to publicly accessible place. Fortunately there is &lt;a href=&quot;https://github.com/hmalphettes/kibana-proxy&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;kibana-proxy&lt;/a&gt; which provides authentication on top of it. To run kibana-proxy we’ll need node.js let’s install both of them:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;apt-get&lt;/span&gt; update
&lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;apt-get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;apt-get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; nodejs
&lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;apt-get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; clone https://github.com/hmalphettes/kibana-proxy.git
&lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; kibana-proxy
&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; submodule init
&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; submodule update
&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt;
node app.js &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;kibana-proxy is now running but in order to access it from outside we need to open firewall port:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;azure vm endpoint create --endpoint-name kibana-proxy machine-dns-name &lt;span class=&quot;token number&quot;&gt;80&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3003&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now when you point your browser to &lt;code class=&quot;language-text&quot;&gt;http://machine-dns-name/&lt;/code&gt; you should see kibana welcome screen.&lt;/p&gt;
&lt;h2 id=&quot;restrict-access-to-kibana-proxy&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#restrict-access-to-kibana-proxy&quot; aria-label=&quot;restrict access to kibana proxy permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Restrict access to kibana-proxy&lt;/h2&gt;
&lt;p&gt;You probably don’t want anyone to be able to see your logs that’s why we need to setup authentication. &lt;code class=&quot;language-text&quot;&gt;kibana-proxy&lt;/code&gt; implements this through Google OAuth - so let’s enable it for our installation. First we’ll need &lt;code class=&quot;language-text&quot;&gt;APP_ID&lt;/code&gt; (Client ID) and &lt;code class=&quot;language-text&quot;&gt;APP_SECRET&lt;/code&gt; (Client secret) so let’s go to &lt;a href=&quot;https://console.developers.google.com/project&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;google developer console&lt;/a&gt; and create a new project. Next we need to enable OAuth for our project in &lt;em&gt;APIs &amp;#x26; auth &gt; Credentials&lt;/em&gt;:&lt;/p&gt;
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 713px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/2757d878cb8ce6cdca4e91c01b0c220a/01267/google_oauth_setup.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: 105%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAVCAIAAADJt1n/AAAACXBIWXMAAAsTAAALEwEAmpwYAAACD0lEQVQ4y32UW5LbIBBFve98ZQHZSH7yl83YmrKEHhYg68WzG1AKkD22x5lTconCXLq53ehwbj8KeiaEnE6n4/H0URTH47EoirIsCSE1IXWCkLppGkKqtm3XVayJgzFGJ0weGW2tBQBEhAQmHsf7jLUH57xzzidcwnsfvsXvuMOW8N4jorX2/re1VgghE/GllNKgDeQAWbWLAeLsNE3jOAoh/hN8S08AgCcxIhprz+eSVOTSXe57fyVsQWvtMMa/iaMboe3o+RydV1oDQHbuVRyCMSZncsgO5UXLMldV2TTNsizxwOnnH3DpNFrrbPghZ2it3baNsrGs6r7v53kWQiipxL5Hdm6dFovO4/3M0YebeJxmUjd1XTNKLYCxRkmptVJaaaOVUoiQ3X11GxF5gjHW95e2bRlj6oaNBlhEfCOObhtDCCnLqmmasiwppWJdc4GllHjz/02pAMB7P/AhxmVsGIaBc8qokHJXPPBGvIWQq5dBBGOMQ/dYpOw5vBiWWz9FZZRSzgcdi+kf9sK88n2HAUDXdZdL37Vd0kfrOOf5CIxxAHwV5/1y2koscp2lWIRY52m+Xq/TNA3XaxqMud+f0r63J7pwFWGU26ziBUh347Ux84X5FO+LAlTc//gNP//Ar78otB84U0q/uRhf07bWCKm7QbVc9aNSWn9+Xp7Jk09p549B8PvzPd77LP4HIl/CQ9zh4OAAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source srcset=&quot;/static/2757d878cb8ce6cdca4e91c01b0c220a/8ac56/google_oauth_setup.webp 240w,
/static/2757d878cb8ce6cdca4e91c01b0c220a/d3be9/google_oauth_setup.webp 480w,
/static/2757d878cb8ce6cdca4e91c01b0c220a/69b3e/google_oauth_setup.webp 713w&quot; sizes=&quot;(max-width: 713px) 100vw, 713px&quot; type=&quot;image/webp&quot;&gt;
          &lt;source srcset=&quot;/static/2757d878cb8ce6cdca4e91c01b0c220a/8ff5a/google_oauth_setup.png 240w,
/static/2757d878cb8ce6cdca4e91c01b0c220a/e85cb/google_oauth_setup.png 480w,
/static/2757d878cb8ce6cdca4e91c01b0c220a/01267/google_oauth_setup.png 713w&quot; sizes=&quot;(max-width: 713px) 100vw, 713px&quot; type=&quot;image/png&quot;&gt;
          &lt;img class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/2757d878cb8ce6cdca4e91c01b0c220a/01267/google_oauth_setup.png&quot; alt=&quot;google oauth setup&quot; title=&quot;google oauth setup&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;p&gt;Make sure &lt;em&gt;AUTHORIZED REDIRECT URI&lt;/em&gt; looks like &lt;code class=&quot;language-text&quot;&gt;http://machind-dns-name.cloudapp.net/auth/google/callback&lt;/code&gt;. For more secure setup you should be using &lt;code class=&quot;language-text&quot;&gt;https&lt;/code&gt; but for simplicity we’ll skip that.&lt;/p&gt;
&lt;p&gt;Now we need to start &lt;code class=&quot;language-text&quot;&gt;kibana-proxy&lt;/code&gt; again this time passing it &lt;code class=&quot;language-text&quot;&gt;APP_ID&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;APP_SECRET&lt;/code&gt; along with &lt;code class=&quot;language-text&quot;&gt;AUTHORIZED_EMAILS&lt;/code&gt; through environment variables (&lt;code class=&quot;language-text&quot;&gt;kibana-proxy-start.sh&lt;/code&gt;):&lt;/p&gt;
&lt;div id=&apos;kibana_proxy_start&apos;&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;APP_ID&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;fill_me_appid
&lt;span class=&quot;token builtin class-name&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;APP_SECRET&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;fill_me_app_secret
&lt;span class=&quot;token builtin class-name&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;AUTHORIZED_EMAILS&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;my_email_list
&lt;span class=&quot;token builtin class-name&quot;&gt;exec&lt;/span&gt; /usr/bin/nodejs app.js&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
Now when you go to `http://machine-dns-name/` you should get redirect to Google authorization page.
&lt;p&gt;We want to run the &lt;code class=&quot;language-text&quot;&gt;kibana-proxy&lt;/code&gt; continuously - the simplest way to achieve that is to make use of &lt;a href=&quot;https://github.com/nodejitsu/forever&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;forever&lt;/a&gt; module. However in this guide we’ll use upstart scripts described below.&lt;/p&gt;
&lt;h2 id=&quot;fluentd-installation&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#fluentd-installation&quot; aria-label=&quot;fluentd installation permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Fluentd installation&lt;/h2&gt;
&lt;p&gt;To push log entries to our elasticsearch instance we need &lt;code class=&quot;language-text&quot;&gt;fluentd&lt;/code&gt; &lt;em&gt;agent&lt;/em&gt; installed on the machine we want to gather logs from.
Fluentd &lt;em&gt;agent&lt;/em&gt; comes in 2 forms: fluentd gem if you wish to have more control features and updates and td-agent if you care for stability over new features. We’ll go with fluentd gem for this guide.&lt;/p&gt;
&lt;p&gt;Since fluentd is implemented in Ruby with most performance critical parts written in C. To install it we need ruby first but obtaining it with rvm is a piece of cake:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; -sSL https://get.rvm.io &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;bash&lt;/span&gt; -s stable
&lt;span class=&quot;token builtin class-name&quot;&gt;source&lt;/span&gt; ~/.rvm/scripts/rvm
rvm &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2.1&lt;/span&gt;.1
&lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; gem &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; fluentd --no-ri --no-rdoc
&lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; fluentd -s&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now we have fluentd installed with sample configuration available in &lt;code class=&quot;language-text&quot;&gt;/etc/fluentd/fluent.conf&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Since we would like our log entries to be pushed to elasticsearch we need a &lt;a href=&quot;https://github.com/uken/fluent-plugin-elasticsearch&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;plugin&lt;/a&gt; for that too:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;gem &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; fluent-plugin-elasticsearch
gem &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; fluent-plugin-tail-multiline&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Let’s edit &lt;code class=&quot;language-text&quot;&gt;fluent.confg&lt;/code&gt; file so that our agents reads sample log files from rails app and forwards them to elasticsearch instance:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&amp;lt;source&amp;gt;
  type tail_multiline
  format /^(?&amp;lt;level_short&amp;gt;[^,]*), \[(?&amp;lt;time&amp;gt;[^\s]*) .(?&amp;lt;request_id&amp;gt;\d+)\]\s+(?&amp;lt;level&amp;gt;[A-Z]+)[-\s:]*(?&amp;lt;message&amp;gt;.*)/
  path /path/to/log/file/staging.log
  pos_file /path/to/positions/file/fluentd_tail.pos
  tag app_name.environment
&amp;lt;/source&amp;gt;

&amp;lt;match app_name.**&amp;gt;
  type elasticsearch
  host machine-dns-name.cloudapp.net
  logstash_format true
  flush_interval 10s # for testing
&amp;lt;/match&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The format we see above will following line of Rails log file:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;I, [2014-05-22T12:24:44.434963 #11837]  INFO -- : Completed 200 OK in 884ms (Views: 395.7ms | ActiveRecord: 115.0ms)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;and break it down to following groups/fields:&lt;/p&gt;
&lt;table class=&quot;table&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;Key&lt;/th&gt;&lt;th&gt;Value&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
  &lt;td&gt;
    time
  &lt;/td&gt;
  &lt;td&gt;
    2014/05/22 12:24:44
  &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td&gt;
    level_short
  &lt;/td&gt;
  &lt;td&gt;
    I
  &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td&gt;
    request_id
  &lt;/td&gt;
  &lt;td&gt;
    11837
  &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td&gt;
    level
  &lt;/td&gt;
  &lt;td&gt;
    INFO
  &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
  &lt;td&gt;
    message
  &lt;/td&gt;
  &lt;td&gt;
    Completed 200 OK in 884ms (Views: 395.7ms | ActiveRecord: 115.0ms)
  &lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;em&gt;Note that although builtin &lt;code class=&quot;language-text&quot;&gt;in_tail&lt;/code&gt; plugin supports multiline log entries I either don’t completely understand how to use it or there is no way to have full stack trace logged as a single message. Moreover &lt;code class=&quot;language-text&quot;&gt;tail_multiline&lt;/code&gt; doesn’t seem to support multiple input paths that’s why in order to monitor multiple files you would have to duplicate the source section.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The only thing left is to start fluentd and watch our logs&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;rvmsudo fluetnd -d&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;upstart-for-fluentd-elasticsearch-and-kibana-proxy&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#upstart-for-fluentd-elasticsearch-and-kibana-proxy&quot; aria-label=&quot;upstart for fluentd elasticsearch and kibana proxy permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Upstart for fluentd, elasticsearch and kibana-proxy&lt;/h2&gt;
&lt;p&gt;The final thing we need to do is to setup above components to be run as services. Since we’re using Ubuntu for our servers we’ll use upstart congiurations for that.&lt;/p&gt;
&lt;h3 id=&quot;upstart-for-fluentd&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#upstart-for-fluentd&quot; aria-label=&quot;upstart for fluentd permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Upstart for fluentd&lt;/h3&gt;
&lt;p&gt;Since we have installed fluentd in ubuntu user rvm but we wan’t we have to generate a wrapper script for it&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;rvm wrapper default fluentd&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;and then use generated wrapper &lt;code class=&quot;language-text&quot;&gt;~/.rvm/wrappers/default/fluentd&lt;/code&gt; in our upstart script.
Let’s create our upstart script and put it inside &lt;code class=&quot;language-text&quot;&gt;/etc/init/fluetnd.conf&lt;/code&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;description &lt;span class=&quot;token string&quot;&gt;&quot;Fluentd&quot;&lt;/span&gt;
start on runlevel &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2345&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# All except below&lt;/span&gt;
stop on runlevel &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;016&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# Halt, Single-User, Reboot&lt;/span&gt;
respawn
respawn limit &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;60&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# Restart if ended abruptly&lt;/span&gt;
&lt;span class=&quot;token builtin class-name&quot;&gt;exec&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; -u ubuntu /home/ubuntu/.rvm/wrappers/default/fluentd&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;upstart-for-elasticsearch&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#upstart-for-elasticsearch&quot; aria-label=&quot;upstart for elasticsearch permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Upstart for elasticsearch&lt;/h3&gt;
&lt;p&gt;Elasticsearch already comes with a script for starting it in properly configured jvm we’ll utilize it in our upstart config &lt;code class=&quot;language-text&quot;&gt;/etc/init/elasticsearch.conf&lt;/code&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;description &lt;span class=&quot;token string&quot;&gt;&quot;Elasticsearch&quot;&lt;/span&gt;
start on runlevel &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2345&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# All except below&lt;/span&gt;
stop on runlevel &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;016&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# Halt, Single-User, Reboot&lt;/span&gt;
respawn
respawn limit &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;60&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# Restart if ended abruptly&lt;/span&gt;
setuid ubuntu
&lt;span class=&quot;token builtin class-name&quot;&gt;exec&lt;/span&gt; /path/to/your/elasticsearch/bin/elasticsearch&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;upstart-for-kibana-proy&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#upstart-for-kibana-proy&quot; aria-label=&quot;upstart for kibana proy permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Upstart for kibana-proy&lt;/h3&gt;
&lt;p&gt;With the &lt;a href=&quot;#kibana_proxy_start&quot;&gt;kibana-proxy-start.sh&lt;/a&gt; the upstart configuration for kibana-proxy is dead simple:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;description &lt;span class=&quot;token string&quot;&gt;&quot;kibana-proxy&quot;&lt;/span&gt;
start on runlevel &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2345&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# All except below&lt;/span&gt;
stop on runlevel &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;016&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# Halt, Single-User, Reboot&lt;/span&gt;
respawn
respawn limit &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;60&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# Restart if ended abruptly&lt;/span&gt;
chdir /where/you/installed/kibana-proxy
setuid ubuntu
&lt;span class=&quot;token builtin class-name&quot;&gt;exec&lt;/span&gt; ./kibana-proxy-start.sh&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;running-services&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#running-services&quot; aria-label=&quot;running services permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Running services&lt;/h3&gt;
&lt;p&gt;Once you have your upstart scripts configuration ready you can now start services with a descriptive syntax:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;service&lt;/span&gt; elasticsearch start&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I you’re having trouble getting upstart to work you can always check its configuration with:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;initctl check-config&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;To find out why a particular service won’t start check out&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;dmesg&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;grep&lt;/span&gt; elasticsearch&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Finally you can find you log files in &lt;code class=&quot;language-text&quot;&gt;/var/log/upstart/servicename.*&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Now if you have setup everything correctly and of course you have some log messages generated by apps when you navigate to
&lt;a href=&quot;http://machine-dns-name.cloudapp.net/index.html#/dashboard/file/logstash.json&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;http://machine-dns-name.cloudapp.net/index.html#/dashboard/file/logstash.json&lt;/a&gt; you should see a nice dashboard filling up with log entries:
&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;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 84.58333333333331%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAARCAIAAABSJhvpAAAACXBIWXMAAAsTAAALEwEAmpwYAAACgklEQVQ4y33TTU+cQBgHcL5Fk67CzDMvMAPDIm/DgrKyb11cN6bVemiT2h707hfpp2jSi00PTVy7rQd76n6rBjDGg/YXMmFInj8zD4xx9fXL929XNzc/b29vV9er6+vVj9av9fr3I+v1+u7uz2bzt7PZbFarlZEeHWfzOuj7YRgKIRBCuIUQYoxJKW3HEVISQmiLc04pJYQwxoy9y8/6zYXk3FMN/xH1SDd9GPst4/D9i9NzN0qCKIofRFGUPC+O4yRJsiwzji9fHZ2FOs8cITBg0qKUWs8wTZNzbreMZZ1iFjn9UHjSU83agyAIw7Db9pMAgBACAEaUUctECJlAsGV24U08fl7XVMuyDM/zAQAoCGV3wW0oYIT/ryn2/aYYIdTXSviOtW0JZQMAF4xQ0kTAE2/uGEopjLEteTwMhO9sb5m2y7lkjrKZTTHGjmcTCrjdalcMBCin7bKV54VuvL+jJ5FQtuPyvvaiMtjJfRVJFcvBLA6LPrJQ2xFEOFGRDLSykGVI1529G84/VPVZNT7drc+q6qSoP1bL88nyfHrwaXRyuVheTFXi+olLGPFTd/91Pnq7m45Dw+YsKaJsP8lHOh/rQZXqMslHWTMdZYOqeZKPsmyY6mGi95LmZi8uRpnwbSMuJ7nWUriAgAIlmBBoLkDQ/DJAKWGMMkYYJZQzTglzpas8XwppLA9Cxh0AbJqm1X7xpjH3rUGu63rKE8KRUlLKer2Xva0eBgwATcOKyu3HOSYUIWRZ1nA4XCwWdT2v5/VBfbBYHBZFked5Ow601s0RiKI0SZqDEcaD2eFRNZ3tFgWlrCzL2Ww2GU9m0+l83oXU83v1eDwuWmVZpqn+ByK/1sblWLUaAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source srcset=&quot;/static/f957e9bca2a953c7a0ce64fc73ba3697/8ac56/kibana_in_action.webp 240w,
/static/f957e9bca2a953c7a0ce64fc73ba3697/d3be9/kibana_in_action.webp 480w,
/static/f957e9bca2a953c7a0ce64fc73ba3697/e46b2/kibana_in_action.webp 960w,
/static/f957e9bca2a953c7a0ce64fc73ba3697/f992d/kibana_in_action.webp 1440w,
/static/f957e9bca2a953c7a0ce64fc73ba3697/48a02/kibana_in_action.webp 1858w&quot; sizes=&quot;(max-width: 960px) 100vw, 960px&quot; type=&quot;image/webp&quot;&gt;
          &lt;source srcset=&quot;/static/f957e9bca2a953c7a0ce64fc73ba3697/8ff5a/kibana_in_action.png 240w,
/static/f957e9bca2a953c7a0ce64fc73ba3697/e85cb/kibana_in_action.png 480w,
/static/f957e9bca2a953c7a0ce64fc73ba3697/d9199/kibana_in_action.png 960w,
/static/f957e9bca2a953c7a0ce64fc73ba3697/07a9c/kibana_in_action.png 1440w,
/static/f957e9bca2a953c7a0ce64fc73ba3697/2093e/kibana_in_action.png 1858w&quot; sizes=&quot;(max-width: 960px) 100vw, 960px&quot; type=&quot;image/png&quot;&gt;
          &lt;img class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/f957e9bca2a953c7a0ce64fc73ba3697/d9199/kibana_in_action.png&quot; alt=&quot;kibana in action&quot; title=&quot;kibana in action&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;&gt;
        &lt;/picture&gt;
    &lt;/span&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[ng-click and double post]]></title><description><![CDATA[Recently I was fixing a bug in an application written in angularjs which turned out to be pretty interesting for me. At first I couldn’t reproduce the error and just when I got frustrated it happened exactly as stated in the issue tracker. As it turned out the problem was caused by fast clicking on the same button…]]></description><link>undefined/ngclick-and-double-post/</link><guid isPermaLink="false">undefined/ngclick-and-double-post/</guid><pubDate>Wed, 21 May 2014 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Recently I was fixing a bug in an application written in angularjs which turned out to be pretty interesting for me. At first I couldn’t reproduce the error and just when I got frustrated it happened exactly as stated in the issue tracker. As it turned out the problem was caused by fast clicking on the same button.
Click handler triggered an http POST to server which creates a row in table - no wonder it looked strange when 2 rows where created after someone accidentally clicked twice.&lt;/p&gt;
&lt;h2 id=&quot;some-solutions&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#some-solutions&quot; aria-label=&quot;some solutions permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Some solutions&lt;/h2&gt;
&lt;p&gt;I’ve quickly googled to find out what others are doing in such scenario and found at least couple of ways of handling it - some of them I have considered while others where completely new to me.&lt;/p&gt;
&lt;h3 id=&quot;disable-button&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#disable-button&quot; aria-label=&quot;disable button permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Disable button&lt;/h3&gt;
&lt;p&gt;The most simple approach is to use &lt;code class=&quot;language-text&quot;&gt;ng-disabled&lt;/code&gt; on the same button as &lt;code class=&quot;language-text&quot;&gt;ng-click&lt;/code&gt; directive. Which would look like this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;html&quot;&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;button&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;ng-click&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;executePost()&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;ng-disabled&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;buttonDisabled&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Click me&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;button&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;$scope&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;executePost&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  $scope&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;buttonDisabled &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;runHttpPost&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;//do something useful with a response&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;finally&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      $scope&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;buttonDisabled &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;As you can see the code is pretty straight forward especially when you make use of angularjs promise api provided by &lt;code class=&quot;language-text&quot;&gt;$q&lt;/code&gt; service.&lt;/p&gt;
&lt;h3 id=&quot;stop-relying-on-the-result-of-asynchronous-action&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#stop-relying-on-the-result-of-asynchronous-action&quot; aria-label=&quot;stop relying on the result of asynchronous action permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Stop relying on the result of asynchronous action&lt;/h3&gt;
&lt;p&gt;Another approach is to design user interface in such a way that the we can safely predict what result the action will produce. For instance if we’re editing an entity and have performed as much validation as possible on client side it’s offen safe to assume that the request will be processed successfully and our changes will persist. If so we don’t have to wait for the server to finish processing and can move to a next screen in the application that will display values already available in  browser. As a bonus our application will feel much faster and in many cases it makes a significant difference. It’s not always easy though and sometimes requires significant changes in the way we design our user interface as well as our &lt;a href=&quot;http://codebetter.com/gregyoung/2010/02/16/cqrs-task-based-uis-event-sourcing-agh/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;server api&lt;/a&gt;. &lt;a href=&quot;http://blog.alexmaccaw.com/asynchronous-ui&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Alex MacCaw&lt;/a&gt; summarised it nicely.&lt;/p&gt;
&lt;h3 id=&quot;make-sure-a-second-request-will-not-make-it-to-the-server&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#make-sure-a-second-request-will-not-make-it-to-the-server&quot; aria-label=&quot;make sure a second request will not make it to the server permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Make sure a second request will not make it to the server&lt;/h3&gt;
&lt;p&gt;An approach I haven’t thought about is to actually prevent second request that looks identical to the first one and is created just after the first one. Michał Ostruszka &lt;a href=&quot;http://blog.codebrag.com/post/57412530001/preventing-duplicated-requests-in-angularjs&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;described an implememtation&lt;/a&gt; of this technique. I haven’t actually tried it as it seemed way too complex for an issue that I was fixing. The approach can be very tempting as it allows to handle double requests globally - once per application. Although I suspect it may be difficult to use if the act of making request that was blocked is causing side affects to the state of the application.&lt;/p&gt;
&lt;h2 id=&quot;bi-click-approach&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#bi-click-approach&quot; aria-label=&quot;bi click approach permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;code class=&quot;language-text&quot;&gt;bi-click&lt;/code&gt; approach&lt;/h2&gt;
&lt;p&gt;Most of async operation in modern browser based libraries are expressed using a flavour of promise/deferred api. This is no different in angularjs which provides &lt;a href=&quot;https://docs.angularjs.org/api/ng/service/$q&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$q&lt;/code&gt;&lt;/a&gt;. So if we would like to block the button until the operation is completed it seems like a natural fit to use promises to achieve that. Here is an example of such directive:&lt;/p&gt;
&lt;iframe class=&quot;jsfiddle&quot; width=&quot;100%&quot; height=&quot;300&quot; src=&quot;http://jsfiddle.net/miensol/7PETf/3/embedded/&quot; allowfullscreen=&quot;allowfullscreen&quot; frameborder=&quot;0&quot;&gt;&lt;/iframe&gt;
&lt;h3 id=&quot;further-usage&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#further-usage&quot; aria-label=&quot;further usage permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Further usage&lt;/h3&gt;
&lt;p&gt;Every web developer out there has probably implemented an ajax throbber of some kind. In Angularjs world most of the examples I see are very similar to our button blocking with &lt;code class=&quot;language-text&quot;&gt;isDisabled&lt;/code&gt; flag. Usually it will mean something along these lines:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;$scope&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;executePost&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  $scope&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;showThrobber &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;runHttpPost&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;finally&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      $scope&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;showThrobber &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;html&quot;&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;ajax-thorbber&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;ng-show&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;showThrobber&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;While there is nothing wrong in particular with this example I find handling those flags in a controller rather tedious. As with the &lt;code class=&quot;language-text&quot;&gt;bi-click&lt;/code&gt; example one can very easily create a directive to handle throbber toggling in one place.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Nonintrusive http proxy in nodejs]]></title><description><![CDATA[In my previous posts I wrote about problems that might occur when
using http proxy written in nodejs to debug http issues.
Today I’m going to describe how to use nodejs builtin parser to
overcome these problems.
##Nodejs streams
Node.js has decent support for handling streams. Especially
the  function takes a lot of…]]></description><link>undefined/non-intrusive-http-proxy-in-nodejs/</link><guid isPermaLink="false">undefined/non-intrusive-http-proxy-in-nodejs/</guid><pubDate>Sun, 23 Mar 2014 22:14:00 GMT</pubDate><content:encoded>&lt;p&gt;In my previous posts I wrote about problems that might occur when
using http proxy written in nodejs to debug http issues.
Today I’m going to describe how to use nodejs builtin parser to
overcome these problems.
##Nodejs streams
Node.js has decent support for handling streams. Especially
the &lt;code class=&quot;language-text&quot;&gt;pipe&lt;/code&gt; function takes a lot of burden away - whereas previously
it had to be carefully handled by programmer.
As a first step let’s use a simple socket server and tunnel http requests
through it:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; net &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;net&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; stdout &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; process&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;stdout&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; server &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; net&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createServer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;clientSocket&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; serverSocket &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; net&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;connect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;8888&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;localhost&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

      clientSocket&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;serverSocket&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      clientSocket&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;stdout&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      serverSocket&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;clientSocket&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      serverSocket&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;stdout&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
server&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;listen&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;9000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The above code creates a socket server listening on port &lt;code class=&quot;language-text&quot;&gt;9000&lt;/code&gt;.
When it gets a connection from client it will immediately try to
connect to other server listening on port &lt;code class=&quot;language-text&quot;&gt;8888&lt;/code&gt; - this is a port
used by Fiddler or Charles. After the connection is established
it uses &lt;code class=&quot;language-text&quot;&gt;pipe&lt;/code&gt; function to pass all data coming in on port &lt;code class=&quot;language-text&quot;&gt;9000&lt;/code&gt;
to port &lt;code class=&quot;language-text&quot;&gt;8888&lt;/code&gt; as well as to standard output just so we can see
what data is sent from client. We also need to pass data returned
from port &lt;code class=&quot;language-text&quot;&gt;8888&lt;/code&gt; back to client that’s why there is the second pair
of &lt;code class=&quot;language-text&quot;&gt;pipe&lt;/code&gt; calls.&lt;/p&gt;
&lt;p&gt;With that we can already use &lt;code class=&quot;language-text&quot;&gt;curl&lt;/code&gt; to see raw http traffic written
directly to standard output.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; http://wp.pl/ --proxy http://localhost:9000/&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;##Creating http proxy on network level
The above example albeit simple doesn’t really provide any value as
we still need a &lt;em&gt;external&lt;/em&gt; proxy to properly pass http traffic.
In order to make it a &lt;strong&gt;real&lt;/strong&gt; http proxy we need to add parsing logic
that will extract information about target server where we should pass
incoming data too. While building a very simple http parser isn’t difficult
why don’t we use existing one that is built right into node.js core http module?&lt;/p&gt;
&lt;p&gt;Using node.js http parser isn’t exactly documented and I guess it’s not
part of public API. Nevertheless it is exposed to client code intentionally
and a quick look through the core http module source code gives
enough examples of how to use it. With existing parser
instance the only thing left to do is to extract &lt;code class=&quot;language-text&quot;&gt;Host&lt;/code&gt; header
value, use it to connect to target server. Here is a core part
of code required:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;net&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createServer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;socketRequest&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; requestParser &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; HttpParsingStream&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createForRequest&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;socketRequest&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    requestParser&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;headers&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;//pause the request until we setup necessary plumbing&lt;/span&gt;
        req&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;pause&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;//extract information about target server&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; hostNameHeader &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; req&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;headers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;host&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            hostAndPort &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; hostNameHeader&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;:&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            host &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; hostAndPort&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            port &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;parseInt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;hostAndPort&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;80&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// now we now where to tunnel client request&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; srvSocket &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; net&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;connect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;port&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; host&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token comment&quot;&gt;//a response parser as a replacement for stdout&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; responseParser &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; HttpParsingStream&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createForResponse&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;srvSocket&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            srvSocket&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;responseParser&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token comment&quot;&gt;//pipe data from server to client&lt;/span&gt;
            srvSocket&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;socketRequest&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

            &lt;span class=&quot;token comment&quot;&gt;//flush data buffered in parser to target server&lt;/span&gt;
            requestParser&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;writeCurrentChunks&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;srvSocket&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token comment&quot;&gt;//pipe remaining data from client to target server&lt;/span&gt;
            socketRequest&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;srvSocket&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token comment&quot;&gt;//resume processing&lt;/span&gt;
            req&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;resume&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;//pipe data from client to request parser&lt;/span&gt;
    socketRequest&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;requestParser&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;listen&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;9000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The above code makes use of &lt;code class=&quot;language-text&quot;&gt;HttpParsingStream&lt;/code&gt; which is a hand
rolled writable &lt;code class=&quot;language-text&quot;&gt;Stream&lt;/code&gt; that uses node.js http parser to emit
events. As you can see we first pipe client socket to &lt;code class=&quot;language-text&quot;&gt;requestParser&lt;/code&gt;
to get information about target server. As soon as we get &lt;code class=&quot;language-text&quot;&gt;headers&lt;/code&gt;
event the incoming client request is paused, we setup connection
to target server, write raw data buffered in &lt;code class=&quot;language-text&quot;&gt;requestParser&lt;/code&gt;
and setup &lt;code class=&quot;language-text&quot;&gt;pipe&lt;/code&gt;s in a similar fashion as in the previous example.
The most important property of this http proxy is that it
&lt;strong&gt;does not change&lt;/strong&gt; data coming from client and from target server
in any way which is invaluable when debugging problems in
http implementations.&lt;/p&gt;
&lt;h2 id=&quot;httpparsingstream-explained&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#httpparsingstream-explained&quot; aria-label=&quot;httpparsingstream explained permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;HttpParsingStream explained&lt;/h2&gt;
&lt;p&gt;The above example relies on 2 instances of &lt;code class=&quot;language-text&quot;&gt;HttpParsingStream&lt;/code&gt;
for request and response respectively:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; net &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;net&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    http &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;http&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    stream &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;stream&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    Writable &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; stream&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Writable&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    parsers &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; http&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;parsers&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    HTTPParser &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; process&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;binding&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;http_parser&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;HTTPParser&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    util &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;util&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;HttpParsingStream&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;Writable&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; socket &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; options&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;socket&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;//get an instance of node parser&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; parser &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; parsers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;alloc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;//buffer for raw data&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; streamChunks &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; that &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;//initialize as request or response parser&lt;/span&gt;
    parser&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;reinitialize&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;options&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;parserMode&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    parser&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;socket &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; socket&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    socket&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;parser &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; parser&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;//called by node http module when headers are parsed&lt;/span&gt;
    parser&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;onIncoming&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        that&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;emit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;headers&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;data&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token comment&quot;&gt;//this is one of ways to get &apos;end&apos; event&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;end&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            that&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;emit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;end&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token comment&quot;&gt;//free parser&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;freeParser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;parser&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    socket&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;close&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        that&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;emit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;socket.close&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;_write&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;chunk&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; encoding&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; callback&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        streamChunks&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            chunk&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; chunk&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            encoding&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; encoding
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;//pass data to parser&lt;/span&gt;
        parser&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;execute&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;chunk&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; chunk&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        callback &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;callback&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;//write data currently in buffer to other stream&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;writeCurrentChunks&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;writableStream&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        streamChunks&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;chunkObj&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            writableStream&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;chunkObj&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;chunk&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; chunkObj&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;encoding&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
util&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;inherits&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;HttpParsingStream&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Writable&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;HttpParsingStream&lt;/code&gt; accepts 2 options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;socket&lt;/code&gt; for underlying request and response&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;parserMode&lt;/code&gt; used to properly initialise node.js http parser&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here’s how we create objects with it:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;
HttpParsingStream&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;createForRequest&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;socket&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;HttpParsingStream&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        socket&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; socket&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        parserMode&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; HTTPParser&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;REQUEST&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;//used only for debugging&lt;/span&gt;
        name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;request&apos;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
HttpParsingStream&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;createForResponse&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;socket&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;HttpParsingStream&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        socket&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; socket&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        parserMode&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; HTTPParser&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;RESPONSE&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;//used only for debugging&lt;/span&gt;
        name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;response&apos;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Because &lt;code class=&quot;language-text&quot;&gt;HttpParsingStream&lt;/code&gt; is a &lt;code class=&quot;language-text&quot;&gt;Writable&lt;/code&gt; stream we can
use it as:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;socketRequest&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;HttpParsingStream&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createForRequest&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;socketRequest&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

serverSocket&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;HttpParsingStream&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createForResponse&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;serverSocket&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;and let node.js code handle buffering, pausing and resuming.
There is also one additional function used to clean up and return
a parser instance back to pool - it’s a copy paste from node.js
http module source code:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;freeParser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;parser&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; req&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;parser&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        parser&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_headers &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        parser&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;onIncoming &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;parser&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;socket&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            parser&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;socket&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;onend &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            parser&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;socket&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ondata &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            parser&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;socket&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;parser &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        parser&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;socket &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        parser&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;incoming &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        parsers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;free&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;parser&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        parser &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;req&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        req&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;parser &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;why-create-yet-another-http-proxy-implementation&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#why-create-yet-another-http-proxy-implementation&quot; aria-label=&quot;why create yet another http proxy implementation permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Why create yet another http proxy implementation?&lt;/h2&gt;
&lt;p&gt;proxy-mirror a simple http debugging tool that I wrote
so far relies on an excellent http-proxy module.
However because http-proxy was created to be used mostly as a
reverse proxy to route http traffic to different http servers
it does not provide a way to access raw tcp data. With the above
code I now have an easy way to access the data - so I can
display it in a byte level manner - a feature of Fiddler that
I find handy from time to time.&lt;/p&gt;
&lt;p&gt;Moreover the target server will receive a request from client in an unchanged
form. The same applies for response received by client.
This is extremely important when resolving issues related
to improper implementations of HTTP protocol.&lt;/p&gt;
&lt;p&gt;I haven’t yet checked how the above code handles WebSocket
connections - I’ll explore that in a next post. For the referece
you can find full code in this &lt;a href=&quot;https://gist.github.com/9726643&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;gist&lt;/a&gt;.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Curl and a missing slash]]></title><description><![CDATA[will result in following output when the proxy is Fiddler: while
a simple implementation relaying on node.js core http module and http-proxy module outputs this: Meanwhile without the proxy parameter the actual response is: but
when the proxy setting is present: As
you may have noticed the difference in requests (apart…]]></description><link>undefined/curl-and-missing-slash/</link><guid isPermaLink="false">undefined/curl-and-missing-slash/</guid><pubDate>Mon, 24 Feb 2014 21:55:00 GMT</pubDate><content:encoded>&lt;div class=&quot;css-full-post-content js-full-post-content&quot;&gt;
  While I was playing around with &lt;a href=&quot;https://github.com/miensol/proxy-mirror&quot; target=&quot;_blank&quot;&gt;proxy-mirror&lt;/a&gt; I noticed an interesting behaviour when testing the proxy with &lt;a href=&quot;http://en.wikipedia.org/wiki/CURL&quot; target=&quot;_blank&quot;&gt;curl&lt;/a&gt;. The
  following command:
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;curl http://wp.pl --proxy http://localhost:8888/&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;will result in following output when the proxy is Fiddler:&lt;/p&gt;
&lt;pre style=&quot;font-size: 12px&quot;&gt;[Fiddler] Response Header parsing failed.
Response Data:
&amp;lt;plaintext&amp;gt;
43 6F 6E 6E 65 63 74 69 6F 6E 3A 20 63 6C 6F 73 65 0D 0A 0D 0A 3C 48 54  Connection: close....&amp;lt;HT
4D 4C 3E 3C 48 45 41 44 3E 3C 54 49 54 4C 45 3E 34 30 30 20 42 61 64 20  ML&amp;gt;&amp;lt;HEAD&amp;gt;&amp;lt;TITLE&amp;gt;400 Bad
52 65 71 75 65 73 74 3C 2F 54 49 54 4C 45 3E 3C 2F 48 45 41 44 3E 0A 3C  Request&amp;lt;/TITLE&amp;gt;&amp;lt;/HEAD&amp;gt;.&amp;lt;
42 4F 44 59 3E 3C 48 32 3E 34 30 30 20 42 61 64 20 52 65 71 75 65 73 74  BODY&amp;gt;&amp;lt;H2&amp;gt;400 Bad Request
3C 2F 48 32 3E 0A 59 6F 75 72 20 72 65 71 75 65 73 74 20 68 61 73 20 62  &amp;lt;/H2&amp;gt;.Your request has b
61 64 20 73 79 6E 74 61 78 20 6F 72 20 69 73 20 69 6E 68 65 72 65 6E 74  ad syntax or is inherent
6C 79 20 69 6D 70 6F 73 73 69 62 6C 65 20 74 6F 20 73 61 74 69 73 66 79  ly impossible to satisfy
2E 0A 3C 48 52 3E 0A 3C 41 44 44 52 45 53 53 3E 3C 41 20 48 52 45 46 3D  ..&amp;lt;HR&amp;gt;.&amp;lt;ADDRESS&amp;gt;&amp;lt;A HREF=
22 68 74 74 70 3A 2F 2F 77 77 77 2E 77 70 2E 70 6C 2F 22 3E 61 72 69 73  &quot;http://www.wp.pl/&quot;&amp;gt;aris
3C 2F 41 3E 3C 2F 41 44 44 52 45 53 53 3E 0A 3C 2F 42 4F 44 59 3E 3C 2F  &amp;lt;/A&amp;gt;&amp;lt;/ADDRESS&amp;gt;.&amp;lt;/BODY&amp;gt;&amp;lt;/
48 54 4D 4C 3E 0A                                                        HTML&amp;gt;.
&lt;/pre&gt;
&lt;p&gt;while
a simple implementation relaying on node.js core http module and http-proxy module outputs this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;An error has occurred: {&amp;quot;bytesParsed&amp;quot;:0,&amp;quot;code&amp;quot;:&amp;quot;HPE_INVALID_CONSTANT&amp;quot;}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Meanwhile without the proxy parameter the actual response is:&lt;/p&gt;
&lt;pre&gt;
HTTP/1.1 301 Moved Permanently
Server: aris
Location: http://www.wp.pl
Content-type: text/html
Content-Length: 0
Connection: close
&lt;/pre&gt;
&lt;h2&gt;Curl forgiving behaviour&lt;/h2&gt;As it turns out the actual outgoing HTTP request is different depending on the presence of &lt;span style=&quot;font-family: Courier New;&quot;&gt;–-proxy&lt;/span&gt; parameter. Without it the target server receives and responds with:
&lt;pre&gt;
GET / HTTP/1.1
User-Agent: curl/7.26.0
Host: wp.pl
Accept: */*

HTTP/1.1 301 Moved Permanently
Server: aris
Location: http://www.wp.pl
Content-type: text/html
Content-Length: 0
Connection: close
&lt;/pre&gt;
&lt;p&gt;but
when the proxy setting is present:&lt;/p&gt;
&lt;pre&gt;
GET http://wp.pl HTTP/1.1
User-Agent: curl/7.26.0
Host: wp.pl
Accept: */*
Proxy-Connection: Keep-Alive

UNKNOWN 400 Bad Request
Server: aris
Content-Type: text/html
Date: Sun, 23 Feb 2014 16:01:36 GMT
Last-Modified: Sun, 23 Feb 2014 16:01:36 GMT
Accept-Ranges: bytes
Connection: close

&amp;lt;HTML&amp;gt;&amp;lt;HEAD&amp;gt;&amp;lt;TITLE&amp;gt;400 Bad Request&amp;lt;/TITLE&amp;gt;&amp;lt;/HEAD&amp;gt;
&amp;lt;BODY&amp;gt;&amp;lt;H2&amp;gt;400 Bad Request&amp;lt;/H2&amp;gt;
Your request has bad syntax or is inherently impossible to satisfy.
&amp;lt;HR&amp;gt;
&amp;lt;ADDRESS&amp;gt;&amp;lt;A HREF=&quot;http://www.wp.pl/&quot;&amp;gt;aris&amp;lt;/A&amp;gt;&amp;lt;/ADDRESS&amp;gt;
&amp;lt;/BODY&amp;gt;&amp;lt;/HTML&amp;gt;
&lt;/pre&gt;
&lt;p&gt;As
you may have noticed the difference in requests (apart from additional header) is in first line – where in the first case curl assumed we want to &lt;span style=&quot;font-family: Courier New;&quot;&gt;GET /&lt;/span&gt;. The former uses a relative URI while the later absolute.
Now if we change the command line just a little bit so that the address looks like &lt;a href=&quot;http://wp.pl/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;http://wp.pl/&lt;/a&gt; the server will receive request with correct absolute URI and will respond with 301.&lt;/p&gt;
  &lt;h2&gt;UNKNOWN Status Line&lt;/h2&gt;Careful readers may have already noticed the &lt;a href=&quot;http://www.w3.org/Protocols/rfc2616/rfc2616-sec6.html#sec6.1&quot; target=&quot;_blank&quot;&gt;Status Line&lt;/a&gt; of response returned by server is malformed. According to the spec it should have following form:
&lt;pre&gt;Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF
&lt;/pre&gt;
&lt;p&gt;That’s the reason why Fiddler warns users about protocol violation and the reason of error inside node.js proxy.&lt;/p&gt;
  &lt;h2&gt;A less intrusive proxy&lt;/h2&gt;An example described above leads to other questions about behaviour of http proxy especially if we think about implementing HTTP debugging tool like &lt;a href=&quot;https://github.com/miensol/proxy-mirror&quot; target=&quot;_blank&quot;&gt;proxy-mirror&lt;/a&gt;. It’s only a guess
  but I suspect that there are other subtle differences between requests sent by client and those received by target server when the proxy is implemented using http-proxy module or core http module. I am aware of at least one such case where &lt;a href=&quot;https://groups.google.com/forum/#!topic/nodejs/1aug0Jq8rYY&quot;
  target=&quot;_blank&quot;&gt;HTTP Headers are lowercased&lt;/a&gt;. If I’m right a debugging tool relaying on them would make it really hard to spot certain problems – like protocol violations on both client and server side.
&lt;p&gt;In my next blog post I’ll describe how to built even less intrusive proxy without building the http parser by hand.&lt;/p&gt;
&lt;/div&gt;</content:encoded></item><item><title><![CDATA[An HTTPS system proxy with node]]></title><description><![CDATA[openssl rsa -passin pass:x -in proxy-mirror.pass.key -out proxy-mirror.key
rm proxy-mirror.pass.key
echo “Generated proxy-mirror.key” openssl req -new -batch -key proxy-mirror.key -out proxy-mirror.csr -subj /CN=proxy-mirror/emailAddress=piotr.mionskowski@gmail.com/OU=proxy-mirror/C=PL/O=proxy-mirror
echo “Generated…]]></description><link>undefined/an-https-system-proxy-with-node/</link><guid isPermaLink="false">undefined/an-https-system-proxy-with-node/</guid><pubDate>Fri, 03 Jan 2014 06:34:00 GMT</pubDate><content:encoded>&lt;p&gt;Creating a simple http proxy in node.js is super easy thanks to an excellent module – &lt;a href=&quot;https://github.com/nodejitsu/node-http-proxy&quot; target=&quot;_blank&quot;&gt;http-proxy&lt;/a&gt;.
  With only the following code you’ll have a proxy that can be used as system or
  browser level proxy:&lt;/p&gt;
```
var httpProxy = require(&apos;http-proxy&apos;);
var proxyServer = httpProxy.createServer(function (req,res,proxy) {
  var hostNameHeader = req.headers.host,
  hostAndPort = hostNameHeader.split(&apos;:&apos;),
  host = hostAndPort[0],
  port = parseInt(hostAndPort[1]) || 80;
  proxy.proxyRequest(req,res, {
    host: host,
    port: port
  });
});
proxyServer.listen(8888);
```
&lt;h2&gt;Adding support for HTTPS&lt;/h2&gt;
&lt;p&gt;The first thing we will need is a certificate that will be used by &lt;a href=&quot;http://en.wikipedia.org/wiki/Transport_Layer_Security&quot; target=&quot;_blank&quot;&gt;TLS&lt;/a&gt; implementation for encryption. A server has access to certificate private and public key thus it is
  able to get a clear text from a message encrypted with public key. It’s a common knowledge that asymmetric encryption is more expensive in terms of CPU cycles than its symmetric counterpart. That’s way when using HTTPS connection asymmetric encryption
  is only used during initial handshake to exchange a session key in a secure manner between client and server. This session key is then used by both client and server for traffic encryption using symmetric algorithm.&lt;/p&gt;
&lt;p&gt;Naturally to get or rather to buy a proper certificate one would have to be verified by a valid certification authority. Fortunately for the sake of a demo we can generate a self signed certificate. That’s really easy, a nice description is available
  on &lt;a href=&quot;https://devcenter.heroku.com/articles/ssl-certificate-self&quot; target=&quot;_blank&quot;&gt;heroku help pages&lt;/a&gt;:&lt;/p&gt;
```
openssl genrsa -des3 -passout pass:x -out proxy-mirror.pass.key 2048
echo &quot;Generated proxy-mirror.pass.key&quot;
&lt;p&gt;openssl rsa -passin pass:x -in proxy-mirror.pass.key -out proxy-mirror.key
rm proxy-mirror.pass.key
echo “Generated proxy-mirror.key”&lt;/p&gt;
&lt;p&gt;openssl req -new -batch -key proxy-mirror.key -out proxy-mirror.csr -subj /CN=proxy-mirror/emailAddress=&lt;a href=&quot;mailto:piotr.mionskowski@gmail.com&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;piotr.mionskowski@gmail.com&lt;/a&gt;/OU=proxy-mirror/C=PL/O=proxy-mirror
echo “Generated proxy-mirror.csr”&lt;/p&gt;
&lt;p&gt;openssl x509 -req -days 365 -in proxy-mirror.csr -signkey proxy-mirror.key -out proxy-mirror.crt
echo “Generated proxy-mirror.crt”&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;
&amp;lt;h3&amp;gt;http-proxy support for https&amp;lt;/h3&amp;gt;
&amp;lt;p&amp;gt;http-proxy module supports various https configuration for example passing traffic from https to http and vice versa. Unfortunately I couldn’t find a way to get it working without preconfiguring target host and port – which was a problem while I was implementing
  &amp;lt;a
  href=&amp;quot;https://github.com/miensol/proxy-mirror&amp;quot; target=&amp;quot;_blank&amp;quot;&amp;gt;proxy-mirror&amp;lt;/a&amp;gt;. Here is what &amp;lt;em&amp;gt;curl&amp;lt;/em&amp;gt;will print out when trying to use such proxy:&amp;lt;/p&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;curl -vk —proxy &lt;a href=&quot;https://localhost:8888/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;https://localhost:8888/&lt;/a&gt; &lt;a href=&quot;https://pl-pl.facebook.com/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;https://pl-pl.facebook.com/&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;timeout on name lookup is not supported&lt;/li&gt;
&lt;li&gt;About to connect() to proxy localhost port 8888 (#0)&lt;/li&gt;
&lt;li&gt;Trying 127.0.0.1…&lt;/li&gt;
&lt;li&gt;connected&lt;/li&gt;
&lt;li&gt;Connected to localhost (127.0.0.1) port 8888 (#0)&lt;/li&gt;
&lt;li&gt;Establish HTTP proxy tunnel to pl-pl.facebook.com:443&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&gt; CONNECT pl-pl.facebook.com:443 HTTP/1.1
&gt; Host: pl-pl.facebook.com:443
&gt; User-Agent: curl/7.26.0
&gt; Proxy-Connection: Keep-Alive
&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;
&amp;lt;p&amp;gt;I suspect the problem is inherently related to the way http-proxy uses nodejs core http(s) modules – I might be wrong here though. The workaround I’ve used in &amp;lt;a href=&amp;quot;https://github.com/miensol/proxy-mirror&amp;quot; target=&amp;quot;_blank&amp;quot;&amp;gt;proxy-mirror&amp;lt;/a&amp;gt; was to listen
  to &amp;lt;em&amp;gt;&amp;lt;a href=&amp;quot;http://nodejs.org/api/http.html#http_event_connect&amp;quot; target=&amp;quot;_blank&amp;quot;&amp;gt;CONNECT&amp;lt;/a&amp;gt;    &amp;lt;/em&amp;gt;event on http server, establish socket connection to a fake https server listening on different port. When the https connection is established the
  fake https server handler proxies requests further. The advantage of this approach is that we can use the same proxy address for both http and https. Here is the code:&amp;lt;/p&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;var httpProxy = require(‘http-proxy’),
fs = require(‘fs’),
https = require(‘https’),
net = require(‘net’),
httpsOptions = {
key: fs.readFileSync(‘proxy-mirror.key’, ‘utf8’),
cert: fs.readFileSync(‘proxy-mirror.crt’, ‘utf8’)
};&lt;/p&gt;
&lt;p&gt;var proxyServer = httpProxy.createServer(function (req, res, proxy) {
console.log(‘will proxy request’, req.url);
var hostNameHeader = req.headers.host,
hostAndPort = hostNameHeader.split(’:’),
host = hostAndPort[0],
port = parseInt(hostAndPort[1]) || 80;
proxy.proxyRequest(req, res, {
host: host,
port: port
});
});&lt;/p&gt;
&lt;p&gt;proxyServer.addListener(‘connect’, function (request, socketRequest, bodyhead) {
var srvSocket = net.connect(8889, ‘localhost’, function () {
socketRequest.write(‘HTTP/1.1 200 Connection Established\r\n\r\n’);
srvSocket.write(bodyhead);
srvSocket.pipe(socketRequest);
socketRequest.pipe(srvSocket);
});
});&lt;/p&gt;
&lt;p&gt;var fakeHttps = https.createServer(httpsOptions, function (req, res) {
var hostNameHeader = req.headers.host,
hostAndPort = hostNameHeader.split(’:’),
host = hostAndPort[0],
port = parseInt(hostAndPort[1]) || 443;&lt;/p&gt;
&lt;p&gt;proxyServer.proxy.proxyRequest(req, res, {
host: host,
port: port,
changeOrigin: true,
target: {
https: true
}
});
});&lt;/p&gt;
&lt;p&gt;proxyServer.listen(8888);
fakeHttps.listen(8889);&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;
&amp;lt;h2&amp;gt;HTML5 WebSocket support&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;The above code has still problems handling &amp;lt;a href=&amp;quot;http://en.wikipedia.org/wiki/WebSocket&amp;quot; target=&amp;quot;_blank&amp;quot;&amp;gt;WebSockets&amp;lt;/a&amp;gt;. This is because browsers, according to the spec, change the way they establish initial connection when they detect that they are
  behind an http proxy. As you can read on &amp;lt;a href=&amp;quot;http://en.wikipedia.org/wiki/WebSocket#Proxy_traversal&amp;quot; target=&amp;quot;_blank&amp;quot;&amp;gt;wikipedia&amp;lt;/a&amp;gt; more existing http proxy implementation suffer from this.&amp;amp;#160; I still haven’t figured out how to handle this scenario
  elegantly with http-proxy and node.js, when I do I will post my findings here.&amp;lt;/p&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content:encoded></item><item><title><![CDATA[Building an HTTP sniffer with node.js]]></title><link>undefined/building-http-sniffer-with-nodejs/</link><guid isPermaLink="false">undefined/building-http-sniffer-with-nodejs/</guid><pubDate>Wed, 01 Jan 2014 22:14:00 GMT</pubDate><content:encoded>&lt;p&gt;Whether to inspect a server response, optimize network usage or just to fiddle with new REST API it almost always make sense to use an application that can display http requests and responses for investigation. On Windows there is the great &lt;a href=&quot;http://fiddler2.com/&quot; target=&quot;_blank&quot;&gt;Fiddler&lt;/a&gt;. While it’s possible to use Fiddler on other platforms using virtualization software I think it’s an overkill. Fortunately there are alternatives. &lt;a href=&quot;http://www.charlesproxy.com/&quot; target=&quot;_blank&quot;&gt;Charles&lt;/a&gt; looks like
  the most advanced one offering most if not all features available in Fiddler. There is also a little less popular &lt;a href=&quot;http://www.tuffcode.com/&quot; target=&quot;_blank&quot;&gt;HTTP Scoop&lt;/a&gt;. Both Charles and HTTP Scoop aren’t free but in my opinion they are worth
  the price especially if used often. Command line lovers might find &lt;a href=&quot;http://mitmproxy.org/&quot; target=&quot;_blank&quot;&gt;mitmproxy&lt;/a&gt; suit their needs. If you only need basic features &lt;a href=&quot;https://ngrok.com/&quot; target=&quot;_blank&quot;&gt;ngrok&lt;/a&gt; might serve you well.
  To dive a bit deeper and see http traffic on a tcp level &lt;a href=&quot;http://www.wireshark.org/&quot; target=&quot;_blank&quot;&gt;WireShark&lt;/a&gt; is indispensable.&lt;/p&gt;
&lt;p&gt;As you can see there are plenty of tools available to help understand what is happening on http level. As I was learning about http caching a question popped to my head. How hard would it be to actually build a simple http sniffer?&lt;/p&gt;
&lt;h2&gt;proxy-mirror – a simple http inspector&lt;/h2&gt;
&lt;p&gt;As it turned out it’s actually not that hard to built one thus &lt;a href=&quot;https://github.com/miensol/proxy-mirror&quot; target=&quot;_blank&quot;&gt;proxy-mirror&lt;/a&gt; came to be. Of course this is a very simplistic http sniffer – nowhere near to tools I mentioned above both
  in terms of features and reliability – but it works (at least in most scenarios :-)). It’s open source and I learned couple of new things about HTTP while implementing it – more on that in future posts. Here are some screen shoots of the the tool:
  &lt;img src=&quot;https://raw.github.com/miensol/proxy-mirror/master/misc/screenshot-landscape.png&quot; width=&quot;603&quot; height=&quot;367&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;
  &lt;img src=&quot;https://raw.github.com/miensol/proxy-mirror/master/misc/screenshot-portrait.png&quot; width=&quot;609&quot; height=&quot;652&quot;&gt;
&lt;/p&gt;
&lt;p&gt;As you might have guessed from screenshots proxy-mirror is a web application. Right now it’s not very easy to try it out – the instructions are in the &lt;a href=&quot;https://github.com/miensol/proxy-mirror&quot; target=&quot;_blank&quot;&gt;Readme&lt;/a&gt; – I’ll try to fix it soon.&lt;/p&gt;
&lt;h2&gt;How it works&lt;/h2&gt;
&lt;p&gt;I wanted to run proxy-mirror on many platforms and rely on a foundation that has both great support for http and building web applications. I picked node.js over java or ruby mainly because I wanted to sharpen my skills in it.&lt;/p&gt;
&lt;p&gt;You can think of proxy-mirror as 2 logical components. The first is a regular http proxy that you can use by configuring your browser or system. I didn’t want to focus on building that first so I utilized a great node module call &lt;a href=&quot;https://github.com/nodejitsu/node-http-proxy&quot; target=&quot;_blank&quot;&gt;http-proxy&lt;/a&gt;. With it’s helped you can have a system wide proxy in couple of minutes. The http proxy component emits events whenever a request or response goes through it. Those events are consumed by the second logical component –
  a web application built with &lt;a href=&quot;http://expressjs.com/?utm_source=buffer&amp;amp;utm_campaign=Buffer&amp;amp;utm_content=buffer73c90&amp;amp;utm_medium=google&quot; target=&quot;_blank&quot;&gt;express.js&lt;/a&gt;. The information about http traffic received from events is then pushed
  to browser part through &lt;a href=&quot;http://socket.io/&quot; target=&quot;_blank&quot;&gt;socket.io&lt;/a&gt; where a simple SPA built with &lt;a href=&quot;http://miensol.blogspot.com/2013/09/angularjs-my-new-superhero-tool.html&quot; target=&quot;_blank&quot;&gt;my beloved&lt;/a&gt;&amp;nbsp;&lt;a href=&quot;http://angularjs.org/&quot; target=&quot;_blank&quot;&gt;AngularJS&lt;/a&gt; displays information about them.&lt;/p&gt;
&lt;h2&gt;Features&lt;/h2&gt;
&lt;p&gt;Right now proxy-mirror has only couple of features:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;http and https support – although the latter one requires additional setup&lt;/li&gt;
  &lt;li&gt;simple session list – a &lt;a href=&quot;http://angular-ui.github.io/ng-grid/&quot; target=&quot;_blank&quot;&gt;grid&lt;/a&gt; with list of request/response pairs that you can inspect&lt;/li&gt;
  &lt;li&gt;a detailed view – both for request and response that can display headers, message body and a preview right in the browser&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Although it still is a very simple (and buggy) application I actually found that it has most of features I frequently use – probably except for filtering. Maybe someday it will become a reasonable alternative for Charles - at least for me.&lt;/p&gt;
&lt;p&gt;I think building an http sniffer is a great exercise in the process of learning how http(s) works. I guess the famous saying about journey being more more important than the destination fits nice here.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Combine Express.js and ASP.NET Web API]]></title><description><![CDATA[Navigating to http://localhost:3000/hello will give you response from Express: When you go to http://localhost:3000/webapi/values you’ll get a standard ValuesController response: Note that both requests are logged in console using connect.logger middleware:]]></description><link>undefined/combine-expressjs-and-aspnet-web-api/</link><guid isPermaLink="false">undefined/combine-expressjs-and-aspnet-web-api/</guid><pubDate>Sun, 03 Nov 2013 12:00:00 GMT</pubDate><content:encoded>&lt;div class=&quot;css-full-post-content js-full-post-content&quot;&gt;
  I’m really excited about the &lt;a href=&quot;http://owin.org/&quot; target=&quot;_blank&quot;&gt;OWIN&lt;/a&gt; initiative. This “standard” enables countless new ways of combining existing http web stacks with .net – a thing that up until recently was either impossible or not feasible.
  It gets even more positive knowing that Microsoft supports the case actively.
  &lt;h2&gt;OWIN - why you should care?&lt;/h2&gt;
  &lt;p&gt;Open Web Interface for .NET aims to define a standard interface between web servers and web applications. Adhering to this interface will allow decoupling of server implementations from web frameworks. The idea isn’t something novel and other platforms
    benefited from it immensely. In Ruby we have pretty mature &lt;a href=&quot;http://rack.github.io/&quot; target=&quot;_blank&quot;&gt;Rack&lt;/a&gt; which allows hosting &lt;a href=&quot;http://rubyonrails.org/&quot; target=&quot;_blank&quot;&gt;Rails&lt;/a&gt;, &lt;a href=&quot;http://www.sinatrarb.com/&quot; target=&quot;_blank&quot;&gt;Sinatra&lt;/a&gt; or
    any other rack compatible application on a web server of your &lt;a href=&quot;https://www.ruby-toolbox.com/categories/web_servers&quot; target=&quot;_blank&quot;&gt;choice&lt;/a&gt;. In Node.js world there is &lt;a href=&quot;http://www.senchalabs.org/connect/&quot; target=&quot;_blank&quot;&gt;Connect&lt;/a&gt; middleware
    with frameworks like &lt;a href=&quot;http://expressjs.com/&quot; target=&quot;_blank&quot;&gt;Express&lt;/a&gt; and &lt;a href=&quot;https://github.com/mauricemach/zappa&quot; target=&quot;_blank&quot;&gt;Zappa&lt;/a&gt; built on top of it. To be fair Connect is not &lt;a href=&quot;http://stackoverflow.com/questions/5284340/what-is-node-js-connect-express-and-middleware&quot;
    target=&quot;_blank&quot;&gt;exactly the same thing as Rack&lt;/a&gt; but the analogy serves well to understand underlying ideas.&lt;/p&gt;
  &lt;p&gt;Having a common middleware and frameworks built on top of it not only allows you to swap your web server at whim. It also means that you’re now able to combine many application into one easily even if they are implemented in different frameworks. It
    took me some time to realize how powerful concept it is until I built a demo for &lt;a href=&quot;http://github.com/miensol/conf2013&quot; target=&quot;_blank&quot;&gt;a conference presentation&lt;/a&gt;. I wanted to have single web server running in background so that I can easily
    switch between pages built with Angular, Backbone and Knockout. I also didn’t want to throw out separate templates scaffolded with &lt;a href=&quot;http://yeoman.io/&quot; target=&quot;_blank&quot;&gt;Yeoman&lt;/a&gt; and have a shared REST-like api built with Express. How surprised
    I was when the only thing I needed to do was to call equivalent of:
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;connect.use(angularApp);
connect.use(knockoutApp);
connect.use(backboneApp);&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/p&gt;
  &lt;h2&gt;OWIN opens a new world for .NET web stacks&lt;/h2&gt;This all may sound blurry for a .NET newbie or maybe even to experienced developer so I’ll give some examples of what is or will be possible to do in a near future.
  &lt;ul&gt;
    &lt;li&gt;&lt;strong&gt;IIS as option not requirement&lt;/strong&gt; – having a way to add a full fledged web interface for a windows service was not an easy thing to do. If only you could you use Asp.Net MVC things would be so much easier. Guess what, when Asp.Net MVC
      will support OWIN and I’m positive it someday will, this will be a no brainer.&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;Combine Nancy, FubuMVC, pick a name&lt;/strong&gt; – maybe you would like to use some existing component and not have to rewrite it to match you stack. Or maybe you work on a really big project and some teams prefer one framework over the other.
      You are right, this already is possible.&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;Integration tests&lt;/strong&gt; – say you would like to execute end to end tests over your web application. Right know you’ll either have to deploy your asp.net mvc app to IIS or IIS Express. This means spinning up separate processes even if you
      would like to run a single test on you development machine. You may be lucky and be using asp.net web api and be able to use &lt;a href=&quot;http://msdn.microsoft.com/pl-pl/library/system.web.http.selfhost.httpselfhostserver(v=vs.108).aspx&quot; target=&quot;_blank&quot;&gt;HttpSelfHostServer&lt;/a&gt; but
      then again you’re limited only to this stack. With OWIN it already is possible to use a lightweight &lt;a href=&quot;https://github.com/Bobris/Nowin&quot; target=&quot;_blank&quot;&gt;Nowin&lt;/a&gt; or &lt;a href=&quot;http://katanaproject.codeplex.com/&quot; target=&quot;_blank&quot;&gt;Katana&lt;/a&gt; to run
      any compatible application inside your tests.&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;Faster Tests&lt;/strong&gt; – is hosting a http server inside you tests too expensive? With OWIN you might actually be able to run &lt;a href=&quot;http://dhickey.ie/post/2013/08/27/Introducing-OwinTesting.aspx&quot; target=&quot;_blank&quot;&gt;tests entirely in memory&lt;/a&gt; with
      no network involved whatsoever.&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;Cross cutting concerns&lt;/strong&gt; – maybe you need to apply the same authentication mechanism to couple of separate applications. Yes you’re right implementing it as HttpModule might work, but what about this one that you have to support which
      is based on &lt;a href=&quot;http://nancyfx.org/&quot; target=&quot;_blank&quot;&gt;Nancy&lt;/a&gt;. Nancy already supports OWIN so you’re good to go.&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;Combining Express.js and Asp.Net Web Api&lt;/strong&gt; – so you’re building a web app using Express.js but you’ve found that it would be nice to reuse some part of the existing code that is built in .NET. With the excellent &lt;a href=&quot;http://tjanczuk.github.io/edge/&quot;
      target=&quot;_blank&quot;&gt;edge.js&lt;/a&gt; and OWIN enabled middleware built on top of it called &lt;a href=&quot;https://github.com/bbaia/connect-owin&quot; target=&quot;_blank&quot;&gt;connect-owin&lt;/a&gt; you’re now allowed to this.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h2&gt;One app using both Express.js and ASP.NET Web Api&lt;/h2&gt;The last example of OWIN usage seemed like the coolest to me so I wanted to try if it’s really doable at the moment. This wasn’t as easy as one could wish but bare in mind that the OWIN initiative is just starting getting momentum and we’re really on
  a bleeding edge. The &lt;a href=&quot;https://github.com/miensol/connect-webapi-samples&quot; target=&quot;_blank&quot;&gt;connect-webapi-samples&lt;/a&gt; repo contains a sample of single web app where some requests are served by express.js while others using ASP.NET Web Api. You can
  start the server with:
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;msbuild ./Connect.WebApi.sln
node ./index.js&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Navigating to &lt;a href=&quot;http://localhost:3000/hello&quot;&gt;&lt;a href=&quot;http://localhost:3000/hello&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;http://localhost:3000/hello&lt;/a&gt;&lt;/a&gt; will give you response from Express:&lt;/p&gt;
&lt;a href=&quot;http://lh4.ggpht.com/-jUULKIlKPak/UnY0rAwhXlI/AAAAAAAABf4/P0sElEwX-uU/s1600-h/image%25255B8%25255D.png&quot;&gt;
    &lt;img alt=&quot;image&quot; border=&quot;0&quot; height=&quot;154&quot; src=&quot;http://lh5.ggpht.com/-dMKd-Kuu8-c/UnY0rjiQa2I/AAAAAAAABgA/Qk30CJz0lRE/image_thumb%25255B4%25255D.png?imgmax=800&quot; style=&quot;background-image: none; border-bottom-width: 0px; border-left-width: 0px; border-right-width: 0px; border-top-width: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;&quot; title=&quot;image&quot; width=&quot;601&quot;&gt;
  &lt;/a&gt;
&lt;p&gt;When you go to &lt;a href=&quot;http://localhost:3000/webapi/values&quot;&gt;&lt;a href=&quot;http://localhost:3000/webapi/values&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;http://localhost:3000/webapi/values&lt;/a&gt;&lt;/a&gt; you’ll get a standard &lt;i&gt;ValuesController&lt;/i&gt; response:&lt;/p&gt;
&lt;a href=&quot;http://lh5.ggpht.com/-lpDHvGGL6O4/UnY0sJlyz4I/AAAAAAAABgE/RNt-5mImYzs/s1600-h/image%25255B10%25255D.png&quot;&gt;
    &lt;img alt=&quot;image&quot; border=&quot;0&quot; height=&quot;201&quot; src=&quot;http://lh6.ggpht.com/-Fi3AA5tgaNI/UnY0tBvfyxI/AAAAAAAABgQ/d4KN1caqBDs/image_thumb%25255B6%25255D.png?imgmax=800&quot; style=&quot;background-image: none; border-bottom-width: 0px; border-left-width: 0px; border-right-width: 0px; border-top-width: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;&quot; title=&quot;image&quot; width=&quot;596&quot;&gt;
  &lt;/a&gt;
&lt;p&gt;Note that both requests are logged in console using &lt;em&gt;connect.logger&lt;/em&gt; middleware:
&lt;a href=&quot;http://lh5.ggpht.com/-izO1Mw9h9KM/UnY0tlpMA1I/AAAAAAAABgU/P-8I1auBGGU/s1600-h/image%25255B16%25255D.png&quot;&gt;
&lt;img alt=&quot;image&quot; border=&quot;0&quot; height=&quot;33&quot; src=&quot;http://lh4.ggpht.com/-S18Xwf8AVr0/UnY0t8N6U-I/AAAAAAAABgc/XYCYSirgo88/image_thumb%25255B10%25255D.png?imgmax=800&quot; style=&quot;background-image: none; border-bottom-width: 0px; border-left-width: 0px; border-right-width: 0px; border-top-width: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;&quot; title=&quot;image&quot; width=&quot;602&quot;&gt;
&lt;/a&gt;&lt;/p&gt;
  &lt;p&gt;I was thinking about a case where this combination could become handy. In a project I’m currently involved in we’re using Highcharts to present beautiful charts to clients. Unfortunately some of them still use ancient browsers like IE7 which does not
    handle many Highcharts displayed on one page – or rather dies trying to render them. For those browsers we actually produce similar chart images on server. This however requires a lot of boring code to convert from Higchart chart configuration to
    the 3rd party library format we use for rasterizing.&lt;/p&gt;
  &lt;p&gt;What we could do very easily with OWIN is to keep a .NET component that generates a complete Highchart configuration and add a very thin “middleware” layer that would take a real configuration pass it into &lt;a href=&quot;http://phantomjs.org/&quot; target=&quot;_blank&quot;&gt;Phantomjs&lt;/a&gt; and
    get back an image that would look exactly the same as real chart. I’m pretty sure it would be much more robust solution than our current approach.&lt;/p&gt;
&lt;/div&gt;</content:encoded></item><item><title><![CDATA[Backbone – when used properly…]]></title><link>undefined/backbone-when-used-properly/</link><guid isPermaLink="false">undefined/backbone-when-used-properly/</guid><pubDate>Sun, 27 Oct 2013 14:27:00 GMT</pubDate><content:encoded>  &lt;p&gt;...&lt;b&gt;it keeps one’s head out of one’s butt. &lt;/b&gt;
  &lt;/p&gt;
  &lt;p&gt;This little gem was the first JavaScript MVC like tool that caught my eye. It has a very &lt;a href=&quot;https://github.com/jashkenas/backbone/graphs/contributors&quot; target=&quot;_blank&quot;&gt;vibrant community&lt;/a&gt; and seems to have reached certain &lt;a href=&quot;https://github.com/jashkenas/backbone/issues&quot;
    target=&quot;_blank&quot;&gt;maturity level&lt;/a&gt;. More importantly it is so small library that everyone can grok its source code fully in couple of hours. And yet I haven’t actually used it in any project even thought I had couple of occasions.&lt;/p&gt;
  &lt;p&gt;I guess it was partially because I had read &lt;a href=&quot;http://www.thoughtworks.com/&quot; target=&quot;_blank&quot;&gt;ThoughtWorks&lt;/a&gt; technology radar &lt;a href=&quot;http://thoughtworks.fileburst.com/assets/technology-radar-october-2012.pdf&quot; target=&quot;_blank&quot;&gt;October 2012 edition&lt;/a&gt; where
    author’s claim that:&lt;/p&gt;
  &lt;blockquote&gt;
    &lt;p&gt;Backbone.js is a great example of an abstraction pushed too far (…) We find that it blurs the framework and model too much, forcing either bad architectural decisions or elaborate framework hackery in order to preserve sanity.&lt;/p&gt;
  &lt;/blockquote&gt;
  &lt;p&gt;Back then I had to make a quick decision which framework/library to use, if any, on a project that I started working on and the article steered my away from using Backbone.js. Just for the record the project was developed with &lt;a href=&quot;/2013/09/angularjs-my-new-superhero-tool.html&quot;&gt;Angular.js&lt;/a&gt;.&lt;/p&gt;
  &lt;h2&gt;Forming my own opinion&lt;/h2&gt;
  &lt;p&gt;It really bugged me why the technology radar authors stated such a harsh opinion about a tool that has caught some much attention. It seemed even more interesting because I haven’t found a follow up or a more elaborate and concrete comment about the
    decision to put Backbone.js on hold. I did however find some time to do a simple demo for a presentation I gave on our company internal conference.&lt;/p&gt;
  &lt;p&gt;The demo I built has only 2 pages. First one shows how to make a page more interactive with a filtered table and couple of elements that trigger the same behaviour. Second view was created just to see how easy it is to make use of html push state. The
    source code is available on &lt;a href=&quot;https://github.com/miensol/conf2013/tree/master/backbonejs&quot;&gt;github&lt;/a&gt;.&lt;/p&gt;
  &lt;p&gt;Due to its minimalistic nature it’s really easy to start working with Backbone. The documentation is easy to follow and if you don’t find enough explanation you can always dive into reading the source. The library let’s you choose how you would like
    to render you views. Out of the box it provides support for client side templates by leveraging &lt;a href=&quot;http://underscorejs.org/&quot;&gt;underscore.js&lt;/a&gt;.&lt;/p&gt;
  &lt;p&gt;Views are in fact the main force that drives code control. As there is no typical Controller I found it hard to decide where to put some of the initialization logic. For simple cases Router might be a good choice however as the application grows I pretty
    sure this approach would not be sufficient. It also means that you are now responsible for composition of smaller views into a complete page. I know this problem is solvable in many ways – &lt;a href=&quot;http://lostechies.com/derickbailey/&quot;&gt;Derick Bailey’s&lt;/a&gt; plugin
    &lt;a
    href=&quot;http://marionettejs.com/&quot;&gt;Marionette&lt;/a&gt;is an excellent addition that fills the gaps not provided by Backbone.&lt;/p&gt;
  &lt;p&gt;What I find most disturbing is the way we attach events to DOM elements by providing selectors. I use this approach on daily basis in a project solely based on jQuery but there are several shortcomings that in my opinion make it hard to apply to large
    applications. First of all it means that you typically would add artificial CSS classes to elements. This isn’t bad at first as long as you use those classes only for attaching events and not for providing ways to style your application. An important
    implication follows –it’s nearly impossible to have a UI designer to work on html and CSS parts without breaking application behaviour. You can however mitigate this by establishing some rules and naming conventions. For instance that all artificial
    classes used to attach events are prefixed with ‘js-‘ and shall not be used inside CSS files.&lt;/p&gt;
  &lt;h3&gt;Prefer composition over inheritance.&lt;/h3&gt;
  &lt;p&gt;The most important part of the presentation logic are models, view models or presentation models (depending on a pattern flavour you’re using). I think it should be the main place where your application behaviour is defined. Whenever a tool that I’m
    using is trying to push some structure over me in that single place I immediately get suspicious. Unfortunately it’s not different in Backbone. The way you define and implement your models inside Backbone app is through deriving from base class provided
    by the library. By doing this you gain many of the commonly required features of model object like filtering, validation and even associations. It speeds up a development a lot especially when you are in need of this commonly requested functionality
    like form editing in CRUD applications.&lt;/p&gt;
  &lt;p&gt;However, from my experience, preferring inheritance over composition hurts the most when used to built model part of an client side MVC. I guess this is true for me mainly because I often change the structure and the way different parts of model talk
    to each other way more often than views and controllers interactions. Having a predefined structure, imposed by framework, limits ways you can define the model and this sometimes leads to pain points that are hard to overcome. In general &lt;a href=&quot;http://stackoverflow.com/questions/49002/prefer-composition-over-inheritance&quot;
    target=&quot;_blank&quot;&gt;inheritance is much stronger form of coupling&lt;/a&gt; than composition even in a language as malleable as JavaScript so I think that my observations might be true for others too. As all ways this is a question of getting the right balance
    between having a lot of features ready and waiting for you and keeping you model as flexible as possible to survive the harsh realities of requirement changes.&lt;/p&gt;
  &lt;h3&gt;Don’t listen to me, try it yourself…&lt;/h3&gt;
  &lt;p&gt;I’ve pointed some of, in my opinion, weak points of Backbone. I realize that I might be wrong in some parts and have missed out some important aspects. The fact that the community behind the tool is so active and from what I see always willing to help
    some newbies can probably out weight cons I’ve listed. I think Backbone is a very effective tool for many programmers out there – it just does fully adhere to my rules.&lt;/p&gt;
  &lt;p&gt;However when choosing a framework to use on a project one should not be focussed on finding good or bad opinions on the web. I think its much better to spent a week or couple of days with &lt;strong&gt;the team&lt;/strong&gt; actually using the tool to build real
    features. This can give an immense feedback generated by the project team within actual context – one that you would never get reading reviews on the web.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[AngularJs modules to the rescue]]></title><description><![CDATA[We’ve
declared a new module called myApp and stated that it depends on another module called ngResource. In line 3 we are declaring a factory for itemsStorage that requires resource service
and inject it as a value of parameter. As you may suspect under the hood the dependency injection mechanism inspects parameter…]]></description><link>undefined/angularjs-modules-to-rescue/</link><guid isPermaLink="false">undefined/angularjs-modules-to-rescue/</guid><pubDate>Mon, 16 Sep 2013 17:44:00 GMT</pubDate><content:encoded>&lt;div class=&quot;css-full-post-content js-full-post-content&quot;&gt;
  Building large scale JavaScript application is a tough problem. The language nature is malleable and it does not have proper modules mechanism built in. Some argue that &lt;a href=&quot;http://lostechies.com/derickbailey/2012/06/04/anders-hejlsberg-is-right-you-cannot-maintain-large-programs-in-javascript/&quot;
  target=&quot;_blank&quot;&gt;you can’t really built and maintain&lt;/a&gt; big applications built with JavaScript.&amp;nbsp; Others say that the key in succeeding is to &lt;a href=&quot;http://addyosmani.com/largescalejavascript/&quot; target=&quot;_blank&quot;&gt;never built big applications&lt;/a&gt; but
  to approach things in a more clever way – by applying &lt;a href=&quot;http://en.wikipedia.org/wiki/Divide_and_conquer_algorithm&quot; target=&quot;_blank&quot;&gt;divide and conquer&lt;/a&gt; rule.
  &lt;h2&gt;Dividing code base&lt;/h2&gt;Due to lack of modules mechanism in &lt;a href=&quot;http://en.wikipedia.org/wiki/ECMAScript&quot; target=&quot;_blank&quot;&gt;ECMAScript&lt;/a&gt; 5th edition, which is the version most commonly available in browsers, there were couple of implementations created. &lt;a href=&quot;http://requirejs.org/&quot;
  target=&quot;_blank&quot;&gt;RequireJs&lt;/a&gt; and &lt;a href=&quot;https://github.com/amdjs/amdjs-api/wiki/AMD&quot; target=&quot;_blank&quot;&gt;AMD&lt;/a&gt; are just 2 most popular ones. Angular team decided to provide it’s own implementation of modules and left the asynchronous loading of them to
  existing tools. I suspect that it was because they didn’t want to create a dependency on 3rd party library and because of their use of dependency injection. The framework relies on modules heavily making it possible to use just the parts that you actually
  need saving precious network and loading time. Here is how to define a module:
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;var myApp = angular.module(&amp;#39;myApp&amp;#39;, [&amp;#39;ngResource&amp;#39;]);

myApp.factory(&amp;#39;itemsStorage&amp;#39;, function ($resource) {
  var itemsStorage = ...;
  // items storage implementation
  return itemsStorage;
});&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We’ve
declared a new module called &lt;em&gt;myApp &lt;/em&gt;and stated that it depends on another module called &lt;em&gt;ngResource&lt;/em&gt;. In line 3 we are declaring a factory for &lt;em&gt;itemsStorage&lt;/em&gt; that requires &lt;em&gt;&lt;span class=&quot;math math-inline&quot;&gt;resource&amp;#x3C;/em&gt; service. Angular will automatically resolve &amp;#x3C;em&gt;&lt;/span&gt;resource&lt;/em&gt; service
and inject it as a value of parameter. As you may suspect under the hood the dependency injection mechanism inspects parameter names of our function and thus it is able to know how to satisfy them with proper values. Be careful when using JavaScript
minimizing tools because most of them will by default shorten parameter names and that will break the DI. The only work around for it is to disable an option responsible for parameters in minimizer. Most of the times I find it useful to split one module
definition across couple of files. It is a supported scenario but there are some quirks to it.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;var myApp = angular.module(&amp;#39;myApp&amp;#39;);

myApp.directive(&amp;#39;timeAgo&amp;#39;, function(){
  return function($scope, $element, $attrs){
    // timeAgo directive link implmentation
  };
});&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The
first line says that we would like to retrieve &lt;em&gt;myApp&lt;/em&gt; module so that we can extend or use it. This API may be confusing, it was for me, as it may look like we’re actually declaring a module that has no dependencies. The distinction between extending
and declaring a module has an important ramification. You’re now responsible of loading file with module declaration before files that extend module functionality. In order to declare module with no dependencies you have to pass an empty array as a
second argument:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;var secondModule = angular.module(&amp;#39;secondModule&amp;#39;, []);&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;h2&gt;A praise of dependency injection&lt;/h2&gt;
  &lt;p&gt;Dependency injection is a very useful concept especially in statically typed languages as C# or Java. It really helps you decouple your code as your classes no longer require to know about the implementation details of their dependencies. There are
    several ways to implement this pattern however must commonly used is a constructor injection. A lot of IoC containers exists both in .NET and Java world: Castle.Windsor, StructureMap, Guice or Ninject are just a few. However I have never seen a viable
    implementation of DI in JavaScript until AngularJs.&lt;/p&gt;
  &lt;p&gt;At first it seemed like a magic, so much that I actually had to dig into the framework code base to see how it’s done. As it turned out the idea behind the implementation is really simple. I did however encounter problems while trying to figure out
    why a particular service cannot be resolved or a directive isn’t working. Usually it was because of typos in parameter names or a missing dependency in module declaration. I know that the Angular team has put effort to make it easier to figure out
    those kind of problems in a recent release.&lt;/p&gt;
  &lt;p&gt;I’ve heard opinions that in a dynamic language as JavaScript the DI provides little to know gain instead adding an accidental complexity. I do agree that it is possible to live without however it requires much more discipline to keep a code clean. Whenever
    you create a service (a piece of code) that will be used in several places you have to make sure not to leak implementation details to clients (the ones that use the service). Without DI it means you have to make it easy to create a service by hand,
    typically by providing a factory method or a parameter less constructor. If you won’t take care of it upfront it will be harder to refactor the service implementation later on because of the number of clients that create it. When using DI at least
    this one task is forced upon you upfront.&lt;/p&gt;
  &lt;p&gt;Now what makes an actual implementation of DI practical is its ease of use. If you remember a time when most of C# and Java IoC containers required declaring actual object graph in an XML files you’ll understand what I mean. I think Angular team made
    using dependency injection feel easy and very natural and that’s what makes it so useful.&lt;/p&gt;
  &lt;h2&gt;Dependency resolution and conflicts&lt;/h2&gt;There is an important limitation in Angular modules implementation around conflict resolution. Basically the framework uses last wins approach so you really have to be careful while naming things. It may seem not important at first but let’s consider
  following code sample.
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;var A = angular.module(&amp;#39;A&amp;#39;, []);

A.factory(&amp;#39;serviceA&amp;#39;, function(){
 return function(){
  console.log(&amp;#39;using serviceA defined in module A&amp;#39;);
 };
});

var B = angular.module(&amp;#39;B&amp;#39;, [&amp;#39;A&amp;#39;]);

B.factory(&amp;#39;serviceB&amp;#39;, function(serviceA){
 return function(){
  console.group(&amp;#39;using serviceB defined in module A&amp;#39;);
  serviceA();
  console.groupEnd();
 };
});

var C = angular.module(&amp;#39;C&amp;#39;, [&amp;#39;A&amp;#39;]);

C.factory(&amp;#39;serviceA&amp;#39;, function(){
 return function(){
  console.log(&amp;#39;using serviceA defined in module C&amp;#39;);
 };
});

C.factory(&amp;#39;serviceC&amp;#39;, function(serviceA){
 return function(){
  console.group(&amp;#39;using serviceC defined in module C&amp;#39;);
  serviceA();
  console.groupEnd();
 };
});&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;As you can see we have 3 modules here &lt;em&gt;A, B &lt;/em&gt;and&lt;em&gt; C&lt;/em&gt;. But in line &lt;em&gt;21&lt;/em&gt; inside &lt;em&gt;C&lt;/em&gt; module definition we’re declaring &lt;em&gt;serviceA&lt;/em&gt;. Since module &lt;em&gt;C&lt;/em&gt; depends on &lt;em&gt;A&lt;/em&gt; that already defined &lt;em&gt;serviceA&lt;/em&gt; we’re actually
    overriding the implementation. It’s quite useful to be able to override and stuff our custom implementation of particular service provided by other module. Except that we have no control over the scope of our modification. In the above example the &lt;em&gt;serviceA&lt;/em&gt; defined
    in module &lt;em&gt;C&lt;/em&gt; will be the one used everywhere at runtime. Even though module &lt;em&gt;B&lt;/em&gt; knows nothing bout &lt;em&gt;C.&lt;/em&gt; Calling declared services like this:
```
serviceA();
serviceB();
serviceC();
```
Will
    produce following output:
    &lt;/p&gt;&lt;div&gt;
      &lt;a href=&quot;http://lh3.ggpht.com/-1Kk4GFZY1Ac/UjdAULJnNPI/AAAAAAAAA-0/Ysrp9fPRtO4/s1600-h/image%25255B13%25255D.png&quot;&gt;
        &lt;img alt=&quot;image&quot; border=&quot;0&quot; height=&quot;140&quot; src=&quot;http://lh4.ggpht.com/-jfB6FQ9O_RI/UjdAUlHuWHI/AAAAAAAAA-8/w1-wyY2sB70/image_thumb%25255B5%25255D.png?imgmax=800&quot; style=&quot;background-image: none; border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;&quot; title=&quot;image&quot; width=&quot;379&quot;&gt;
      &lt;/a&gt;
    &lt;/div&gt;You can play around with this &lt;a href=&quot;http://jsfiddle.net/miensol/z5TVc/&quot; target=&quot;_blank&quot;&gt;sample on jsfiddle&lt;/a&gt;.&lt;p&gt;&lt;/p&gt;
  &lt;p&gt;What can we do about it? The only advice I’ve seen is to use prefix on &lt;em&gt;service&lt;/em&gt; names. Now this is a working and simple approach however the code will not look great. I wonder how hard it would be to modify angular injector part to gain the ability
    to gain more control over overriding things…&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[AngularJs – my new superhero tool.]]></title><description><![CDATA[Introduction to angular]]></description><link>undefined/angularjs-my-new-superhero-tool/</link><guid isPermaLink="false">undefined/angularjs-my-new-superhero-tool/</guid><pubDate>Sun, 15 Sep 2013 11:53:00 GMT</pubDate><content:encoded>&lt;p&gt;As I mentioned in my previous post I’ll describe my thoughts and findings about 3 popular JavaScript libraries that help building large web application. I’ll start with &lt;a href=&quot;http://angularjs.org/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;AngularJs&lt;/a&gt; which is the first one I’ve used in a real product.&lt;/p&gt;
&lt;h2 id=&quot;model-view-whatever&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#model-view-whatever&quot; aria-label=&quot;model view whatever permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Model View Whatever&lt;/h2&gt;
&lt;p&gt;Angular team didn’t try hard to map their concepts to classical MVC pattern. You can see it even in the title of its home page. Instead they focused on making a development path of a large web application as smooth and productive, in a long term, as possible. This means its really important to return to &lt;a href=&quot;http://docs.angularjs.org/api/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;documentation&lt;/a&gt; and &lt;a href=&quot;http://docs.angularjs.org/guide/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;developer guide&lt;/a&gt; if you feel you’re getting lost along the way. Learning Angular is a really interesting journey especially that many concepts that I previously had categorized as not for the web turned out to be totally useful.&lt;/p&gt;
&lt;h2 id=&quot;model-and-view-model&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#model-and-view-model&quot; aria-label=&quot;model and view model permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Model and view model&lt;/h2&gt;
&lt;p&gt;This term has really a short definition according to angular way:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;a model is any data that is reachable as a property of an angular &lt;a href=&quot;http://docs.angularjs.org/guide/scope&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Scope&lt;/a&gt; object&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The nice thing about it is that it really is up to you how you choose to encapsulate the most valuable and complex logic inside your model or view model classes. No base “&lt;em&gt;class”&lt;/em&gt; , no artificial properties and helpers is required. In fact the framework won’t force you to build a proper view model for data-binding. While this freedom gives you more flexibility it also means that you are responsible for keeping your &lt;a href=&quot;http://docs.angularjs.org/guide/dev_guide.mvc.understanding_controller&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Controllers&lt;/a&gt; clean and thin. I prefer to put logic that encapsulates data and provides global, shared behaviour into separate classes totally unaware of the UI. Depending on the use case I’ll then put an instance of this model into scope or  if the presentation logic is more complex create a view model that wraps some model objects. To make the model objects easily accessible and sharable between views angular provides &lt;a href=&quot;http://docs.angularjs.org/guide/dev_guide.services&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;services&lt;/a&gt;. For a very simple logic that augments the way a single piece of data is presented there are &lt;a href=&quot;http://docs.angularjs.org/guide/dev_guide.templates.filters&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;filters&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;One important thing to understand though is that data-binding is only happening between view (and directives) and a scope object. If a model object provides events fired when its state changes they have to implemented in a traditional way. When I say traditional I mean that you typically will need to apply &lt;a href=&quot;http://en.wikipedia.org/wiki/Observer_pattern&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Observer pattern&lt;/a&gt; – or rather use one &lt;a href=&quot;https://github.com/js-coder/observable&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;of implementations available&lt;/a&gt;. This is somewhat different from the dirty checking mechanism that sits behind all the angular data-binding magic. Fortunately the framework provides a way to connect a non angular event to the scope with [&lt;span class=&quot;math math-inline&quot;&gt;apply](http://docs.angularjs.org/api/ng.&lt;/span&gt;rootScope.Scope#$apply) method. However be warned that you have to be really careful here to call it &lt;a href=&quot;http://stackoverflow.com/questions/12729122/prevent-error-digest-already-in-progress-when-calling-scope-apply&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;only outside of angular digest cycle&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;controller--keep-it-thin&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#controller--keep-it-thin&quot; aria-label=&quot;controller  keep it thin permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Controller – keep it thin&lt;/h2&gt;
&lt;p&gt;A &lt;a href=&quot;http://docs.angularjs.org/guide/dev_guide.mvc.understanding_controller&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;controller&lt;/a&gt; is mainly responsible for setting up the scope object and as such is created on a per view basis. It is the most common entry point for an application behaviour triggered by DOM events. While its often easy to put more and more business logic inside them you should really try hard not to. As a reward I often found myself being able to reuse more logic than I anticipated. Another rule of thumb is to never access DOM elements from controller. Angular has a special place for all DOM related activities called directives.&lt;/p&gt;
&lt;h2 id=&quot;directive--a-way-to-reusable-ui&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#directive--a-way-to-reusable-ui&quot; aria-label=&quot;directive  a way to reusable ui permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Directive — a way to reusable ui&lt;/h2&gt;
&lt;p&gt;This is the part of angular that causes lot of confusion when it comes to building custom directives. Especially that whenever you need to manipulate DOM in any way you should use them. To make things &lt;em&gt;easier&lt;/em&gt; there is a lot of not so obvious vocabulary used like &lt;a href=&quot;http://docs.angularjs.org/api/ng.$compile&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;compile&lt;/a&gt;, &lt;a href=&quot;http://docs.angularjs.org/api/ng.$interpolate&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;interpolate&lt;/a&gt;, link and my favourite &lt;a href=&quot;http://docs.angularjs.org/guide/directive&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;transclude&lt;/a&gt;. In my opinion directives make working with data-binding in angular so productive. They are kind of hard to understand deeply at first, but reading &lt;a href=&quot;http://docs.angularjs.org/guide/directive&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;the guide&lt;/a&gt; couple of times helps a lot. To demonstrate its power I’ll just say that entire &lt;a href=&quot;http://jqueryui.com/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;jQuery ui&lt;/a&gt; is easily accessible with just one directive. I guess I have to little experience to provide some tips about building directives - the most complex one I’ve built was &lt;a href=&quot;http://jsfiddle.net/YShcw/1/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;paginate&lt;/a&gt;. Here is a HTML snippet of how to use it:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;html&quot;&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;paginate&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;items&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;ul&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;li&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;ng-repeat&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;item in pager.paged&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
          {{ item.index }} {{ item.text }} 
      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;li&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;ul&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;button&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;ng-click&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;pager.previous()&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Previous&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;button&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;span&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;ng-repeat&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;page in pager.pages&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
           &lt;span class=&quot;token attr-name&quot;&gt;ng-class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;pager.classForPage(page)&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;a&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;ng-click&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;pager.goTo(page)&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;{{ page }} &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;span&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;button&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;ng-click&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;pager.next()&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Next&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;button&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Directive is the hardest part to fully understand but if you do learn them and built them in a generic way you can accelerate development a lot.&lt;/p&gt;
&lt;h2 id=&quot;views&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#views&quot; aria-label=&quot;views permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Views&lt;/h2&gt;
&lt;p&gt;I’ve only touched couple of aspects of Angular - there is a lot more to it. In particular I haven’t commented on View part in MVC trio. Angular tends to be criticised for the way it handles views. Mainly because you may get to a stage where it is hard to see actual html inside tons of directives attached to DOM elements. An alternative approach would be to use existing template engines like &lt;a href=&quot;http://handlebarsjs.com/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Handlebars&lt;/a&gt; – that’s the way it’s done in &lt;a href=&quot;http://emberjs.com/&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener noreferrer&quot;&gt;Ember.js&lt;/a&gt; – but it’s not really practical in Angular.&lt;/p&gt;
&lt;p&gt;However I really like the idea that behaviour of html elements is immediately visible when you scan views mainly because declarative nature of directives. It makes it possible for an CSS or UI design expert, not familiar with Angular nor JavaScript, to make safe changes to views. In addition you no longer need to repeat selectors to access DOM and attach behaviour to it. This eliminates some of the maintenance burden. Like with any tool you have to be careful though not to overload html with directives and never put logic inside your views even if its only presentation related. If you find yourself repeating the same set of directives in many places of your codebase it may be good to step back a little and think of a way to encapsulate a common behaviour – probably with a more specific directives.&lt;/p&gt;
&lt;p&gt;I’ll soon try to comment on features that Angular provides that make it suitable for large scale application development.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Javascript MV* frameworks]]></title><description><![CDATA[Building a web application today isn’t nearly as hard as it was couple of years ago. Back then creating a rich client application using HTML and JS was possible but the number of options you had is a fraction of what is available today. The first
SPAI helped building was relatively simple project –built with ExtJs…]]></description><link>undefined/javascript-mv-frameworks/</link><guid isPermaLink="false">undefined/javascript-mv-frameworks/</guid><pubDate>Fri, 16 Aug 2013 07:27:00 GMT</pubDate><content:encoded>&lt;p&gt;Building a web application today isn’t nearly as hard as it was couple of years ago. Back then creating a rich client application using HTML and JS was possible but the number of options you had is a fraction of what is available today. The first
&lt;a href=&quot;http://en.wikipedia.org/wiki/Single-page_application&quot; target=&quot;_blank&quot;&gt;SPA&lt;/a&gt;I helped building was relatively simple project –built with &lt;a href=&quot;http://www.sencha.com/products/extjs&quot; target=&quot;_blank&quot;&gt;ExtJs&lt;/a&gt; library when it was still in version
2. There were of course other options like &lt;a href=&quot;http://dojotoolkit.org/&quot; target=&quot;_blank&quot;&gt;dojo&lt;/a&gt; but with our team’s little experience in web technology ExtJs seemed like a better choice solely because of its superior support. Shortly after I worked
on another web application built with &lt;a href=&quot;http://www.asp.net/web-forms&quot; target=&quot;_blank&quot;&gt;Web Forms&lt;/a&gt; and &lt;a href=&quot;http://jquery.com/&quot; target=&quot;_blank&quot;&gt;jQuery&lt;/a&gt;.  We finished both projects, they worked on most browsers but we didn’t avoid creating
a mess in JavaScript. Presentation logic was mixed with business rules scattered through event handlers inside unstructured components source code. Just to be fair it definitely was not caused by the frameworks we used but because of our lack of knowledge
and experience.  I guess that happened to lots of developers and wise people soon enough realized that there has to be a better way of doing things. I think that this was the main reason of the explosion of JS libraries/frameworks options that aim
to help structuring client side code.&lt;/p&gt;
&lt;h2&gt;MVC, MVP, MVVM or …&lt;/h2&gt;The number of libraries and frameworks available is overwhelming. &lt;a href=&quot;http://angularjs.org/&quot; target=&quot;_blank&quot;&gt;AngularJS&lt;/a&gt;, &lt;a href=&quot;http://backbonejs.org/&quot; target=&quot;_blank&quot;&gt;Backbone.js&lt;/a&gt;, &lt;a href=&quot;http://emberjs.com/&quot; target=&quot;_blank&quot;&gt;Ember&lt;/a&gt;,
&lt;a href=&quot;http://javascriptmvc.com/&quot; target=&quot;_blank&quot;&gt;JavaScriptMVC&lt;/a&gt;, &lt;a href=&quot;http://knockoutjs.com/&quot; target=&quot;_blank&quot;&gt;Knockout&lt;/a&gt; or &lt;a href=&quot;http://sammyjs.org/&quot; target=&quot;_blank&quot;&gt;Sammy.js&lt;/a&gt; are just a few I had a chance to look at from the &lt;a href=&quot;https://github.com/search?q=javascript+mvc&amp;amp;ref=cmdform&quot;
target=&quot;_blank&quot;&gt;outstanding list&lt;/a&gt;. You can even compare &lt;a href=&quot;http://todomvc.com/&quot; target=&quot;_blank&quot;&gt;how to built simple TODO application&lt;/a&gt; with them. &lt;a href=&quot;http://addyosmani.com/blog/&quot; target=&quot;_blank&quot;&gt;Addy Osmani&lt;/a&gt; wrote an excellent &lt;a href=&quot;http://coding.smashingmagazine.com/2012/07/27/journey-through-the-javascript-mvc-jungle/&quot;
target=&quot;_blank&quot;&gt;article&lt;/a&gt; that really helps making your choice sane. Most if not all of those frameworks utilize one or more of MV* patterns. An important thing to remember though is that &lt;a href=&quot;http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller&quot;
target=&quot;_blank&quot;&gt;Model View Controller&lt;/a&gt; is more an architectural pattern for presentation than an code design pattern like &lt;a href=&quot;http://www.oodesign.com/builder-pattern.html&quot; target=&quot;_blank&quot;&gt;Builder&lt;/a&gt;. It means it does not provide very concrete implementation
template but rather a guidance for objects/modules/roles relationships. Similar observations apply to MVC cousins namely &lt;a href=&quot;http://martinfowler.com/eaaDev/PresentationModel.html&quot; target=&quot;_blank&quot;&gt;Model View ViewModel or Presentation Model&lt;/a&gt; and
&lt;a
href=&quot;http://martinfowler.com/eaaDev/ModelViewPresenter.html&quot; target=&quot;_blank&quot;&gt;Model View Presenter&lt;/a&gt;. This can cause some confusion for someone already familiar with MVC pattern in Asp.net mvc, Fubu or Rails. I always try to find a framework/library author’s explanation of how they applied above patterns – it really helps understanding
  core concepts of their work.
  &lt;h2&gt;Library or Framework&lt;/h2&gt;Some of the tools are called frameworks while other libraries. But what’s the difference anyway? A very common and brief explanation is the one provided by &lt;a href=&quot;http://martinfowler.com/&quot; target=&quot;_blank&quot;&gt;Martin Fowler&lt;/a&gt; inside &lt;a href=&quot;http://martinfowler.com/bliki/InversionOfControl.html&quot;
  target=&quot;_blank&quot;&gt;Inversion of Control article&lt;/a&gt;:
  &lt;blockquote&gt;Inversion of Control is a key part of what makes a framework different to a library. A library is essentially a set of functions
    &lt;strong&gt;that you can call&lt;/strong&gt;, these days usually organized into classes. Each call does some work and returns control to the client. A framework embodies some abstract design, with more behavior built in. In order to use it you need to insert
    your behavior into various places in the framework either by subclassing or by plugging in your own classes. The framework&apos;s code then
    &lt;strong&gt;calls your code&lt;/strong&gt;at these points.There are various ways you can plug your code in to be called.&lt;/blockquote&gt;Of course the distinction is not always firm and clear. Still, it is important to keep in mind while choosing
  &lt;em&gt;the right&lt;/em&gt;tool for a job. A library will usually give you more control inside infrastructure code but it often requires more work to unify boilerplate gluing code and requires some degree of experience. A framework on the other hand will typically
  provide you with a setup where you can hook your code hopefully focused mostly on the valuable functional stuff. A framework will limit your freedom to some extent in turn it will eliminate some part of work that you presumably would have to do in order
  to keep your design clean.
  &lt;h2&gt;Productivity&lt;/h2&gt;For me the biggest advantage of using a modern MV* JavaScript framework is productivity. After some time I realized that the amount of boring, repetitive code focused only on filling DOM with data and giving it behaviour is substantial. Sure I am able
  to separate presentation concerns rather cleanly without aid from any tool. However what’s the point if so many great libraries and frameworks, created by way more experienced people, is out there. It gets even more valid point when working on a big
  project. Even if all the team members are experienced and closely collaborating it will be hard to have and maintain a common, well understood structure among different parts of JavaScript code base just because understanding and preferences about MVC
  and related patterns will vary. In my next blog posts I’ll try to review 3 tools that caught my eye. Namely &lt;a href=&quot;http://angularjs.org/&quot; target=&quot;_blank&quot;&gt;AngularJS&lt;/a&gt;, &lt;a href=&quot;http://backbonejs.org/&quot; target=&quot;_blank&quot;&gt;Backbone.js&lt;/a&gt; and &lt;a href=&quot;http://knockoutjs.com/&quot;
  target=&quot;_blank&quot;&gt;Knockout&lt;/a&gt; that seem to be most popular these days. They all show some signs of maturity and have vibrant community around them. It will by no means be a comparison as they really are different beasts built with different goals in mind.
  The only comparison I may be tempted to do is about productivity. Still I already know it will not be comprehensive as there will be only one person working on the codebase and the micro product will be focused mostly on a rich data visualization –
  which is what I do mostly now. Maybe it will help to the framework/library that we’ll use in our current project.</content:encoded></item><item><title><![CDATA[URL Rewrite problem with POST request]]></title><link>undefined/url-rewrite-problem-with-post-request/</link><guid isPermaLink="false">undefined/url-rewrite-problem-with-post-request/</guid><pubDate>Wed, 31 Jul 2013 18:15:00 GMT</pubDate><content:encoded>&lt;h4&gt;Greetings&lt;/h4&gt;
&lt;p&gt;Hello Everyone! In this blog I would like to share my thoughts and findings on programming, software and a like. I will post here so that I can improve my writing skills and find stuff I was working on previously easier.&lt;/p&gt;
&lt;h2&gt;URL Rewrite&lt;/h2&gt;
&lt;p&gt;IIS users had waited a bit for Apache equivalent of &lt;a href=&quot;http://httpd.apache.org/docs/current/mod/mod_rewrite.html&quot; target=&quot;_blank&quot;&gt;mod_rewrite&lt;/a&gt;. Finally we&apos;ve got a decent module from Microsoft -&amp;nbsp;&lt;a href=&quot;http://www.iis.net/downloads/microsoft/url-rewrite&quot;
  target=&quot;_blank&quot;&gt;Url Rewrite&lt;/a&gt;. Among basic features as &lt;a href=&quot;http://www.hanselman.com/blog/RedirectingASPNETLegacyURLsToExtensionlessWithTheIISRewriteModule.aspx&quot; target=&quot;_blank&quot;&gt;rewriting all URLs to extension-less equivalents&lt;/a&gt;, &lt;a href=&quot;http://www.iis.net/learn/extensions/url-rewrite-module/request-blocking-rule-template&quot;
  target=&quot;_blank&quot;&gt;blocking unwanted URLs&lt;/a&gt;&amp;nbsp;or even more common &lt;a href=&quot;http://www.iis.net/learn/extensions/url-rewrite-module/user-friendly-url-rule-template&quot; target=&quot;_blank&quot;&gt;providing friendly URLs&lt;/a&gt;&amp;nbsp;the module provides a nice GUI inside
  IIS Manager so you can quickly test you ideas without referring to documentation. More importantly rewrite rules of your web site can be configured through Web.config configuration section.
  &lt;br /&gt;
  &lt;br /&gt;The feature I like the most is the ability to create a &lt;a href=&quot;http://en.wikipedia.org/wiki/Reverse_proxy&quot; target=&quot;_blank&quot;&gt;reversed proxy&lt;/a&gt;&amp;nbsp;inside an IIS web site with a little help of another IIS module - &lt;a href=&quot;http://www.iis.net/downloads/microsoft/application-request-routing&quot;
  target=&quot;_blank&quot;&gt;Application Request Routing&lt;/a&gt;. I have used it couple of times, mostly to be able to make &quot;cross domain&quot; POSTs. One important thing is to remember to enable proxy in ARR settings inside IIS Manager. Following command line will do it
  for you:
  &lt;br /&gt;&lt;pre class=&quot;brush: bash&quot;&gt;%windir%\system32\inetsrv\appcmd.exe set config -section:system.webServer/proxy /enabled:&quot;True&quot; /commit:apphost&lt;br /&gt;&lt;/pre&gt;
  &lt;h2&gt;Interfering with ASP.NET modules&lt;/h2&gt;
&lt;/p&gt;
&lt;p&gt;URL Rewrite is a native IIS module and from my understanding it deals with HTTP on a pretty low level. Most of custom IIS modules that I&apos;ve used or built were written in managed code. This means that they use ASP.NET stack that provides some higher level
  API to deal with requests and responses. However some of those APIs have important side effects one can easily overlook. Why is that important? Because combining several modules into one request/response pipeline can cause hard to debug bugs.
  &lt;br /&gt;I&apos;ve came a cross the same problem twice - as it turned out - it was caused exactly by this interference. Specifically after some happy months of rewriting http POSTs using URL Rewrite suddenly features using it stopped working. In both cases the problem
  was caused by seemingly not intrusive call:
  &lt;br /&gt;&lt;pre class=&quot;brush: csharp&quot;&gt;var request = HttpContext.Current.Request;&lt;br /&gt;var parameter = request[&quot;formOrQueryOrServerVariableKey&quot;];&lt;br /&gt;&lt;/pre&gt;As you may already know this code looks for a value inside&amp;nbsp;&lt;a class=&quot;CRefLink&quot; href=&quot;http://www.blogger.com/blogger.g?blogID=8010146885187116176#&quot;
  title=&quot;QueryString in HttpRequest&quot;&gt;QueryString&lt;/a&gt;, &lt;a class=&quot;CRefLink&quot; href=&quot;http://www.blogger.com/blogger.g?blogID=8010146885187116176#&quot; title=&quot;Form in HttpRequest&quot;&gt;&lt;b&gt;Form&lt;/b&gt;&lt;/a&gt;, &lt;a class=&quot;CRefLink&quot; href=&quot;http://www.blogger.com/blogger.g?blogID=8010146885187116176#&quot;
  title=&quot;Cookies in HttpRequest&quot;&gt;Cookies&lt;/a&gt;, or &lt;a class=&quot;CRefLink&quot; href=&quot;http://www.blogger.com/blogger.g?blogID=8010146885187116176#&quot; title=&quot;ServerVariables in HttpRequest&quot;&gt;ServerVariables&lt;/a&gt; collection member specified in the &lt;var&gt;key&lt;/var&gt; parameter.
  The important part is a Form which is an abstraction over html form that typically translates to http POST body. ASP.NET reads the body of a http request and decodes form url encoded values into NameValueCollection. This is done by reading input stream
  of the request which internally is buffered on disk. However since this actually is &lt;b&gt;a network stream it can only be read once&lt;/b&gt;. This of course means that depending on the order of modules and at which stage of request pipeline one module decides
  to read it the other ones may not be able to access it. Exactly this scenario caused URL Rewrited POST request to &lt;b&gt;hang until timeout&lt;/b&gt;.
  &lt;br /&gt;
  &lt;h4&gt;Glimpse&lt;/h4&gt;
  &lt;p&gt;One of the modules affected by this problem is part of a great tool called &lt;a href=&quot;http://getglimpse.com/&quot; target=&quot;_blank&quot;&gt;Glimpse&lt;/a&gt;. After an hour of looking through code base of this diagnostic tool I&apos;ve found what I was looking for inside &lt;a href=&quot;https://github.com/Glimpse/Glimpse/blob/62ed7717a31591d94aba982914a924ffc88d64d6/source/Glimpse.AspNet/RequestMetadata.cs&quot;
    target=&quot;_blank&quot;&gt;RequestMetadata &lt;/a&gt;class. Specifically&amp;nbsp;RequestIsAjax method that in turn is called by &lt;a href=&quot;https://github.com/Glimpse/Glimpse/blob/62ed7717a31591d94aba982914a924ffc88d64d6/source/Glimpse.Core/Policy/AjaxPolicy.cs&quot; target=&quot;_blank&quot;&gt;AjaxPolicy&lt;/a&gt;&amp;nbsp;during
    &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/system.web.httpapplication.beginrequest.aspx&quot; target=&quot;_blank&quot;&gt;BeginRequest&lt;/a&gt;event. I&apos;ve created a &lt;a href=&quot;https://github.com/Glimpse/Glimpse/pull/498&quot; target=&quot;_blank&quot;&gt;pull request&lt;/a&gt; that hopefully
    will fix the issue.&lt;/p&gt;
  &lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;One thing that I definitely will remember from this investigation is to always be very careful while writing ASP.NET http module.&lt;/p&gt;</content:encoded></item></channel></rss>