   (:use [circle.logging :only (add-file-appender)])
   (:use [circle.util.except :only (throw-if throw-if-not)])
   (:use [clojure.tools.logging :only (with-logs error infof errorf)]))
+
+;; Clojure has queues, they're not very well documented. They work
+;; like other standard clojure structures, and support peek, pop,
+;; conj.
+
+(def queue (ref clojure.lang.PersistentQueue/EMPTY))
+
+(def in-progress (ref #{}))
+(def max-in-progress 5)
+(def run-agent (agent nil))
+
+(declare run-first)
 
 (defn start* [build]
   (dosync


(defn log-result [b]
  (if (build/successful? b)
    (infof "Build %s successful" (build/build-name b))
    (errorf "Build %s failed" (build/build-name b))))

(defn run-build [b & {:keys [cleanup-on-failure]
                          :or {cleanup-on-failure true}}]

     (when (and (-> @b :failed?) cleanup-on-failure) 
       (cleanup-nodes b)))))

(defn may-start-build? []
  (< (count @in-progress) max-in-progress))

(defn run-first []
  (dosync
   (when (may-start-build?)
     (when-let [b (peek @queue)]
       (alter queue pop)
       (alter in-progress conj b)
       (send-off run-agent run-build b)
       (infof "dequeing build %s" (build/build-name b))))))

(defn add-build [b]
  (dosync
   (alter queue conj b)
   (infof "adding build %s to the queue. There are %s queued builds" (build/build-name b) (count @queue)))
  (run-first))
