Autoformat test/scf/storage.clj for indentation fixes

The previous commit changed a lot of the nesting of the
code in this file because it introduced several new
"deftest" calls, in order to work properly with the
with-test-db fixture.  This commit simply attempts to
clean up the whitespace / indentation of the file.

--- test/com/puppetlabs/puppetdb/test/scf/storage.clj
+++ test/com/puppetlabs/puppetdb/test/scf/storage.clj
@@ -39,19 +39,19 @@

     (testing "should be equal for the base case"
       (is (= (resource-identity-hash {})
-             (resource-identity-hash {}))))
+            (resource-identity-hash {}))))

     (testing "shouldn't change for identical input"
       (doseq [i (range 10)
               :let [r (catutils/random-kw-resource)]]
         (is (= (resource-identity-hash r)
-               (resource-identity-hash r)))))
+              (resource-identity-hash r)))))

     (testing "shouldn't change for equivalent input"
       (is (= (resource-identity-hash {:foo 1 :bar 2})
-             (resource-identity-hash {:bar 2 :foo 1})))
+            (resource-identity-hash {:bar 2 :foo 1})))
       (is (= (resource-identity-hash {:tags #{1 2 3}})
-             (resource-identity-hash {:tags #{3 2 1}}))))
+            (resource-identity-hash {:tags #{3 2 1}}))))

     (testing "should be different for non-equivalent resources"
       ; Take a population of 5 resource, put them into a set to make
@@ -62,7 +62,7 @@
             pairs      (combinations candidates 2)]
         (doseq [[r1 r2] pairs]
           (is (not= (resource-identity-hash r1)
-                    (resource-identity-hash r2))))))))
+                (resource-identity-hash r2))))))))

 (deftest catalog-dedupe
   (testing "Catalogs with the same metadata but different content should have different hashes"
@@ -91,9 +91,9 @@
                     tweaked-hash    (catalog-similarity-hash tweaked-catalog)]]
         (if (= catalog tweaked-catalog)
           (is (= hash tweaked-hash)
-              (str catalog "\n has hash: " hash "\n and \n" tweaked-catalog "\n has hash: " tweaked-hash))
+            (str catalog "\n has hash: " hash "\n and \n" tweaked-catalog "\n has hash: " tweaked-hash))
           (is (not= hash tweaked-hash)
-              (str catalog "\n has hash: " hash "\n and \n" tweaked-catalog "\n has hash: " tweaked-hash))))))
+            (str catalog "\n has hash: " hash "\n and \n" tweaked-catalog "\n has hash: " tweaked-hash))))))

   (testing "Catalogs with different metadata but the same content should have the same hashes"
     (let [catalog            (:basic catalogs)
@@ -115,7 +115,7 @@
               :let [tweaked-catalog (nth (iterate apply-monkey catalog) nmonkeys)
                     tweaked-hash    (catalog-similarity-hash tweaked-catalog)]]
         (is (= hash tweaked-hash)
-            (str catalog "\n has hash: " hash "\n and \n" tweaked-catalog "\n has hash: " tweaked-hash))))))
+          (str catalog "\n has hash: " hash "\n and \n" tweaked-catalog "\n has hash: " tweaked-hash))))))

 (deftest fact-persistence
   (testing "Persisted facts"
@@ -125,332 +125,332 @@
                  "hostname" "myhost"
                  "kernel" "Linux"
                  "operatingsystem" "Debian"}]
