<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Igor Perikov</title>
    <description>The latest articles on Forem by Igor Perikov (@igorperikov).</description>
    <link>https://forem.com/igorperikov</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F216665%2F325dee10-f5fa-4878-ae09-4b610a806b47.jpeg</url>
      <title>Forem: Igor Perikov</title>
      <link>https://forem.com/igorperikov</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/igorperikov"/>
    <language>en</language>
    <item>
      <title>Why I like Go HTTP client as a Java developer</title>
      <dc:creator>Igor Perikov</dc:creator>
      <pubDate>Tue, 26 Nov 2019 10:18:39 +0000</pubDate>
      <link>https://forem.com/igorperikov/why-i-like-go-http-client-as-a-java-developer-32hp</link>
      <guid>https://forem.com/igorperikov/why-i-like-go-http-client-as-a-java-developer-32hp</guid>
      <description>&lt;p&gt;We live in era of microservices. Those have &lt;strong&gt;A LOT&lt;/strong&gt; of communication happening inside their ecosystems. You might have seen so-called death stars of microservices:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F6k7c3k8t9wdw7ybui209.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F6k7c3k8t9wdw7ybui209.jpeg" alt="microservice_death_stars"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;image by &lt;a href="http://www.csl.cornell.edu/~delimitrou/papers/2019.asplos.microservices.pdf" rel="noopener noreferrer"&gt;Cornell University researchers&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Every single click in modern internet triggers multitudes of network calls and, as you probably know, &lt;a href="https://blog.acolyer.org/2014/12/18/the-network-is-reliable/" rel="noopener noreferrer"&gt;network is unreliable&lt;/a&gt;. This is one of the reasons &lt;strong&gt;you should set request timeouts&lt;/strong&gt; when fetching something over the wire. It's better to incorporate some other techniques as well, but that's the topic for another article (and even whole book). &lt;/p&gt;

&lt;h2&gt;
  
  
  Why bother about timeouts? 
&lt;/h2&gt;

&lt;p&gt;Setting them is very important, because network might fail, your instance might get slow or crash. You don't want users to wait indefinitely just because 1 of your 1000 servers suddenly shut down. People hate waiting, it affects their happiness and, therefore, &lt;a href="https://www.machmetrics.com/speed-blog/how-does-page-load-time-affect-your-site-revenue/" rel="noopener noreferrer"&gt;your revenue&lt;/a&gt;. If network call gets stuck, you should abandon it, retry and, unless your cluster is having problems, it most likely to succeed. &lt;/p&gt;

&lt;p&gt;Let's see how we can implement this in Java and Go. &lt;/p&gt;

&lt;h2&gt;
  
  
  Common Java approach
&lt;/h2&gt;

&lt;p&gt;Most popular http client in java is &lt;a href="https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient" rel="noopener noreferrer"&gt;Apache HttpClient&lt;/a&gt;. Here's how configuring request timeouts will look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;RequestConfig&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;RequestConfig&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;custom&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setConnectTimeout&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setConnectionRequestTimeout&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setSocketTimeout&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Those 3 are all different and independent. Biggest problem we're facing here is how to represent 500 ms as 3 different timeouts, should it be 100 + 100 + 300 or 50 + 50 + 400? And, more importantly, do we even care if connect timeout will take 200 ms? Imagine that server will complete request in 50 ms, so total response time would be 250 ms, in most situations  &lt;strong&gt;you don't care, it's completely fine!&lt;/strong&gt;&lt;br&gt;
 &lt;br&gt;
On the other side you can't set timeouts much bigger, because it will lead to a longer requests. Also, socket timeout is just a timeout between any consecutive packets being read from the socket, &lt;strong&gt;not the whole response&lt;/strong&gt; being sent back to you. &lt;/p&gt;

&lt;p&gt;Nonetheless, it's all we can do using Apache HttpClient. Let's take a look at Go. &lt;/p&gt;
&lt;h2&gt;
  
  
  Go standard library
&lt;/h2&gt;

&lt;p&gt;Go, however, has support for whole client call timeout:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;callTimeoutMs&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;2000&lt;/span&gt;
&lt;span class="n"&gt;httpClient&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Timeout&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;callTimeoutMs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Millisecond&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;httpClient&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"http://httpbin.org/delay/1"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// this waits 1 second&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we're setting call timeout to 2 seconds and calling &lt;a href="http://httpbin.org/" rel="noopener noreferrer"&gt;httpbin&lt;/a&gt;, which will imitate work for 1 second long and return a response after. Launching this will lead to a successful call. &lt;/p&gt;

