        (route server-router1))
 
 
-  (dispatch {:unit :server
-             :components {:a #(println "a" %)
-                          :b #(println "b" %)
-                          :c #(println "c" %)
-                          :d #(println "d" %)
-                          :e #(println "e" %)
-                          :f #(println "f" %)
-                          :browser #(println "browser" %)
-                          :server #(println "server" %)}
-             :ruleset {:units {:browser #{:a :b :c}
-                               :server #{:d :e :f}}}}
-            {::component (list :c)
-             :foo :bar})
+  ;;; via core.async
+
+  (do (def browser-comp-ch     (a/chan))
+      (def browser-comp-ch-pub (a/pub browser-comp-ch #(peek (:ow.starbuck.message-router/component %))))
+      (def browser-router-ch   (a/chan))
+
+      (def server-comp-ch     (a/chan))
+      (def server-comp-ch-pub (a/pub server-comp-ch #(peek (:ow.starbuck.message-router/component %))))
+      (def server-router-ch   (a/chan))
+
+      (def browser-components2 {:components {:input-validator browser-comp-ch
+                                             :input-sanitizer browser-comp-ch}
+                                :tunnels {:server #(do (println % "(browser -> server)")
+                                                       (a/put! server-router-ch %))}})
+
+      (def server-components2 {:components {:auth-checker server-comp-ch
+                                            :booker server-comp-ch
+                                            :invoice-generator server-comp-ch
+                                            ;;;:notifier server-comp-ch
+                                            :DEFAULT server-comp-ch}
+                               :tunnels {:browser #(do (println % "(server -> browser)")
+                                                       (a/put! browser-router-ch %))}})
+
+      (def browser-router2 (make-router ruleset1 browser-components2 :unit :browser))
+      (def server-router2 (make-router ruleset1 server-components2 :unit :server))
+
+      (defn start-async-component [comp-kw input-pub output-ch]
+        (let [sub-ch (a/sub input-pub comp-kw (a/chan))
+              timeout (+ 20000 (rand-int 2000))]
+          (a/go-loop [[msg _] (a/alts! [sub-ch (a/timeout timeout)])]
+            (println "got component msg in" comp-kw "-" msg)
+            (when msg
+              (a/put! output-ch (update msg :visited-components #(conj % [comp-kw (java.util.Date.)])))
+              (recur (a/alts! [sub-ch (a/timeout timeout)]))))))
+
+      (defn start-async-router [router router-kw input-ch output-ch]
+        (let [timeout (+ 20000 (rand-int 2000))]
+          (a/go-loop [[msg _] (a/alts! [input-ch (a/timeout timeout)])]
+            (println "got router msg in" router-kw "-" msg)
+            (when msg
+              (route router msg)
+              (recur (a/alts! [input-ch (a/timeout timeout)])))))))
+
+  (do (doseq [c #{:input-validator :input-sanitizer}]
+        (start-async-component c browser-comp-ch-pub browser-router-ch))
+
+      (doseq [c #{:auth-checker :booker :invoice-generator :notifier}]
+        (start-async-component c server-comp-ch-pub server-router-ch))
+
+      (start-async-router browser-router2 :browser browser-router-ch browser-comp-ch)
+      (start-async-router server-router2 :server server-router-ch server-comp-ch))
+
+  (->> (message :book-flight {:foo :bar})
+       #_(route browser-router2)    ;; you can start like this
+       (a/put! browser-router-ch) ;; or this
+       )
 
   )

(defn route [{:keys [dispatch?] :as router} msg]
  (let [resmsgs (advance router msg)]
    (if dispatch?
      (map (partial dispatch router) resmsgs)
      resmsgs)))

(defn message [route map & {:keys [max-transitions]


                             :booker {:next [:invoice-generator (fn [msg] :notifier)]}}}}})


  ;;; via fns

  (do (def browser-components1 {:components {:input-validator #(doto % (println "(input-validator)"))
                                             :input-sanitizer #(doto % (println "(input-sanitizer)"))}
                                :tunnels {:server #(doto % (println "(browser -> server)"))}})

      (def server-components1 {:components {:auth-checker #(doto % (println "(auth-checker)"))
                                            :booker #(doto % (println "(booker)"))
                                            :invoice-generator #(doto % (println "(invoice-generator)"))
                                        ;;;:notifier #(doto % (println "(notifier)"))
                                            :DEFAULT #(doto % (println "(DEFAULT)"))}
                               :tunnels {:browser #(doto % (println "(server -> browser)"))}})

      (def browser-router1 (make-router ruleset1 browser-components1 :unit :browser))
      (def server-router1 (make-router ruleset1 server-components1 :unit :server)))

  (->> (message :book-flight {:foo :bar})
       (route browser-router1)
       first
       (route browser-router1)