-        (add-certname! certname)
-        (add-facts! certname facts (now))
-        (testing "should have entries for each fact"
-          (is (= (query-to-vec "SELECT certname, fact, value FROM certname_facts ORDER BY fact")
-                 [{:certname certname :fact "domain" :value "mydomain.com"}
-                  {:certname certname :fact "fqdn" :value "myhost.mydomain.com"}
-                  {:certname certname :fact "hostname" :value "myhost"}
-                  {:certname certname :fact "kernel" :value "Linux"}
-                  {:certname certname :fact "operatingsystem" :value "Debian"}])))
-        (testing "should add the certname if necessary"
-          (is (= (query-to-vec "SELECT name FROM certnames")
-                 [{:name certname}])))
-        (testing "replacing facts"
-          (let [new-facts {"domain" "mynewdomain.com"
-                           "fqdn" "myhost.mynewdomain.com"
-                           "hostname" "myhost"
-                           "kernel" "Linux"
-                           "uptime_seconds" "3600"}]
-            (replace-facts! {"name"  certname "values" new-facts} (now))
-            (testing "should have only the new facts"
-              (is (= (query-to-vec "SELECT fact, value FROM certname_facts ORDER BY fact")
-                     [{:fact "domain" :value "mynewdomain.com"}
-                      {:fact "fqdn" :value "myhost.mynewdomain.com"}
-                      {:fact "hostname" :value "myhost"}
-                      {:fact "kernel" :value "Linux"}
-                      {:fact "uptime_seconds" :value "3600"}]))))))))
+      (add-certname! certname)
+      (add-facts! certname facts (now))
+      (testing "should have entries for each fact"
+        (is (= (query-to-vec "SELECT certname, fact, value FROM certname_facts ORDER BY fact")
+              [{:certname certname :fact "domain" :value "mydomain.com"}
+               {:certname certname :fact "fqdn" :value "myhost.mydomain.com"}
+               {:certname certname :fact "hostname" :value "myhost"}
+               {:certname certname :fact "kernel" :value "Linux"}
+               {:certname certname :fact "operatingsystem" :value "Debian"}])))
+      (testing "should add the certname if necessary"
+        (is (= (query-to-vec "SELECT name FROM certnames")
+              [{:name certname}])))
+      (testing "replacing facts"
+        (let [new-facts {"domain" "mynewdomain.com"
+                         "fqdn" "myhost.mynewdomain.com"
+                         "hostname" "myhost"
+                         "kernel" "Linux"
+                         "uptime_seconds" "3600"}]
+          (replace-facts! {"name"  certname "values" new-facts} (now))
+          (testing "should have only the new facts"
+            (is (= (query-to-vec "SELECT fact, value FROM certname_facts ORDER BY fact")
+                  [{:fact "domain" :value "mynewdomain.com"}
+                   {:fact "fqdn" :value "myhost.mynewdomain.com"}
+                   {:fact "hostname" :value "myhost"}
+                   {:fact "kernel" :value "Linux"}
+                   {:fact "uptime_seconds" :value "3600"}]))))))))

 (let [catalog  (:basic catalogs)
       certname (:certname catalog)]

-(deftest catalog-persistence
-  (testing "Persisted catalogs"
-
-        (add-certname! certname)
-        (let [hash (add-catalog! catalog)]
-          (associate-catalog-with-certname! hash certname (now)))
-
-        (testing "should contain proper catalog metadata"
-          (is (= (query-to-vec ["SELECT cr.certname, c.api_version, c.catalog_version FROM catalogs c, certname_catalogs cr WHERE cr.catalog=c.hash"])
-                 [{:certname certname :api_version 1 :catalog_version "123456789"}])))
-
-        (testing "should contain a complete tags list"
-          (is (= (query-to-vec ["SELECT name FROM tags ORDER BY name"])
-                 [{:name "class"} {:name "foobar"}])))
-
-        (testing "should contain a complete classes list"
-          (is (= (query-to-vec ["SELECT name FROM classes ORDER BY name"])
-                 [{:name "baz"} {:name "foobar"}])))
-
-        (testing "should contain a complete edges list"
-          (is (= (query-to-vec [(str "SELECT r1.type as stype, r1.title as stitle, r2.type as ttype, r2.title as ttitle, e.type as etype "
-                                     "FROM edges e, catalog_resources r1, catalog_resources r2 "
-                                     "WHERE e.source=r1.resource AND e.target=r2.resource "
-                                     "ORDER BY r1.type, r1.title, r2.type, r2.title, e.type")])
-                 [{:stype "Class" :stitle "foobar" :ttype "File" :ttitle "/etc/foobar" :etype "contains"}
-                  {:stype "Class" :stitle "foobar" :ttype "File" :ttitle "/etc/foobar/baz" :etype "contains"}
-                  {:stype "File" :stitle "/etc/foobar" :ttype "File" :ttitle "/etc/foobar/baz" :etype "required-by"}])))
-
-        (testing "should contain a complete resources list"
-          (is (= (query-to-vec ["SELECT type, title FROM catalog_resources ORDER BY type, title"])
-                 [{:type "Class" :title "foobar"}
-                  {:type "File" :title "/etc/foobar"}
-                  {:type "File" :title "/etc/foobar/baz"}]))
-
-          (testing "properly associated with the host"
-            (is (= (query-to-vec ["SELECT cc.certname, cr.type, cr.title FROM catalog_resources cr, certname_catalogs cc WHERE cc.catalog=cr.catalog ORDER BY cr.type, cr.title"])
-                   [{:certname certname :type "Class" :title "foobar"}
-                    {:certname certname :type "File"  :title "/etc/foobar"}
-                    {:certname certname :type "File"  :title "/etc/foobar/baz"}])))
-
-          (testing "with all parameters"
-            (is (= (query-to-vec ["SELECT cr.type, cr.title, rp.name, rp.value FROM catalog_resources cr, resource_params rp WHERE rp.resource=cr.resource ORDER BY cr.type, cr.title, rp.name"])
-                   [{:type "File" :title "/etc/foobar" :name "ensure" :value (db-serialize "directory")}
-                    {:type "File" :title "/etc/foobar" :name "group" :value (db-serialize "root")}
-                    {:type "File" :title "/etc/foobar" :name "user" :value (db-serialize "root")}
-                    {:type "File" :title "/etc/foobar/baz" :name "ensure" :value (db-serialize "directory")}
-                    {:type "File" :title "/etc/foobar/baz" :name "group" :value (db-serialize "root")}
-                    {:type "File" :title "/etc/foobar/baz" :name "require" :value (db-serialize "File[/etc/foobar]")}
-                    {:type "File" :title "/etc/foobar/baz" :name "user" :value (db-serialize "root")}])))
-
-          (testing "with all metadata"
-            (let [result (query-to-vec ["SELECT cr.type, cr.title, cr.exported, cr.tags, cr.sourcefile, cr.sourceline FROM catalog_resources cr ORDER BY cr.type, cr.title"])]
-              (is (= (map #(assoc % :tags (sort (:tags %))) result)
-                     [{:type "Class" :title "foobar" :tags [] :exported false :sourcefile nil :sourceline nil}
-                      {:type "File" :title "/etc/foobar" :tags ["class" "file" "foobar"] :exported false :sourcefile "/tmp/foo" :sourceline 10}
-                      {:type "File" :title "/etc/foobar/baz" :tags ["class" "file" "foobar"] :exported false :sourcefile "/tmp/bar" :sourceline 20}])))))))
+  (deftest catalog-persistence
+    (testing "Persisted catalogs"
+
+      (add-certname! certname)
+      (let [hash (add-catalog! catalog)]
+        (associate-catalog-with-certname! hash certname (now)))
+
+      (testing "should contain proper catalog metadata"
+        (is (= (query-to-vec ["SELECT cr.certname, c.api_version, c.catalog_version FROM catalogs c, certname_catalogs cr WHERE cr.catalog=c.hash"])
+              [{:certname certname :api_version 1 :catalog_version "123456789"}])))
+
+      (testing "should contain a complete tags list"
+        (is (= (query-to-vec ["SELECT name FROM tags ORDER BY name"])
+              [{:name "class"} {:name "foobar"}])))
+
+      (testing "should contain a complete classes list"
+        (is (= (query-to-vec ["SELECT name FROM classes ORDER BY name"])
+              [{:name "baz"} {:name "foobar"}])))
+
+      (testing "should contain a complete edges list"
+        (is (= (query-to-vec [(str "SELECT r1.type as stype, r1.title as stitle, r2.type as ttype, r2.title as ttitle, e.type as etype "
+                                "FROM edges e, catalog_resources r1, catalog_resources r2 "
+                                "WHERE e.source=r1.resource AND e.target=r2.resource "
+                                "ORDER BY r1.type, r1.title, r2.type, r2.title, e.type")])
+              [{:stype "Class" :stitle "foobar" :ttype "File" :ttitle "/etc/foobar" :etype "contains"}
+               {:stype "Class" :stitle "foobar" :ttype "File" :ttitle "/etc/foobar/baz" :etype "contains"}
+               {:stype "File" :stitle "/etc/foobar" :ttype "File" :ttitle "/etc/foobar/baz" :etype "required-by"}])))
+
+      (testing "should contain a complete resources list"
+        (is (= (query-to-vec ["SELECT type, title FROM catalog_resources ORDER BY type, title"])
+              [{:type "Class" :title "foobar"}
+               {:type "File" :title "/etc/foobar"}
+               {:type "File" :title "/etc/foobar/baz"}]))
+
+        (testing "properly associated with the host"
+          (is (= (query-to-vec ["SELECT cc.certname, cr.type, cr.title FROM catalog_resources cr, certname_catalogs cc WHERE cc.catalog=cr.catalog ORDER BY cr.type, cr.title"])
+                [{:certname certname :type "Class" :title "foobar"}
+                 {:certname certname :type "File"  :title "/etc/foobar"}
+                 {:certname certname :type "File"  :title "/etc/foobar/baz"}])))
+
+        (testing "with all parameters"
+          (is (= (query-to-vec ["SELECT cr.type, cr.title, rp.name, rp.value FROM catalog_resources cr, resource_params rp WHERE rp.resource=cr.resource ORDER BY cr.type, cr.title, rp.name"])
+                [{:type "File" :title "/etc/foobar" :name "ensure" :value (db-serialize "directory")}
+                 {:type "File" :title "/etc/foobar" :name "group" :value (db-serialize "root")}
+                 {:type "File" :title "/etc/foobar" :name "user" :value (db-serialize "root")}
+                 {:type "File" :title "/etc/foobar/baz" :name "ensure" :value (db-serialize "directory")}
+                 {:type "File" :title "/etc/foobar/baz" :name "group" :value (db-serialize "root")}
+                 {:type "File" :title "/etc/foobar/baz" :name "require" :value (db-serialize "File[/etc/foobar]")}
+                 {:type "File" :title "/etc/foobar/baz" :name "user" :value (db-serialize "root")}])))
+
+        (testing "with all metadata"
+          (let [result (query-to-vec ["SELECT cr.type, cr.title, cr.exported, cr.tags, cr.sourcefile, cr.sourceline FROM catalog_resources cr ORDER BY cr.type, cr.title"])]
+            (is (= (map #(assoc % :tags (sort (:tags %))) result)
+                  [{:type "Class" :title "foobar" :tags [] :exported false :sourcefile nil :sourceline nil}
+                   {:type "File" :title "/etc/foobar" :tags ["class" "file" "foobar"] :exported false :sourcefile "/tmp/foo" :sourceline 10}
+                   {:type "File" :title "/etc/foobar/baz" :tags ["class" "file" "foobar"] :exported false :sourcefile "/tmp/bar" :sourceline 20}])))))))

   (deftest catalog-replacement
-      (testing "should noop if replaced by themselves"
-          (add-certname! certname)
-          (let [hash (add-catalog! catalog)]
-            (replace-catalog! catalog (now))
-
-            (is (= (query-to-vec ["SELECT name FROM certnames"])
-                   [{:name certname}]))
-
-            (is (= (query-to-vec ["SELECT hash FROM catalogs"])
-                   [{:hash hash}])))))
-;
+    (testing "should noop if replaced by themselves"
+      (add-certname! certname)
+      (let [hash (add-catalog! catalog)]
+        (replace-catalog! catalog (now))
+
+        (is (= (query-to-vec ["SELECT name FROM certnames"])
+              [{:name certname}]))
+
+        (is (= (query-to-vec ["SELECT hash FROM catalogs"])
+              [{:hash hash}])))))
+  ;
   (deftest catalog-duplicates
-      (testing "should share structure when duplicate catalogs are detected for the same host"
-          (add-certname! certname)
-          (let [hash (add-catalog! catalog)
-                prev-dupe-num (.count (:duplicate-catalog metrics))
-                prev-new-num  (.count (:new-catalog metrics))]
-
-            ;; Do an initial replacement with the same catalog
-            (replace-catalog! catalog (now))
-            (is (= 1 (- (.count (:duplicate-catalog metrics)) prev-dupe-num)))
-            (is (= 0 (- (.count (:new-catalog metrics)) prev-new-num)))
-
-            ;; Store a second catalog, with the same content save the version
-            (replace-catalog! (assoc catalog :version "abc123") (now))
-            (is (= 2 (- (.count (:duplicate-catalog metrics)) prev-dupe-num)))
-            (is (= 0 (- (.count (:new-catalog metrics)) prev-new-num)))
-
-            (is (= (query-to-vec ["SELECT name FROM certnames"])
-                   [{:name certname}]))
-
-            (is (= (query-to-vec ["SELECT certname FROM certname_catalogs"])
-                   [{:certname certname}]))
-
-            (is (= (query-to-vec ["SELECT hash FROM catalogs"])
-                   [{:hash hash}])))))
+    (testing "should share structure when duplicate catalogs are detected for the same host"
+      (add-certname! certname)
+      (let [hash (add-catalog! catalog)
+            prev-dupe-num (.count (:duplicate-catalog metrics))
+            prev-new-num  (.count (:new-catalog metrics))]
+
+        ;; Do an initial replacement with the same catalog
+        (replace-catalog! catalog (now))
+        (is (= 1 (- (.count (:duplicate-catalog metrics)) prev-dupe-num)))
+        (is (= 0 (- (.count (:new-catalog metrics)) prev-new-num)))
+
+        ;; Store a second catalog, with the same content save the version
+        (replace-catalog! (assoc catalog :version "abc123") (now))
+        (is (= 2 (- (.count (:duplicate-catalog metrics)) prev-dupe-num)))
+        (is (= 0 (- (.count (:new-catalog metrics)) prev-new-num)))
+
+        (is (= (query-to-vec ["SELECT name FROM certnames"])
+              [{:name certname}]))
+
+        (is (= (query-to-vec ["SELECT certname FROM certname_catalogs"])
+              [{:certname certname}]))
+
+        (is (= (query-to-vec ["SELECT hash FROM catalogs"])
+              [{:hash hash}])))))

   (deftest catalog-empty
-      (testing "should not fail when inserting an 'empty' catalog"
-          (add-catalog! (:empty catalogs))))
+    (testing "should not fail when inserting an 'empty' catalog"
+      (add-catalog! (:empty catalogs))))

   (deftest catalog-manual-deletion
-      (testing "should noop if replaced by themselves after using manual deletion"
-          (add-certname! certname)
-          (add-catalog! catalog)
-          (delete-catalog! certname)
-          (add-catalog! catalog)
-
-          (is (= (query-to-vec ["SELECT name FROM certnames"])
-                 [{:name certname}]))))
+    (testing "should noop if replaced by themselves after using manual deletion"
+      (add-certname! certname)
+      (add-catalog! catalog)
+      (delete-catalog! certname)
+      (add-catalog! catalog)
+
+      (is (= (query-to-vec ["SELECT name FROM certnames"])
+            [{:name certname}]))))

   (deftest catalog-deletion-verify
-      (testing "should be removed when deleted"
-          (add-certname! certname)
-          (let [hash (add-catalog! catalog)]
-            (delete-catalog! hash))
-
-          (is (= (query-to-vec ["SELECT * FROM tags"])
-                 []))
-
-          (is (= (query-to-vec ["SELECT * FROM classes"])
-                 []))
-
-          (is (= (query-to-vec ["SELECT * FROM edges"])
-                 []))
-
-          (is (= (query-to-vec ["SELECT * FROM catalog_resources"])
-                 []))))
+    (testing "should be removed when deleted"
+      (add-certname! certname)
+      (let [hash (add-catalog! catalog)]
+        (delete-catalog! hash))
+
+      (is (= (query-to-vec ["SELECT * FROM tags"])
+            []))
+
+      (is (= (query-to-vec ["SELECT * FROM classes"])
+            []))
+
+      (is (= (query-to-vec ["SELECT * FROM edges"])
+            []))
+
+      (is (= (query-to-vec ["SELECT * FROM catalog_resources"])
+            []))))

   (deftest catalog-deletion-certnames
-      (testing "when deleted, should leave certnames alone"
-          (add-certname! certname)
-          (add-catalog! catalog)
-          (delete-catalog! certname)
-
-          (is (= (query-to-vec ["SELECT name FROM certnames"])
-                 [{:name certname}]))))
+    (testing "when deleted, should leave certnames alone"
+      (add-certname! certname)
+      (add-catalog! catalog)
+      (delete-catalog! certname)
+
+      (is (= (query-to-vec ["SELECT name FROM certnames"])
+            [{:name certname}]))))

   (deftest catalog-deletion-otherhosts
-      (testing "when deleted, should leave other hosts' resources alone"
-          (add-certname! certname)
-          (add-certname! "myhost2.mydomain.com")
-          (let [hash1 (add-catalog! catalog)
-                ;; Store the same catalog for a different host
-                hash2 (add-catalog! (assoc catalog :certname "myhost2.mydomain.com"))]
-            (associate-catalog-with-certname! hash1 certname (now))
-            (associate-catalog-with-certname! hash2 "myhost2.mydomain.com" (now))
-            (delete-catalog! hash1))
-
-          ;; myhost should still be present in the database
-          (is (= (query-to-vec ["SELECT name FROM certnames ORDER BY name"])
-                 [{:name certname} {:name "myhost2.mydomain.com"}]))
-
-          ;; myhost1 should not have any catalogs associated with it
-          ;; anymore
-          (is (= (query-to-vec ["SELECT certname FROM certname_catalogs ORDER BY certname"])
-                 [{:certname "myhost2.mydomain.com"}]))
-
-          ;; no tags for myhost
-          (is (= (query-to-vec [(str "SELECT t.name FROM tags t, certname_catalogs cc "
-                                     "WHERE t.catalog=cc.catalog AND cc.certname=?")
-                                     certname])
-                 []))
-
-          ;; no classes for myhost
-          (is (= (query-to-vec [(str "SELECT c.name FROM classes c, certname_catalogs cc "
-                                     "WHERE c.catalog=cc.catalog AND cc.certname=?")
-                                     certname])
-                 []))
-
-          ;; no edges for myhost
-          (is (= (query-to-vec [(str "SELECT COUNT(*) as c FROM edges e, certname_catalogs cc "
-                                     "WHERE e.catalog=cc.catalog AND cc.certname=?")
-                                     certname])
-                 [{:c 0}]))
-
-          ;; All the other resources should still be there
-          (is (= (query-to-vec ["SELECT COUNT(*) as c FROM catalog_resources"])
-                 [{:c 3}]))))
+    (testing "when deleted, should leave other hosts' resources alone"
+      (add-certname! certname)
+      (add-certname! "myhost2.mydomain.com")
+      (let [hash1 (add-catalog! catalog)
+            ;; Store the same catalog for a different host
+            hash2 (add-catalog! (assoc catalog :certname "myhost2.mydomain.com"))]
+        (associate-catalog-with-certname! hash1 certname (now))
+        (associate-catalog-with-certname! hash2 "myhost2.mydomain.com" (now))
+        (delete-catalog! hash1))
+
+      ;; myhost should still be present in the database
+      (is (= (query-to-vec ["SELECT name FROM certnames ORDER BY name"])
+            [{:name certname} {:name "myhost2.mydomain.com"}]))
+
+      ;; myhost1 should not have any catalogs associated with it
+      ;; anymore
+      (is (= (query-to-vec ["SELECT certname FROM certname_catalogs ORDER BY certname"])
+            [{:certname "myhost2.mydomain.com"}]))
+
+      ;; no tags for myhost
+      (is (= (query-to-vec [(str "SELECT t.name FROM tags t, certname_catalogs cc "
+                              "WHERE t.catalog=cc.catalog AND cc.certname=?")
+                            certname])
+            []))
+
+      ;; no classes for myhost
+      (is (= (query-to-vec [(str "SELECT c.name FROM classes c, certname_catalogs cc "
+                              "WHERE c.catalog=cc.catalog AND cc.certname=?")
+                            certname])
+            []))
+
+      ;; no edges for myhost
+      (is (= (query-to-vec [(str "SELECT COUNT(*) as c FROM edges e, certname_catalogs cc "
+                              "WHERE e.catalog=cc.catalog AND cc.certname=?")
+                            certname])
+            [{:c 0}]))
+
+      ;; All the other resources should still be there
+      (is (= (query-to-vec ["SELECT COUNT(*) as c FROM catalog_resources"])
+            [{:c 3}]))))

   (deftest catalog-delete-without-gc
-      (testing "when deleted without GC, should leave params"
-          (add-certname! certname)
-          (let [hash1 (add-catalog! catalog)]
-            (associate-catalog-with-certname! hash1 certname (now))
-            (delete-catalog! hash1))
-
-          ;; All the params should still be there
-          (is (= (query-to-vec ["SELECT COUNT(*) as c FROM resource_params"])
-                 [{:c 7}]))))
+    (testing "when deleted without GC, should leave params"
+      (add-certname! certname)
+      (let [hash1 (add-catalog! catalog)]
+        (associate-catalog-with-certname! hash1 certname (now))
+        (delete-catalog! hash1))
+
+      ;; All the params should still be there
+      (is (= (query-to-vec ["SELECT COUNT(*) as c FROM resource_params"])
+            [{:c 7}]))))

   (deftest catalog-delete-with-gc
-      (testing "when deleted and GC'ed, should leave no dangling params or edges"
-          (add-certname! certname)
-          (let [hash1 (add-catalog! catalog)]
-            (associate-catalog-with-certname! hash1 certname (now))
-            (delete-catalog! hash1))
-          (garbage-collect!)
-
-          (is (= (query-to-vec ["SELECT * FROM resource_params"])
-                 []))
-          (is (= (query-to-vec ["SELECT * FROM edges"])
-                 []))))
+    (testing "when deleted and GC'ed, should leave no dangling params or edges"
+      (add-certname! certname)
+      (let [hash1 (add-catalog! catalog)]
+        (associate-catalog-with-certname! hash1 certname (now))
+        (delete-catalog! hash1))
+      (garbage-collect!)
+
+      (is (= (query-to-vec ["SELECT * FROM resource_params"])
+            []))
+      (is (= (query-to-vec ["SELECT * FROM edges"])
+            []))))

   (deftest catalog-dissociation-without-gc
-      (testing "when dissociated and not GC'ed, should still exist"
-          (add-certname! certname)
-          (let [hash1 (add-catalog! catalog)]
-            (associate-catalog-with-certname! hash1 certname (now))
-            (dissociate-catalog-with-certname! hash1 certname))
-
-          (is (= (query-to-vec ["SELECT * FROM certname_catalogs"])
-                 []))
-
-          (is (= (query-to-vec ["SELECT COUNT(*) as c FROM catalogs"])
-                 [{:c 1}]))))
+    (testing "when dissociated and not GC'ed, should still exist"
+      (add-certname! certname)
+      (let [hash1 (add-catalog! catalog)]
+        (associate-catalog-with-certname! hash1 certname (now))
+        (dissociate-catalog-with-certname! hash1 certname))
+
+      (is (= (query-to-vec ["SELECT * FROM certname_catalogs"])
+            []))
+
+      (is (= (query-to-vec ["SELECT COUNT(*) as c FROM catalogs"])
+            [{:c 1}]))))

   (deftest catalog-dissociation-with-gc
-      (testing "when dissociated and GC'ed, should no longer exist"
-          (add-certname! certname)
-          (let [hash1 (add-catalog! catalog)]
-            (associate-catalog-with-certname! hash1 certname (now))
-            (dissociate-catalog-with-certname! hash1 certname))
-          (garbage-collect!)
-
-          (is (= (query-to-vec ["SELECT * FROM certname_catalogs"])
-                 []))
-
-          (is (= (query-to-vec ["SELECT * FROM catalogs"])
-                 [])))))
+    (testing "when dissociated and GC'ed, should no longer exist"
+      (add-certname! certname)
+      (let [hash1 (add-catalog! catalog)]
+        (associate-catalog-with-certname! hash1 certname (now))
+        (dissociate-catalog-with-certname! hash1 certname))
+      (garbage-collect!)
+
+      (is (= (query-to-vec ["SELECT * FROM certname_catalogs"])
+            []))
+
+      (is (= (query-to-vec ["SELECT * FROM catalogs"])
+            [])))))

 (deftest catalog-bad-input
   (testing "should noop"
     (testing "on bad input"
-        (is (thrown? AssertionError (add-catalog! {})))
-
-        ; Nothing should have been persisted for this catalog
-        (is (= (query-to-vec ["SELECT count(*) as nrows from certnames"])
-               [{:nrows 0}])))))
+      (is (thrown? AssertionError (add-catalog! {})))
+
+      ; Nothing should have been persisted for this catalog
+      (is (= (query-to-vec ["SELECT count(*) as nrows from certnames"])
+            [{:nrows 0}])))))

 (deftest catalog-referential-integrity-violation
-    (testing "on input that violates referential integrity"
-      ; This catalog has an edge that points to a non-existant resource
-      (let [catalog (:invalid catalogs)]
-          (is (thrown? AssertionError (add-catalog! {})))
-
-          ; Nothing should have been persisted for this catalog
-          (is (= (query-to-vec ["SELECT count(*) as nrows from certnames"])
-                 [{:nrows 0}])))))
+  (testing "on input that violates referential integrity"
+    ; This catalog has an edge that points to a non-existant resource
+    (let [catalog (:invalid catalogs)]
+      (is (thrown? AssertionError (add-catalog! {})))
+
+      ; Nothing should have been persisted for this catalog
+      (is (= (query-to-vec ["SELECT count(*) as nrows from certnames"])
+            [{:nrows 0}])))))

 (deftest node-deactivation
-    (let [certname        "foo.example.com"
-          query-certnames #(query-to-vec ["select name, deactivated from certnames"])
-          deactivated?    #(instance? java.sql.Timestamp (:deactivated %))]
-      (add-certname! certname)
-
-      (testing "deactivating a node"
-        (testing "should mark the node as deactivated"
+  (let [certname        "foo.example.com"
+        query-certnames #(query-to-vec ["select name, deactivated from certnames"])
+        deactivated?    #(instance? java.sql.Timestamp (:deactivated %))]
+    (add-certname! certname)
+
+    (testing "deactivating a node"
+      (testing "should mark the node as deactivated"
+        (deactivate-node! certname)
+        (let [result (first (query-certnames))]
+          (is (= certname (:name result)))
+          (is (deactivated? result))))
+
+      (testing "should not change the node if it's already inactive"
+        (let [original (query-certnames)]
           (deactivate-node! certname)
+          (is (= original (query-certnames))))))
+
+    (testing "activating a node"
+      (testing "should activate the node if it was inactive"
+        (activate-node! certname)
+        (is (= (query-certnames) [{:name certname :deactivated nil}])))
+
+      (testing "should do nothing if the node is already active"
+        (let [original (query-certnames)]
+          (activate-node! certname)
+          (is (= original (query-certnames))))))
+
+    (testing "auto-reactivated based on a command"
+      (let [before-deactivating (to-timestamp (ago (days 1)))
+            after-deactivating  (to-timestamp (from-now (days 1)))]
+        (testing "should activate the node if the command happened after it was deactivated"
+          (deactivate-node! certname)
+          (is (= true (maybe-activate-node! certname after-deactivating)))
+          (is (= (query-certnames) [{:name certname :deactivated nil}])))
+
+        (testing "should not activate the node if the command happened before it was deactivated"
+          (deactivate-node! certname)
+          (is (= false (maybe-activate-node! certname before-deactivating)))
           (let [result (first (query-certnames))]
             (is (= certname (:name result)))
             (is (deactivated? result))))

-        (testing "should not change the node if it's already inactive"
-          (let [original (query-certnames)]
-            (deactivate-node! certname)
-            (is (= original (query-certnames))))))
-
-      (testing "activating a node"
-        (testing "should activate the node if it was inactive"
+        (testing "should do nothing if the node is already active"
           (activate-node! certname)
-          (is (= (query-certnames) [{:name certname :deactivated nil}])))
-
-        (testing "should do nothing if the node is already active"
-          (let [original (query-certnames)]
-            (activate-node! certname)
-            (is (= original (query-certnames))))))
-
-      (testing "auto-reactivated based on a command"
-        (let [before-deactivating (to-timestamp (ago (days 1)))
-              after-deactivating  (to-timestamp (from-now (days 1)))]
-          (testing "should activate the node if the command happened after it was deactivated"
-            (deactivate-node! certname)
-            (is (= true (maybe-activate-node! certname after-deactivating)))
-            (is (= (query-certnames) [{:name certname :deactivated nil}])))
-
-          (testing "should not activate the node if the command happened before it was deactivated"
-            (deactivate-node! certname)
-            (is (= false (maybe-activate-node! certname before-deactivating)))
-            (let [result (first (query-certnames))]
-              (is (= certname (:name result)))
-              (is (deactivated? result))))
-
-          (testing "should do nothing if the node is already active"
-            (activate-node! certname)
-            (is (= true (maybe-activate-node! certname (now))))
-            (is (= (query-certnames) [{:name certname :deactivated nil}])))))))
+          (is (= true (maybe-activate-node! certname (now))))
+          (is (= (query-certnames) [{:name certname :deactivated nil}])))))))

 (deftest node-staleness-age
   (testing "retrieving stale nodes based on age"
@@ -458,27 +458,27 @@
           deactivated?    #(instance? java.sql.Timestamp (:deactivated %))]

       (testing "should return nothing if all nodes are more recent than max age"
-          (let [catalog (:empty catalogs)
-                certname (:certname catalog)]
-            (add-certname! certname)
-            (replace-catalog! catalog (now))
-              (is (= (stale-nodes (ago (days 1))) [])))))))
+        (let [catalog (:empty catalogs)
+              certname (:certname catalog)]
+          (add-certname! certname)
+          (replace-catalog! catalog (now))
+          (is (= (stale-nodes (ago (days 1))) [])))))))

 (deftest node-stale-catalogs-facts
-      (testing "should return nodes with a mixture of stale catalogs and facts (or neither)"
-        (let [mutators [#(replace-catalog! (assoc (:empty catalogs) :certname "node1") (ago (days 2)))
-                        #(replace-facts! {"name" "node1" "values" {"foo" "bar"}} (ago (days 2)))]]
-          (add-certname! "node1")
-          (doseq [func-set (subsets mutators)]
-              (dorun (map #(%) func-set))
-              (is (= (stale-nodes (ago (days 1))) ["node1"]))))))
+  (testing "should return nodes with a mixture of stale catalogs and facts (or neither)"
+    (let [mutators [#(replace-catalog! (assoc (:empty catalogs) :certname "node1") (ago (days 2)))
+                    #(replace-facts! {"name" "node1" "values" {"foo" "bar"}} (ago (days 2)))]]
+      (add-certname! "node1")
+      (doseq [func-set (subsets mutators)]
+        (dorun (map #(%) func-set))
+        (is (= (stale-nodes (ago (days 1))) ["node1"]))))))

 (deftest node-max-age
-      (testing "should only return nodes older than max age, and leave others alone"
-          (let [catalog (:empty catalogs)]
-            (add-certname! "node1")
-            (add-certname! "node2")
-            (replace-catalog! (assoc catalog :certname "node1") (ago (days 2)))
-            (replace-catalog! (assoc catalog :certname "node2") (now))
-
-            (is (= (set (stale-nodes (ago (days 1)))) #{"node1"})))))
+  (testing "should only return nodes older than max age, and leave others alone"
+    (let [catalog (:empty catalogs)]
+      (add-certname! "node1")
+      (add-certname! "node2")
+      (replace-catalog! (assoc catalog :certname "node1") (ago (days 2)))
+      (replace-catalog! (assoc catalog :certname "node2") (now))
+
+      (is (= (set (stale-nodes (ago (days 1)))) #{"node1"})))))


Support ::dynamics for testing foreign parsers on planner test

--- test/com/wsscode/pathom/connect/planner_test.cljc
+++ test/com/wsscode/pathom/connect/planner_test.cljc
@@ -1,9 +1,9 @@
 (ns com.wsscode.pathom.connect.planner-test
-  (:require [clojure.edn :as edn]
-            [clojure.java.io :as io]
+  (:require [clojure.java.io :as io]
             [clojure.test :refer :all]
             [clojure.walk :as walk]
             [com.wsscode.pathom.connect :as pc]
+            [com.wsscode.pathom.connect.foreign :as pcf]
             [com.wsscode.pathom.connect.planner :as pcp]
             [com.wsscode.pathom.core :as p]
             [edn-query-language.core :as eql]
@@ -85,7 +85,7 @@
     env))

 (defn compute-run-graph
-  [{::keys     [resolvers render-graphviz? time?]
+  [{::keys     [resolvers render-graphviz? time? dynamics]
     ::eql/keys [query]
     :or        {render-graphviz? true
                 time?            false}
@@ -96,7 +96,17 @@
                                    (assoc :edn-query-language.ast/node
                                      (eql/query->ast (p/lift-placeholders (base-graph-env) query)))))
                   resolvers
-                  (pc/merge-indexes (register-index resolvers)))
+                  (pc/merge-indexes (register-index resolvers))
+
+                  dynamics
+                  (as-> <>
+                    (reduce
+                      (fn [env' [name resolvers]]
+                        (pc/merge-indexes env'
+                          (pcf/internalize-parser-index*
+                            (assoc (register-index resolvers) ::pc/index-source-id name))))
+                      <>
+                      dynamics)))
         options (assoc options ::env env)]
     (cond->
       (if time?


*test-out* interferes with slime, so I ignore it.

--- src/midje/util/report.clj
+++ src/midje/util/report.clj
@@ -6,36 +6,36 @@

 (defmethod clojure.test/report :mock-argument-match-failure [m]
-  (with-test-out
+;  (with-test-out
    (inc-report-counter :fail)
    (println "\nFAIL at" (midje-position-string (:position m)))
    (when (seq *testing-contexts*) (println (testing-contexts-str)))
    (println "You never said" (:name (meta (:function m))) "would be called with these arguments:")
-   (println (pr-str (:actual m)))))
+   (println (pr-str (:actual m))))

 (defmethod clojure.test/report :mock-incorrect-call-count [m]
-  (with-test-out
+;  (with-test-out
    (inc-report-counter :fail)
    (println "\nFAIL for" (midje-position-string (:position m)))
    (when (seq *testing-contexts*) (println (testing-contexts-str)))
    (println "This expectation was never satisfied:")
-   (println (:expected m) "should be called at least once.")))
+   (println (:expected m) "should be called at least once."))

 (defmethod clojure.test/report :mock-expected-result-failure [m]
-  (with-test-out
+;  (with-test-out
    (inc-report-counter :fail)
    (println "\nFAIL at" (midje-position-string (:position m)))
    (when (seq *testing-contexts*) (println (testing-contexts-str)))
    (println "expected:" (pr-str (:expected m)))
-   (println "  actual:" (pr-str (:actual m)))))
+   (println "  actual:" (pr-str (:actual m))))

 (defmethod clojure.test/report :mock-expected-result-functional-failure [m]
-  (with-test-out
+;  (with-test-out
    (inc-report-counter :fail)
    (println "\nFAIL at" (midje-position-string (:position m)))
    (when (seq *testing-contexts*) (println (testing-contexts-str)))
    (println "Actual result did not pass expected function.")
    (println "expected function:" (pr-str (:expected m)))
-   (println "    actual result:" (pr-str (:actual m)))))
+   (println "    actual result:" (pr-str (:actual m))))


Minor: comment explaining smoothing

Minor: comment explaining smoothing

--- src/cljs/fractals_clojurescript/core.cljs
+++ src/cljs/fractals_clojurescript/core.cljs
@@ -25,6 +25,8 @@

 (defn smoothed-count
+  "Smooth the iterations to a continuous value
+  (a la http://linas.org/art-gallery/escape/escape.html)"
   [iterations final-modulus]
   (- iterations
      (/


CMR-766: Added additional special case polygons.


CMR-525: retrieve concept by id should not return deleted ones.

--- src/cmr/search/services/query_service.clj
+++ src/cmr/search/services/query_service.clj
@@ -120,7 +120,12 @@
 (deftracefn find-concept-by-id
   "Executes a search to metadata-db and returns the concept with the given cmr-concept-id."
   [context concept-id]
-  (meta-db/get-latest-concept context concept-id))
+  (let [concept (meta-db/get-latest-concept context concept-id)]
+    (when (:deleted concept)
+      (err/throw-service-error
+        :not-found
+        (format "Concept with concept-id: %s has been deleted" concept-id)))
+    concept))

 (deftracefn reset
   "Clear the cache for search app"


re-enable our unit tests against native SQL substitution.

--- test/metabase/query_processor/parameters_test.clj
+++ test/metabase/query_processor/parameters_test.clj
@@ -12,7 +12,7 @@
             [metabase.test.util :as tu]))

 (tu/resolve-private-fns metabase.query-processor.parameters
-  absolute-date->range)
+  absolute-date->range relative-date->range expand-date-range-param)

 (expect {:end "2016-03-31", :start "2016-01-01"} (absolute-date->range "Q1-2016"))
 (expect {:end "2016-02-29", :start "2016-02-01"} (absolute-date->range "2016-02"))
@@ -20,201 +20,201 @@
 (expect {:end "2016-04-23", :start "2016-04-18"} (absolute-date->range "2016-04-18~2016-04-23"))

 ;; we hard code "now" to a specific point in time so that we can control the test output
-;(defn- test-relative [value]
-;  (with-redefs-fn {#'clj-time.core/now (fn [] (t/date-time 2016 06 07 12 0 0))}
-;    #(relative-date->range value nil)))
-;
-;(expect {:end "2016-06-06", :start "2016-05-31"} (test-relative "past7days"))
-;(expect {:end "2016-06-06", :start "2016-05-08"} (test-relative "past30days"))
-;(expect {:end "2016-06-11", :start "2016-06-05"} (test-relative "thisweek"))
-;(expect {:end "2016-06-30", :start "2016-06-01"} (test-relative "thismonth"))
-;(expect {:end "2016-12-31", :start "2016-01-01"} (test-relative "thisyear"))
-;(expect {:end "2016-06-04", :start "2016-05-29"} (test-relative "lastweek"))
-;(expect {:end "2016-05-31", :start "2016-05-01"} (test-relative "lastmonth"))
-;(expect {:end "2015-12-31", :start "2015-01-01"} (test-relative "lastyear"))
-;(expect {:end "2016-06-06", :start "2016-06-06"} (test-relative "yesterday"))
-;(expect {:end "2016-06-07", :start "2016-06-07"} (test-relative "today"))
+(defn- test-relative [value]
+  (with-redefs-fn {#'clj-time.core/now (fn [] (t/date-time 2016 06 07 12 0 0))}
+    #(relative-date->range value nil)))
+
+(expect {:end "2016-06-06", :start "2016-05-31"} (test-relative "past7days"))
+(expect {:end "2016-06-06", :start "2016-05-08"} (test-relative "past30days"))
+(expect {:end "2016-06-11", :start "2016-06-05"} (test-relative "thisweek"))
+(expect {:end "2016-06-30", :start "2016-06-01"} (test-relative "thismonth"))
+(expect {:end "2016-12-31", :start "2016-01-01"} (test-relative "thisyear"))
+(expect {:end "2016-06-04", :start "2016-05-29"} (test-relative "lastweek"))
+(expect {:end "2016-05-31", :start "2016-05-01"} (test-relative "lastmonth"))
+(expect {:end "2015-12-31", :start "2015-01-01"} (test-relative "lastyear"))
+(expect {:end "2016-06-06", :start "2016-06-06"} (test-relative "yesterday"))
+(expect {:end "2016-06-07", :start "2016-06-07"} (test-relative "today"))

 ;;; +-------------------------------------------------------------------------------------------------------+
 ;;; |                                           NATIVE QUERIES                                             |
 ;;; +-------------------------------------------------------------------------------------------------------+

-;(defrecord NativeParametersDriver []
-;  clojure.lang.Named
-;  (getName [_] "NativeParametersDriver"))
-;
-;(extend NativeParametersDriver
-;  driver/IDriver
-;  {:features (constantly #{:native-parameters})})
-;
-;(defrecord NonParametersDriver []
-;  clojure.lang.Named
-;  (getName [_] "NonParametersDriver"))
-;
-;(extend NonParametersDriver
-;  driver/IDriver
-;  {:features (constantly #{})})
-;
-;;; basic parameter substitution
-;(expect
-;  {:database   1
-;   :driver     (NativeParametersDriver.)
-;   :type       :native
-;   :native     {:query "SELECT * FROM table WHERE id = 666"}}
-;  (expand-parameters {:database   1
-;                      :driver     (NativeParametersDriver.)
-;                      :type       :native
-;                      :native     {:query "SELECT * FROM table WHERE id = {{foo}}"}
-;                      :parameters [{:hash   "abc123"
-;                                    :name   "foo"
-;                                    :type   "id"
-;                                    :target ["parameter" "foo"]
-;                                    :value  "666"}]}))
-;
-;;; independent subclause substitution
-;(expect
-;  {:database   1
-;   :driver     (NativeParametersDriver.)
-;   :type       :native
-;   :native     {:query "SELECT * FROM table WHERE id = 123 AND foo = 666"}}
-;  (expand-parameters {:database   1
-;                      :driver     (NativeParametersDriver.)
-;                      :type       :native
-;                      :native     {:query "SELECT * FROM table WHERE id = 123 <AND foo = {{foo}}>"}
-;                      :parameters [{:hash   "abc123"
-;                                    :name   "foo"
-;                                    :type   "id"
-;                                    :target ["parameter" "foo"]
-;                                    :value  "666"}]}))
-;
-;;; multi-clause substitution (subclauses are joined by SQL "AND")
-;(expect
-;  {:database   1
-;   :driver     (NativeParametersDriver.)
-;   :type       :native
-;   :native     {:query "SELECT * FROM table WHERE foo=666 AND bar='yipee'"}}
-;  (expand-parameters {:database   1
-;                      :driver     (NativeParametersDriver.)
-;                      :type       :native
-;                      :native     {:query "SELECT * FROM table [[WHERE <foo={{foo}}> <bar='{{bar}}'>]]"}
-;                      :parameters [{:hash   "abc123"
-;                                    :name   "foo"
-;                                    :type   "id"
-;                                    :target ["parameter" "foo"]
-;                                    :value  "666"}
-;                                   {:hash   "def456"
-;                                    :name   "bar"
-;                                    :type   "category"
-;                                    :target ["parameter" "bar"]
-;                                    :value  "yipee"}]}))
-;
-;;; date range substitution
-;(expect
-;  (let [yesterday (tf/unparse (tf/formatters :year-month-day) (t/yesterday))]
-;    {:database   1
-;     :driver     (NativeParametersDriver.)
-;     :type       :native
-;     :native     {:query (str "SELECT * FROM table WHERE date BETWEEN '" yesterday "' AND '" yesterday "'")}})
-;  (expand-parameters {:database   1
-;                      :driver     (NativeParametersDriver.)
-;                      :type       :native
-;                      :native     {:query "SELECT * FROM table WHERE date BETWEEN '{{foo:start}}' AND '{{foo:end}}'"}
-;                      :parameters [{:hash   "abc123"
-;                                    :name   "foo"
-;                                    :type   "date"
-;                                    :target ["parameter" "foo"]
-;                                    :value  "yesterday"}]}))
-;
-;;; if target is not appropriate then parameter is skipped
-;(expect
-;  {:database   1
-;   :driver     (NativeParametersDriver.)
-;   :type       :native
-;   :native     {:query "SELECT * FROM table WHERE id = 123 "}}
-;  (expand-parameters {:database   1
-;                      :driver     (NativeParametersDriver.)
-;                      :type       :native
-;                      :native     {:query "SELECT * FROM table WHERE id = 123 <AND foo = {{foo}}>"}
-;                      :parameters [{:hash   "abc123"
-;                                    :name   "foo"
-;                                    :type   "id"
-;                                    :target ["dimension" ["field" 123]]
-;                                    :value  "666"}]}))
-;
-;;; date range calculations
-;(expect
-;  [{:type "date", :target ["parameter" "foo:start"], :value "2014-05-10"}
-;   {:type "date", :target ["parameter" "foo:end"], :value "2014-05-16"}]
-;  (expand-date-range-param nil {:target ["parameter" "foo"], :type "date", :value "2014-05-10~2014-05-16"}))
-;
-;(expect
-;  [{:type "date", :target ["parameter" "foo:start"], :value (tf/unparse (tf/formatters :year-month-day) (t/yesterday))}
-;   {:type "date", :target ["parameter" "foo:end"], :value (tf/unparse (tf/formatters :year-month-day) (t/yesterday))}]
-;  (expand-date-range-param nil {:target ["parameter" "foo"], :type "date", :value "yesterday"}))
-;
-;;; if driver doesn't support :native-parameters then we skip any substitutions
-;(expect
-;  {:database   1
-;   :driver     (NonParametersDriver.)
-;   :type       :native
-;   :native     {:query "SELECT * FROM table [[WHERE <foo={{foo}}> <bar='{{bar}}'>]]"}}
-;  (expand-parameters {:database   1
-;                      :driver     (NonParametersDriver.)
-;                      :type       :native
-;                      :native     {:query "SELECT * FROM table [[WHERE <foo={{foo}}> <bar='{{bar}}'>]]"}
-;                      :parameters [{:hash   "abc123"
-;                                    :name   "foo"
-;                                    :type   "id"
-;                                    :target ["parameter" "foo"]
-;                                    :value  "666"}]}))
-;
-;;; incomplete clauses are removed (but unmatched individual variables are untouched)
-;(expect
-;  {:database   1
-;   :driver     (NativeParametersDriver.)
-;   :type       :native
-;   :native     {:query "SELECT * FROM table WHERE id = {{foo}}"}}
-;  (expand-parameters {:database   1
-;                      :driver     (NativeParametersDriver.)
-;                      :type       :native
-;                      :native     {:query "SELECT * FROM table WHERE id = {{foo}}"}}))
-;
-;(expect
-;  {:database   1
-;   :driver     (NativeParametersDriver.)
-;   :type       :native
-;   :native     {:query "SELECT * FROM table WHERE "}}
-;  (expand-parameters {:database   1
-;                      :driver     (NativeParametersDriver.)
-;                      :type       :native
-;                      :native     {:query "SELECT * FROM table WHERE <id = {{foo}}>"}}))
-;
-;(expect
-;  {:database   1
-;   :driver     (NativeParametersDriver.)
-;   :type       :native
-;   :native     {:query "SELECT * FROM table "}}
-;  (expand-parameters {:database   1
-;                      :driver     (NativeParametersDriver.)
-;                      :type       :native
-;                      :native     {:query "SELECT * FROM table [[WHERE id = {{foo}}]]"}}))
-;
-;;; when only part of an outer-clause is substituted we remove the entire outer-clause
-;(expect
-;  {:database   1
-;   :driver     (NativeParametersDriver.)
-;   :type       :native
-;   :native     {:query "SELECT * FROM table "}}
-;  (expand-parameters {:database   1
-;                      :driver     (NativeParametersDriver.)
-;                      :type       :native
-;                      :native     {:query "SELECT * FROM table [[WHERE <id = {{foo}}> <blah={{blah}}>]]"}
-;                      :parameters [{:hash   "abc123"
-;                                    :name   "foo"
-;                                    :type   "id"
-;                                    :target ["parameter" "foo"]
-;                                    :value  "666"}]}))
+(defrecord NativeParametersDriver []
+  clojure.lang.Named
+  (getName [_] "NativeParametersDriver"))
+
+(extend NativeParametersDriver
+  driver/IDriver
+  {:features (constantly #{:native-parameters})})
+
+(defrecord NonParametersDriver []
+  clojure.lang.Named
+  (getName [_] "NonParametersDriver"))
+
+(extend NonParametersDriver
+  driver/IDriver
+  {:features (constantly #{})})
+
+;; basic parameter substitution
+(expect
+  {:database   1
+   :driver     (NativeParametersDriver.)
+   :type       :native
+   :native     {:query "SELECT * FROM table WHERE id = 666"}}
+  (expand-parameters {:database   1
+                      :driver     (NativeParametersDriver.)
+                      :type       :native
+                      :native     {:query "SELECT * FROM table WHERE id = {{foo}}"}
+                      :parameters [{:hash   "abc123"
+                                    :name   "foo"
+                                    :type   "id"
+                                    :target ["parameter" "foo"]
+                                    :value  "666"}]}))
+
+;; independent subclause substitution
+(expect
+  {:database   1
+   :driver     (NativeParametersDriver.)
+   :type       :native
+   :native     {:query "SELECT * FROM table WHERE id = 123 AND foo = 666"}}
+  (expand-parameters {:database   1
+                      :driver     (NativeParametersDriver.)
+                      :type       :native
+                      :native     {:query "SELECT * FROM table WHERE id = 123 <AND foo = {{foo}}>"}
+                      :parameters [{:hash   "abc123"
+                                    :name   "foo"
+                                    :type   "id"
+                                    :target ["parameter" "foo"]
+                                    :value  "666"}]}))
+
+;; multi-clause substitution (subclauses are joined by SQL "AND")
+(expect
+  {:database   1
+   :driver     (NativeParametersDriver.)
+   :type       :native
+   :native     {:query "SELECT * FROM table WHERE foo=666 AND bar='yipee'"}}
+  (expand-parameters {:database   1
+                      :driver     (NativeParametersDriver.)
+                      :type       :native
+                      :native     {:query "SELECT * FROM table [[WHERE <foo={{foo}}> <bar='{{bar}}'>]]"}
+                      :parameters [{:hash   "abc123"
+                                    :name   "foo"
+                                    :type   "id"
+                                    :target ["parameter" "foo"]
+                                    :value  "666"}
+                                   {:hash   "def456"
+                                    :name   "bar"
+                                    :type   "category"
+                                    :target ["parameter" "bar"]
+                                    :value  "yipee"}]}))
+
+;; date range substitution
+(expect
+  (let [yesterday (tf/unparse (tf/formatters :year-month-day) (t/yesterday))]
+    {:database   1
+     :driver     (NativeParametersDriver.)
+     :type       :native
+     :native     {:query (str "SELECT * FROM table WHERE date BETWEEN '" yesterday "' AND '" yesterday "'")}})
+  (expand-parameters {:database   1
+                      :driver     (NativeParametersDriver.)
+                      :type       :native
+                      :native     {:query "SELECT * FROM table WHERE date BETWEEN '{{foo:start}}' AND '{{foo:end}}'"}
+                      :parameters [{:hash   "abc123"
+                                    :name   "foo"
+                                    :type   "date"
+                                    :target ["parameter" "foo"]
+                                    :value  "yesterday"}]}))
+
+;; if target is not appropriate then parameter is skipped
+(expect
+  {:database   1
+   :driver     (NativeParametersDriver.)
+   :type       :native
+   :native     {:query "SELECT * FROM table WHERE id = 123 "}}
+  (expand-parameters {:database   1
+                      :driver     (NativeParametersDriver.)
+                      :type       :native
+                      :native     {:query "SELECT * FROM table WHERE id = 123 <AND foo = {{foo}}>"}
+                      :parameters [{:hash   "abc123"
+                                    :name   "foo"
+                                    :type   "id"
+                                    :target ["dimension" ["field" 123]]
+                                    :value  "666"}]}))
+
+;; date range calculations
+(expect
+  [{:type "date", :target ["parameter" "foo:start"], :value "2014-05-10"}
+   {:type "date", :target ["parameter" "foo:end"], :value "2014-05-16"}]
+  (expand-date-range-param nil {:target ["parameter" "foo"], :type "date", :value "2014-05-10~2014-05-16"}))
+
+(expect
+  [{:type "date", :target ["parameter" "foo:start"], :value (tf/unparse (tf/formatters :year-month-day) (t/yesterday))}
+   {:type "date", :target ["parameter" "foo:end"], :value (tf/unparse (tf/formatters :year-month-day) (t/yesterday))}]
+  (expand-date-range-param nil {:target ["parameter" "foo"], :type "date", :value "yesterday"}))
+
+;; if driver doesn't support :native-parameters then we skip any substitutions
+(expect
+  {:database   1
+   :driver     (NonParametersDriver.)
+   :type       :native
+   :native     {:query "SELECT * FROM table [[WHERE <foo={{foo}}> <bar='{{bar}}'>]]"}}
+  (expand-parameters {:database   1
+                      :driver     (NonParametersDriver.)
+                      :type       :native
+                      :native     {:query "SELECT * FROM table [[WHERE <foo={{foo}}> <bar='{{bar}}'>]]"}
+                      :parameters [{:hash   "abc123"
+                                    :name   "foo"
+                                    :type   "id"
+                                    :target ["parameter" "foo"]
+                                    :value  "666"}]}))
+
+;; incomplete clauses are removed (but unmatched individual variables are untouched)
+(expect
+  {:database   1
+   :driver     (NativeParametersDriver.)
+   :type       :native
+   :native     {:query "SELECT * FROM table WHERE id = {{foo}}"}}
+  (expand-parameters {:database   1
+                      :driver     (NativeParametersDriver.)
+                      :type       :native
+                      :native     {:query "SELECT * FROM table WHERE id = {{foo}}"}}))
+
+(expect
+  {:database   1
+   :driver     (NativeParametersDriver.)
+   :type       :native
+   :native     {:query "SELECT * FROM table WHERE "}}
+  (expand-parameters {:database   1
+                      :driver     (NativeParametersDriver.)
+                      :type       :native
+                      :native     {:query "SELECT * FROM table WHERE <id = {{foo}}>"}}))
+
+(expect
+  {:database   1
+   :driver     (NativeParametersDriver.)
+   :type       :native
+   :native     {:query "SELECT * FROM table "}}
+  (expand-parameters {:database   1
+                      :driver     (NativeParametersDriver.)
+                      :type       :native
+                      :native     {:query "SELECT * FROM table [[WHERE id = {{foo}}]]"}}))
+
+;; when only part of an outer-clause is substituted we remove the entire outer-clause
+(expect
+  {:database   1
+   :driver     (NativeParametersDriver.)
+   :type       :native
+   :native     {:query "SELECT * FROM table "}}
+  (expand-parameters {:database   1
+                      :driver     (NativeParametersDriver.)
+                      :type       :native
+                      :native     {:query "SELECT * FROM table [[WHERE <id = {{foo}}> <blah={{blah}}>]]"}
+                      :parameters [{:hash   "abc123"
+                                    :name   "foo"
+                                    :type   "id"
+                                    :target ["parameter" "foo"]
+                                    :value  "666"}]}))

 ;;; +-------------------------------------------------------------------------------------------------------+


make timeout configurable

make timeout configurable

--- clients/clojure/src/samsara/client.clj
+++ clients/clojure/src/samsara/client.clj
@@ -20,6 +20,7 @@
          :sourceId (str (java.util.UUID/randomUUID))
          :publish-interval 3600 ;seconds
          :max-buffer-size 1500
+         :send-timeout-ms  3000
          }))

 (defn get-samsara-config [] @samsara-config)
@@ -90,7 +91,7 @@
 (defn- send-events [events]
   "Send events to samsara api"
   (let [{:keys [status error] :as resp} @(http/post (str (:url (get-samsara-config)) "/events")
-                                                    {:timeout 500 ;;ms
+                                                    {:timeout (:send-timeout-ms (get-samsara-config))
                                                      :headers {"Content-Type" "application/json"
                                                                "X-Samsara-publishedTimestamp" (str (System/currentTimeMillis))}
                                                      :body (to-json events)})]


Fix reference to tasks

Fix reference to tasks

--- src/todo_repl_webapp/handler.clj
+++ src/todo_repl_webapp/handler.clj
@@ -8,7 +8,7 @@

 (defroutes app-routes
   (GET "/" [] "Hello World")
-  (GET "/home" [] (views/home (tasks)))
+  (GET "/home" [] (views/home (web-repl/tasks)))
   (POST "/eval" [evalInput]
     (let [eval-result (e/evaluate evalInput)]
       (println "/eval " evalInput " evals to: " eval-result)


changed docstrings

changed docstrings

changed docstrings for hundreds-to-string and thousands-to-string

--- src/numberreader/core.clj
+++ src/numberreader/core.clj
@@ -63,7 +63,7 @@

 (defn hundreds-to-string
   "Takes a number in the range 0 to 9.
-  Returns a blank string if zero and the string \"arg hundred\" otherwise."
+  Returns a blank string if zero and the string \"hs hundred\" otherwise."
   [hs]
   (if (zero? hs)
     ""
@@ -71,7 +71,7 @@

 (defn thousands-to-string
   "Takes a number in the range 0 to 9.
-  Returns a blank string if zero and and the string \"arg thousand\" otherwise."
+  Returns a blank string if zero and and the string \"ths thousand\" otherwise."
   [ths]
   (if (zero? ths)
     ""


Add io!.

Add io!.

--- src/fhofherr/clj_db_util/transactions.clj
+++ src/fhofherr/clj_db_util/transactions.clj
@@ -81,8 +81,9 @@
   to perform their tasks (this might not be a good idea, in which case I'll
   remove the dialect)."
   [db tx]
-  (jdbc/with-db-transaction [db* (db-repr/db-spec db)]
-    (::value ((:op tx) (db-repr/from-db-spec (db-repr/dialect db) db*)))))
+  (io!
+    (jdbc/with-db-transaction [db* (db-repr/db-spec db)]
+      (::value ((:op tx) (db-repr/from-db-spec (db-repr/dialect db) db*))))))

 (deftx tx-rollback
   "Rollback the transaction. Further steps won't be executed."


Improve error handling.

Improve error handling.

--- src/onyx/plugin/kafka.clj
+++ src/onyx/plugin/kafka.clj
@@ -257,12 +257,11 @@
           :else
           (ProducerRecord. message-topic message-partition k (serializer-fn message)))))

-(defn clear-write-futures! [write-futures]
-  (vswap! write-futures
-          (fn [fs]
-            (when-not (empty? (filter #(.isCancelled ^java.util.concurrent.Future %) fs))
-              (throw (ex-info "Failed assertion: kafka writes cancelled. Rebooting." {})))
-            (doall (remove realized? fs)))))
+(defn clear-write-futures! [fs]
+  (doall (remove (fn [f]
+                   (assert (not (.isCancelled ^java.util.concurrent.Future f)))
+                   (realized? f))
+                 fs)))

 (defrecord KafkaWriteMessages [task-map config topic kpartition producer key-serializer-fn serializer-fn write-futures exception write-callback]
   p/Plugin
@@ -276,11 +275,11 @@
   p/BarrierSynchronization
   (synced? [this epoch]
     (when @exception (throw @exception))
-    (empty? (clear-write-futures! write-futures)))
+    (empty? (vswap! write-futures clear-write-futures!)))

   (completed? [this]
     (when @exception (throw @exception))
-    (empty? (clear-write-futures! write-futures)))
+    (empty? (vswap! write-futures clear-write-futures!)))

   p/Checkpointed
   (recover! [this _ _]
@@ -293,16 +292,16 @@
     true)
   (write-batch [this {:keys [onyx.core/results]} replica _]
     (when @exception (throw @exception))
-    (vswap! write-futures
+    (vswap! write-futures
             (fn [fs]
-              (doall
-               (into (remove realized? fs)
-                     (comp (mapcat :leaves)
-                           (map (fn [msg]
-                                  (send-async! producer
-                                               (message->producer-record key-serializer-fn serializer-fn topic kpartition msg)
-                                               {:send-callback write-callback}))))
-                     (:tree results)))))
+              (-> fs
+                  (clear-write-futures!)
+                  (into (comp (mapcat :leaves)
+                              (map (fn [msg]
+                                     (send-async! producer
+                                                  (message->producer-record key-serializer-fn serializer-fn topic kpartition msg)
+                                                  {:send-callback write-callback}))))
+                        (:tree results)))))
     true))

 (def write-defaults {:kafka/request-size 307200})
@@ -310,7 +309,7 @@
 (deftype ExceptionCallback [e]
   Callback
   (onCompletion [_ v exception]
-    (reset! e exception)))
+    (when exception (reset! e exception))))

 (defn write-messages [{:keys [onyx.core/task-map onyx.core/log-prefix] :as event}]
   (let [_ (s/validate onyx.tasks.kafka/KafkaOutputTaskMap task-map)


Moving on somewhat with 6.11

Moving on somewhat with 6.11

--- src/fpinscala/purely_functional_state.clj
+++ src/fpinscala/purely_functional_state.clj
@@ -1,5 +1,6 @@
 (ns fpinscala.purely-functional-state
-  (:use [fpinscala.strictness-and-laziness :only [unfold-fpins take-via-unfold fold-right]]))
+  (:use [fpinscala.strictness-and-laziness :only [unfold-fpins take-via-unfold fold-right]])
+  (:require [clojure.core.match :refer [match]]))

 (declare simple-rng)

@@ -292,7 +293,7 @@
   `(let [{~@(interleave bindings [:val :next-state]) ~@[]} ~state]
      ~@body))

-(defn- make-result-state
+(defn- make-state
   "Auxiliary function to avoid same map creation all over the place"
   [val next-state]
   {:val val :next-state next-state})
@@ -309,7 +310,7 @@
 (defn unit-state
   "Generalized Unit function from section 6.5 of fpins"
   [a]
-  (fn [rng] (make-result-state a rng)))
+  (fn [rng] (make-state a rng)))

 (defn map-via-flat-map-s
   "Generalized version of map-via-flat-map from exercise 6.9, for exercise 6.10"
@@ -326,7 +327,8 @@
   (fpinscala.strictness-and-laziness/fold-right             ;Notice that this variant is using fold-right
     (unit-state '())                                              ;Check out that "unit-produced" function is used as z value (now - it wouldn't be really
     #(map2-via-flat-map-s % %2 (fn [a b] (cons a b)))                 ;correct to say it is "initial" but rather neutral (or terminating?) element
-    fs))
+    fs))                                                    ;UPDATE (25.11.2015) Check out wikipedia about monad, it is actually "return" also
+                                                            ;called "unit" operation of a monad

 (declare simple-rng-s)

@@ -345,15 +347,15 @@
         ;to make this working same way as in Scala/FPINS option
         nxt-rng (make-simple-rng-s nseed)
         n (.intValue (unsigned-bit-shift-right nseed 16))]
-    (make-result-state n nxt-rng)))
+    (make-state n nxt-rng)))

 (defn non-negative-int-fpins-s
-  "FPINS variant of above function - haha - and I was thinking: Adding one is way too simple :)"
+  "FPINS variant of non-negative-int function, adapted to 'state' variant - haha - and I was thinking: Adding one is way too simple :)"
   [rng]
   (from-state (rng) :let [n nxt-rng]
             (if (< n 0)
-              (make-result-state (- (inc n)) nxt-rng)
-              (make-result-state n nxt-rng))))
+              (make-state (- (inc n)) nxt-rng)
+              (make-state n nxt-rng))))

 ;usage example
 ((state-sequence-fpins (repeat 5 non-negative-int-fpins-s)) (make-simple-rng-s 42))
@@ -367,4 +369,29 @@
 ;but returns function which again accepts some state and will
 ;produce new value and next state. This yields flexibility which
 ;plain map lacks, flat-map is able to adjust behavior
-;based on value+;based on value
+
+;here - I try to mimic get, set and modify of FPINS/6.6
+(def get-state (fn [s] (make-state s s)))
+(def set-state (fn [s] (make-state nil s)))
+;(def modify-state (fn [s f]
+;                    (for [])))
+
+;here is step-machine function from Runar Bjarnasson's explanation of 6.1 on fpins google group
+;it is using core.match as writing with if, cond etc would make it ridiculously complex
+
+(defn machine [locked candies coins]
+         {:locked locked :candies candies :coins coins})
+
+(defn step-machine
+  "inputs is sequence of either coins or turns, s is 'machine' in focus"
+  [i s]
+  (match [i s]
+         [_ {:locked _ :candies 0 :coins _}] s
+         [:coin {:locked false :candies _ :coins _}] s
+         [:turn {:locked true :candies _ :coins _}] s
+         [:coin {:locked true :candies candies :coins coins}]
+         (machine false candies (inc coins))
+         [:turn {:locked false :candies candies :coins coins}]
+         (machine true (dec candies) coins)))
+


patterns: Removed unused logic

patterns: Removed unused logic

--- src/overtime/patterns.clj
+++ src/overtime/patterns.clj
@@ -37,13 +37,10 @@
   PatternParam
   (set-start-time [p-param _time] p-param)
   (get-p-param-val [p-param param-key _time]
-    (cond
-      ; If value is a lazy sequence, get first one in sequence
-      (seq? p-param) (first p-param)
-      ; If a keyword was given, this is a sound parameter (as opposed to a synth)
-      param-key (snd/sound-param param-key p-param)
-      ; Otherwise use the param value as is
-      :else p-param))
+    ; If value is a lazy sequence, get first one in sequence, otherwise get sound parameter
+    (if (seq? p-param)
+      (first p-param)
+      (snd/sound-param param-key p-param)))
   (get-p-param-next [p-param] (if (seq? p-param) (next p-param) p-param)))

 (extend-type nil


small stylistic changes and comments

small stylistic changes and comments

--- src/quick_chess/core.cljs
+++ src/quick_chess/core.cljs
@@ -94,9 +94,18 @@
 (defn piece-style
   [data]
   {:text-align "center"
+   :height (/ (:width data) (count (first (:board data))) 2)
    :font-size (*
                (min (:height data) (:width data))
                0.06)})
+
+(defn selection-char-style
+  [data]
+  {:text-align "center"
+   :height (/ (:width data) (count (first (:board data))) 3)
+   :font-size (*
+               (min (:height data) (:width data))
+               0.03)})

 (defn slider-view
   "adjusts the size of the board"
@@ -135,12 +144,14 @@
   (fn [col-idx elem]
     ^{:key col-idx}
     [:td {:style (td-style state (:color elem))}
+     ;;merge implementation isnt that great create our own
+     ;;or reorganize init-state.
      [:div {:style (piece-style state)} (:piece elem)]
      (let [binding (get (merge
                          (get-in state [:string-map :white :pos->str])
                          (get-in state [:string-map :black :pos->str]))
-                        [row-idx col-idx] "_")]
-       [:div {:style {:text-align "center"}} binding])]))
+                        [row-idx col-idx] "")]
+       [:div {:style (selection-char-style state)} binding])]))

 (defn row-view
   [state]


remove ISwap & IReset protocols impl and introduce updates batching & scheduling

--- src/scrum/reconciler.cljs
+++ src/scrum/reconciler.cljs
@@ -1,8 +1,21 @@
 (ns scrum.reconciler)
+
+(def queue (volatile! []))
+(def schedule (volatile! []))
+
+(defn- queue-update! [f]
+  (vswap! queue conj f))
+
+(defn- schedule-update! [f]
+  (vswap! schedule conj f)
+  (js/requestAnimationFrame #(when-not (zero? (count @schedule)) (f))))
+

 (defprotocol IReconciler
   (dispatch! [this controller action args])
-  (broadcast! [this action args]))
+  (dispatch-sync! [this controller action args])
+  (broadcast! [this action args])
+  (broadcast-sync! [this action args]))

 (deftype Reconciler [state controllers meta]
   Object
@@ -37,20 +50,6 @@
   IHash
   (-hash [this] (goog/getUid this))

-  IReset
-  (-reset! [_ newv]
-    (-swap! state (constantly newv)))
-
-  ISwap
-  (-swap! [this f]
-    (reset! state (f (-deref state))))
-  (-swap! [this f a]
-    (reset! state (f (-deref state) a)))
-  (-swap! [this f a b]
-    (reset! state (f (-deref state) a b)))
-  (-swap! [this f a b rest]
-    (reset! state (apply f (-deref state) a b rest)))
-
   IPrintWithWriter
   (-pr-writer [this writer opts]
     (-write writer "#object [scrum.reconciler.Reconciler ")
@@ -59,7 +58,20 @@

   IReconciler
   (dispatch! [this cname action args]
-    (-swap! this #(let [ctrl (get controllers cname)
+    (queue-update! #(let [ctrl (get controllers cname)
+                          cstate (get % cname)]
+                      (->> cstate
+                        (ctrl action args)
+                        (assoc % cname))))
+    (schedule-update!
+     #(swap! state (fn [state]
+                     (let [new-state (reduce (fn [state f] (f state)) state @queue)]
+                       (vreset! queue [])
+                       (vreset! schedule [])
+                       new-state)))))
+
+  (dispatch-sync! [this cname action args]
+    (swap! state #(let [ctrl (get controllers cname)
                         cstate (get % cname)]
                     (->> cstate
                       (ctrl action args)
@@ -67,4 +79,8 @@

   (broadcast! [this action args]
     (doseq [controller (keys controllers)]
-      (dispatch! this controller action args))))
+      (dispatch! this controller action args)))
+
+  (broadcast-sync! [this action args]
+    (doseq [controller (keys controllers)]
+      (dispatch-sync! this controller action args))))


Ability to set status text of worksheet window

--- src/sqls/ui/worksheet.clj
+++ src/sqls/ui/worksheet.clj
@@ -51,7 +51,8 @@
                                                                              :text "Rollback")
                                                          ])
         center-panel (seesaw.core/vertical-panel :items [query-text-area tabs-panel])
-        south-panel (seesaw.core/horizontal-panel :items [" "])
+        south-panel (seesaw.core/horizontal-panel :items [(seesaw.core/label :id :status-bar-text
+                                                                             :text " ")])
         border-panel (seesaw.core/border-panel :north menu-panel
                                                :center center-panel
                                                :south south-panel)
@@ -341,3 +342,12 @@
       (seesaw.core/text! log-text new-text))))

+(defn status-text
+  "Set status bar text."
+  [^javax.swing.JFrame frame
+   ^String message]
+  (assert (not= frame nil))
+  (assert (not= message nil))
+  (let [status-bar-text (seesaw.core/select frame [:#status-bar-text])]
+    (assert (not= status-bar-text nil))
+    (seesaw.core/text! status-bar-text message)))


🐛 Read sub from :user/subject instead of attributes

Why:
- Old users don't have the sub attribute saved in the database.

--- src/territory_bro/api.clj
+++ src/territory_bro/api.clj
@@ -147,7 +147,8 @@
                              :users (->> (user/get-users conn {:ids (congregation/get-users state cong-id)})
                                          (map (fn [user]
                                                 (-> (:user/attributes user)
-                                                    (assoc :id (:user/id user))))))}))))))
+                                                    (assoc :id (:user/id user))
+                                                    (assoc :sub (:user/subject user))))))}))))))

 (defn- api-command! [conn state command]
   (let [command (assoc command


add check for all players removed from round

--- src/wombats/game/core.clj
+++ src/wombats/game/core.clj
@@ -10,13 +10,16 @@
             [wombats.sockets.game :as game-sockets]))

 (defn- round-over?
-  [{:keys [game-config frame]}]
+  [{:keys [game-config frame initiative-order]}]
   (let [{round-length :game/round-length} game-config
         {round-start-time :frame/round-start-time} frame
         end-time (t/plus (c/from-date round-start-time)
                          (t/millis round-length))]
-    (t/after? (t/now)
-              end-time)))
+    ;; Check to see if all players / ai are dead, or the
+    ;; max time limit has elapsed
+    (or (empty? initiative-order)
+     (t/after? (t/now)
+               end-time))))

 (defn- push-frame-to-datomic
   [{:keys [frame players] :as game-state} update-frame]


Handle EOF exceptions in health-check connections (#279)

--- waiter/src/waiter/scheduler.clj
+++ waiter/src/waiter/scheduler.clj
@@ -23,6 +23,7 @@
             [waiter.metrics :as metrics]
             [waiter.utils :as utils])
   (:import (clojure.lang PersistentQueue)
+           (java.io EOFException)
            (java.net ConnectException SocketTimeoutException)
            (java.util.concurrent TimeoutException)
            (org.joda.time DateTime)))
@@ -217,6 +218,7 @@
               {:keys [status error]} (async/<! (http/get http-client instance-health-check-url))
               error-flag (cond
                            (instance? ConnectException error) :connect-exception
+                           (instance? EOFException error) :hangup-exception
                            (instance? SocketTimeoutException error) :timeout-exception
                            (instance? TimeoutException error) :timeout-exception)]
           (log-health-check-issues service-instance instance-health-check-url status error)
@@ -382,6 +384,7 @@
     (if-not service
       service->service-instances'
       (let [{:strs [health-check-url]} (service-id->service-description-fn (:id service))
+            connection-errors #{:connect-exception :hangup-exception :timeout-exception}
             update-unhealthy-instance (fn [instance status error]
                                         (-> instance
                                             (assoc :healthy? false
@@ -392,8 +395,7 @@
                                                         (not= error :connect-exception)
                                                         (conj :has-connected)

-                                                        (and (not= error :connect-exception)
-                                                             (not= error :timeout-exception))
+                                                        (not (contains? connection-errors error))
                                                         (conj :has-responded))))))
             health-check-refs (map (fn [instance]
                                      (let [chan (async/promise-chan)]


Implement some of the 'answer question' logic

--- util/clojure-cli/src/commcare_cli/form_player.clj
+++ util/clojure-cli/src/commcare_cli/form_player.clj
@@ -11,17 +11,14 @@
            [org.javarosa.core.services.locale Localization]
            [org.javarosa.core.services.storage StorageManager]
            [org.javarosa.core.model Constants]
-           [org.javarosa.core.model.data SelectMultiData]
+           [org.javarosa.core.model.data AnswerDataFactory SelectMultiData UncastData]
            [org.javarosa.core.model.condition EvaluationContext]
            [org.javarosa.core.model.instance FormInstance]
            [org.javarosa.core.model.trace StringEvaluationTraceSerializer]
            [org.javarosa.engine XFormEnvironment]
-           [org.javarosa.form.api FormEntrySession]
-           [org.javarosa.form.api FormEntryController]
-           [org.javarosa.form.api FormEntrySessionReplayer]
-           [org.javarosa.form.api FormEntrySessionReplayer$ReplayError]
-           [org.javarosa.xpath XPathNodeset]
-           [org.javarosa.xpath XPathParseTool]
+           [org.javarosa.form.api FormEntrySession FormEntryController
+            FormEntrySessionReplayer FormEntrySessionReplayer$ReplayError]
+           [org.javarosa.xpath XPathNodeset XPathParseTool]
            [org.javarosa.xpath.expr XPathFuncExpr]
            [org.javarosa.xpath.parser XPathSyntaxException]
            [org.commcare.session SessionFrame]
@@ -58,7 +55,7 @@
         choices-text))))

 (defn show-question [entry-prompt]
-  (println (.getQuestionPrompt entry-prompt))
+  (println entry-prompt)
   (let [choices (.getSelectChoices entry-prompt)]
     (when (not (nil? choices))
       (show-choices entry-prompt choices))
@@ -75,17 +72,17 @@
 (defn show-event [entry-controller step-func]
   (helpers/clear-view)
   (let [event (.getEvent (.getModel entry-controller))]
-  (cond
-    (= event FormEntryController/EVENT_BEGINNING_OF_FORM) (println "Form Start: Press Return to proceed")
-    (= event FormEntryController/EVENT_END_OF_FORM) (println "Form End: Press Return to Complete Entry")
-                ;;mProcessOnExit = true;
-    (= event FormEntryController/EVENT_GROUP) (do (step-func entry-controller)
-                                        (show-event entry-controller step-func))
-    (= event FormEntryController/EVENT_QUESTION) (show-question (.getQuestionPrompt (.getModel entry-controller)))
-    (= event FormEntryController/EVENT_REPEAT) (do (step-func entry-controller)
-                                         (show-event entry-controller step-func))
-    (= event FormEntryController/EVENT_REPEAT_JUNCTURE) (println "Repeats Not Implemented, press return to exit")
-    (= event FormEntryController/EVENT_PROMPT_NEW_REPEAT) (new-repeat-question))))
+    (cond
+      (= event FormEntryController/EVENT_BEGINNING_OF_FORM) (println "Form Start: Press Return to proceed")
+      (= event FormEntryController/EVENT_END_OF_FORM) (println "Form End: Press Return to Complete Entry")
+      ;;mProcessOnExit = true;
+      (= event FormEntryController/EVENT_GROUP) (do (step-func entry-controller)
+                                                    (show-event entry-controller step-func))
+      (= event FormEntryController/EVENT_QUESTION) (show-question (.getQuestionPrompt (.getModel entry-controller)))
+      (= event FormEntryController/EVENT_REPEAT) (do (step-func entry-controller)
+                                                     (show-event entry-controller step-func))
+      (= event FormEntryController/EVENT_REPEAT_JUNCTURE) (println "Repeats Not Implemented, press return to exit")
+      (= event FormEntryController/EVENT_PROMPT_NEW_REPEAT) (new-repeat-question))))

 (defn display-relevant [entry-model]
   (let [debug-info
@@ -167,8 +164,73 @@
     :else (println "Invalid command: " command)
   ))

-(defn answer-question [user-input]
-  "TODO")
+(defn validate-number-input [user-input max-number]
+  (try
+    (let [i (Integer/parseInt user-input)]
+      (if (or (< i 1) (> i max-number))
+        (doall
+          (println "Enter a number between 1 and " max-number)
+          -1)
+        (- i 1)))
+    (catch NumberFormatException e
+      (doall
+        (println "Enter a number between 1 and " max-number)
+        -1))))
+
+(defn set-question-answer [entry-controller string-value]
+  (try
+    (let [entry-prompt (.getQuestionPrompt (.getModel entry-controller))
+          value (.cast (AnswerDataFactory/template
+                         (.getControlType entry-prompt)
+                         (.getDataType entry-prompt))
+                       (UncastData. string-value))
+          response (.answerQuestion entry-controller value)]
+      (cond
+        (= response FormEntryController/ANSWER_OK) (.stepToNextEvent entry-controller)
+        (= response FormEntryController/ANSWER_REQUIRED_BUT_EMPTY) (println "Answer is required")
+        (= response FormEntryController/ANSWER_CONSTRAINT_VIOLATED) (println (.getConstraintText entry-controller))))
+    (catch Exception e
+      (println (.getMessage e)))))
+
+(defn get-selected-choices-string [entry-prompt]
+  (let [choices (.getSelectChoices entry-prompt)
+        selections (get-selected-choices entry-prompt choices)]
+    (.getString (.uncast (SelectMultiData. selections)))))
+
+(defn process-input [entry-controller user-input]
+  (let [entry-prompt (.getQuestionPrompt (.getModel entry-controller))
+        question-type (.getControlType entry-prompt)
+        choices (.getSelectChoices entry-prompt)]
+    (if (not (nil? choices))
+      (if (and (string/blank? user-input) (= Constants/CONTROL_SELECT_MULTI question-type))
+        (get-selected-choices-string entry-prompt)
+        (let [index (validate-number-input user-input choices)]
+          (cond (= Constants/CONTROL_SELECT_ONE question-type) (.getValue (nth choices index))
+                ;; TODO: does this let you select multiple things?
+                (= Constants/CONTROL_SELECT_MULTI question-type) (.getValue (nth choices index)))))
+      user-input)))
+
+(defn answer-question-event [entry-controller user-input]
+    (let [string-value (process-input entry-controller user-input)]
+      (set-question-answer entry-controller string-value)
+      true))
+
+(defn create-new-repeat [entry-controller user-input]
+  (let [i (validate-number-input user-input 2)]
+    (cond
+      (= 1 i) (doto entry-controller (.newRepeat) (.stepToNextEvent))
+      (= 2 i) (.stepToNextEvent entry-controller))))
+
+(defn answer-question [entry-controller user-input]
+  (let [event (.getEvent (.getModel entry-controller))]
+    (cond
+      (= event FormEntryController/EVENT_BEGINNING_OF_FORM) (do (.stepToNextEvent entry-controller) true)
+      (= event FormEntryController/EVENT_END_OF_FORM) false ;; TODO mProcessOnExit = true;
+      (= event FormEntryController/EVENT_QUESTION) (answer-question-event entry-controller user-input)
+      (= event FormEntryController/EVENT_REPEAT) false
+      (= event FormEntryController/EVENT_REPEAT_JUNCTURE) false
+      (= event FormEntryController/EVENT_PROMPT_NEW_REPEAT) (do (create-new-repeat entry-controller user-input) true)
+      :else (doall (println "Bad state; quitting") false))))

 (defn process-loop [entry-controller]
   (show-event entry-controller
@@ -177,7 +239,7 @@
   (let [user-input (read-line)]
     (when (if (string/starts-with? user-input ":")
             (process-command entry-controller (subs user-input 1))
-            (answer-question user-input))
+            (answer-question entry-controller user-input))
       (recur entry-controller))))

 ;; FormDef CommCareSession String String -> None


Add description to logged error

Add description to logged error

--- src/onyx/peer/virtual_peer.clj
+++ src/onyx/peer/virtual_peer.clj
@@ -54,7 +54,7 @@
             (when (:lifecycle state)
               (component/stop @(:lifecycle state)))))))
     (catch Throwable e
-      (taoensso.timbre/error e))
+      (taoensso.timbre/error "Error in processing loop:" e))
     (finally
      (taoensso.timbre/info "Fell out of processing loop"))))


Better history and ajax handling.

Better history and ajax handling.

--- src-cljs/kixi/hecuba/tabs/programmes.cljs
+++ src-cljs/kixi/hecuba/tabs/programmes.cljs
@@ -17,6 +17,36 @@

 (enable-console-print!)

+(defn back-to-programmes [history]
+  (fn [_ _]
+    (history/update-token-ids! history :sensors nil)
+    (history/update-token-ids! history :devices nil)
+    (history/update-token-ids! history :properties nil)
+    (history/update-token-ids! history :projects nil)
+    (history/update-token-ids! history :programmes nil)
+    (fixed-scroll-to-element "programmes-div")))
+
+(defn back-to-projects [history]
+  (fn [_ _]
+    (history/update-token-ids! history :sensors nil)
+    (history/update-token-ids! history :devices nil)
+    (history/update-token-ids! history :properties nil)
+    (history/update-token-ids! history :projects nil)
+    (fixed-scroll-to-element "projects-div")))
+
+(defn back-to-properties [history]
+  (fn [_ _]
+    (history/update-token-ids! history :sensors nil)
+    (history/update-token-ids! history :devices nil)
+    (history/update-token-ids! history :properties nil)
+    (fixed-scroll-to-element "properties-div")))
+
+(defn back-to-devices [history]
+  (fn [_ _]
+    (history/update-token-ids! history :sensors nil)
+    (history/update-token-ids! history :devices nil)
+    (fixed-scroll-to-element "devices-div")))
+
 (defn update-when [x pred f & args]
   (if pred (apply f x args) x))

@@ -41,7 +71,7 @@
                                                        template
                                                        nav-event)]

-      (om/update! data :active-components (-> nav-event :args :ids))
+      ;; (om/update! data :active-components (-> nav-event :args :ids))

       (when uri
         (println "Fetching: " uri)
@@ -57,6 +87,12 @@
                   :response-format :text}
                  (cond-> (= content-type "application/json")
                          (merge {:response-format :json :keywords? true}))))))
+    (recur)))
+
+(defn history-loop [history-channel tables]
+  (go-loop []
+    (let [nav-event (<! history-channel)]
+      (om/update! tables :active-components (-> nav-event :args :ids)))
     (recur)))

 (defn selected-range-change
@@ -251,10 +287,7 @@
           [:h2 "Projects"]
           [:ul {:class "breadcrumb"}
            [:li [:a
-                 {:onClick (fn projects-div-history-change
-                             [_ _]
-                             (history/update-token-ids! history :programmes nil)
-                             (fixed-scroll-to-element "programmes-div"))}
+                 {:onClick (back-to-programmes history)}
                  (title-for programmes)]]]
           (om/build projects-table projects {:opts {:histkey :projects}})])))))

@@ -322,15 +355,10 @@
           [:h2 "Properties"]
           [:ul {:class "breadcrumb"}
            [:li [:a
-                 {:onClick (fn [_ _]
-                             (history/update-token-ids! history :projects nil)
-                             (history/update-token-ids! history :programmes nil)
-                             (fixed-scroll-to-element "programmes-div"))}
+                 {:onClick (back-to-programmes history)}
                  (title-for programmes)]]
            [:li [:a
-                 {:onClick (fn [_ _]
-                             (history/update-token-ids! history :projects nil)
-                             (fixed-scroll-to-element "projects-div"))}
+                 {:onClick (back-to-projects history)}
                  (title-for projects)]]]
           (om/build properties-table properties {:opts {:histkey :properties}})])))))

@@ -362,6 +390,36 @@

 (defn devices-div [tables owner]
   (reify
+    om/IDidUpdate
+    (did-update [_ prev-props prev-state]
+      (let [{:keys [properties devices active-components]} tables
+            new-property-id (:properties active-components)]
+
+        (println "Active Components: " active-components)
+
+        ;; handle selection perties table
+        (when-not new-property-id
+          (println "Clearing devices data.")
+          (om/update! devices :data [])
+          (om/update! devices :selected nil))
+
+        (if (and new-property-id
+                 (not (= (:property-id devices) new-property-id)))
+          (GET (str "/4/entities/" new-property-id "/devices/")
+               {:handler  (fn [x]
+                            (println "Fetching devices for property: " new-property-id)
+                            (om/update! devices :data x)
+                            (om/update! devices :selected nil))
+                ;; TODO: Add Error Handler
+                ;; FIXME: This should be application/edn
+                :headers {"Accept" "application/json"}
+                :response-format :json
+                :keywords? true})
+          (println "Not fetching devices!"))
+        (om/update! devices :property-id new-property-id)
+
+        ;; handle seledevices table
+        (om/update! devices :selected (:devices active-components))))
     om/IRender
     (render [_]
       (let [{:keys [programmes projects properties devices active-components]} tables
@@ -371,23 +429,14 @@
           [:h2  "Devices"]
           [:ul {:class "breadcrumb"}
            [:li [:a
-                 {:onClick (fn [_ _]
-                             (history/update-token-ids! history :properties nil)
-                             (history/update-token-ids! history :projects nil)
-                             (history/update-token-ids! history :programmes nil)
-                             (fixed-scroll-to-element "programmes-div"))}
+                 {:onClick (back-to-programmes history)}
                  (title-for programmes)]]
            [:li [:a
-                 {:onClick (fn [_ _]
-                             (history/update-token-ids! history :properties nil)
-                             (history/update-token-ids! history :projects nil)
-                             (fixed-scroll-to-element "projects-div"))}
+                 {:onClick (back-to-projects history)}
                  (title-for projects)]]
            [:li [:a
-                 {:onClick (fn [_ _]
-                             (history/update-token-ids! history :properties nil)
-                             (fixed-scroll-to-element "properties-div"))}
-                 (title-for properties :title-key :addressStreetTwo)]]]
+                 {:onClick (back-to-properties history)}
+                 (title-for properties :title-key :address-street-two)]]]
           (om/build devices-table devices {:opts {:histkey :devices}})])))))

 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -404,30 +453,16 @@
             [:h2 {:id "sensors"} "Sensors"]
             [:ul {:class "breadcrumb"}
              [:li [:a
-                   {:onClick (fn [_ _]
-                               (history/update-token-ids! history :devices nil)
-                               (history/update-token-ids! history :properties nil)
-                               (history/update-token-ids! history :projects nil)
-                               (history/update-token-ids! history :programmes nil)
-                               (fixed-scroll-to-element "programmes-div"))}
+                   {:onClick (back-to-programmes history)}
                    (title-for programmes)]]
              [:li [:a
-                   {:onClick (fn [_ _]
-                               (history/update-token-ids! history :devices nil)
-                               (history/update-token-ids! history :properties nil)
-                               (history/update-token-ids! history :projects nil)
-                               (fixed-scroll-to-element "projects-div"))}
+                   {:onClick (back-to-projects history)}
                    (title-for projects)]]
              [:li [:a
-                   {:onClick (fn [_ _]
-                               (history/update-token-ids! history :devices nil)
-                               (history/update-token-ids! history :properties nil)
-                               (fixed-scroll-to-element "properties-div"))}
-                   (title-for properties :title-key :addressStreetTwo)]]
+                   {:onClick (back-to-properties history)}
+                   (title-for properties :title-key :address-street-two)]]
              [:li [:a
-                   {:onClick (fn [_ _]
-                               (history/update-token-ids! history :devices nil)
-                               (fixed-scroll-to-element "devices-div"))}
+                   {:onClick (back-to-devices history)}
                    (title-for devices :title-key [:location :name])]]]
             (om/build sensor/table data {:opts {:histkey :sensors
                                                 :path    :readings}})]))))))
@@ -442,6 +477,9 @@
         (let [history     (om/get-shared owner :history)
               m           (mult (history/set-chan! history (chan)))
               tap-history #(tap m (chan))]
+
+          ;; handle navigation changes
+          (history-loop (tap-history) tables)

           ;; (ajax (tap-history) tables [:programmes] {:template      "/4/programmes/"
           ;;                                           :content-type  "application/edn"
@@ -452,9 +490,9 @@
           ;; (ajax (tap-history) tables [:properties] {:template      "/4/projects/:projects/properties/"
           ;;                                           :content-type "application/json"
           ;;                                           :selection-key :properties})
-          (ajax (tap-history) tables [:devices] {:template      "/4/entities/:properties/devices/"
-                                                 :content-type  "application/json"
-                                                 :selection-key :devices})
+          ;; (ajax (tap-history) tables [:devices] {:template      "/4/entities/:properties/devices/"
+          ;;                                        :content-type  "application/json"
+          ;;                                        :selection-key :devices})
           (ajax (tap-history) tables [:sensors] {:template "/4/entities/:properties/devices/:devices"
                                                  :content-type "application/json"
                                                  :selection-key :sensors} (:chart data))