&lt;p&gt;If we set call timeout to 1 second it will fail with a message similar to given , which is exactly what we are looking for!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;2019/11/25 19:06:09 Get http://httpbin.org/delay/1: net/http:
 request canceled (Client.Timeout exceeded while awaiting headers)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On the contrary, configuring call timeout only &lt;strong&gt;is not always the best we can achieve.&lt;/strong&gt; Imagine having a long and heavy request which takes 10 seconds to complete. It would be nasty to wait 10 seconds for response and figure out that servers was trying to establish connection all this time and no actual work was done. &lt;/p&gt;

&lt;p&gt;Solution to this? Connect timeout. Yes, the one we were sort of blaming earlier. Combined with call timeout it gives robust protection to your network interactions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;callTimeoutMs&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;10000&lt;/span&gt;
&lt;span class="n"&gt;connectTimeoutMs&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;25&lt;/span&gt;
&lt;span class="n"&gt;httpClient&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Timeout&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;callTimeoutMs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Millisecond&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Transport&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Transport&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;DialContext&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;net&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Dialer&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;Timeout&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;connectTimeoutMs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Millisecond&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DialContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;httpClient&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"http://httpbin.org/delay/5"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// this waits for 5 seconds&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Exceeding connect timeout will give us desirable behavior: &lt;br&gt;
&lt;code&gt;2019/11/25 19:12:25 Get http://httpbin.org/delay/5: dial tcp 54.172.95.6:80: i/o timeout&lt;/code&gt;&lt;br&gt;
Go gives you a lot of flexibility with it's standard HTTP client, and library is supported by the vendor - perfect combination, &lt;strong&gt;that's why I like it very much!&lt;/strong&gt; Now let's get back to Java world one more time. &lt;/p&gt;
&lt;h2&gt;
  
  
  So, is Java doomed? 
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;No&lt;/strong&gt;. There are less popular alternatives, such as &lt;a href="https://docs.oracle.com/en/java/javase/11/docs/api/java.net.http/java/net/http/HttpClient.html" rel="noopener noreferrer"&gt;JDK 11&lt;/a&gt; http client and &lt;a href="https://square.github.io/okhttp/" rel="noopener noreferrer"&gt;OkHttp&lt;/a&gt;, which supports call timeout features. Sadly, those are not the top results when searching on Google, so people are less aware of them or not willing to start using them.&lt;/p&gt;
&lt;h2&gt;
  
  
  JDK 11
&lt;/h2&gt;

&lt;p&gt;It is a modern http client delivered with standard library, which supports HTTP/1.1, HTTP/2, async calls via CompletableFuture and provides convenient api to work with. Let's combine both timeouts with it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;HttpClient&lt;/span&gt; &lt;span class="n"&gt;httpClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;HttpClient&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;newBuilder&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;connectTimeout&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Duration&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ofMillis&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;HttpClient&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Version&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;HTTP_1_1&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="nc"&gt;HttpRequest&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;HttpRequest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;newBuilder&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;GET&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;uri&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;URI&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;create&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"http://httpbin.org/delay/1"&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Duration&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ofMillis&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;httpClient&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;send&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;HttpResponse&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;BodyHandlers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ofString&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This client will provide nice and easy to understand error messages(especially compared to Go) for connect and call timeouts respectively:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Exception in thread "main" java.net.http.HttpConnectTimeoutException: 
 HTTP connect timed out

Exception in thread "main" java.net.http.HttpTimeoutException:
 request timed out
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  OkHttp
&lt;/h2&gt;

&lt;p&gt;OkHttp supports call and connect timeouts too. Both can be configured at client abstraction level, which is slightly more convenient compared to JDK11 implementation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;OkHttpClient&lt;/span&gt; &lt;span class="n"&gt;httpClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;OkHttpClient&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Builder&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;connectTimeout&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Duration&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ofMillis&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;callTimeout&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Duration&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ofMillis&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How to choose timeout values, anyway? 
&lt;/h2&gt;

&lt;p&gt;Last thing I'd like to mention is how to derive those 2 numbers. Call timeout is more about SLA/SLO you have with other services and connect timeout is about expectations from underlying network. For example, if you're sending requests to the same datacenter, then 100ms would be fine (although it should establish connection faster than 5ms), but operating on top of mobile networks (which are more error-prone) will require higher connect timeouts. &lt;/p&gt;

