title: Can I make a fully non-blocking backend application with http-kit and core.async?
body: <p>I'm wondering if it's possible to put together a fully non-blocking Clojure backend web application with http-kit.</p>
  
  <p>(Actually any Ring-compatible http server would be fine by me; I'm mentioning http-kit because it <a href="http://http-kit.org/server.html">claims</a> to have an event-driven, non-blocking model).</p>
  
  <hr>
  
  <h1>EDIT: TL;DR</h1>
  
  <p>This question is a symptom of some misconceptions I had about the nature of non-blocking/asynchronous/event-driven systems. In case you're in the same place as I was, here are some clarifications.</p>
  
  <p>Making an event-driven system with the performance benefits of it being non-blocking (like in Node.js) is possible only if all (say, most) of <strong><em>your IO is handled in a non-blocking way from the ground up</em></strong>. This means that all your DB drivers, HTTP servers and clients, Web services etc. have to offer an asynchronous interface in the first place. <strong>In particular:</strong></p>
  
  <ul>
  <li>if your database driver offers a synchronous interface, there's no way to make it non-blocking. (Your thread is blocked, no way to retrieve it). If you want non blocking, you need to use something else.</li>
  <li>High-level coordination utilities like core.async cannot make a system non-blocking. They can help you manage non-blocking code, but don't enable it.</li>
  <li>If your IO drivers are synchronous, you <em>can</em> use core.async to have the <em>design</em> benefits of asynchrony, but you won't get the performance benefits of it. Your threads will still be wasting time waiting for each response.</li>
  </ul>
  
  <p>Now, specifically:</p>
  
  <ul>
  <li>http-kit as an HTTP server offers a non-blocking, asynchronous interface. See below.</li>
  <li>However, many Ring middlewares, since they're essentially synchronous, won't be compatible with this approach. Basically, any Ring middleware that updates the returned response will not be useable.</li>
  </ul>
  
  <hr>
  
  <p>If I got it right (and I'm not an expert, so please tell me if I'm working on wrong assumptions), the principles of such a non-blocking model for a web application are the following:</p>
  
  <ol>
  <li>Have a few super-fast OS threads handle all the CPU-intensive computing; these <em>must never be waiting</em>.</li>
  <li>Have a lot of "weak threads" handle the IO (database calls, web-service calls, sleeping, etc.); these <em>are meant mostly to be waiting</em>.</li>
  <li>This is beneficial because the waiting time spent on the handling of a request is typically 2 (disk access) to 5 (web services calls) orders of magnitude higher than the computing time.</li>
  </ol>
  
  <p>From what I have seen, this model is supported by default on the <a href="http://www.playframework.com/">Play Framework</a> (Scala) and <a href="http://nodejs.org/">Node.js</a> (JavaScript) platforms, with promise-based utilities for managing asynchrony programmatically.</p>
  
  <p>Let's try to do this in a Ring-based clojure app, with Compojure routing. I have a route that constructs the response by calling the <code>my-handle</code> function:</p>
  
  <pre><code>(defroutes my-routes
    (GET "/my/url" req (my-handle req))
    )
  (def my-app (noir.util.middleware/app-handler [my-routes]))
  (defn start-my-server! [] 
    (http-kit/run-server my-app))
  </code></pre>
  
  <p>It seems the commonly accepted way of managing asynchrony in Clojure applications is CSP-based, with the use of the <a href="https://github.com/clojure/core.async">core.async</a> library, with which I'm totally fine. So if I wanted to embrace the non-blocking principles listed above, I'd implement <code>my-handle</code> this way :</p>
  
  <pre><code>(require '[clojure.core.async :as a])
  
  (defn my-handle [req]
    (a/&lt;!!
      (a/go ; `go` makes channels calls asynchronous, so I'm not really waiting here
       (let [my-db-resource (a/thread (fetch-my-db-resource)) ; `thread` will delegate the waiting to "weaker" threads
             my-web-resource (a/thread (fetch-my-web-resource))]
         (construct-my-response (a/&lt;! my-db-resource)
                                (a/&lt;! my-web-resource)))
       )))
  </code></pre>
  
  <p>The CPU-intensive <code>construct-my-response</code> task is performed in a <code>go</code>-block whereas the waiting for external resources is done in <code>thread</code>-blocks, as suggested by Tim Baldridge in <a href="https://www.youtube.com/watch?v=enwIIGzhahw">this video on core.async</a> (38'55'')</p>
  
  <p>But that is not enough to make my application non-blocking. Whatever thread goes through my route and will call the <code>my-handle</code> function, will be <strong>waiting</strong> for the response to be constructed, right?</p>
  
  <p><em>Would it be beneficial (as I believe) to make this HTTP handling non-blocking as well, if so how can I achieve it?</em></p>
  
  <hr>
  
  <p><strong>EDIT</strong></p>
  
  <p>As codemomentum pointed out, the missing ingredient for a non-blocking handling of the request is to use http-kit channels. In conjunction with core.async, the above code would become something like this : </p>
  
  <pre><code>(defn my-handle! [req]
    (http-kit/with-channel req channel
      (a/go 
       (let [my-db-resource (a/thread (fetch-my-db-resource))
             my-web-resource (a/thread (fetch-my-web-resource))
             response (construct-my-response (a/&lt;! my-db-resource)
                                             (a/&lt;! my-web-resource))]
         (send! channel response)
         (close channel))
       )))
  </code></pre>
  
  <p>This lets you embrace an asynchronous model indeed.</p>
  
  <p>The problem with this is that it is pretty much incompatible with Ring middleware. A Ring middleware uses a function call for obtaining the response, which makes it essentially synchronous. More generally speaking, it seems event-driven handling is not compatible with a pure functional programming interface, because triggering events means having side-effects.</p>
  
  <p>I'd be glad to know if there is a Clojure library that addresses this.</p>