         result (function)]
     [(- (System/currentTimeMillis) start) result]))
 
-(defn run-with-bench [number-of-users step]
-  (let [cs (repeatedly number-of-users async/chan)]
+(defn run-with-bench [concurrency step]
+  (let [cs (repeatedly concurrency async/chan)]
     (doseq [c cs]
       (go (>! c (bench step))))
-    (repeatedly number-of-users #(collect-result cs))))
+    (repeatedly concurrency #(first (alts!! cs)))))
 
 
 

;(STEP 5 "Non blocking http")


(defn chan-http-get [url c]
  (let [start (System/currentTimeMillis)]
    (http/get url {} #(async/put! c [(- (System/currentTimeMillis) start)
                                     (= 200 (:status %))]))))

(defn run-non-blocking [number-of-users url]
  (let [cs (repeatedly number-of-users async/chan)]
    (doseq [c cs]
        (go (chan-http-get url c)))
    (repeatedly number-of-users #(collect-result cs))))


; (STEP 6 "With timeout")

(defn chan-http-get-with-timeout [url timeout result-channel]
  (let [
          now     #(System/currentTimeMillis)
        start   (now)
        response (async/chan)]
    (go
      (http/get url {} #(async/put! response [(- (now) start) (= 200 (:status %))]))
      (let [[result c] (async/alts! [response (async/timeout timeout)])]
        (if (= c response)
          (>! result-channel result)
          (>! result-channel [timeout false]))))))

(defn run-non-blocking-with-timeout [number-of-users timeout url]
  (let [cs (repeatedly number-of-users async/chan)]
    (doseq [c cs]
        (go (chan-http-get-with-timeout url timeout c)))
    (repeatedly number-of-users #(collect-result cs))))


; (STEP 7 "Constantly")

(defn run-constantly [number-of-users number-of-requests timeout url]
  (let [cs       (repeatedly number-of-users async/chan)
        results  (async/chan)]
    (doseq [c cs]
        (chan-http-get-with-timeout url timeout c))
    (go-loop [i 0]
      (let [[result c] (async/alts! cs)]
        (chan-http-get-with-timeout url timeout c)
        (>! results result)
        (when (<= i number-of-requests)

(ns clj-tutorials.core
  (:require [org.httpkit.client :as http]
            [clojure.core.async :as async :refer [go go-loop alts! alts!! put! <!! <! >!]]))




;;; Load testing using core.async (@mhjort) ;;;






;STEP 1
(defn run1 [concurrency step]
  (let [cs (repeatedly concurrency async/chan)]
    (doseq [c cs]
      (go (>! c (step))))))



;STEP 2
(defn run-with-results [concurrency step]
  (let [cs (repeatedly concurrency async/chan)]
    (doseq [c cs]
      (go (>! c (step))))
    (repeatedly concurrency #(first (alts!! cs)))))


;STEP 3