&lt;h2&gt;
  
  
  Wrap-up
&lt;/h2&gt;

&lt;p&gt;In this article we discussed why timeouts are important, why 'classic' timeouts doesn't meet modern requirements and which instruments to use to force them. I hope you found something useful in it.&lt;/p&gt;

</description>
      <category>java</category>
      <category>go</category>
      <category>http</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Mighty-watcher digest #1</title>
      <dc:creator>Igor Perikov</dc:creator>
      <pubDate>Fri, 04 Oct 2019 16:40:50 +0000</pubDate>
      <link>https://forem.com/igorperikov/mighty-watcher-digest-1-jal</link>
      <guid>https://forem.com/igorperikov/mighty-watcher-digest-1-jal</guid>
      <description>&lt;p&gt;Introductory post on what &lt;a href="https://dev.to/igorperikov/open-source-made-easier-1hh8"&gt;mighty-watcher is&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;First of all, thanks to everyone who have supported me in any way ❤️ I don't know how many of you have tried &lt;a href="https://github.com/igorperikov/mighty-watcher"&gt;mighty-watcher&lt;/a&gt; so far, but if u did, I hope you enjoyed it. I feel motivated to keep writing articles, especially about things, other than mighty-watcher. TBH, I've already started writing a new one! It will be &lt;strong&gt;more technical&lt;/strong&gt; with a bit of comparison between java and go. &lt;/p&gt;

&lt;h2&gt;
  
  
  Development news
&lt;/h2&gt;

&lt;p&gt;There are currently 2 things which are in-progress:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Right now I am working on &lt;a href="https://github.com/IgorPerikov/mighty-watcher/issues/60"&gt;supporting advanced mode&lt;/a&gt;. It's a mode for those who are looking for harder issues, have broad experience and probably have contributed to repository already. &lt;/li&gt;
&lt;li&gt;My brother is implementing support for html reports. It was his idea on how to make output more convenient and user-friendly. You can track his progress &lt;a href="https://github.com/IgorPerikov/mighty-watcher/pull/61"&gt;here&lt;/a&gt;. Here is example:
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PSBs4nny--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/yw79cosagla12izadydu.png" alt="HTML report"&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Hacktoberfest
&lt;/h2&gt;

&lt;p&gt;If you haven't finished your hacktoberfest goals yet or just want to make a contribution to kotlin-based project - I have some &lt;a href="https://github.com/igorperikov/mighty-watcher/issues?q=is%3Aissue+is%3Aopen+label%3Ahacktoberfest"&gt;issues&lt;/a&gt; available. Or use it to find issues in your favorite(and starred ⭐) open-source projects. As usual if you have something in mind - &lt;strong&gt;don't hesitate&lt;/strong&gt; to discuss it. &lt;/p&gt;

</description>
      <category>github</category>
      <category>hacktoberfest</category>
      <category>kotlin</category>
    </item>
    <item>
      <title>Open source made easier</title>
      <dc:creator>Igor Perikov</dc:creator>
      <pubDate>Tue, 01 Oct 2019 06:44:51 +0000</pubDate>
      <link>https://forem.com/igorperikov/open-source-made-easier-1hh8</link>
      <guid>https://forem.com/igorperikov/open-source-made-easier-1hh8</guid>
      <description>&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;I made a program that finds, among your starred repositories, the issues that are most likely to be a good choice for making a contribution. For a quick start, check out the How-To on the &lt;a href="https://github.com/igorperikov/mighty-watcher#how-to-use"&gt;GitHub project page&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--W4zOEpev--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://github.com/IgorPerikov/mighty-watcher/blob/master/docs/example.gif%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--W4zOEpev--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://github.com/IgorPerikov/mighty-watcher/blob/master/docs/example.gif%3Fraw%3Dtrue" width="95%"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why would one need it?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Developers are obsessed&lt;/strong&gt; with open source development nowadays. Everyone wants to give back to the community, to get some new skills and experience while working on the most widely known software products. Imagine getting invaluable insights from experienced engineers all over the world: pretty exciting, right?&lt;/p&gt;

