Update file block store layout.

Update file block store layout.

--- src/blocks/store/file.clj
+++ src/blocks/store/file.clj
@@ -1,22 +1,20 @@
 (ns blocks.store.file
-  "Block storage backed by files in nested directories. Each block is stored in
-  a separate file. File block stores may be constructed using the
-  `file://<path-to-root>` URI form.
+  "This store provides block storage backed by files in local directories. Each
+  block is stored in a separate file. File block stores may be constructed
+  using the `file://<path-to-root-dir>` URI form. Under the root directory, the
+  store keeps a block files in a subdirectory, alongside some layout metadata
+  and a directory.
+
+      $ROOT/meta.properties
+      $ROOT/blocks/111497df/35011497df3588b5a3...
+      $ROOT/landing/block.123456789.tmp

   In many filesystems, performance degrades as the number of files in a
   directory grows. In order to reduce this impact and make navigating the
-  blocks a bit more efficient, block files are stored in directories under the
-  store root. All path elements are lower-case hex-encoded bytes from the
-  multihash.
-
-  The directories under the root consist of the first four bytes of the
-  multihashes of the blocks stored in them. Within each directory, blocks are
-  stored in files whose names consist of the rest of their digests.
-
-  Thus, a block containing the content `foobar` would have the sha1 digest
-  `97df3501149...` and be stored under the root directory at:
-
-      root/111497df/35011497df3588b5a3...
+  blocks more efficient, block files are stored in multiple subdirectories
+  consisting of the first four bytes of the multihashes of the blocks stored in
+  them. Within each directory, blocks are stored in files whose names consist
+  of the rest of their digests.

   In addition to the blocks, a `meta.properties` file at the root holds
   information about the current storage layout for future-proofing. This
@@ -41,72 +39,63 @@
     java.time.Instant))

-;; ## FileSystem Utilities
-
-(def ^:private meta-properties-file
-  "Name of the properties file holding store-level metadata."
-  "meta.properties")
-
-
-(defn- initialize-meta
-  "Initialize the store by inspecting the metadata file for the current layout
-  version. If the version is not recognized, an error is thrown, otherwise this
-  returns the metadata properties as a map. If the metadata file does not
-  exist, it is created with the current version."
+(def layout-version
+  "The current supported storage layout version."
+  "1")
+
+
+
+;; ## Metadata
+
+(defn- meta-file
+  "Construct the store-level metadata properties file from the store root."
+  ^File
+  [root]
+  (io/file root "meta.properties"))
+
+
+(defn- read-meta-properties
+  "Read the store's metadata file if it exists."
   [^File root]
-  (let [meta-file (io/file root meta-properties-file)
-        supported "1"]
-    (if (.exists meta-file)
-      ; Check for correct format/version.
-      (let [props (doto (java.util.Properties.)
-                    (.load (io/reader meta-file)))
-            version (.getProperty props "version")]
-        (when (not= version supported)
-          (throw (ex-info
-                   (str "Unknown storage layout version " (pr-str version)
-                        " does not match supported version "
-                        (pr-str supported))
-                   {:supported supported
-                    :meta props})))
-        {:version version})
-      ; No file yet, probably a new store.
-      (let [version supported
-            props (doto (java.util.Properties.)
-                    (.setProperty "version" version))]
-        (with-open [out (io/writer meta-file)]
-          (.store props out " blocks.store.file"))
-        {:version version}))))
-
-
-(defn- seek-marker
-  "Given a marker string, determine whether the file should be skipped, recursed
-  into with a substring, or listed in full. Returs nil if the file should be
-  skipped, otherwise a vector of the file and a marker to recurse with."
-  [marker ^File file]
-  (if (empty? marker)
-    [file nil]
-    (let [fname (.getName file)
-          len (min (count marker) (count fname))
-          cmp (compare (subs fname  0 len)
-                       (subs marker 0 len))]
-      (when-not (neg? cmp)
-        (if (zero? cmp)
-          [file (subs marker len)]
-          [file nil])))))
-
-
-(defn- find-files
-  "Walks a directory tree depth first, returning a sequence of files found in
-  lexical order. Intelligently skips directories based on the given marker."
-  [^File file marker]
-  (if (.isDirectory file)
-    (->> (.listFiles file)
-         (keep (partial seek-marker marker))
-         (sort-by first)
-         (keep (partial apply find-files))
-         (flatten))
-    (when (.isFile file)
-      [file])))
+  (let [props-file (meta-file root)]
+    (when (.exists props-file)
+      (into {}
+            (map (juxt (comp keyword key) val))
+            (doto (java.util.Properties.)
+              (.load (io/reader props-file)))))))
+
+
+(defn- write-meta-properties
+  "Write a metadata properties file and returns the data map."
+  [^File root]
+  (let [props-file (meta-file root)
+        props (doto (java.util.Properties.)
+                (.setProperty "version" layout-version))]
+    (.mkdirs root)
+    (with-open [out (io/writer props-file)]
+      (.store props out " blocks.store.file"))
+    {:version layout-version}))
+
+
+
+;; ## Landing Area
+
+(defn- landing-dir
+  "Construct the landing directory from the store root."
+  ^File
+  [root]
+  (io/file root "landing"))
+
+
+(defn- landing-file
+  "Create an empty temporary file to land block data into. Marks the resulting
+  file for automatic cleanup if it is not moved."
+  ^File
+  [^File root]
+  (let [tmp-dir (landing-dir root)]
+    (.mkdirs tmp-dir)
+    (doto (File/createTempFile "block" ".tmp" tmp-dir)
+      (.deleteOnExit))))

 (defn- rm-r
@@ -118,11 +107,36 @@

-;; ## File Block Functions
-
-(def ^:private dir-prefix-length
+;; ## Block Files
+
+(def ^:private prefix-length
   "Number of characters to use as a prefix for top-level directory names."
   8)
+
+
+(defn- blocks-dir
+  "Construct the block directory from the store root."
+  ^File
+  [root]
+  (io/file root "blocks"))
+
+
+(defn- block-files
+  "Walks a block directory tree depth first, returning a sequence of files
+  found in lexical order. Intelligently skips subdirectories based on the given
+  marker."
+  [^File root after]
+  (->
+    (.listFiles (blocks-dir root))
+    (sort)
+    (cond->>
+      after
+      (drop-while #(nat-int? (compare after (.getName ^File %)))))
+    (->>
+      (mapcat
+        (fn list-blocks
+          [^File subdir]
+          (sort (.listFiles subdir)))))))

 (defn- file-stats
@@ -137,33 +151,25 @@
 (defn- id->file
   "Determine the filesystem path for a block of content with the given hash
   identifier."
-  ^java.io.File
-  [root id]
-  (let [hex (multihash/hex id)]
-    (io/file
-      root
-      (subs hex 0 dir-prefix-length)
-      (subs hex dir-prefix-length))))
+  ^File
+  [^File root id]
+  (let [hex (multihash/hex id)
+        len (min (dec (count hex)) prefix-length)
+        subdir (subs hex 0 len)
+        fragment (subs hex len)]
+    (io/file (blocks-dir root) subdir fragment)))

 (defn- file->id
   "Reconstruct the hash identifier represented by the given file path. Returns
   nil if the file is not a proper block."
-  [root ^File file]
-  (let [root (str root)
-        path (.getPath file)]
-    (cond
-      (= meta-properties-file (.getName file))
-      nil
-
-      (not (str/starts-with? path root))
-      (log/warnf "File %s is not a child of root directory %s" file root)
-
-      :else
-      (let [hex (str/replace (subs path (inc (count root))) "/" "")]
-        (if (re-matches #"[0-9a-fA-F]+" hex)
-          (multihash/decode (hex/parse hex))
-          (log/warnf "File %s did not form valid hex entry: %s" file hex))))))
+  [^File root ^File file]
+  (let [prefix (str (blocks-dir root))
+        path (.getPath file)
+        hex (str/replace (subs path (inc (count prefix))) "/" "")]
+    (if (re-matches #"[0-9a-fA-F]+" hex)
+      (multihash/decode (hex/parse hex))
+      (log/warnf "File %s did not form valid hex entry: %s" file hex))))

 (defn- file->block
@@ -173,20 +179,9 @@
     (with-meta
       (data/create-block
         id (:size stats) (:stored-at stats)
-        (fn file-reader
-          []
-          (FileInputStream. file)))
+        ; OPTIMIZE: use java.io.RandomAccessFile to read subranges
+        (fn reader [] (FileInputStream. file)))
       (meta stats))))
-
-
-(defn- temp-file
-  "Create an empty temporary file to land block data into. Marks the resulting
-  file for automatic cleanup."
-  ^File
-  [^File root]
-  (.mkdirs root)
-  (doto (File/createTempFile "block" ".tmp" root)
-    (.deleteOnExit)))

@@ -201,8 +196,17 @@

   (start
     [this]
-    (let [meta-props (initialize-meta root)
-          version (:version meta-props)]
+    ; TODO: auto-migrate v0 layouts?
+    (let [properties (or (read-meta-properties root)
+                         (write-meta-properties root))
+          version (:version properties)]
+      (when (not= layout-version version)
+        (throw (ex-info
+                 (str "Unknown storage layout version " (pr-str version)
+                      " does not match supported version "
+                      (pr-str layout-version))
+                 {:supported layout-version
+                  :properties properties})))
       (log/debug "Using storage layout version" version)
       (assoc this :version version)))

@@ -219,7 +223,7 @@
     (let [out (s/stream)]
       (d/future
         (try
-          (loop [files (find-files root (:after opts))]
+          (loop [files (block-files root (:after opts))]
             (when-let [file (first files)]
               (if-let [id (file->id root file)]
                 ; Check that the id is still before the marker, if set.
@@ -260,10 +264,10 @@
       (let [id (:id block)
             file (id->file root id)]
         (when-not (.exists file)
-          (io/make-parents file)
-          (let [tmp (temp-file root)]
+          (let [tmp (landing-file root)]
             (with-open [content (data/content-stream block nil nil)]
               (io/copy content tmp))
+            (io/make-parents file)
             (.setWritable tmp false false)
             (.renameTo tmp file)))
         (file->block id file))))
@@ -283,7 +287,8 @@
   (-erase!
     [this]
     (d/future
-      (rm-r root)
+      (rm-r (landing-dir root))
+      (rm-r (blocks-dir root))
       true)))


capture *recursion-limit* on gen call

capture *recursion-limit* on gen call

--- src/clj/clojure/spec.clj
+++ src/clj/clojure/spec.clj
@@ -20,7 +20,7 @@
   "A soft limit on how many times a branching spec (or/alt/*/opt-keys/multi-spec)
   can be recursed through during generation. After this a
   non-recursive branch will be chosen."
-  8)
+  4)

 (def ^:dynamic *fspec-iterations*
   "The number of times an anonymous fn specified by fspec will be (generatively) tested during conform"
@@ -207,7 +207,7 @@
   sequential collection (i.e. a generator for s/? should return either
   an empty sequence/vector or a sequence/vector with one item in it)"
   ([spec] (gen spec nil))
-  ([spec overrides] (gensub spec overrides [] nil spec)))
+  ([spec overrides] (gensub spec overrides [] {::recursion-limit *recursion-limit*} spec)))

 (defn- ->sym
   "Returns a symbol from a symbol or var"
@@ -697,7 +697,7 @@

 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; impl ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 (defn- recur-limit? [rmap id path k]
-  (c/and (> (get rmap id) *recursion-limit*)
+  (c/and (> (get rmap id) (::recursion-limit rmap))
          (contains? (set path) k)))

 (defn- inck [m k]


This should be nil?

This should be nil?

--- src/cljs/go/compiler.clj
+++ src/cljs/go/compiler.clj
@@ -510,7 +510,7 @@
         (emit-comment doc (:jsdoc init))
         (emitln (when-not redefine? "var ")
                 mname
-                (when (or (= 'clj-nil (:tag init)) (not init))
+                (when (or (= 'clj-nil (:tag init)) (nil? init))
                   " interface{}")
                 " = " (or init "nil"))
         ;; NOTE: JavaScriptCore does not like this under advanced compilation


Towards higher performance

Towards higher performance

--- src/cljs/klang/core.cljs
+++ src/cljs/klang/core.cljs
@@ -90,6 +90,12 @@
    ;; If we freeze we won't pull from the mult channel and buffer instead
    ;; Before they get into this array they will be transduced!
    :logs []
+   ;; Stuff for rendering part of the log messages depending on the scrolling
+   ;; position
+   ;; sp == scrolling position
+   :sp-start 0
+   ;; The uuid of the top element
+   :sp-uuid ""
    })

@@ -311,16 +317,17 @@
         (if (:frozen @db) "Thaw" "Freeze")]]
       ]
      ;;;;;;;;;; The main logs ;;;;;;;;;
-     [:div#KLANG_LOG_DIV.klang-logs
+     [:div.klang-logs
       {:style (:div-logs css)
        :id "KLANG_LOG_DIV"
        ;; Save scrolling position
-       :on-scroll #(action! db ::scroll
-                            ;; By the time we handle the action we might
-                            ;; have a different showing tab so we need
-                            ;; to capture it here
-                            {:tab (:showing-tab @db)
-                             :y (.. % -target -scrollTop)})}
+       :on-scroll (fn[ev] (action!
+                           db ::scroll
+                           ;; By the time we handle the action we might
+                           ;; have a different showing tab so we need
+                           ;; to capture it here
+                           {:tab (:showing-tab @db)
+                            :y (.. ev -target -scrollTop)}))}
       [render-logs (get-in @db [:tabs (:showing-tab @db) :logs])]
       ]]))

@@ -789,7 +796,7 @@
    (.highlight js/hljs "clojure" msg true)))

 (defn msg->str
-  "Converts a message to a string. Also ensures the data is "
+  "Converts a message to a string. Also calls js->clj."
   [msg]
   (as-> (str (js->clj msg)) s
     (.substr s 1 (- (.-length s) 2))))


copy login to compressed module

copy login to compressed module

--- src/cljs/ohds/login.cljs
+++ src/cljs/ohds/login.cljs
@@ -1,6 +1,9 @@
 (ns ohds.login
   (:require [petrol.core :refer [wrap Message EventSource]]
-            [cljs-http.client :as http]))
+            [cljs-http.client :as http]
+            [ohds.login.messages :as m]
+            [ohds.components :as c]
+            [ohds.model :refer [valid-login?]]))

 (defrecord LoginResult [body])

@@ -18,3 +21,14 @@
        map->LoginResult
        (http/post "/api/v1/login"
                   {:form-params (:login app)}))}))
+
+
+(defn login [ch state]
+  [:span
+   [:legend "Login"]
+   (c/text-input ch m/->ChangeUsername "username" "Username" state)
+   (c/password-input ch m/->ChangePassword "password" "Password")
+   (c/checkbox "administrator" "Administrator" ch (m/->ToggleAdmin))
+
+   (when (valid-login? state)
+     (c/submit ch m/->FieldworkerLogin "Login"))])


Fix "Unable to resolve symbol: log-d in this context" error

--- src/clojure/neko/log.clj
+++ src/clojure/neko/log.clj
@@ -59,8 +59,9 @@
   [tag]
   (let [intern-logger
         (fn [log-name log-fn]
-          `(intern *ns* (with-meta ~(symbol log-name) {:private true})
-                   (partial ~log-fn ~tag)))]
+          `(intern *ns* (symbol ~log-name)
+                   (-> (partial ~log-fn ~tag)
+                       (with-meta  {:private true}))))]
     `(do
        ~(intern-logger "log-d" `log-debug)
        ~(intern-logger "log-e" `log-error)


Some more cleanup in core, and switching some things around for safer playing around.

--- src/chicken_coop/core.clj
+++ src/chicken_coop/core.clj
@@ -18,15 +18,15 @@
        (recur))))

-(defn close-door! [hb floor-io]
+(defn close-door! [hb floor-btn]
   (hb/forward! hb)
-  (wait-till (closed? floor-io)
+  (wait-till (closed? floor-btn)
     (hb/stop! hb)))

-(defn open-door! [hb roof-io]
+(defn open-door! [hb roof-btn]
   (hb/reverse! hb)
-  (wait-till (closed? roof-io)
+  (wait-till (closed? roof-btn)
     (hb/stop! hb)))

@@ -59,10 +59,10 @@

 (defn init-state!
-  [floor-io roof-io light-ain]
+  [floor-btn roof-btn light-ain]
   (cond
-    (closed? floor-io) :night
-    (closed? roof-io) :day
+    (closed? floor-btn) :night
+    (closed? roof-btn) :day
     (> (read! light-ain) 0.35) :day
     :else :night))

@@ -77,28 +77,38 @@
         temp-ain  (ain 35)
         mtr-ctrl  (hb/hbridge [16 17 18] :header :P8)
         timer     (time-sm
-                    (init-state! floor-io roof-io light-ain)
-                    (partial close-door! hb roof-io)
-                    (partial open-door! hb roof-io))]
+                    (init-state! floor-btn roof-btn light-ain)
+                    (partial close-door! mtr-ctrl roof-btn)
+                    (partial open-door! mtr-ctrl roof-btn))]
+    (setup-shutdown-hook!
+      (fn [] (doseq [p (concat
+                         [floor-btn
+                          roof-btn]
+                         (for [x [:power :-pin :+pin]]
+                               (mtr-ctrl x)))]
+               (close! p))))
     (loop [time-sm time-sm]
       (recur (trans-sm! timer (read! light-ain))))))

 (defn play []
   (println "ready to initialize")
-  (let [g (gpio :P8 11 :low)
-        a (ain 33)]
+  (let [g  (gpio :P8 11 :out)
+        a1 (ain 33)
+        a2 (ain 35)]
     (setup-shutdown-hook!
       (fn [] (close! g)))
     (println "Pin settings" ((pinout-spec*) [:P8 11]))
     (println "initialized successfully")
-    (doseq [_ (range 100)]
-      (println "Writing :on")
-      (write! g :on)
-      (Thread/sleep 1000)
-      (println "Writing :off")
-      (write! g :off)
-      (println "Reading ain:" (read! a))
+    (doseq [_ (range)]
+      (try
+        (println "Reading light" (read! a1))
+        (println "Reading temp" (read! a2))
+        (println "Reading btn" (read! g))
+        (println "")
+        (catch Exception e
+          (println "Had an exception")
+          (println e)))
       (Thread/sleep 1000))))


todomvc: bump clojars deps

todomvc: bump clojars deps

--- examples/todomvc/project.clj
+++ examples/todomvc/project.clj
@@ -26,13 +26,13 @@
                                            [cljsjs/jquery-ui "1.11.4-0"]
                                            [cljsjs/filesaverjs "1.1.20151003-0"]]}

-             :clojars-deps {:dependencies [[carry "0.5.0"]
+             :clojars-deps {:dependencies [[carry "0.6.0"]
                                            [carry-atom-sync "0.3.0"]
                                            [carry-debugger "0.6.0"]
                                            [carry-history "0.4.0"]
                                            [carry-logging "0.2.0"]
                                            [carry-persistence "0.4.0"]
-                                           [carry-reagent "0.6.0"]
+                                           [carry-reagent "0.7.0"]
                                            [carry-schema "0.5.0"]]}}

   :cljsbuild {:builds [{:id           "clojars-deps"


todomvc: bump deps

todomvc: bump deps

--- examples/todomvc/project.clj
+++ examples/todomvc/project.clj
@@ -27,12 +27,12 @@
                                            [cljsjs/filesaverjs "1.1.20151003-0"]]}

              :clojars-deps {:dependencies [[carry "0.1.0"]
-                                           [carry-debugger "0.1.0"]
+                                           [carry-debugger "0.2.0"]
                                            [carry-history "0.3.0"]
                                            [carry-logging "0.1.0"]
                                            [carry-persistence "0.3.0"]
                                            [carry-reagent "0.2.0"]
-                                           [carry-schema "0.2.0"]]}}
+                                           [carry-schema "0.3.0"]]}}

   :cljsbuild {:builds [{:id           "clojars-deps"
                         :source-paths ["src"]


retrieve frequencies since 1.7.

retrieve frequencies since 1.7.

--- src/clj/ceres/curator.clj
+++ src/clj/ceres/curator.clj
@@ -22,7 +22,7 @@
               ^ServerAddress sa  (mg/server-address (or (System/getenv "DB_PORT_27017_TCP_ADDR") "127.0.0.1") 27017)]
           (mg/get-db (mg/connect sa opts) "athena"))
     :custom-formatter (f/formatter "E MMM dd HH:mm:ss Z YYYY")
-    :news-accounts #{"FAZ_NET" "dpa" "tagesschau" "SPIEGELONLINE" "SZ" "BILD" "DerWesten" "ntvde" "tazgezwitscher" "welt" "ZDFheute" "N24_de"}}))
+    :news-accounts #{"FAZ_NET" "dpa" "tagesschau" "SPIEGELONLINE" "SZ" "BILD" "DerWesten" "ntvde" "tazgezwitscher" "welt" "ZDFheute" "N24_de" "sternde" "focus_de"}}))

 (def months
   [(range 1 32)
@@ -156,7 +156,8 @@

 (defn get-news-frequencies []
-  (mapv #(vec [% (mc/count (:db @mongo-state) "tweets" {:user.screen_name %})]) (:news-accounts @mongo-state)))
+  (mapv #(vec [% (mc/count (:db @mongo-state) "tweets" {:user.screen_name %
+                                                        :created_at {$gt (t/date-time 2014 7 1)}})]) (:news-accounts @mongo-state)))

 (defn get-tweet-count []
@@ -183,9 +184,10 @@

 (defn compute-diffusion [user]
-  (->> (mc/count (:db @mongo-state) "tweets" {$or [{"entities.user_mentions.screen_name" user}
-                                                   {"retweeted_status.user.screen_name" user}
-                                                   {"in_reply_to_screen_name" user}]})))
+  (->> (mc/count (:db @mongo-state) "tweets" {$and [{$or [{"entities.user_mentions.screen_name" user}
+                                                           {"retweeted_status.user.screen_name" user}
+                                                           {"in_reply_to_screen_name" user}]}
+                                                    {:created_at {$gt (t/date-time 2014 7 1)}}]})))

 (defn get-news-diffusion []
@@ -214,6 +216,8 @@

   (get-hashtag-distribution 6 16)

+  (compute-diffusion "SZ")
+
   (->>
    (mc/find
     (:db @mongo-state)
@@ -238,6 +242,4 @@
       (:db @mongo-state)
       "tweets"
       (:_id x)
-      (update-in x [:created_at] #(f/parse (:custom-formatter @mongo-state) (:created_at %))))))
-
-)
+      (update-in x [:created_at] #(f/parse (:custom-formatter @mongo-state) (:created_at %)))))))


Update version of catacumba on website example.

--- examples/website/project.clj
+++ examples/website/project.clj
@@ -4,7 +4,7 @@
   :license {:name "BSD (2-Clause)"
             :url "http://opensource.org/licenses/BSD-2-Clause"}
   :dependencies [[org.clojure/clojure "1.7.0-RC1"]
-                 [funcool/catacumba "0.2.0-SNAPSHOT"]
+                 [funcool/catacumba "0.2.0"]
                  [hiccup "1.0.5"]]
   :main ^:skip-aot website.core
   :target-path "target/%s"


Change `cljs.analyzer/parse-ns` so that ns dependencies can be optionally followed. Change the analysis cache path in `cljs.analyzer/analyze-file` to use the new functionality.

--- src/clj/cljs/analyzer.clj
+++ src/clj/cljs/analyzer.clj
@@ -1657,12 +1657,13 @@

 (defn parse-ns
   ([src] (parse-ns src nil nil))
+  ([src opts] (parse-ns src nil opts))
   ([src dest opts]
     (env/ensure
       (let [namespaces' (::namespaces @env/*compiler*)
             ret
             (binding [*cljs-ns* 'cljs.user
-                      *analyze-deps* false]
+                      *analyze-deps* (or (:analyze-deps opts) false)]
               (loop [forms (forms-seq src)]
                 (if (seq forms)
                   (let [env (empty-env)
@@ -1686,7 +1687,8 @@
                       (recur (rest forms)))))))]
         ;; TODO this _was_ a reset! of the old namespaces atom; should we capture and
         ;; then restore the entirety of env/*compiler* here instead?
-        (swap! env/*compiler* assoc ::namespaces namespaces')
+        (when-not (false? (:restore opts))
+          (swap! env/*compiler* assoc ::namespaces namespaces'))
         ret))))

 (defn cache-file
@@ -1758,7 +1760,9 @@
                       (str ";; Analyzed by ClojureScript " (util/clojurescript-version) "\n"
                         (pr-str (get-in @env/*compiler* [::namespaces ns])))))
                   (swap! env/*compiler* assoc-in [::analyzed-cljs path] true)))
-               (let [{:keys [ns]} (parse-ns res)]
+               ;; we want want to keep dependency analysis information
+               ;; don't revert the environment - David
+               (let [{:keys [ns]} (parse-ns res {:restore false :analyze-deps true})]
                  (swap! env/*compiler* assoc-in [::analyzed-cljs path] true)
                  (swap! env/*compiler* assoc-in [::namespaces ns]
                    (edn/read-string (slurp cache)))))))))))


Minor bugfixes here and there to make all examples work.

--- src/clj/guangyin/core.clj
+++ src/clj/guangyin/core.clj
@@ -12,7 +12,7 @@
   "Returns true if the given value is an instant.
    Examples:

-    => (instant? (instant))
+    => (instant? (instant :now))
     true
     => (instant? (days 1))
     false"
@@ -87,8 +87,8 @@

 (extend-protocol IDuration
   guangyin.internal.types.ObjectWrapper
-  (duration [this] (duration @this))
-  (duration [this other] (duration @this other))
+  (duration ([this] (duration @this))
+            ([this other] (duration @this other)))
   clojure.lang.Keyword
   (duration [this] (wrap (fields/durations this)))
   java.time.temporal.Temporal
@@ -136,8 +136,8 @@

 (extend-protocol IPeriod
   guangyin.internal.types.ObjectWrapper
-  (period [this] (period @this))
-  (period [this other] (period @this other))
+  (period ([this] (period @this))
+          ([this other] (period @this other)))
   clojure.lang.Keyword
   (period [this] (wrap (fields/periods this)))
   java.time.temporal.TemporalAmount
@@ -178,8 +178,8 @@

 (extend-protocol ILocalDate
   guangyin.internal.types.ObjectWrapper
-  (local-date [this] (local-date @this))
-  (local-date [this param] (local-date @this param))
+  (local-date ([this] (local-date @this))
+              ([this param] (local-date @this param)))
   clojure.lang.Keyword
   (local-date [this] (if (= this :now)
                          (wrap (LocalDate/now))
@@ -234,8 +234,8 @@

 (extend-protocol ILocalTime
   guangyin.internal.types.ObjectWrapper
-  (local-time [this] (local-time @this))
-  (local-time [this param] (local-time @this param))
+  (local-time ([this] (local-time @this))
+              ([this param] (local-time @this param)))
   clojure.lang.Keyword
   (local-time [this] (if (= this :now)
                          (wrap (LocalTime/now))
@@ -289,8 +289,8 @@

 (extend-protocol IOffsetTime
   guangyin.internal.types.ObjectWrapper
-  (offset-time [this] (offset-time @this))
-  (offset-time [this param] (offset-time @this param))
+  (offset-time ([this] (offset-time @this))
+               ([this param] (offset-time @this param)))
   clojure.lang.Keyword
   (offset-time [this] (if (= this :now)
                          (wrap (OffsetTime/now))
@@ -312,7 +312,8 @@
                ([this param] (wrap (OffsetTime/parse this (unwrap param)))))
   java.lang.Long
   (offset-time ([hour minute second nanosecond offset]
-                (wrap (OffsetTime/of hour minute second nanosecond offset)))))
+                (wrap (OffsetTime/of hour minute second nanosecond
+                                     @(zone-offset offset))))))

 (defn local-date-time?
   "Returns true if the given value is a local date-time."
@@ -325,8 +326,8 @@

 (extend-protocol ILocalDateTime
   guangyin.internal.types.ObjectWrapper
-  (local-date-time [this] (local-date-time @this))
-  (local-date-time [this param] (local-date-time @this param))
+  (local-date-time ([this] (local-date-time @this))
+                   ([this param] (local-date-time @this param)))
   clojure.lang.Keyword
   (local-date-time [this] (if (= this :now)
                               (wrap (LocalDateTime/now))
@@ -365,9 +366,9 @@

 (extend-protocol IOffsetDateTime
   guangyin.internal.types.ObjectWrapper
-  (offset-date-time [this] (offset-date-time @this))
-  (offset-date-time [this param] (offset-date-time @this param))
-  (offset-date-time [date time offset] (offset-date-time @date time offset))
+  (offset-date-time ([this] (offset-date-time @this))
+                    ([this param] (offset-date-time @this param))
+                    ([date time offset] (offset-date-time @date time offset)))
   clojure.lang.Keyword
   (offset-date-time [this] (if (= this :now)
                                (wrap (OffsetDateTime/now))
@@ -407,9 +408,9 @@

 (extend-protocol IZonedDateTime
   guangyin.internal.types.ObjectWrapper
-  (zoned-date-time [this] (zoned-date-time @this))
-  (zoned-date-time [this param] (zoned-date-time @this param))
-  (zoned-date-time [date time zone] (zoned-date-time @date time zone))
+  (zoned-date-time ([this] (zoned-date-time @this))
+                   ([this param] (zoned-date-time @this param))
+                   ([date time zone] (zoned-date-time @date time zone)))
   clojure.lang.Keyword
   (zoned-date-time [this] (when (= this :now)
                                 (wrap (ZonedDateTime/now))))
@@ -446,8 +447,8 @@

 (extend-protocol IYear
   guangyin.internal.types.ObjectWrapper
-  (year [this] (year @this))
-  (year [this param] (year @this param))
+  (year ([this] (year @this))
+        ([this param] (year @this param)))
   clojure.lang.Keyword
   (year [this] (if (= this :now)
                    (wrap (Year/now))
@@ -527,8 +528,8 @@

 (extend-protocol IMonthDay
   guangyin.internal.types.ObjectWrapper
-  (month-day [this] (month-day @this))
-  (month-day [month day] (month-day @month day))
+  (month-day ([this] (month-day @this))
+             ([month day] (month-day @month day)))
   clojure.lang.Keyword
   (month-day [this] (when (= this :now)
                           (wrap (MonthDay/now))))
@@ -612,6 +613,8 @@
                         (wrap (ZoneId/systemDefault))))
   java.time.temporal.TemporalAccessor
   (zone-id [this] (wrap (ZoneId/from this)))
+  java.time.ZoneId
+  (zone-id [this] (wrap this))
   java.lang.String
   (zone-id ([this] (wrap (ZoneId/of this)))
            ([prefix offset]
@@ -648,8 +651,13 @@
   (zone-offset [this] (zone-offset @this))
   clojure.lang.Keyword
   (zone-offset [this] (wrap (fields/zone-offsets this)))
+  java.time.Duration
+  (zone-offset [this]
+    (wrap (ZoneOffset/ofTotalSeconds (/ (.toMillis this) 1000))))
   java.time.temporal.TemporalAccessor
   (zone-offset [this] (wrap (ZoneOffset/from this)))
+  java.time.ZoneOffset
+  (zone-offset [this] (wrap this))
   java.lang.String
   (zone-offset [this] (wrap (ZoneOffset/of this)))
   java.lang.Long


Eliminate errors from missing sun.misc.Signal

On Android, for instance.

fixes #57

--- src/clj/reply/signals.clj
+++ src/clj/reply/signals.clj
@@ -1,12 +1,16 @@
 (ns reply.signals)

-(defn set-signal-handler! [signal f]
-  (try
-    (sun.misc.Signal/handle
-      (sun.misc.Signal. signal)
-      (proxy [sun.misc.SignalHandler] []
-        (handle [signal] (f signal))))
-    (catch IllegalArgumentException e
-      ; unrecognized signal - CONT on Windows, for instance
-      )))
+(defmacro set-signal-handler! [signal f]
+  (if (try (Class/forName "sun.misc.Signal")
+          (catch Throwable e))
+    `(try
+      (sun.misc.Signal/handle
+        (sun.misc.Signal. ~signal)
+        (proxy [sun.misc.SignalHandler] []
+          (handle [signal#] (~f signal#))))
+      (catch Throwable e#)
+      (catch IllegalArgumentException e#
+        ; unrecognized signal - CONT on Windows, for instance
+        ))
+    `(println "Unable to set signal handlers.")))


Removed JSON-LD-related round-tripping

Removed JSON-LD-related round-tripping

--- src/clj/sparqlab/util.clj
+++ src/clj/sparqlab/util.clj
@@ -1,7 +1,5 @@
 (ns sparqlab.util
-  (:require [clojure.string :as string])
-  (:import [clojure.lang IPersistentMap IPersistentVector]
-           [java.util ArrayList LinkedHashMap]))
+  (:require [clojure.string :as string]))

 (defn is-file?
   [file]
@@ -14,45 +12,3 @@
 (def query-file?
   "Predicate testing if file is named *.rq."
   (every-pred is-file? (partial has-suffix? ".rq")))
-
-(defprotocol LinkedHashMappable
-  "Convert Clojure data structure to LinkedHashMap."
-  (->linked-hash-map [data]))
-
-(extend-protocol LinkedHashMappable
-  IPersistentMap
-  (->linked-hash-map [m]
-    (let [lhm (LinkedHashMap.)]
-      (doseq [[k v] m]
-        (.put lhm
-              (if (keyword? k) (name k) k)
-              (->linked-hash-map v)))
-      lhm))
-
-  IPersistentVector
-  (->linked-hash-map [v]
-    (let [alist (ArrayList.)]
-      (doseq [i v] (.add alist (->linked-hash-map i)))
-      alist))
-
-  Object
-  (->linked-hash-map [o] o))
-
-(defprotocol Clojurizable
-  "Convert LinkedHashMap to Clojure data structure."
-  (->clj [lhm]))
-
-(extend-protocol Clojurizable
-  LinkedHashMap
-  (->clj [lhm]
-    (reduce (fn [m [k v]]
-              (assoc m (keyword k) (->clj v)))
-            {}
-            (iterator-seq (.. lhm entrySet iterator))))
-
-  ArrayList
-  (->clj [alist]
-    (mapv ->clj alist))
-
-  Object
-  (->clj [o] o))


Added some debugging for testing in Galleon.

--- src/clj/traveler/core.clj
+++ src/clj/traveler/core.clj
@@ -45,6 +45,7 @@
    ^{:name "Traveler"
      :id :traveler/root
      :main-menu true}
+   [:any "/debugging" (fn [r] (prn-str (:helmsman r)))]
    [:any "/" dash-redirect]
    ^{:name "Dashboard" :id :traveler/dashboard}
    [:any "/dashboard" (:dashboard liberator-resources)]


Require a secret key.

Require a secret key.

--- src/clj/wordbook/core.clj
+++ src/clj/wordbook/core.clj
@@ -10,9 +10,10 @@

 (def session-settings
-  {:cookie-attrs {:secure (or (and (System/getenv "WB_PRODUCTION") true) false)}
-   :store (cookie-store {:key (get (System/getenv) "WB_SECRET_KEY"
-                                   "change me please")})})
+  (if-let [secret-key (System/getenv "WB_SECRET_KEY")]
+    {:cookie-attrs {:secure (or (and (System/getenv "WB_PRODUCTION") true) false)}
+     :store (cookie-store {:key secret-key})}
+    (throw (Exception. "You must set a secret key."))))

 (defroutes routes
   (context "/auth" [] auth/routes)


Fix edge sorting

Fix edge sorting

Found another instance of expecting SegmentContainers to contain
Segments rather than edges. Also, adding virtual edges was generating
bare Edges rather than sets of one Edge, which made cross counting
wrong.

--- src/cljs/fatlip/core.cljs
+++ src/cljs/fatlip/core.cljs
@@ -331,10 +331,10 @@
                    (filter #(instance? SegmentContainer %))
                    (map (juxt identity
                               (fn [seg-c]
-                                (mapcat #(-> % :edge :characters)
+                                (mapcat #(-> % :characters)
                                         (:segments seg-c)))))
                    (map (fn [[seg-c characters]]
-                          [seg-c (Edge. seg-c seg-c characters)]))
+                          [seg-c #{(Edge. seg-c seg-c characters)}]))
                    (into {})
                    (merge graph-edges))]
     (->> ordered


add docstring

add docstring

--- src/cljs/fatlip/core.cljs
+++ src/cljs/fatlip/core.cljs
@@ -591,6 +591,8 @@

 (defn seed-graph
+  "Set up the attributes the first layer in a sweep needs in order to serve
+  as a basis for ordering the following layer"
   [graph seed-order]
   (let [layer (-> graph
                   :layers


fix ip

fix ip

--- src/cljs/mpd/network.cljs
+++ src/cljs/mpd/network.cljs
@@ -56,7 +56,7 @@
   (log "  network")
   (log "connecting...")

-  (let [ws (js/WebSocket. "ws://127.0.0.1:8197")]
+  (let [ws (js/WebSocket. "ws://10.247.110.131:8197")]
     (doall (map #(aset ws (first %) (second %))
            [["onopen" websocket-open]
             ["onclose" websocket-close]


Fix bug when  returns canvas instead of sketch object.

--- src/cljs/quil/sketch.cljs
+++ src/cljs/quil/sketch.cljs
@@ -112,7 +112,8 @@
         (destroy-previous-sketch host-elem)
         (let [proc-obj (js/Processing. host-elem (make-sketch opts-map))]
           (set! (.-processing-obj host-elem) proc-obj)
-          (set! (.-quil-canvas proc-obj) host-elem)))
+          (set! (.-quil-canvas proc-obj) host-elem)
+          proc-obj))
       (.error js/console
               (if (:host opts-map)
                 (str "ERROR: Cannot find host element: " (:host opts-map))


Implement the `next-slide` function!

Implement the `next-slide` function!

--- src/cljs/slides/core.cljs
+++ src/cljs/slides/core.cljs
@@ -11,25 +11,33 @@
       (dom/section #js {:className "slide"}
         (when-let [bg (:bg model)]
           (dom/img #js {:className "bg" :src bg}))
-        (dom/div #js {:className "slide-content"}
-           (dom/h1 #js {} (:title model)))))))
+        (dom/div #js {:className "slide-content banner"}
+          (dom/h1 #js {} (:title model)))))))
+
+(defn next-slide [e model f])

 (defn app [model owner]
   (reify
     om/IRender
     (render [_]
       (dom/div #js {:className "content"}
-        (om/build slide ((:slides model) (:index model)))))))
+        (dom/a #js {:className "control banner previous"
+                    :href ""
+                    :onClick #(next-slide % model dec)})
+        (om/build slide ((:slides model) (:index model)))
+        (dom/a #js {:className "control banner next"
+                    :href ""
+                    :onClick #(next-slide % model inc)})))))

 (def slide-imgs
   [{:title "A Bird's Eye View of ClojureScript"
     :bg "/images/gull.jpg"}
    {:title "Using Om Components"
-    :bg "/images/gull2.jpg"}])
+    :bg "/images/gull2.jpg"}
+   {:title "Event Handling"
+    :bg "/images/swan.jpg"}])

 (defn main []
   (om/root app app-state {:target (. js/document (getElementById "app"))}))

 (swap! app-state assoc :slides slide-imgs)
-
-;;(swap! app-state assoc :index 0)


(#17108) Introduce a helper function to DRY up mq settings

This commit just introduces an internal helper function to
get rid of the redundant code between `set-store-usage!` and
`set-temp-usage!`.

--- src/com/puppetlabs/mq.clj
+++ src/com/puppetlabs/mq.clj
@@ -13,35 +13,50 @@
             [clojure.tools.logging :as log])
   (:use [cheshire.custom :only (JSONable)]))

+(defn- set-usage!*
+  "Internal helper function for setting `SystemUsage` values on a `BrokerService`
+  instance.
+
+  `broker`    - the `BrokerService` instance
+  `megabytes` - the value to set as the limit for the desired `SystemUsage` setting
+  `usage-fn`  - a function that accepts a `SystemUsage` instance and returns
+                the child object whose limit we are configuring.
+  `desc`      - description of the setting we're configuring, to be used in a log message
+  "
+  [broker megabytes usage-fn desc]
+  {:pre  [(instance? BrokerService broker)
+          ((some-fn nil? integer?) megabytes)
+          (fn? usage-fn)
+          (string? desc)]}
+  (when megabytes
+    (log/info "Setting ActiveMQ " desc " limit to " megabytes " MB")
+    (-> broker
+      (.getSystemUsage)
+      (usage-fn)
+      (.setLimit (* megabytes 1024 1024))))
+  broker)
+
 (defn- set-store-usage!
    "Configures the `StoreUsage` setting for an instance of `BrokerService`.

    `broker`     - the `BrokerService` to configure
-   `megabytes ` - the maximum amount of disk usage to allow for persistent messages"
+   `megabytes ` - the maximum amount of disk usage to allow for persistent messages,
+                  or `nil` to use the default value of 100GB.
+
+   Returns the (potentially modified) `broker` object."
   [broker megabytes]
-  {:pre  [(instance? BrokerService broker)
-          ((some-fn nil? integer?) megabytes)]}
-  (when megabytes
-    (log/info "Setting ActiveMQ StoreUsage limit to " megabytes " MB")
-    (-> broker
-      (.getSystemUsage)
-      (.getStoreUsage)
-      (.setLimit (* megabytes 1024 1024)))))
+  (set-usage!* broker megabytes #(.getStoreUsage %) "StoreUsage"))

 (defn- set-temp-usage!
   "Configures the `TempUsage` setting for an instance of `BrokerService`.

   `broker`     - the `BrokerService` to configure
-  `megabytes ` - the maximum amount of disk usage to allow for temporary messages"
+  `megabytes ` - the maximum amount of disk usage to allow for temporary messages,
+                 or `nil` to use the default value of 50GB.
+
+  Returns the (potentially modified) `broker` object."
   [broker megabytes]
-  {:pre  [(instance? BrokerService broker)
-          ((some-fn nil? integer?) megabytes)]}
-  (when megabytes
-    (log/info "Setting ActiveMQ TempUsage limit to " megabytes " MB")
-    (-> broker
-      (.getSystemUsage)
-      (.getTempUsage)
-      (.setLimit (* megabytes 1024 1024)))))
+  (set-usage!* broker megabytes #(.getTempUsage %) "TempUsage"))

 (defn build-embedded-broker
   "Configures an embedded, persistent ActiveMQ broker.


Fixed indentation.

Fixed indentation.

--- src/hxgm30/language/gen/impl/syntagmata.clj
+++ src/hxgm30/language/gen/impl/syntagmata.clj
@@ -71,7 +71,7 @@
                   (get-in stats [:pseudo-syllables :percent-ranges])))

 (defn syllable
-=  ([this stats position]
+  ([this stats position]
     (case position
       :initial (util/percent->
                 (random/float (:system this))


PDOK-1521 one object with the registerd templates (normal + partials)

--- src/main/clojure/pdok/featured/mustache.clj
+++ src/main/clojure/pdok/featured/mustache.clj
@@ -54,19 +54,12 @@
  (clojure.string/replace template search-prefix (str search-prefix qualifier)))

 (def ^{:private true} registered-templates (atom #{}))
-(def ^{:private true} registered-partials (atom #{}))

-(defn register [registered name template]
-  (if-not (contains? @registered name)
+(defn register [name template]
+  (if-not (contains? @registered-templates name)
     (do
       (loader/register-template name template)
-      (swap! registered conj name))))
-
-(defn register-partial [name template]
-   (if-not (contains? @registered-partials name)
-    (do
-      (loader/register-template name template)
-      (swap! registered-partials conj name))))
+      (swap! registered-templates conj name))))

 (defn render
   ([template feature] (render template nil))
@@ -74,8 +67,8 @@
    (if-not (nil? partials)
      (doseq [[k partial] partials] (let [name (:name partial)
                                          partial-content (:template partial)]
-                                     (register registered-partials name partial-content))))
-   (register registered-templates name template)
+                                     (register name partial-content))))
+   (register name template)
    (stencil/render-file name (lookup-proxy feature))))

 (defn render-resource


fix: missing db config in chunked timeline

--- src/main/clojure/pdok/featured/timeline.clj
+++ src/main/clojure/pdok/featured/timeline.clj
@@ -367,10 +367,10 @@
 (defn process-chunk [config chunk]
   (flush-batch chunk (partial process-chunk* config)))

-(defrecord ChunkedTimeline [config chunk process-fn]
+(defrecord ChunkedTimeline [config db chunk process-fn]
   proj/Projector
   (proj/init [this]
-    (init (:db-config config)) this)
+    (init db) this)
   (proj/new-feature [_ feature] (process-fn feature))
   (proj/change-feature [_ feature] (process-fn feature))
   (proj/close-feature [_ feature] (process-fn feature))
@@ -403,5 +403,6 @@
 (defn create-chunked [config]
   (let [chunk-size (or (:chunk-size config) 10000)
         chunk (ref (clojure.lang.PersistentQueue/EMPTY))
-        process-fn (with-batch chunk chunk-size #() #(process-chunk config chunk))]
-    (->ChunkedTimeline config chunk process-fn)))
+        process-fn (with-batch chunk chunk-size #() #(process-chunk config chunk))
+        db (:db-config config)]
+    (->ChunkedTimeline config db chunk process-fn)))


Fix inbox pagination link.

Fix inbox pagination link.

--- src/oc/storage/representations/activity.clj
+++ src/oc/storage/representations/activity.clj
@@ -24,7 +24,7 @@
     (str "/orgs/" slug "/" collection-type sort-path)))
   ([collection-type {slug :slug :as org} sort-type {start :start direction :direction}]
   (let [concat-str (if (= sort-type :recent-activity) "&" "?")]
-    (str (url collection-type org sort-type) concat-str "start=" start "&direction=" (name direction)))))
+    (str (url collection-type org sort-type) concat-str "start=" start (when direction "&direction=" (name direction))))))

 (defn- is-inbox? [collection-type]
   (= collection-type "inbox"))
@@ -37,7 +37,8 @@
         last-activity (last activity)
         last-activity-date (when activity? (or (:last-activity-at last-activity) (:last-activity-at last-activity)))
         next? (= (:next-count data) config/default-activity-limit)
-        next-url (when next? (url collection-type org sort-type {:start last-activity-date :direction direction}))
+        url-fn (if (is-inbox? collection-type) inbox-url url)
+        next-url (when next? (url-fn collection-type org sort-type {:start last-activity-date :direction direction}))
         next-link (when next-url (hateoas/link-map "next" hateoas/GET next-url {:accept mt/activity-collection-media-type}))]
     next-link))


Types of literals and referents are incompatible

--- test/rdf_path_examples/distance_test.clj
+++ test/rdf_path_examples/distance_test.clj
@@ -12,7 +12,7 @@

 (deftest compute-distance
   (let [distance-fn (partial distance/compute-distance (fn []) {})] ; Mocked distance function
-    (testing "Equivalent resources have distance of 0"
+    (testing "Equivalent resources have no distance."
       (are [resource] (= (distance-fn resource resource) 0)
            {"@value" 1}
            {"@value" "2015-12-30"}
@@ -21,4 +21,10 @@
       (are [a b] (= (distance-fn a b) (distance-fn b a))
            {"@value" 1} {"@value" 3}
            {"@value" "http://example.com/path/to/a/file"} {"@value" "https://example.com/path/to/another/file"}
-           {"@id" "_:b1"} {"@id" "_:b2"}))))
+           {"@id" "_:b1"} {"@id" "_:b2"}))
+    (testing "Mismatching types have maximum distance."
+      (are [a b] (= (distance-fn a b) 1)
+           {"@type" "http://www.w3.org/2001/XMLSchema#decimal"
+            "@value" 1.23}
+           {"@type" "http://purl.org/goodrelations/v1#BusinessEntity"
+            "@id" "_:b1"}))))


no longer need landing-b class

no longer need landing-b class

--- frontend/components/app.cljs
+++ frontend/components/app.cljs
@@ -103,7 +103,6 @@
                                        (when slim-aside? ["aside-slim"])
                                        (when-not logged-in? ["aside-nil"])
                                        ;; The following 2 are meant for the landing ab test to hide old heaqder/footer
-                                       (when new-homepage? ["landing-b"])
                                        (when (= :landing (:navigation-point app)) ["landing"]))}
               (om/build keyq/KeyboardHandler app-without-container-data
                         {:opts {:keymap keymap


Set correct naming in transform parameters

--- src/datasplash/pubsub.clj
+++ src/datasplash/pubsub.clj
@@ -6,10 +6,10 @@

 (defn read-from-pubsub
   "Create an unbounded PCollection from a pubsub stream"
-  [topic options p]
+  [subscription options p]
   (-> p
       (cond-> (instance? Pipeline p) (PBegin/in))
-      (apply-transform (PubsubIO$Read/subscription topic) {} options)))
+      (apply-transform (PubsubIO$Read/subscription subscription) {} options)))

 (defn write-to-pubsub
   "Write the contents of an unbounded PCollection to to a pubsub stream"


render search-form-component in a more testable way

--- src/desdemona/ui/nav.cljs
+++ src/desdemona/ui/nav.cljs
@@ -41,7 +41,7 @@
     [:div.navbar-header
      [:a.navbar-brand.brand-logo {:href "#"}
       "Desdemona"]]
-    [search-form-component]]
+    (search-form-component)]
    [:div.container-fluid
     [:nav
      (let [current-page (session/get :current-page)


add test for transaction with multiple items for one account

--- test/clj_money/models/transactions_test.clj
+++ test/clj_money/models/transactions_test.clj
@@ -261,13 +261,56 @@
            (map #(:balance (accounts/find-by-id storage-spec (:id %))) (:accounts context)))
         "The checking account has the correct balance")))

-; TODO test balances after inserting a transaction before the end
-; subsequent item balances should be updated
-; account balances should be updated correctly
-; walking the list of subsequent items should stop as soon as
-;   the balance is equal to the new value
-
-; create a transaction with more than one item for a given account
+(def multi-context
+  {:users [(factory :user, {:email "john@doe.com"})]
+   :entities [{:name "Personal"
+               :user-id "john@doe.com"}]
+   :accounts [{:name "Checking"
+               :type :asset
+               :entity-id "Personal"}
+              {:name "Salary"
+               :type :income
+               :entity-id "Personal"}
+              {:name "Bonus"
+               :type :income
+               :entity-id "Personal"}
+              {:name "Groceries"
+               :type :expense
+               :entity-id "Personal"}]
+   :transactions [{:transaction-date (t/local-date 2016 3 2)
+                   :entity-id "Personal"
+                   :items [{:action :debit
+                            :account-id "Checking"
+                            :amount 1000}
+                           {:action :debit
+                            :account-id "Checking"
+                            :amount 100}
+                           {:action :credit
+                            :account-id "Salary"
+                            :amount 1000}
+                           {:action :credit
+                            :account-id "Bonus"
+                            :amount 100}]}
+                  {:transaction-date (t/local-date 2016 3 10)
+                   :entity-id "Personal"
+                   :items [{:action :debit
+                            :account-id "Groceries"
+                            :amount 100}
+                           {:action :credit
+                            :account-id "Checking"
+                            :amount 100}]}]})
+
+(deftest create-a-transaction-with-multiple-items-for-one-account
+  (let [context (serialization/realize storage-spec multi-context)
+        [checking-items
+         salary-items
+         groceries-items] (map #(transactions/items-by-account storage-spec (:id %))
+                               (:accounts context))]
+    (is (= [{:index 0 :amount 1000 :balance 1000}
+            {:index 1 :amount  100 :balance 1100}
+            {:index 2 :amount  100 :balance 1000}]
+           checking-items)
+        "The checking account items are correct")))

 ; update a transaction
 ; change amount


Removed unnecessary var referral.

Removed unnecessary var referral.

--- src/leiningen/ancient.clj
+++ src/leiningen/ancient.clj
@@ -2,7 +2,7 @@
       :author "Yannick Scherer"}
   leiningen.ancient
   (:require [leiningen.ancient.verbose :refer [verbose *verbose* yellow green red *colors*]]
-            [leiningen.ancient.maven-metadata :refer [metadata-retrievers retrieve-metadata! latest-version version-seq filter-versions]]
+            [leiningen.ancient.maven-metadata :refer [metadata-retrievers retrieve-metadata! latest-version version-seq]]
             [leiningen.ancient.version :refer [version-outdated? version-sort version-map snapshot? qualified?]]
             [leiningen.ancient.projects :refer [collect-dependencies repository-maps dependency-map]]
             [leiningen.ancient.maven-metadata http local s3p]))


Fixed 'control show' do not work well

Fixed 'control show' do not work well

--- src/leiningen/control.clj
+++ src/leiningen/control.clj
@@ -51,12 +51,15 @@
   [project & args]
   (do
     (load-control-file project)
-    (if-let [cluster-name (first args)]
-      (doseq
-          [c (:clients ((keyword cluster-name) @clusters))
-           a (:addresses ((keyword cluster-name) @clusters))]
-        (println (str (:user c) "@" (:host c)))
-        (println (str (:user @clusters) "@" a))))))
+    (if-let [cluster-name (first args)]
+      (let [user (:user ((keyword cluster-name) @clusters))]
+        (doseq
+            [c (:clients ((keyword cluster-name) @clusters))]
+          (println (str (:user c) "@" (:host c))))
+        (doseq
+            [a (:addresses ((keyword cluster-name) @clusters))]
+          (println (str user "@" a)))))))
+

 (defn control
   "Leiningen plugin for Clojure-Control"


more troll objectives

more troll objectives

--- src/lolitemsets/core.cljs
+++ src/lolitemsets/core.cljs
@@ -58,6 +58,8 @@
 (def troll-objectives {
 "Attack damage per second" algo/build-dps
 "Ability power" (algo/item-wrapper algo/ability-power)
+"Mana" algo/mana
+"Movement speed" algo/move-speed
 "Effective Health (AP)" algo/build-hp-ap
 "Effective Health (AD)" algo/build-hp-ad})


[frontend]: Add repl config

[frontend]: Add repl config

--- frontend/project.clj
+++ frontend/project.clj
@@ -21,14 +21,16 @@

   :profiles {:dev {:dependencies [[day8.re-frame/trace "0.1.0"]
                                   [binaryage/devtools "0.9.4"]
-                                  [re-frisk "0.4.5"]]}}
+                                  [re-frisk "0.4.5"]
+                                  [figwheel-sidecar "0.5.14"]
+                                  [com.cemerick/piggieback "0.2.2"]]}}

   :git-dependencies [["https://github.com/nenadalm/karma-reporter.git" "master"]]

   ; set plugins using aliases helps decrease "$ time lein help" significantly
   :aliases {"cljsbuild" ["update-in" ":plugins" "conj" "[lein-cljsbuild \"1.1.4\"]" "--" "cljsbuild"]
             "less" ["update-in" ":plugins" "conj" "[lein-less \"1.7.5\"]" "--" "less"]
-            "figwheel" ["update-in" ":plugins" "conj" "[lein-figwheel \"0.5.4-7\"]" "--" "figwheel"]
+            "figwheel" ["update-in" ":plugins" "conj" "[lein-figwheel \"0.5.14\"]" "--" "figwheel"]
             "git-deps" ["update-in" ":plugins" "conj" "[lein-git-deps \"0.0.2\"]" "--" "git-deps"]
             "cljfmt" ["update-in" ":plugins" "conj" "[lein-cljfmt \"0.5.6\"]" "--" "cljfmt"]}

@@ -81,6 +83,7 @@
              ;; Start an nREPL server into the running figwheel process
              ;; :nrepl-port 7888

+             :nrepl-middleware [cemerick.piggieback/wrap-cljs-repl]
              ;; Server Ring Handler (optional)
              ;; if you want to embed a ring handler into the figwheel http-kit
              ;; server, this is for simple ring servers, if this


Spec integrant keycloak

Spec integrant keycloak

--- backend/src/akvo/lumen/component/keycloak.clj
+++ backend/src/akvo/lumen/component/keycloak.clj
@@ -296,3 +296,13 @@
         openid-config (fetch-openid-configuration issuer)]
       (log/info "Successfully got openid-config from provider.")
       (assoc this :openid-config openid-config)))
+
+(s/def ::client_id string?)
+(s/def ::client_secret string?)
+
+(s/def ::credentials (s/keys :req-un [::client_id
+                                      ::client_secret]))
+
+(defmethod integrant-key :akvo.lumen.component.keycloak [_]
+  (s/cat :kw keyword?
+         :config (s/keys :req-un [::data ::credentials])))


[#1355] Fix postgis format

[#1355] Fix postgis format

--- backend/src/akvo/lumen/lib/import/flow_v3.clj
+++ backend/src/akvo/lumen/lib/import/flow_v3.clj
@@ -41,18 +41,20 @@
                  (log/debug :geom-type geom-type :points points )
                  (if points
                    (condp = geom-type
-                     "LineString" (postgres/->Geoline
-                                   (format "LINESTRING (%s)" (->> points
+                     "LineString" (when (> (count points) 1)
+                                    (postgres/->Geoline
+                                     (format "LINESTRING (%s)" (->> points
+                                                                    (map (partial string/join " " ))
+                                                                    (string/join ", " )))))
+                     "Polygon"    (let [points (->> (first points)
+                                                    (map (partial string/join " " )))]
+                                    (when (> (count points) 3)
+                                      (postgres/->Geoshape
+                                       (format "POLYGON ((%s))" (->> points                                                                                (string/join ", " ))))))
+                     "MultiPoint" (postgres/->Multipoint
+                                   (format "MULTIPOINT (%s)" (->> points
                                                                   (map (partial string/join " " ))
                                                                   (string/join ", " ))))
-                     "Polygon"    (postgres/->Geoshape
-                                   (format "POLYGON ((%s))" (->> (first points)
-                                                                 (map (partial string/join " " ))
-                                                                 (string/join ", " ))))
-                     "MultiPoint" (postgres/->Multipoint
-                                   (format "MULTIPOINT ((%s))" (->> points
-                                                                    (map (partial string/join " " ))
-                                                                    (string/join " " ))))

                      (log/warn :unmapped-geoshape! geom-type))))
     (v2/render-response type response)))


incremental flag

incremental flag

--- src/cljc/meo/electron/renderer/client_store_search.cljc
+++ src/cljc/meo/electron/renderer/client_store_search.cljc
@@ -231,7 +231,9 @@
 (defn show-more [{:keys [current-state msg-payload]}]
   (let [query-path [:query-cfg :queries (:query-id msg-payload)]
         merged (merge (get-in current-state query-path) msg-payload)
-        new-query (update-in merged [:n] + 15)]
+        new-query (-> merged
+                      (update-in [:n] + 15)
+                      (assoc-in [:incremental] true))]
     {:send-to-self [:search/update new-query]}))

 (defn search-res [{:keys [current-state msg-payload]}]


Change the alphabetical sorting into numeric.

--- src/constraint/core.cljs
+++ src/constraint/core.cljs
@@ -135,20 +135,20 @@
              (- (.-clientY event) (.-top rect))]]
     (update-in world-state [:vertices moving 1] (constantly pos))))

-(defn largest-key [the-map]
-  (-> the-map
-      (keys)
+(defn get-key [edge-str]
+  (->> edge-str
+       (drop 4)
+       (apply str)
+       (js/parseInt)))
+
+(defn largest-key [{:keys [edges]}]
+  (-> (map get-key (keys edges))
       (sort)
       (reverse)
       (first)))

-(defn next-key [a-key]
-  (str edge-id
-       (->> a-key
-            (drop 4)
-            (apply str)
-            (js/parseInt)
-            (inc))))
+(defn next-key [key-num]
+  (str edge-id (inc key-num)))

 (defn get-connected-edges [from to {:keys [edges]}]
   (let [both-ways #{[from to] [to from]}]
@@ -157,7 +157,7 @@

 (defn connect-or-disconnect [from to world-state]
   (let [connected-id (first (first (get-connected-edges from to world-state)))
-        next-to-largest-key (next-key (largest-key (:edges world-state)))
+        next-to-largest-key (next-key (largest-key world-state))
         new-edge [next-to-largest-key [from to :red]]]
     (update-in world-state
                [:edges]


Comment on null handling for MSE

Comment on null handling for MSE

--- src/cortex/optimise.cljc
+++ src/cortex/optimise.cljc
@@ -171,6 +171,9 @@
 ;; Loss Functions
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

+;; OK, this is a bit hacky and probably not ideally implemented yet
+;; But the idea is that we should treat a null in the target vector as a missing value
+;; and therefore propagate zero gradient. Should probably be true for all loss functions.
 (defn process-nulls
   "Replaces non-numbers in the target vector with the activation (to ensure zero gradient)"
   [activation target]


Review comment: simplify equality.

Review comment: simplify equality.

--- src/datomish/schema.cljc
+++ src/datomish/schema.cljc
@@ -99,7 +99,7 @@
   {:db.type/ref     { :valid? #(and (integer? %) (pos? %)) :->SQLite identity :<-SQLite identity }
    :db.type/keyword { :valid? keyword? :->SQLite str :<-SQLite #(keyword (subs % 1)) }
    :db.type/string  { :valid? string? :->SQLite identity :<-SQLite identity }
-   :db.type/boolean { :valid? #?(:clj #(instance? Boolean %) :cljs #(= js/Boolean (type %))) :->SQLite #(if % 1 0) :<-SQLite #(if (= % 1) true false) }
+   :db.type/boolean { :valid? #?(:clj #(instance? Boolean %) :cljs #(= js/Boolean (type %))) :->SQLite #(if % 1 0) :<-SQLite #(not= % 0) }
    :db.type/integer { :valid? integer? :->SQLite identity :<-SQLite identity }
    :db.type/real    { :valid? #?(:clj float? :cljs number?) :->SQLite identity :<-SQLite identity }
    })


Use log fn instead of macro on cljs

Use log fn instead of macro on cljs

--- src/obb_rules/logger.cljc
+++ src/obb_rules/logger.cljc
@@ -5,11 +5,19 @@

 (def ^:dynamic *verbose* false)

-(defmacro log
-  "Logs the given data"
-  [& args]
-  `(when *verbose*
-    (println ~@args)))
+#?(:clj
+  (defmacro log
+    "Logs the given data"
+    [& args]
+    `(when *verbose*
+      (println ~@args))))
+
+#?(:cljs
+  (defn log
+    "Logs the given data"
+    [& args]
+    (when *verbose*
+      (apply println args))))

 (defn ai-turn
   "Logs ai-turn header"


search on all fields not just _content

search on all fields not just _content

--- src-cljs/core.cljs
+++ src-cljs/core.cljs
@@ -90,7 +90,9 @@
                    r (js->clj o)]
                (put! channel r)))
            "POST"
-           (get term "_content")
+           (string/join
+            " AND "
+            (map (fn [[k v]] (str (name k) ": " (pr-str v))) term))
            {"Content-Type" "text/plain"}
            )
     channel))
@@ -193,7 +195,7 @@
                                   (fn [e]
                                     (let [term (.. e -target -value)]
                                       (om/set-state! owner :search-term term)
-                                      (put! search-chan {"_content" term})))
+                                      (put! search-chan {:_content term})))
                                   }))
                  (apply dom/div #js {:className "filters" }
                         (map #(dom/span #js {:className "filter"


Fixes resuming.

Fixes resuming.

--- src/onyx/plugin/kafka.clj
+++ src/onyx/plugin/kafka.clj
@@ -189,17 +189,25 @@
     partition->offset)
   ;;  checkpoint map looks like {part offset}
   (recover! [this replica-version checkpoint]
-    ;; FIXME, only resume the partitions that aren't :emit below
-    (.resume consumer (.assignment consumer))
-    (reset! drained (into {}
-                          (map (fn [p]
-                                 (let [current-offset (get checkpoint p)
-                                       target-offset (get target-offsets p)
-                                       drained? (and current-offset
-                                                     target-offset
-                                                     (>= current-offset target-offset))]
-                                   [p (if drained? :emitted :reading)]))
-                               kpartitions)))
+    (let [partition-statuses
+          (into {}
+                (map (fn [p]
+                       (let [current-offset (get checkpoint p)
+                             target-offset (get target-offsets p)
+                             drained? (and current-offset
+                                           target-offset
+                                           (>= current-offset target-offset))]
+                         [p (if drained? :emitted :reading)]))
+                     kpartitions))
+          resuming-tps (reduce-kv
+                        (fn [all k v]
+                          (if (not= v :emitted)
+                            (conj all (TopicPartition. topic v))
+                            all))
+                        []
+                        partition-statuses)]
+      (.resume consumer resuming-tps)
+      (reset! drained partition-statuses))
     (set! iter nil)
     (set! partition->offset checkpoint)
     (seek-offset! log-prefix consumer kpartitions task-map topic checkpoint)


Tidy whitespace

Tidy whitespace

--- src/overtone/sc/synth.clj
+++ src/overtone/sc/synth.clj
@@ -554,10 +554,10 @@
   "
   [& args]
   `(let [[sname# params# ugens# constants#] (pre-synth ~@args)
-         sdef# (synthdef sname# params# ugens# constants#)
-         arg-names# (map :name params#)
+         sdef#             (synthdef sname# params# ugens# constants#)
+         arg-names#        (map :name params#)
          params-with-vals# (map #(assoc % :value (atom (:default %))) params#)
-         instance-fn# (apply comp (map :instance-fn (filter :instance-fn (map meta ugens#))))
+         instance-fn#      (apply comp (map :instance-fn (filter :instance-fn (map meta ugens#))))
          smap# (with-meta
                  (map->Synth
                   {:name sname#
@@ -565,7 +565,7 @@
                    :args arg-names#
                    :params params-with-vals#
                    :instance-fn instance-fn#})
-                 {:overtone.live/to-string #(str (name (:type %)) ":" (:name %))})]
+                 {:overtone.live/to-string #(str (name (:type %)) ":" (:name %))})] ;; TODO what on earth is this?
      (load-synthdef sdef#)
      (event :new-synth :synth smap#)
      smap#))


Clean up formatting and docstrings

Clean up formatting and docstrings

--- src/overtone/sc/synth.clj
+++ src/overtone/sc/synth.clj
@@ -53,8 +53,9 @@
 ; * *All* inputs must refer to either a constant or the output of another
 ;   UGen that is higher up in the list.
 (defn- with-inputs
-  "Returns ugen object with its input ports connected to constants and upstream
-  ugens according to the arguments in the initial definition."
+  "Returns ugen object with its input ports connected to constants and
+  upstream ugens according to the arguments in the initial
+  definition."
   [ugen ugens constants grouped-params]
   (when-not (contains? ugen :args)
     (if-not (sc-ugen? ugen)
@@ -111,7 +112,8 @@
 ; computation rate of the ugen.  We probably need to have some meta-data
 ; capabilities for supporting varying output rates...
 (defn- with-outputs
-  "Returns a ugen with its output port connections setup according to the spec."
+  "Returns a ugen with its output port connections setup according to
+  the spec."
   [ugen]
   {:post [(every? (fn [val] (not (nil? val))) (:outputs %))]}
   (if (contains? ugen :outputs)
@@ -133,9 +135,10 @@
     (doall final)))

 (defn- make-control-ugens
-  "Controls are grouped by rate, so that a single Control ugen represents
-  each rate present in the params.  The Control ugens are always the top nodes
-  in the graph, so they can be prepended to the topologically sorted tree.
+  "Controls are grouped by rate, so that a single Control ugen
+  represents each rate present in the params.  The Control ugens are
+  always the top nodes in the graph, so they can be prepended to the
+  topologically sorted tree.

   Specifically handles control proxies at :tr, :ar, :kr and :ir"
   [grouped-params]
@@ -171,7 +174,8 @@
 (def DEFAULT-RATE :kr)

 (defn- ensure-param-keys!
-  "throws an error if map m doesn't contain the correct keys: :name, :default and :rate"
+  "Throws an error if map m doesn't contain the correct
+  keys: :name, :default and :rate"
   [m]
   (when-not (and
              (contains? m :name)
@@ -180,22 +184,24 @@
     (throw (IllegalArgumentException. (str "Invalid synth param map. Expected to find the keys :name, :default, :rate, got: " m)))))

 (defn- ensure-paired-params!
-  "throws an error if list l does not contain an even number of elements"
+  "Throws an error if list l does not contain an even number of
+  elements"
   [l]
   (when-not (even? (count l))
     (throw (IllegalArgumentException. (str "A synth requires either an even number of arguments in the form [control default]* i.e. [freq 440 vol 0.5] or a list of maps. You passed " (count l) " args: " l)))))

 (defn- ensure-vec!
-  "throws an error if list l is not a vector"
+  "Throws an error if list l is not a vector"
   [l]
   (when-not (vector? l)
     (throw (IllegalArgumentException. (str "Your synth argument list is not a vector. Instead I found " (type l) ": " l)))))

 (defn- mapify-params
-  "converts a list of param name val pairs to a param map. If the val of a param
-  is a vector, it assumes it's a pair of [val rate] and sets the rate of the
-  param accordingly. If the val is a plain number, it sets the rate to
-  DEFAULT-RATE. All names are converted to strings"
+  "Converts a list of param name val pairs to a param map. If the val
+  of a param is a vector, it assumes it's a pair of [val rate] and
+  sets the rate of the param accordingly. If the val is a plain
+  number, it sets the rate to DEFAULT-RATE. All names are converted to
+  strings"
   [params]
   (for [[p-name p-val] (partition 2 params)]
     (let [param-map
@@ -210,7 +216,7 @@
       param-map)))

 (defn- stringify-names
-  "takes a map and converts the val of key :name to a string"
+  "Takes a map and converts the val of key :name to a string"
   [m]
   (into {} (for [[k v] m] (if (= :name k) [k (str v)] [k v]))))

@@ -277,16 +283,16 @@
 ;  or through buses.
 ;
 (defn synthdef
-  "Transforms a synth definition (ugen-graph) into a form that's ready to save
-  to disk or send to the server.
+  "Transforms a synth definition (ugen-graph) into a form that's ready
+  to save to disk or send to the server.

     (synthdef \"pad-z\" [
   "
   [sname params ugens constants]
-  (let [grouped-params (group-params params)
-       [params pnames] (make-params grouped-params)
-        with-ctl-ugens (concat (make-control-ugens grouped-params) ugens)
-        detailed (detail-ugens with-ctl-ugens constants grouped-params)]
+  (let [grouped-params  (group-params params)
+        [params pnames] (make-params grouped-params)
+        with-ctl-ugens  (concat (make-control-ugens grouped-params) ugens)
+        detailed        (detail-ugens with-ctl-ugens constants grouped-params)]
     (with-meta {:name (str sname)
                 :constants constants
                 :params params
@@ -302,9 +308,10 @@
           params))

 (defn- gen-synth-name
-  "Auto generate an anonymous synth name. Intended for use in synths that have not
-   been defined with an explicit name. Has the form \"anon-id\" where id is a unique
-   integer across all anonymous synths."
+  "Auto generate an anonymous synth name. Intended for use in synths
+   that have not been defined with an explicit name. Has the form
+   \"anon-id\" where id is a unique integer across all anonymous
+   synths."
   []
   (str "anon-" (next-id ::anonymous-synth)))

@@ -316,8 +323,9 @@
       (isa? (type o) :overtone.sc.bus/control-bus)))

 (defn normalize-synth-args
-  "Pull out and normalize the synth name, parameters, control proxies and the ugen form
-   from the supplied arglist resorting to defaults if necessary."
+  "Pull out and normalize the synth name, parameters, control proxies
+   and the ugen form from the supplied arglist resorting to defaults
+   if necessary."
   [args]
   (let [[sname args] (cond
                        (or (string? (first args))
@@ -331,7 +339,8 @@
     [sname params param-proxies ugen-form]))

 (defn gather-ugens-and-constants
-  "Traverses a ugen tree and returns a vector of two sets [#{ugens} #{constants}]."
+  "Traverses a ugen tree and returns a vector of two sets [#{ugens}
+  #{constants}]."
   [root]
   (if (seq? root)
     (reduce
@@ -346,7 +355,8 @@
           cur-ugens (filter (comp not control-proxy?) cur-ugens)
           cur-ugens (map #(if (output-proxy? %)
                             (:ugen %)
-                            %) cur-ugens)
+                            %)
+                         cur-ugens)
           cur-consts (filter number? args)
           [child-ugens child-consts] (gather-ugens-and-constants cur-ugens)
           ugens (conj (set child-ugens) root)
@@ -354,7 +364,8 @@
       [ugens (vec constants)])))

 (defn- ugen-children
-  "Returns the children (arguments) of this ugen that are themselves upstream ugens."
+  "Returns the children (arguments) of this ugen that are themselves
+  upstream ugens."
   [ug]
   (mapcat
     #(cond
@@ -370,8 +381,8 @@
       (:args ug))))

 (defn topological-sort-ugens
-  "Sort into a vector where each node in the directed graph of ugens will always
-  be preceded by its upstream dependencies."
+  "Sort into a vector where each node in the directed graph of ugens
+  will always be preceded by its upstream dependencies."
   [ugens]
   (loop [ugens ugens
          ; start with leaf nodes that don't have any dependencies
@@ -450,9 +461,10 @@
 (defn synth-player
   [name params this & args]
     "Returns a player function for a named synth.  Used by (synth ...)
-    internally, but can be used to generate a player for a pre-compiled
-    synth.  The function generated will accept two optional arguments that
-    must come first, the :position and :target (see the node function docs).
+    internally, but can be used to generate a player for a
+    pre-compiled synth.  The function generated will accept two
+    optional arguments that must come first, the :position
+    and :target (see the node function docs).

     (foo)
     (foo :position :tail :target 0)
@@ -553,8 +565,9 @@
     [(with-meta s-name md) params ugen-form]))

 (defmacro defsynth
-  "Define a synthesizer and return a player function.  The synth definition
-  will be loaded immediately, and a :new-synth event will be emitted.
+  "Define a synthesizer and return a player function.  The synth
+  definition will be loaded immediately, and a :new-synth event will
+  be emitted.

   (defsynth foo [freq 440]
     (sin-osc freq))
@@ -615,7 +628,8 @@
            (:inputs ug))))

 (defn- reverse-ugen-inputs
-  "Replace ugen inputs that are other ugens with their generated symbolic name."
+  "Replace ugen inputs that are other ugens with their generated
+  symbolic name."
   [pnames ugens ug]
   (assoc ug :inputs
          (map
@@ -634,11 +648,12 @@
 ; appended, and then you need to gather up the inputs and place them into
 ; an array at the correct argument location.
 (defn synthdef-decompile
-  "Decompile a parsed SuperCollider synth definition back into clojure code
-  that could be used to generate an identical synth.
-
-  While this probably won't create a synth definition that can directly compile,
-  it can still be helpful when trying to reverse engineer a synth."
+  "Decompile a parsed SuperCollider synth definition back into clojure
+  code that could be used to generate an identical synth.
+
+  While this probably won't create a synth definition that can
+  directly compile, it can still be helpful when trying to reverse
+  engineer a synth."
   [{:keys [name constants params pnames ugens] :as sdef}]
   (let [sname (symbol name)
         param-vec (param-vector params pnames)
@@ -661,12 +676,12 @@
 (def ^{:dynamic true} *demo-time* 2000)

 (defmacro run
-  "Run an anonymous synth definition for a fixed period of time.  Useful for
-  experimentation. Does NOT add  an out ugen - see #'demo for that. You can
-  specify a timeout in seconds as the first argument otherwise it defaults to
-  *demo-time* ms.
-
-  (run (send-reply (impulse 1) \"/foo\" [1] 43)) ;=> send OSC messages out"
+  "Run an anonymous synth definition for a fixed period of time.
+  Useful for experimentation. Does NOT add an out ugen - see #'demo
+  for that. You can specify a timeout in seconds as the first argument
+  otherwise it defaults to *demo-time* ms.
+
+  (run (send-reply (impulse 1) \"/foo\" [1] 43)) ;=> send OSC messages"
   [& body]
   (let [[demo-time body] (if (number? (first body))
                            [(* 1000 (first body)) (second body)]
@@ -677,10 +692,11 @@
        note#)))

 (defmacro demo
-  "Listen to an anonymous synth definition for a fixed period of time.  Useful
-  for experimentation.  If the root node is not an out ugen, then it will add
-  one automatically.  You can specify a timeout in seconds as the first argument
-  otherwise it defaults to *demo-time* ms.
+  "Listen to an anonymous synth definition for a fixed period of time.
+  Useful for experimentation.  If the root node is not an out ugen,
+  then it will add one automatically.  You can specify a timeout in
+  seconds as the first argument otherwise it defaults to *demo-time*
+  ms.

   (demo (sin-osc 440))      ;=> plays a sine wave for *demo-time* ms
   (demo 0.5 (sin-osc 440))  ;=> plays a sine wave for half a second"
@@ -696,11 +712,13 @@
     `((synth "audition-synth" ~body))))

 (defn active-synths
-  "Return a seq of the actively running synth nodes.  If a synth or inst are passed as the filter it will only return nodes of that type.
-
-    (active-synths) ; => [{:type synth :name \"mixer\" :id 12}
-                          {:type synth :name \"my-synth\" :id 24}]
-    (active-synths my-synth) ; => [{:type synth :name \"my-synth\" :id 24}]
+  "Return a seq of the actively running synth nodes.  If a synth or
+  inst are passed as the filter it will only return nodes of that
+  type.
+
+  (active-synths) ;=> [{:type synth :name \"mixer\" :id 12} {:type
+                        synth :name \"my-synth\" :id 24}]
+  (active-synths my-synth) ;=>[{:type synth :name \"my-synth\" :id 24}]
   "
   [& [synth-filter]]
   (let [active-nodes (filter #(= overtone.sc.node.SynthNode (type %))
@@ -715,7 +733,8 @@

 ; TODO: pull out the default param atom stuff into a separate mechanism
 (defn modify-synth-params
-  "Update synth parameter value atoms storing the current default settings."
+  "Update synth parameter value atoms storing the current default
+  settings."
   [s & params-vals]
   (let [params (:params s)]
     (for [[param value] (partition 2 params-vals)]


Switch to using an `atom` to contain a backend's internal state; add a utility method for getting keys from the backend atom. Also, fix bugs revealed by testing that prevented swapping a backend once set.

--- src/doctopus/storage.clj
+++ src/doctopus/storage.clj
@@ -22,6 +22,7 @@

 (defprotocol DoctopusBackend
   (set-backend! [this backend])
+  (get-key-from-backend [this k])
   (load-from-storage [this k])
   (save-to-storage [this k v])
   (remove-from-storage [this k]))
@@ -30,19 +31,22 @@
 (defrecord Backend
     [backend available-backends]
   DoctopusBackend
-  (set-backend! [this backend]
-    (if (contains? (this :available-backends) backend)
-      (assoc this :backend backend)
+  (set-backend! [this backend-key]
+    (if-let [new-backend (backend-key (:available-backends this))]
+      (swap! (:backend this) (fn [_] new-backend))
       (throw (java.lang.RuntimeException.
-              (str "Cannot use declared storage backend: " backend)))))
+              (str "Cannot use declared storage backend: " (name backend))))))
+  (get-key-from-backend [this k]
+    (let [retrieved-backend (deref (:backend this))]
+      (k retrieved-backend)))
   (load-from-storage [this k]
-    (let [load-fn (get-in this [:backend :load-fn])]
+    (let [load-fn (get-key-from-backend this :load-fn)]
       (load-fn k)))
   (save-to-storage [this k v]
-    (let [save-fn (get-in this [:backend :save-fn])]
+    (let [save-fn (get-key-from-backend this :save-fn)]
       (save-fn k v)))
   (remove-from-storage [this k]
-    (let [remove-fn (get-in this [:backend :remove-fn])]
+    (let [remove-fn (get-key-from-backend this :remove-fn)]
       (remove-fn k))))

 (def available-backends


Removed obsolete bindings.

Removed obsolete bindings.

--- src/fm/simrunner/app.clj
+++ src/fm/simrunner/app.clj
@@ -30,7 +30,7 @@
 (defmethod on-event :default [app event-id & args]
   (println (format "on-event{id: %s args: %s}" event-id args)))

-(defn- app [{:keys [app-title working-directory] :as config} view]
+(defn- app [config view]
   {:config config
    :worker (agent nil)
    :state  (atom {:ui    {:view         view


parse scheduler delay as int

parse scheduler delay as int

--- src/shuppet/scheduler.clj
+++ src/shuppet/scheduler.clj
@@ -54,7 +54,10 @@
   []
   (when-not (= (env :environment-name) "local") ;dont want the auto scheduler for our test envs
     (doseq [environment environments]
-      (at-at/after (* (or (env (keyword (str "service-scheduler-delay-" environment))) 10) 60 1000)
+      (at-at/after (* (or
+                       (Integer/parseInt (env (keyword (str "service-scheduler-delay-" environment))))
+                       10)
+                      60 1000)
                    #(schedule environment)
                    (get-pool environment)
                    :desc (rfc2616-time)))))


Update core.clj

Update core.clj

--- src/hello_world/core.clj
+++ src/hello_world/core.clj
@@ -40,7 +40,7 @@
 )

-(defn handler [{{name "name"} {empfaenger "empfaenger"} :params}]
+(defn handler [{{name "name", empfaenger "empfaenger"} :params}]
   (-> (r/response (page [name empfaenger]))
       (r/content-type "text/html")))


fix display of error reporting of strings

Signed-off-by: Chris Granger <5654cde260ae99bc4d30054171b8bcd902efd19a@gmail.com>

--- src/lt/objs/console.cljs
+++ src/lt/objs/console.cljs
@@ -64,12 +64,11 @@

 (defn error [e]
   (status-bar/console-class "error")
-  (log (str (if (.-stack e)
-              (.-stack e)
-              (let [pr-e (pr-str e)]
-                (if (not= pr-e "[object Object]")
-                  pr-e
-                  (str e)))))
+  (log (str (cond
+             (.-stack e) (.-stack e)
+             (string? e) e
+             (not= (pr-str e) "[object Object]") (pr-str e)
+             :else (str e)))
        "error"))

 (.on js/process "uncaughtException" #(error %))


event channels require special treatment

--- informing/src/app/core.cljs
+++ informing/src/app/core.cljs
@@ -32,15 +32,15 @@
    {:app {:name "Informing"
           :version "0.1.0"
           }
-    :cha {:dom-viewport-resize nil
+    :dom {:document-height nil
+          :document-scroll {:x nil :y nil}
+          :viewport {:width nil :height nil}
+          }
+    :ech {:dom-viewport-resize nil
           :env-mouse-down nil
           :env-mouse-move nil
           :env-mouse-up nil
           }
-    :dom {:document-height nil
-          :document-scroll {:x nil :y nil}
-          :viewport {:width nil :height nil}
-          }
     :env {:mouse nil
           :time nil
           }
@@ -57,18 +57,24 @@

 ;; -----------------------------------------------------------------------------
-;; Channels
-
-(defn get-channel [k]
-  (get-in @omni-state [:cha k]))
-
-(defn swap-channel! [k cha]
-  (swap! omni-state assoc-in [:cha k] cha))
-
-(defonce setup-channels!
+;; Event Channels
+
+(defn get-event-channel [k]
+  (get-in @omni-state [:ech k :channel]))
+
+(defn get-event-listener-key [k]
+  (get-in @omni-state [:ech k :listener-key]))
+
+(defn swap-event-channel! [k [channel listener-key]]
+  (swap! omni-state assoc-in [:ech k :channel] channel)
+  (swap! omni-state assoc-in [:ech k :listener-key] listener-key))
+
+(defonce setup-event-channels!
   (do
-    (swap-channel! :dom-viewport-resize (poly/channel-for-viewport-resize!))
-    (swap-channel! :env-mouse-move (poly/channel-for-mouse-move! js/window))
+    (swap-event-channel! :dom-viewport-resize
+                         (poly/channel-for-viewport-resize!))
+    (swap-event-channel! :env-mouse-move
+                         (poly/channel-for-mouse-move! js/window))
     true))

@@ -172,13 +178,13 @@
   (poly/listen-for-viewport-resize! on-dom-viewport-resize))

 (defonce listen-for-dom-viewport-resize!
-  (poly/listen-take! (get-channel :dom-viewport-resize) on-dom-viewport-resize))
+  (poly/listen-take! (get-event-channel :dom-viewport-resize) on-dom-viewport-resize))

 (defonce listen-for-dom-window-load!
   (poly/listen! js/window "load" on-dom-window-load))

 (defonce listen-for-env-mouse-move!
-  (poly/listen-take! (get-channel :env-mouse-move) on-env-mouse-move))
+  (poly/listen-take! (get-event-channel :env-mouse-move) on-env-mouse-move))

 ;; -----------------------------------------------------------------------------
@@ -302,7 +308,7 @@
     [:p "Document height " rc-dom-document-h "px"]
 ;    [:p "Document scroll " rc-dom-document-scroll-x " by " rc-dom-document-scroll-y]
 ;    [:p "Mouse position " "(" rc-env-mouse-pos-x ", " rc-env-mouse-pos-y ")"]
-    [:p "Mouse " (rx (str @rc-env-mouse))]
+    [:p "Mouse " (rx (str (into (sorted-map) @rc-env-mouse)))]
     [:p "Frames/second (60 max) " rdom/fps]
     [:p "Button Clicks " rc-gui-click-count " "
      [:button {:on-click on-gui-button-click} "Click Me!"]]


Tweak embed plugins for a slightly nicer formatting

--- src/omchaya/plugins.cljs
+++ src/omchaya/plugins.cljs
@@ -96,7 +96,8 @@
            [:div.image-preview
             [:a {:target "_blank"
                  :href piece}
-             [:img.image-embed {:src piece}]]]
+             [:img.image-embed {:src piece}]]
+            [:div.name piece]]
            piece)) activity-pieces))

 (defn youtube-embed [activity-pieces]
@@ -108,7 +109,8 @@
                       :height "315"
                       :src (str "http://www.youtube.com/embed/" video-id)
                       :frameBorder 0
-                      :allowFullScreen true}]]
+                      :allowFullScreen true}]
+            [:div.name piece]]
            piece)) activity-pieces))

 (defn vimeo-embed [activity-pieces]
@@ -121,5 +123,6 @@
                       :frameBorder 0
                       :webkitAllowFullScreen true
                       :mozAllowFullScreen true
-                      :allowFullScreen true}]]
+                      :allowFullScreen true}]
+            [:div.name piece]]
            piece)) activity-pieces))


remove debug msg

remove debug msg

--- src/overtone/sc/core.clj
+++ src/overtone/sc/core.clj
@@ -334,7 +334,6 @@
   "Makes the current thread sleep until scsynth has successfully connected"
   []
   (while (not (connected?))
-    (println "waiting...")
     (Thread/sleep 100)))

 (defn quit


Display values separately that can't be mapped within original input

--- src/pinpointer/core.cljc
+++ src/pinpointer/core.cljc
@@ -33,6 +33,9 @@

 (defn- space [n]
   (times n \space))
+
+(defn- pad-left [s n]
+  (str (space (- n (count s))) s))

 (defn- wavy-line [n]
   (colorize :red (times n \^)))
@@ -100,21 +103,35 @@
                  spec))

 (defn- print-error [total value [i problem trace]]
-  (doseq [chunk trace
-          :let [[line & lines] (format-data value chunk)]]
-    (println (str " (" (inc i) "/" total ")\n"))
-    (println "     Input:" line)
-    (doseq [line lines]
-      (println "           " line))
-    (let [[line & lines] (as-> (:pred problem) it
-                           (simplify-spec it)
-                           (with-out-str (fipp/pprint it))
-                           (str/split it #"\n"))]
-      (println "  Expected:" line)
-      (doseq [line lines]
-        (println "           " line)))
-    (when-let [reason (:reason problem)]
-      (println "    Reason:" reason))))
+  (letfn [(print-with-caption [caption s]
+            (println (str (pad-left caption 10) \:) s))
+          (print-data [caption chunk]
+            (let [[line & lines] (format-data (:val (first chunk)) chunk)]
+              (print-with-caption caption line)
+              (doseq [line lines]
+                (println "           " line))))
+          (print-spec [caption spec]
+            (let [[line & lines] (as-> spec it
+                                   (simplify-spec it)
+                                   (with-out-str (fipp/pprint it))
+                                   (str/split it #"\n"))]
+              (print-with-caption caption line)
+              (doseq [line lines]
+                (println "           " line))))]
+   (let [[chunk & more] (rseq trace)]
+     (println (str " (" (inc i) "/" total ")\n"))
+     (print-data "Input" chunk)
+     (print-spec "Expected" (:pred problem))
+     (when-let [reason (:reason problem)]
+       (print-with-caption "Reason" reason))
+     (when (seq more)
+       (doseq [chunk more]
+         (->> "\n    --- This comes originally from ---\n"
+              (colorize :cyan)
+              println)
+         (print-data "Original" chunk)
+         (println (pad-left "Spec" 10))
+         (print-spec "Applied" (:spec (first chunk))))))))

 (defn pinpoint-out
   ([ed] (pinpoint-out ed {}))


Correct key for -webkit-user-select

Correct key for -webkit-user-select

--- src/re_com/validate.cljs
+++ src/re_com/validate.cljs
@@ -229,7 +229,7 @@
                   :transition-timing-function :turn :unicode-bidi :unicode-range :unset :vertical-align :vh :visibility :vmax :vmin :vw :white-space :widows
                   :width :will-change :word-break :word-spacing :word-wrap :writing-mode :z-index
                   ; ----- Browser specific styles
-                  ::-webkit-user-select :-moz-user-select :-ms-user-select :user-select
+                  :-webkit-user-select :-moz-user-select :-ms-user-select :user-select
                   :-webkit-flex-flow :-webkit-flex-direction :-webkit-flex-wrap :-webkit-justify-content :-webkit-align-items :-webkit-align-content
                   :-webkit-flex :-webkit-flex-grow :-webkit-flex-shrink :-webkit-flex-basis :-webkit-order :-webkit-align-self})


Use a pool of sockets for riemann.graphite.

If the handler returned by riemann.graphite/graphite is used concurrently,
using a single socket will cause nontrivial levels of lock contention.

This socket pool implementation used here could surely be improved, but it
appears to be correct and functional.

Also cleaned up some unnecessary reflection.

--- src/riemann/graphite.clj
+++ src/riemann/graphite.clj
@@ -4,6 +4,7 @@
   (:import [java.net Socket])
   (:import [java.io Writer])
   (:import [java.io OutputStreamWriter])
+  (:import [java.util.concurrent ArrayBlockingQueue])
   (:use [clojure.string :only [split join replace]])
   (:use clojure.tools.logging)
   (:use riemann.common))
@@ -42,50 +43,39 @@
   [opts]
   (let [opts (merge {:host "localhost"
                      :port 2003
+                     :socket-count (* 2 (.availableProcessors
+                                         (Runtime/getRuntime)))
                      :path graphite-path-percentiles} opts)
-        sock (ref nil)
-        out  (ref nil)
-        close (fn []
-                ; Close conn
-                (when (deref out) (.close (deref out)))
-                (when (deref sock) (.close (deref sock)))
-                (dosync
-                  (ref-set sock nil)
-                  (ref-set out nil)))
-        open (fn []
-               (info (str "Opening connection to " opts))
-               (close)
-
-                ; Open conn
-                (dosync
-                  (ref-set sock (Socket. (:host opts) (:port opts)))
-                  (ref-set out (OutputStreamWriter.
-                                 (.getOutputStream (deref sock))))))
+        sockets (ArrayBlockingQueue. (:socket-count opts) true)
+        add-socket (fn []
+                     (info (str "Opening connection to " opts))
+                     (let [sock (Socket. (:host opts) (:port opts))
+                           out (OutputStreamWriter.(.getOutputStream sock))]
+                       (.offer sockets [sock out])))
         path (:path opts)]
-
+
     ; Try to connect immediately
     (try
-      (open)
+      (dotimes [n (:socket-count opts)]
+        (add-socket))
       (catch Exception e
         (warn e (str "Couldn't send to graphite " opts))))
-
     (fn [event]
       (when (:metric event)
-        (let [string (str (join " " [(path event)
+        (let [[sock out] (.take sockets)
+              string (str (join " " [(path event)
                                      (float (:metric event))
                                      (int (:time event))])
                           "\n")]
-          (locking sock
-            (when (deref sock)
-              (try
-                  (.write (deref out) string)
-                  (.flush (deref out))
-
-                (catch Exception e
-                  (warn e (str "Couldn't send to graphite " opts))
-                  (close)
-
-                  (future
-                    ; Reconnect in 5 seconds
-                    (Thread/sleep 5000)
-                    (locking sock (open))))))))))))
+          (try
+            (.write ^OutputStreamWriter out string)
+            (.flush ^OutputStreamWriter out)
+            (.offer sockets [sock out])
+            (catch Exception e
+              (warn e (str "Couldn't send to graphite " opts))
+              (.close out)
+              (.close sock)
+              (future
+                ; Reconnect in 5 seconds
+                (Thread/sleep 5000)
+                (add-socket)))))))))


punting on p60

punting on p60

--- src/rwn4clojure/core.clj
+++ src/rwn4clojure/core.clj
@@ -623,6 +623,53 @@
               (for [g fns]
                 (apply g vs))))]
     (is (all? (p59 f)))))
+
+;; Write a function which behaves like reduce, but returns each
+;; intermediate value of the reduction. Your function must accept
+;; either two or three arguments, and the return sequence must be lazy.
+#_(defn p60 [__]
+  [#_(= (take 5 (__ + (range))) [0 1 3 6 10])
+   (= (__ conj [1] [2 3 4]) [[1] [1 2] [1 2 3] [1 2 3 4]])
+   (= (last (__ * 2 [3 4 5])) (reduce * 2 [3 4 5]) 120)])
+#_(deftest t60
+  (let [f' (fn f'
+            ([g ini vs]
+             (reduce (fn [acc v]
+                       (conj acc (g (last acc) v)))
+                     [ini]
+                     vs))
+            ([g vs]
+             (f g (first vs) (rest vs))))
+        f'' (fn f''
+            ([g ini vs]
+             (cons ini (f g vs)))
+            ([g vs]
+             (lazy-seq
+              (cons (g (first vs))
+                    (f'' g (rest vs))))))
+        f''' (fn f'''
+            ([g vs]
+             (iterate (fn [v]
+                        (g v))
+                      [vs []]))
+            ([g ini vs]
+             (cons ini (f''' g vs))))
+        f'''' (fn f''''
+            ([g vs]
+             (let [result (atom [])]
+               (map (fn [v]
+                      (if (seq @result)
+                        (swap! result conj (g (last @result) v))
+                        (swap! result conj (g v))))
+                    vs)
+               @result)))
+        f (fn f
+            ([g vs]
+             (loop [v vs, acc []]
+               (if v
+                 (conj acc (g (last acc) v))
+                 acc))))]
+    (is (all? (p60 f)))))

 (defn p61 [__]
   [(= (__ [:a :b :c] [1 2 3]) {:a 1, :b 2, :c 3})


51, 52

51, 52

--- src/sandbox/4clojure.clj
+++ src/sandbox/4clojure.clj
@@ -177,3 +177,9 @@
 ;;50 Split by Type
 #(vals (group-by type %))

+;;51 Advanced Destructuring
+[1 2 3 4 5]
+
+;;52 Intro to Destructuring
+;;[c e]
+


Add support for query filters to query (@bpot)

--- src/taoensso/faraday.clj
+++ src/taoensso/faraday.clj
@@ -793,6 +793,7 @@
   "Retrieves items from a table (indexed) with options:
     prim-key-conds - {<key-attr> [<comparison-operator> <val-or-vals>] ...}.
     :last-prim-kvs - Primary key-val from which to eval, useful for paging.
+    :query-filter  - {<key-attr> [<comparison-operator> <val-or-vals>] ...}.
     :span-reqs     - {:max _ :throttle-ms _} controls automatic multi-request
                      stitching.
     :return        - e/o #{:all-attributes :all-projected-attributes :count
@@ -818,7 +819,7 @@

   Ref. http://goo.gl/XfGKW for query+scan best practices."
   [client-opts table prim-key-conds
-   & [{:keys [last-prim-kvs span-reqs return index order limit consistent?
+   & [{:keys [last-prim-kvs query-filter span-reqs return index order limit consistent?
               return-cc?] :as opts
        :or   {span-reqs {:max 5}
               order     :asc}}]]
@@ -831,6 +832,7 @@
                  :always (.setScanIndexForward (case order :asc true :desc false))
                  last-prim-kvs   (.setExclusiveStartKey
                                   (clj-item->db-item last-prim-kvs))
+                 query-filter    (.setQueryFilter (query|scan-conditions query-filter))
                  limit           (.setLimit     (int g))
                  index           (.setIndexName      g)
                  consistent?     (.setConsistentRead g)


Refactor: extract set-search-path

Refactor: extract set-search-path

--- src/territory_bro/db.clj
+++ src/territory_bro/db.clj
@@ -6,6 +6,7 @@
   (:require [cheshire.core :as cheshire]
             [clojure.java.io :as io]
             [clojure.java.jdbc :as jdbc]
+            [clojure.string :as str]
             [clojure.tools.logging :as log]
             [conman.core :as conman]
             [hikari-cp.core :as hikari-cp]
@@ -151,10 +152,16 @@
       (.locations (strings "classpath:db/flyway/tenant"))
       (.load)))

+(defn set-search-path [conn schemas]
+  (doseq [schema schemas]
+    (assert (re-matches #"^[a-zA-Z0-9_]+$" schema)
+            {:schema schema}))
+  (jdbc/execute! conn [(str "set search_path to " (str/join "," schemas))]))
+
 (defmacro with-db [binding & body]
   ;; TODO: add congregation schema to search path
   `(jdbc/with-db-transaction [~(first binding) (:default databases) {:isolation :serializable}]
-     (jdbc/execute! ~(first binding) [(str "set search_path to " (:database-schema config/env))])
+     (set-search-path ~(first binding) [(:database-schema config/env)])
      ~@body))

 (defn- load-queries [queries-atom]


Ignoring a FileNotFound excpetion that can bring down a supervisor.

--- storm-core/src/clj/backtype/storm/daemon/supervisor.clj
+++ storm-core/src/clj/backtype/storm/daemon/supervisor.clj
@@ -1,4 +1,5 @@
 (ns backtype.storm.daemon.supervisor
+  (:import [java.io IOException])
   (:import [backtype.storm.scheduler ISupervisor])
   (:use [backtype.storm bootstrap])
   (:use [backtype.storm.daemon common])
@@ -142,6 +143,8 @@
     ;; this avoids a race condition with worker or subprocess writing pid around same time
     (rmpath (worker-pids-root conf id))
     (rmpath (worker-root conf id))
+  (catch IOException e
+    (log-warn-error e "Failed to cleanup worker " id ". Will retry later"))
   (catch RuntimeException e
     (log-warn-error e "Failed to cleanup worker " id ". Will retry later")
     )))


Initialize webworker only on browser environment.

--- src/uxbox/data/core.cljs
+++ src/uxbox/data/core.cljs
@@ -11,5 +11,9 @@
             [uxbox.constants :as c]
             [uxbox.util.workers :as uw]))

-(defonce worker (uw/init "/js/worker.js"))
+;; This excludes webworker instantiation on nodejs where
+;; the tests are run.

+(when (not= *target* "nodejs")
+  (defonce worker (uw/init "/js/worker.js")))
+