&lt;p&gt;However, people struggle hard to find appropriate tasks to work on. If you are new to the project, it is most likely that the maintainers won’t let you work on some big, fancy feature, lest you miss a plenty of details and corner cases. Everyone agrees that &lt;strong&gt;one would better start with the easiest tasks&lt;/strong&gt;, learn the ropes, get some trust from maintainers, and then proceed to harder ones.&lt;/p&gt;

&lt;h2&gt;
  
  
  So, how do you find these easy issues to work on?
&lt;/h2&gt;

&lt;p&gt;Some time ago, GitHub started listing appropriate issues, e.g., &lt;a href="https://github.com/golang/go/contribute"&gt;https://github.com/golang/go/contribute&lt;/a&gt;. You can access this list from the header of the Issues page. This is how it looks like:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--eIrDOGLK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://github.com/IgorPerikov/mighty-watcher/blob/master/docs/github_contribute_section.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--eIrDOGLK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://github.com/IgorPerikov/mighty-watcher/blob/master/docs/github_contribute_section.png%3Fraw%3Dtrue"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Although it is pretty accurate, it sometimes lacks the appropriate labeling or misses some items.&lt;/p&gt;

&lt;p&gt;My usual &lt;em&gt;"let-me-make-a-contribution"&lt;/em&gt; day used to look like this: I was looking through my starred repositories and jumping to this “new contribution” section, or was scrolling the issues list manually. That was a very monotonous and time-consuming task, so I used to get bored quickly by this process and would give up. That is when I decided to automate it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Solution
&lt;/h2&gt;

&lt;p&gt;First, I needed to work out the rules of the game. I did some research and came up with the following heuristics:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An issue should not be closed.&lt;/li&gt;
&lt;li&gt;Assigned means assigned, don’t waste your time on it.&lt;/li&gt;
&lt;li&gt;An issue should be marked with an “easy” label or something similar.&lt;/li&gt;
&lt;li&gt;Old issues are likely to be outdated; if it remains unsolved for too long, maintainers are likely not interested in it and probably less interested to help you during the process.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Furthermore, it turns out that every repository uses its own set of labels, and &lt;strong&gt;it is rarely just “help wanted”&lt;/strong&gt;. There are multitudes of them. I looked through all the labels in my starred repositories and other popular ones and came up with a &lt;a href="https://github.com/IgorPerikov/mighty-watcher/blob/master/src/main/kotlin/com/github/igorperikov/mightywatcher/service/EasyLabelsStorage.kt"&gt;final list of ~60 labels&lt;/a&gt;. &lt;strong&gt;If any of your repositories have different labels, create a pull request or contact me&lt;/strong&gt; — I will add it as soon as possible. As I set boundaries, it was the time to create the program itself.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xrInnPHV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://github.com/IgorPerikov/mighty-watcher/blob/master/docs/logo_deepskyblue.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xrInnPHV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://github.com/IgorPerikov/mighty-watcher/blob/master/docs/logo_deepskyblue.png%3Fraw%3Dtrue"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I built a Kotlin application, which looks through the list of starred repositories and searches for the issues with predefined labels, sorts them and has them printed to the console. The current way of distribution is a Docker image — people are more likely to have it installed than Java ;)&lt;/p&gt;

&lt;p&gt;As the labels list grew, I noticed a drastic decrease in speed and an increase in the consumption of API usage limits. The first edition of the tool was searching for issues with all given labels, although 95% of them had never been used in that repo! That was my “AHA!” moment, so I added an additional call to fetch all the labels from the repository and intersect them with my list. I got a significant improvement of the performance, and utilized less of the API limits.&lt;/p&gt;

&lt;p&gt;On a daily basis, the tool works fine as a guide to the world of open-source contributions, it will also help you to achieve your &lt;a href="https://hacktoberfest.digitalocean.com/"&gt;Hacktoberfest&lt;/a&gt; goals. To try it, go to the project page and follow the &lt;a href="https://github.com/igorperikov/mighty-watcher#how-to-use"&gt;instructions&lt;/a&gt;. If you lack starred repositories - I have some &lt;a href="https://github.com/igorperikov/mighty-watcher#lacking-starred-repositories"&gt;advices&lt;/a&gt; for you as well.&lt;/p&gt;

&lt;p&gt;If you have something to say — do it in the section below, or in the dedicated &lt;a href="https://github.com/IgorPerikov/mighty-watcher/issues/67"&gt;feedback issue&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>github</category>
      <category>hacktoberfest</category>
      <category>kotlin</category>
    </item>
  </channel>
</rss>
