Remove reference to dropped flense.editor.layout namespace

--- src/flense_nw/app.cljs
+++ src/flense_nw/app.cljs
@@ -8,7 +8,6 @@
             flense.actions.movement
             flense.actions.paredit
             [flense.editor :refer [editor-view]]
-            flense.editor.layout
             [flense.model :as model]
             [flense-nw.cli :refer [cli-view]]
             [flense-nw.error :refer [error-bar-view]]


Better error messages

Better error messages

--- src/instaskip/core.clj
+++ src/instaskip/core.clj
@@ -52,7 +52,7 @@
            (migrate/routes dir innkeeper-config)

            :else
-           (exit 1 "Invalid options for migrate-routes")))
+           (exit 1 "Invalid options for migrate-routes. The -d flag is mandatory.")))

 (defn- create [opts innkeeper-config]
   (m/match opts
@@ -60,7 +60,7 @@
            (actions/create route team innkeeper-config)

            :else
-           (exit 1 "Invalid options for create")))
+           (exit 1 "Invalid options for create. Both -R and -T flags should be present.")))

 (defn- list-paths [opts innkeeper-config]
   (m/match opts
@@ -79,7 +79,7 @@
            (actions/list-path (Integer. path-id) innkeeper-config)

            :else
-           (exit 1 "Invalid options for hosts-for-path")))
+           (exit 1 "Invalid options for hosts-for-path. The -i flag should be present.")))

 (defn- list-hosts [innkeeper-config]
   (actions/list-hosts innkeeper-config))
@@ -93,7 +93,7 @@
            (actions/list-routes {} innkeeper-config)

            :else
-           (exit 1 "Invalid options for list-routes")))
+           (exit 1 "Invalid options for list-routes.")))

 (defn- list-route [opts innkeeper-config]
   (m/match opts
@@ -101,7 +101,7 @@
            (actions/list-route (Integer. id) innkeeper-config)

            :else
-           (exit 1 "Invalid options for list-route. Id should be present.")))
+           (exit 1 "Invalid options for list-route. The -i flag should be present.")))

 (defn- delete-route [opts innkeeper-config]
   (m/match opts
@@ -109,7 +109,7 @@
            (actions/delete-route (Integer. id) innkeeper-config)

            :else
-           (exit 1 "Invalid options for list-route. Id should be present.")))
+           (exit 1 "Invalid options for list-route. The -i flag should be present.")))

 (defn- parse-action [params url token]
   (let [options (params :options)


Minor tweak for email settings validation :mailbox_with_mail:

--- src/metabase/email.clj
+++ src/metabase/email.clj
@@ -18,7 +18,8 @@
   "SMTP secure connection protocol. (tls, ssl, or none)"
   :default "none"
   :setter  (fn [new-value]
-             (assert (contains? #{"tls" "ssl" "none"} new-value))
+             (when-not (nil? new-value)
+               (assert (contains? #{"tls" "ssl" "none"} new-value)))
              (setting/set-string! :email-smtp-security new-value)))

 ;; ## PUBLIC INTERFACE


Dont do entry point for kibana-nginx

Dont do entry point for kibana-nginx

It's baked into the image now

--- src/terraboot/elasticsearch.clj
+++ src/terraboot/elasticsearch.clj
@@ -62,7 +62,7 @@
         nginx (docker-systemd-unit "mastodonc" "kibana-nginx"
                                       {:options [(str "--env " "ES_HOST=" es-host)
                                                  "--net=host"]
-                                       :entry-point "/bin/bash -c \"envsubst < /etc/nginx/conf.d/mysite.template > /etc/nginx/conf.d/default.conf && nginx -g 'daemon off;'\""}
+                                       }
                                       )]
     (cloud-config-coreos [logstash
                           nginx])))


Switch to port 3000

Switch to port 3000

--- marketing/src/marketing/env.clj
+++ marketing/src/marketing/env.clj
@@ -3,7 +3,7 @@
   (:require [clojure.tools.logging :as log]
             [clojure.string :as string]))

-(def ^:private all-env-vars [{:name ::PORT :default 5000 :int? true}
+(def ^:private all-env-vars [{:name ::PORT :default 3000 :int? true}
                              {:name ::HOST :default "localhost"}
                              {:name ::REPO_URL}
                              {:name ::WEB_FLUSH_COMMAND :default "flush"}


adding example json response

adding example json response

--- src/one_route/core.clj
+++ src/one_route/core.clj
@@ -1,5 +1,6 @@
 (ns one-route.core
-  (:use [ring.middleware.reload])
+  (:use [ring.middleware.reload]
+        [ring.util.response])
   (:require [compojure.handler :as handler]
             [compojure.core
              :as c-core
@@ -10,6 +11,7 @@

 (defroutes api
   (GET "/" [] (slurp "resources/public/html/index.html"))
+  (GET "/health" [] (response {:health "green"}))
   (c-route/resources "/"))

 (def app


Add introduction and Pollock description

--- src/uk/co/tombooth/pollock.cljs
+++ src/uk/co/tombooth/pollock.cljs
@@ -7,7 +7,11 @@

 ;;
DRAFT ARTICLE

-;; Learning Clojure by building a digital Jackson Pollock.
+;; Learning Clojure by building a digital Jackson Pollock. This
+;; article and the source code backing it can be [found on
+;; github](https://www.github.com/tombooth/painting-in-clojure).
+;; Below is an example of what we will be building, running the code
+;; found in this page.

 ;; <canvas id="pollock" style="width: 100%; border: 5px solid #eee"></canvas>
@@ -15,6 +19,15 @@
 ;; <button id="fill">Fill canvas</button>

+
+;; ## Jackson Pollock
+
+;; He was an abstract artist who lived through the first half of the
+;; 20th century and is most famous for his drip paintings. This style
+;; of painting involves him using sticks brushes, sticks and cans to
+;; apply paint to the canvas with the motion of his gestures causing
+;; the artworks to come alive. You can get a good idea of how this
+;; comes together from [this youtube video](https://www.youtube.com/watch?v=7bICqvmKL5s).

 ;; ## Setting the scene


Allow to set Content-Type explicitly

Allow to set Content-Type explicitly

--- src/postal/message.clj
+++ src/postal/message.clj
@@ -68,9 +68,13 @@
 (defn eval-bodypart [part]
   (condp (fn [test type] (some #(= % type) test)) (:type part)
     [:inline :attachment]
-    (doto (javax.mail.internet.MimeBodyPart.)
-      (.attachFile (fileize (:content part)))
-      (.setDisposition (name (:type part))))
+    (let [attachment-part (doto (javax.mail.internet.MimeBodyPart.)
+                            (.attachFile (fileize (:content part)))
+                            (.setDisposition (name (:type part))))]
+
+      (when (:content-type part)
+        (.setHeader attachment-part "Content-Type" (:content-type part)))
+      attachment-part)
     (doto (javax.mail.internet.MimeBodyPart.)
       (.setContent (:content part) (:type part)))))


Updated provider and variables ingest.

Updated provider and variables ingest.

--- src/cmr_edsc_stubs/data/core.clj
+++ src/cmr_edsc_stubs/data/core.clj
@@ -38,11 +38,13 @@
     (create-provider provider-data :local :metadata-db))
   ([provider-data environment-type service-key]
     (let [endpoint (client-util/get-endpoint environment-type service-key)]
-      (client/post (format "%s/providers" endpoint)
-       {:body provider-data
-        :content-type :json
-        :throw-exceptions false
-        :headers util/local-token-header}))))
+      (-> {:body provider-data
+           :content-type :json
+           :throw-exceptions false
+           :headers util/local-token-header}
+          ((partial client/post (format "%s/providers" endpoint)))
+          (select-keys [:status :body])
+          (update-in [:body] #(json/parse-string % true))))))

 (defn create-ges-disc-provider
   []
@@ -81,14 +83,16 @@
           client (ingest/create-client {:endpoint deployment
                                         :token util/local-token
                                         :return-body? true})]
-      (doseq [var-files [(data-sources/get-ges-disc-airx3std-ch4-variables)
-                         ;; add more groups of variables here
-                         ]]
-        (doseq [var-data (map slurp var-files)]
-          (let [native-id (str (java.util.UUID/randomUUID))]
-            (ingest/create-variable client
-                                    provider-id
-                                    native-id
-                                    var-data
-                                    {:content-type submit-content-type
-                                     :accept accept-content-type})))))))
+      (for [var-files [(data-sources/get-ges-disc-airx3std-ch4-variables)
+                       ;; add more groups of variables here
+                       ]]
+        (for [var-file var-files]
+          (do
+            (println "Loading" (str var-file) "...")
+            (let [native-id (str (java.util.UUID/randomUUID))]
+              (ingest/create-variable client
+                                      provider-id
+                                      native-id
+                                      (slurp var-file)
+                                      {:content-type submit-content-type
+                                       :accept accept-content-type}))))))))


Changed doubly-scale-fuzzy-context

Changed doubly-scale-fuzzy-context

since it is not clear which values are necessary to use for the
resulting context. Thus objects and attributes now get paired with all
values occuring in the context.

Signed-off-by: Daniel Borchmann <25857343a15bf1edafebc2912e82ecf775c585c1@mailbox.tu-dresden.de>

--- src/conexp/contrib/fuzzy/fca.clj
+++ src/conexp/contrib/fuzzy/fca.clj
@@ -104,16 +104,13 @@
   context ctx."
   [ctx]
   (let [inz  (incidence ctx),
+        vals (-> (set (vals inz)) (disj 0)),
         objs (set-of [g ny]
                      [g (objects ctx),
-                      m (attributes ctx),
-                      :let [ny (inz [g m])],
-                      :when (not (zero? ny))]),
+                      ny vals]),
         atts (set-of [m lambda]
-                     [g (objects ctx),
-                      m (attributes ctx),
-                      :let [lambda (inz [g m])],
-                      :when (not (zero? lambda))]),
+                     [m (attributes ctx),
+                      lambda vals]),
         inci  (set-of [[g ny] [m lambda]]
                       [[g ny] objs,
                        [m lambda] atts,


No-doc Aeron publication manager

No-doc Aeron publication manager

--- src/onyx/messaging/aeron/publication_manager.clj
+++ src/onyx/messaging/aeron/publication_manager.clj
@@ -1,4 +1,4 @@
-(ns onyx.messaging.aeron.publication-manager
+(ns ^:no-doc onyx.messaging.aeron.publication-manager
   (:require [taoensso.timbre :refer [error fatal info] :as timbre]
             [clojure.core.async :refer [chan >!! <!! put! close! sliding-buffer thread]])
   (:import [uk.co.real_logic.aeron Aeron Aeron$Context FragmentAssembler Publication Subscription AvailableImageHandler]


Add default buttons

Add default buttons

--- src/discuss/utils/bootstrap.cljs
+++ src/discuss/utils/bootstrap.cljs
@@ -3,10 +3,22 @@
   (:require [om.dom :as dom]
             [discuss.utils.common :as lib]))

+(defn button
+  "Create dom element of a bootstrap button."
+  [fn class & strs]
+  (dom/button #js {:className (str "btn " class)
+                   :onClick   fn
+                   :key       (lib/get-unique-key)}
+              strs))
+
 (defn button-primary
   "Create dom element of a bootstrap primary button."
-  [fn & strs]
-  (dom/button #js {:className "btn btn-primary"
-                   :onClick   fn
-                   :key       (lib/get-unique-key)}
-              strs))+  [fn & strs] (button fn "btn-primary" strs))
+
+(defn button-default
+  "Create dom element of a bootstrap default button."
+  [fn & strs] (button fn "btn-default" strs))
+
+(defn button-default-sm
+  "Create dom element of a bootstrap default small button."
+  [fn & strs] (button fn "btn-default btn-sm" strs))


[CS] Output street segment XML in larger chunks

--- src/vip/data_processor/output/street_segment.clj
+++ src/vip/data_processor/output/street_segment.clj
@@ -21,7 +21,7 @@
                   (xml-node precinct_split_id)]]
     (simple-xml :street_segment id children)))

-(def chunk-size 1000)
+(def chunk-size 10000)

 (defn xml-nodes [ctx]
   (let [sql-table (get-in ctx [:tables :street-segments])


Back to realtime

Back to realtime

Back to implementing realtime again after a lengthy front end bug

--- src/webapp/framework/client/components/main.cljs
+++ src/webapp/framework/client/components/main.cljs
@@ -63,7 +63,7 @@

                                   (div {:style {:padding "20px" :backgoundColor "white"}})

-                                  ( select id,item from todo_items  where id > 43
+                                  (realtime select id,item from todo_items  where id > 43
                                                   {}
                                                   (container
                                                     (inline  "10%" (str (<-- :id)))


Faster compare of derefed reactions, and refactor

--- src/reagent/ratom.cljs
+++ src/reagent/ratom.cljs
@@ -32,28 +32,23 @@
                  false))))))

 (defn- in-context [obj f]
-  (set! (.-cljsCapPos obj) 0)
+  (set! (.-capPos obj) 0)
   (binding [*ratom-context* obj]
     (f)))

 (defn- deref-capture [f obj]
   (let [watch (.-watching obj)]
-    (set! (.-cljsCaptured obj) (.-watching obj))
+    (set! (.-captured obj) (.-watching obj))
     (when (dev?)
       (set! (.-ratomGeneration obj)
             (set! generation (inc generation))))
     (let [res (in-context obj f)
-          capt (.-cljsCaptured obj)]
-      (set! (.-cljsCaptured obj) nil)
+          capt (.-captured obj)]
       (set! (.-dirty? obj) false)
-      (when-not (arr-eq capt watch)
+      (when-not (or (identical? capt watch)
+                    (arr-eq capt watch))
         (._update-watching obj capt))
       res)))
-
-(defn check-derefs [f]
-  (let [ctx (js-obj)
-        res (in-context ctx f)]
-    [res (some? (.-cljsCaptured ctx))]))

 (defn- add-item [a x]
   (when (== -1 (.indexOf a x))
@@ -61,19 +56,19 @@

 (defn- notify-deref-watcher! [derefable]
   (when-some [obj *ratom-context*]
-    (let [c (.-cljsCaptured obj)]
+    (let [c (.-captured obj)]
       (if (nil? c)
-        (do (set! (.-cljsCapPos obj) -1)
-            (set! (.-cljsCaptured obj) (array derefable)))
+        (do (set! (.-capPos obj) -1)
+            (set! (.-captured obj) (array derefable)))
         ;; Try to avoid allocating new array
-        (let [p (.-cljsCapPos obj)]
+        (let [p (.-capPos obj)]
           (if (== p -1)
             (add-item c derefable)
             (if (identical? derefable (aget c p))
-              (set! (.-cljsCapPos obj) (inc p))
-              (let [c1 (set! (.-cljsCaptured obj) (.slice c 0 p))]
+              (set! (.-capPos obj) (inc p))
+              (let [c1 (set! (.-captured obj) (.slice c 0 p))]
                 (add-item c1 derefable)
-                (set! (.-cljsCapPos obj) -1)))))))))
+                (set! (.-capPos obj) -1)))))))))

 (defn- check-watches [old new]
   (when debug
@@ -531,6 +526,11 @@
       (aset obj key rea))
     res))

+(defn check-derefs [f]
+  (let [ctx (js-obj)
+        res (in-context ctx f)]
+    [res (some? (.-captured ctx))]))
+

 ;;; wrap


Add helper for generating a server response

Add a helper for generating a server response with the correct
Content-Type and a reasonable status code.

--- src/scavenger/core.clj
+++ src/scavenger/core.clj
@@ -12,15 +12,20 @@
 (defn get-all-items []
   (map first (q '[:find (pull ?c [*]) :where [?c item/name]] (db conn))))

+(defn generate-response [data & [status]]
+  {:status (or status 200)
+   :headers {"Content-Type" "application/edn"}
+   :body (pr-str data)})
+
 (defroutes app-routes
   (GET "/items" []
-    (response (str (into [] (get-all-items)))))
+    (generate-response (into [] (get-all-items))))
   (POST "/items" {body :body}
     (let [tempid (d/tempid :items)
           data (merge (read-string (slurp body)) {:db/id tempid})
           tx @(d/transact conn [data])
           id (d/resolve-tempid (db conn) (:tempids tx) tempid)]
-      (response (str (d/touch (d/entity (db conn) id))))))
+      (generate-response (d/touch (d/entity (db conn) id)))))
   (GET "/" []
     (-> (resource-response "index.html" {:root "public"})
         (content-type "text/html")))


Better tests

Better tests

--- test/caesium/binding_test.clj
+++ test/caesium/binding_test.clj
@@ -72,19 +72,20 @@
 (defn check-method
   "Check a method binding a non-const fn."
   [^Method method params]
+  (info method)
   (is (= (if (= "randombytes" (.getName method))
            Void/TYPE
            Integer/TYPE)
          (.getGenericReturnType method)))
   (doseq [param params]
-    (let [param-type (.getParameterizedType ^Parameter param)
-          annotation-types (->> (.getAnnotations ^Parameter param)
-                                (map #(.annotationType ^Annotation %))
-                                set)]
-      (condp (fn [x y] (x y)) param-type
-        #{ByteArray ByteBuffer} (is (= #{Pinned} annotation-types))
-        #{Long/TYPE} (is (= #{size_t} annotation-types))
-        #{LongLongByReference} (is (= #{} annotation-types))))))
+    (info param)
+    (is (= (condp (fn [x y] (x y)) (.getParameterizedType ^Parameter param)
+             #{ByteArray ByteBuffer} #{Pinned}
+             #{Long/TYPE}  #{LongLong}
+             #{LongLongByReference} #{})
+           (->> (.getAnnotations ^Parameter param)
+                (map #(.annotationType ^Annotation %))
+                set)))))

 (defn check-const-method
   "Check a method binding a const fn."


white space cleanup

white space cleanup

--- test/clabango/test/parser.clj
+++ test/clabango/test/parser.clj
@@ -204,8 +204,6 @@
   (is (= (render "{% if not foo %}foo is true{% endif %}" {:foo false})
          "foo is true")))

-
-
 (deftest test-nested-if
   (is (= (render (str "{% if foo %}before bar {% if bar %}"
                       "foo & bar are true"


(maint) Override java version in tests

(maint) Override java version in tests

The version of directory-server we use, being from 2010, doesn't
understand the concept of java versions with more than one digit. This
causes test failures because at some point during initialization it
needs to parse the java version. It doesn't actually *use* the version,
it's just parsed as a side effect of loading a static SystemUtils class.
So we can just fake it out with a totally bogus but properly formatted
version number.

--- test/clj_ldap/test/server.clj
+++ test/clj_ldap/test/server.clj
@@ -14,6 +14,15 @@
            (org.apache.directory.shared.ldap.schema.manager.impl DefaultSchemaManager)))

 (defonce server (atom nil))
+
+(defn- override-java-version!
+  "Override the java.version property as the ancient version of
+  directory-server we use for tests seems not to understand the concept of a
+  version number with multiple digits (ie. 11 or 14). This version isn't
+  actually used anywhere, just parsed as a side effect of loading a SystemUtils
+  class, so it only needs to appear valid."
+  []
+  (System/setProperty "java.version" "0.0.0"))

 (defn- add-partition!
   "Adds a partition to the embedded directory service"
@@ -36,6 +45,7 @@
 (defn start-ldap-server
   "Start an embedded ldap server"
   [port]
+  (override-java-version!)
   (let [work-dir (fs/temp-dir)
         schema-dir (fs/file work-dir "schema")
         _ (fs/mkdir schema-dir)


Multiple literals should just always error

--- test/desdemona/query_test.clj
+++ test/desdemona/query_test.clj
@@ -89,8 +89,10 @@
            (#'q/dsl->logic '(or (= (:type x) "egress")
                                 (= (:ip x) "10.0.0.1"))))))
   (testing "multiple literals"
-    (is (= '(clojure.core.logic/featurec x {:ip "10.0.0.1"})
-           (#'q/dsl->logic '(= (:ip x) "10.0.0.1" "10.0.0.1")))))
+    (is (thrown? IllegalArgumentException
+                 (#'q/dsl->logic '(= (:ip x) "10.0.0.1" "10.0.0.1"))))
+    (is (thrown? IllegalArgumentException
+                 (#'q/dsl->logic '(= (:ip x) "10.0.0.1" "10.0.0.2")))))
   (testing "linking events"
     (is (= '(fresh [s#]
               (clojure.core.logic/featurec x {:ip s#})


robustify against 500 response

robustify against 500 response

--- src-cljs/core.cljs
+++ src-cljs/core.cljs
@@ -86,9 +86,10 @@
     (.send XhrIo (string/join "?" ["/tracks.json" ])
            (fn [e]
              (let [xhr (.-target e)
-                   o (.getResponseJson xhr)
-                   r (js->clj o)]
-               (put! channel r)))
+                   code (.getStatus xhr)
+                   o (and (< code 400) (.getResponseJson xhr))
+                   r (and o (js->clj o))]
+               (put! channel (or r []))))
            "POST"
            (string/join
             " AND "


Add elb/asg helpers

Add elb/asg helpers

--- src/terraboot/core.clj
+++ src/terraboot/core.clj
@@ -5,6 +5,7 @@
             [clj-yaml.core :as yaml]
             [clojure.pprint :refer [pprint]]))

+(def account-id "12345")
 (letfn [(merge-in* [a b]
           (if (map? a)
             (merge-with merge-in* a b)
@@ -104,15 +105,94 @@
                                       (update-in [:vpc_security_group_ids] concat default-sg-ids)))))

 (defn elb [name spec]
-  (resource "aws_elb" name (-> {:listeners [{:instance_port 80
-                                             :lb_port 80
-                                             :instance_protocol "http"
-                                             :lb_protocol "http"}
-                                            {:instance_port 443
-                                             :instance_protocol "http"
-                                             :lb_port 443
-                                             :lb_protocol "http"}
-                                            (merge-in spec)]})))
+  (let [defaults {:cert_name false
+                  :instances []
+                  :health_check_url "/"
+                  :lb_protocol "http"}
+        spec (merge-in defaults spec)
+        {:keys [health_check_url
+                lb_protocol
+                instances
+                cert_name]} spec
+        secure_protocol (if (= lb_protocol "http")
+                          "https"
+                          "ssl")
+        default-listener {:instance_port 80
+                          :instance_protocol lb_protocol
+                          :lb_port 80
+                          :lb_protocol lb_protocol}
+
+        listeners (if cert_name
+                    [default-listener {
+                                       :instance_port 80
+                                       :instance_protocol lb_protocol
+                                       :lb_port 443
+                                       :lb_protocol secure_protocol
+                                       :ssl_certificate_id (str "arn:aws:iam::" account-id ":server-certificate/" cert_name)}]
+                    [default-listener])
+        ]
+    (let [elb-sg (str "elb_" name)
+          allow-sg (str "allow_elb_" name)]
+      (merge-in (security-group allow-sg {}
+                                {:port 80
+                                 :source_security_group_id (id-of "aws_security_group" elb-sg)
+                                 })
+                (security-group elb-sg {})
+                (resource "aws_elb" name {:subnets []
+                                          :security_groups [(id-of "aws_security_group" elb-sg)
+                                                            (id-of "aws_security_group" "allow_external_http_https")
+                                                            (id-of "aws_security_group" "allow_outbound")]
+                                          :listener listeners
+                                          :instances instances
+                                          :health_check {:healthy_threshold 2
+                                                         :unhealthy_threshold 2
+                                                         :timeout 3
+                                                         :target (str "HTTP:80" health_check_url)
+                                                         :interval 5}
+                                          :cross_zone_load_balancing true
+                                          :idle_timeout 60
+                                          :connection_draining true
+                                          :connection_draining_timeout 60
+                                          :tags {:Name name}})))))
+
+(defn asg [name {:keys [] :as spec}]
+  (let [sgs (spec :sgs)
+        elb? (spec :elb)
+        sgs (if elb?
+              (conj sgs (str "allow_elb_" name))
+              sgs)
+
+        asg-config
+        (merge-in
+         (resource "aws_launch_configuration" name
+                   {:name_prefix (str name "-")
+                    :image_id (spec :image_id)
+                    :instance_type (spec :instance_type)
+                    :user_data (spec :user_data)
+                    :lifecycle { :create_before_destroy true }
+                    :key_name (get spec :key_name "ops-terraboot")
+                    :security_groups (map #(id-of "aws_security_group" %) sgs)})
+
+         (resource "aws_autoscaling_group" name
+                   {:vpc_zone_identifier []
+                    :name name
+                    :max_size (spec :max_size)
+                    :min_size (spec :min_size)
+                    :health_check_type (spec :health_check_type)
+                    :health_check_grace_period (spec :health_check_grace_period)
+                    :launch_configuration (output-of "aws_launch_configuration" name "name")
+                    :lifecycle { :create_before_destroy true }
+                    :load_balancers (if elb? [(output-of "aws_elb" name "name")]
+                                        [])
+                    :tag {
+                          :key "Name"
+                          :value "autoscale-#{name}"
+                          :propagate_at_launch true
+                          }}))]
+    (if (spec :elb)
+      (merge-in asg-config (elb name (spec :elb)))
+      asg-config)))
+
 (def all-external "0.0.0.0/0")

 (def region "eu-central-1")


Now setup to detect duplicates in maps at second level

--- src/terraboot/core.clj
+++ src/terraboot/core.clj
@@ -12,8 +12,8 @@
           [mfns]
           (fn [a b]
             (if (map? a)
-              (do (when (seq (clojure.set/intersection (set (keys a)) (set (keys b))))
-                    (prn "Duplicate key"))
+              (do (when-let [dups (seq (clojure.set/intersection (set (keys a)) (set (keys b))))]
+                    (prn "Duplicate keys: " dups))
                   (merge-with ((first mfns) (rest mfns)) a b))
               b)))
         (merge-in*
@@ -27,8 +27,8 @@
           (partial merge-with
                   ((first fn-seq) (rest fn-seq))))]
   (def merge-in
-    (merge-with-fn-seq (conj (repeat merge-in*) merge-in*
-                             merge-in* sensitive-merge-in*))))
+    (merge-with-fn-seq (conj (repeat merge-in*) sensitive-merge-in*
+                             merge-in*))))

 (defn output-of [type resource-name & values]
   (str "${"


Fixed collapsed menu cells not being repeated

--- src/varjocafe/view.clj
+++ src/varjocafe/view.clj
@@ -39,6 +39,9 @@
                                    (refine [html/any-node] (html/replace-vars {:allergens allergens}))))
                  [:.food html/any-node] (html/replace-vars {:food (:name food)}))

+(html/defsnippet collapsed-menu-cell "templates/layout.html" [:.restaurant-row.collapsed (indented :.menu)]
+                 [])
+
 (html/defsnippet menu-cell "templates/layout.html" [:.restaurant-row.expanded (indented :.menu)]
                  [restaurant date]
                  [(indent-of :.food)] nil
@@ -67,6 +70,9 @@
                  [:.restaurant-row] (html/set-attr :data-restaurant-id (:id restaurant))
                  [:.restaurant-name html/any-node] (html/replace-vars {:restaurant-name (:name restaurant)})
                  [:.restaurant-address html/any-node] (html/replace-vars {:restaurant-address (format/restaurant-address restaurant)})
+                 [:.collapsed (indent-of :.menu)] nil
+                 [:.collapsed :.menu] (html/clone-for [date dates]
+                                                      (html/substitute (collapsed-menu-cell)))
                  [:.expanded (indent-of :.menu)] nil
                  [:.expanded :.menu] (html/clone-for [date dates]
                                                      (html/substitute (menu-cell restaurant date)))


Testing openredis

Testing openredis

--- src/wlmmap/handler.clj
+++ src/wlmmap/handler.clj
@@ -32,7 +32,7 @@
       (clojure.string/replace #"\"" "\\\\\"")))

 (def server1-conn
-  {:pool {} :spec {:uri (System/getenv "REDISTOGO_URL")}})
+  {:pool {} :spec {:uri (System/getenv "OPENREDIS_URL")}})

 (defmacro wcar* [& body]
   `(car/wcar server1-conn ~@body))
@@ -40,7 +40,7 @@
 (defn- generate-markers
   "return a string with the javascript code to generate addressPoints."
   [params]
-  (let [mons (take 1000 (wcar* (car/smembers "frfr")))
+  (let [mons (take 2000 (wcar* (car/smembers "frfr")))
         all (remove #(nil? %)
                     (for [m mons]
                       (let [res (read-string (wcar* (car/get m)))


Updating references to JavaParser calls

Updating references to JavaParser calls

--- src/app/javaparser.clj
+++ src/app/javaparser.clj
@@ -1,15 +1,15 @@
-(import japa.parser.JavaParser)
-(import japa.parser.ast.CompilationUnit)
-(import japa.parser.ast.Node)
-(import japa.parser.ast.body.ClassOrInterfaceDeclaration)
-(import japa.parser.ast.body.EnumDeclaration)
-(import japa.parser.ast.body.EnumConstantDeclaration)
-(import japa.parser.ast.body.ConstructorDeclaration)
-(import japa.parser.ast.body.FieldDeclaration)
-(import japa.parser.ast.body.MethodDeclaration)
-(import japa.parser.ast.body.ModifierSet)
-(import japa.parser.ast.body.TypeDeclaration)
-(import japa.parser.ast.body.VariableDeclaratorId)
+(import com.github.javaparser.JavaParser)
+(import com.github.javaparser.ast.CompilationUnit)
+(import com.github.javaparser.ast.Node)
+(import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration)
+(import com.github.javaparser.ast.body.EnumDeclaration)
+(import com.github.javaparser.ast.body.EnumConstantDeclaration)
+(import com.github.javaparser.ast.body.ConstructorDeclaration)
+(import com.github.javaparser.ast.body.FieldDeclaration)
+(import com.github.javaparser.ast.body.MethodDeclaration)
+(import com.github.javaparser.ast.body.ModifierSet)
+(import com.github.javaparser.ast.body.TypeDeclaration)
+(import com.github.javaparser.ast.body.VariableDeclaratorId)

 ; ============================================
 ; Parsing
@@ -178,7 +178,7 @@
 (extend-protocol Named
   ConstructorDeclaration
   (getName [this]
-    (.getDeclarationAsString this false false false))
+    (.getDeclarationAsString this false false))
   (getQName [this]
     (let [pn (.getParentNode this)]
       (str (getQName pn) "." (getName this)))))


Add mockup of beckon.

Add mockup of beckon.

--- src/clojure/beckon.clj
+++ src/clojure/beckon.clj
@@ -1 +1,21 @@
-(ns beckon)
+(ns beckon
+  (:import [com.hypirion.beckon SignalAtoms]
+           [sun.misc Signal]))
+
+(defn signal-atom [signal-name]
+  (SignalAtoms/getSignalAtom signal-name))
+
+(defn raise! [signal-name]
+  (Signal/raise (Signal. signal-name)))
+
+(defn true!
+  "Takes a function of no arguments, and returns a function taking no arguments
+  which calls f and returns true. f has presumably side effects."
+  [f]
+  (fn [] (f) true))
+
+(defn false!
+  "Takes a function of no arguments, and returns a function taking no arguments
+  which calls f and returns false. f has presumably side effects."
+  [f]
+  (fn [] (f) true))


Add UUIDs to instruction maps

Add UUIDs to instruction maps

--- src/clojush/random.clj
+++ src/clojush/random.clj
@@ -52,7 +52,7 @@
                                            close-parens-probabilities [0.772 0.206 0.021 0.001]
                                            silent-instruction-probability 0}}]
    (let [markers (concat epigenetic-markers
-                         [:instruction]
+                         [:instruction :uuid]
                          (if random-insertion [:random-insertion]))]
      (zipmap markers
              (map (fn [marker]
@@ -69,6 +69,7 @@
                                 true
                                 false)
                       :random-insertion true
+                      :uuid (java.util.UUID/randomUUID)
                       ))
                   markers)))))


Avoid NPE for the function 'third'

Avoid NPE for the function 'third'

--- src/clouseau/utils.clj
+++ src/clouseau/utils.clj
@@ -41,7 +41,7 @@
 (defn third
     "Simple utility function - returns third item from a given sequence."
     [coll]
-    (nth coll 2))
+    (get coll 2))

 (defn substring
     "Call method String.substring()."


dirty reads test: missing->dirty

dirty reads test: missing->dirty

--- src/jepsen/voltdb/dirty_read.clj
+++ src/jepsen/voltdb/dirty_read.clj
@@ -107,7 +107,7 @@
                                   (map :value))
             strong-reads (reduce set/union strong-read-sets)
             unseen       (set/difference strong-reads reads)
-            missing      (set/difference reads strong-reads)
+            dirty        (set/difference reads strong-reads)
             lost         (set/difference writes strong-reads)]
         ; We expect one strong read per node
         (info :strong-read-sets (count strong-read-sets))
@@ -116,12 +116,12 @@
         ; All strong reads had darn well better be equal
         (assert (apply = (map count (cons strong-reads strong-read-sets))))

-        {:valid?            (and (empty? missing) (empty? lost))
+        {:valid?            (and (empty? dirty) (empty? lost))
          :read-count        (count reads)
          :strong-read-count (count strong-reads)
          :unseen-count      (count unseen)
-         :missing-count     (count missing)
-         :missing           missing
+         :dirty-count       (count dirty)
+         :dirty             dirty
          :lost-count        (count lost)
          :lost              lost}))))


Seq now uses a stack based iterator

Seq now uses a stack based iterator

--- src/main/cljs/lean_map/core.cljs
+++ src/main/cljs/lean_map/core.cljs
@@ -91,9 +91,14 @@
                 (BitmapIndexedNode. medit new-datamap 0 (array key2 val2 key1 val1)))))))))

   (inode-seq [inode]
-    (if (zero? datamap)
-      (NodeSeq. nil arr -1 (dec (alength arr)) 0 (.inode-seq (aget arr (dec (alength arr)))) nil)
-      (NodeSeq. nil arr (dec (* 2 (bit-count datamap))) (dec (alength arr)) 0 nil nil)))
+    (let [nodes (make-array 7)
+          cursors-lengths (make-array 14)]
+      (aset nodes 0 inode)
+      (aset cursors-lengths 0 0)
+      (aset cursors-lengths 1 (.node-arity inode))
+      (if (zero? datamap)
+        (create-inode-seq arr 0 nodes cursors-lengths 0 (.data-arity inode))
+        (NodeSeq. nil arr 0 nodes cursors-lengths 0 (.data-arity inode) nil))))

   (inode-assoc [inode aedit shift hash key val changed?]
     (let [bit (bitpos hash shift)]
@@ -462,7 +467,7 @@
   ITransientMap
   (-dissoc! [tcoll key] (.without! tcoll key)))

-(deftype NodeSeq [meta nodes dlen nloc i s ^:mutable __hash]
+(deftype NodeSeq [meta arr lvl nodes cursors-lengths data-idx data-len ^:mutable __hash]
   Object
   (toString [coll]
     (pr-str* coll))
@@ -473,7 +478,7 @@
   (-meta [coll] meta)

   IWithMeta
-  (-with-meta [coll meta] (NodeSeq. meta nodes dlen nloc i s __hash))
+  (-with-meta [coll meta] (NodeSeq. meta arr lvl nodes cursors-lengths data-idx data-len __hash))

   ICollection
   (-conj [coll o] (cons o coll))
@@ -484,14 +489,10 @@
   ISequential
   ISeq
   (-first [coll]
-    (if (nil? s)
-      [(aget nodes i) (aget nodes (inc i))]
-      (first s)))
+    [(aget arr (* data-idx 2)) (aget arr (inc (* data-idx 2)))])

   (-rest [coll]
-    (if (nil? s)
-      (create-inode-seq nodes (+ i 2) dlen nloc nil)
-      (create-inode-seq nodes i dlen nloc (next s))))
+    (create-inode-seq arr lvl nodes cursors-lengths data-idx data-len))

   ISeqable
   (-seq [this] this)
@@ -506,14 +507,28 @@
   (-reduce [coll f] (seq-reduce f coll))
   (-reduce [coll f start] (seq-reduce f start coll)))

-(defn- create-inode-seq [nodes i dlen nloc s]
-  (if (nil? s)
-    (cond
-      (< i dlen)
-      (NodeSeq. nil nodes dlen nloc i nil nil)
-      (> nloc dlen)
-      (NodeSeq. nil nodes dlen (dec nloc) i (.inode-seq (aget nodes nloc)) nil))
-    (NodeSeq. nil nodes dlen nloc i s nil)))
+(defn- create-inode-seq [arr lvl nodes cursors-lengths data-idx data-len]
+  (if (< (inc data-idx) data-len)
+    (NodeSeq. nil arr lvl nodes cursors-lengths (inc data-idx) data-len nil)
+    (let [nodes     (aclone nodes)
+          cursors-lengths (aclone cursors-lengths)]
+      (loop [lvl lvl]
+        (when (>= lvl 0)
+          (let [node-idx (aget cursors-lengths (* lvl 2))
+                node-len (aget cursors-lengths (inc (* lvl 2)))]
+            (if (< node-idx node-len)
+              (let [node (.get-node (aget nodes lvl) node-idx)
+                    has-nodes ^boolean (.has-nodes? node)
+                    new-lvl (if has-nodes (inc lvl) lvl)]
+                (aset cursors-lengths (* lvl 2) (inc node-idx))
+                (when has-nodes
+                  (aset nodes new-lvl node)
+                  (aset cursors-lengths (* new-lvl 2) 0)
+                  (aset cursors-lengths (inc (* new-lvl 2)) (.node-arity node)))
+                (if ^boolean (.has-data? node)
+                  (NodeSeq. nil (.get-array node) new-lvl nodes cursors-lengths 0 (.data-arity node) nil)
+                  (recur (inc lvl))))
+              (recur (dec lvl)))))))))

 (extend-protocol IPrintWithWriter
   NodeSeq
@@ -524,29 +539,6 @@

 (def lem (.-EMPTY PersistentHashMap))
 (def cem (.-EMPTY cljs.core/PersistentHashMap))
-
-(defn node-next-seq [arr lvl nodes cursors-lengths data-idx data-len]
-  (if (< (inc data-idx) data-len)
-    [arr lvl nodes cursors-lengths (inc data-idx) data-len]
-    (let [nodes     (aclone nodes)
-          cursors-lengths (aclone cursors-lengths)]
-     (loop [lvl lvl]
-       (when (>= lvl 0)
-         (let [node-idx (aget cursors-lengths (* lvl 2))
-               node-len (aget cursors-lengths (inc (* lvl 2)))]
-          (if (< node-idx node-len)
-            (let [node (.get-node (aget nodes lvl) node-idx)
-                  has-nodes ^boolean (.has-nodes? node)
-                  new-lvl (if has-nodes (inc lvl) lvl)]
-              (aset cursors-lengths (* lvl 2) (inc node-idx))
-              (when has-nodes
-                (aset nodes new-lvl node)
-                (aset cursors-lengths (* new-lvl 2) 0)
-                (aset cursors-lengths (inc (* new-lvl 2)) (.node-arity node)))
-              (if ^boolean (.has-data? node)
-                [(.get-array node) new-lvl nodes cursors-lengths 0 (.data-arity node)]
-                (recur (inc lvl))))
-            (recur (dec lvl)))))))))

 (comment
   (def test-keys (mapv (fn [i]
@@ -558,22 +550,6 @@
              (if (< i 100)
                (recur (assoc m (nth test-keys i) i) (inc i))
                m)))
-  (let [thm (loop [m lem i 0]
-              (if (< i 10000)
-                (recur (assoc m (nth test-keys i) i) (inc i))
-                m))
-        root (.-root thm)
-        nodes (make-array 7)
-        cursors-lengths (make-array 14)]
-    (aset nodes 0 root)
-    (aset cursors-lengths 0 0)
-    (aset cursors-lengths 1 (.node-arity root))
-    (let [args [(.get-array root) 0 nodes cursors-lengths 0 (.data-arity root)]
-          args (if ^boolean (.has-data? root) args (apply node-next-seq args))]
-      (loop [i 1 args args]
-        (if-let [nargs (apply node-next-seq args)]
-          (recur (inc i) nargs)
-          i))))
   (let [times 1000
         hm1 (loop [m lem i 0]
                (if (< i times)


don't "serialize" :created_at or :updated_at

--- src/metabase/models/revision.clj
+++ src/metabase/models/revision.clj
@@ -30,7 +30,8 @@
 (extend-protocol IRevisioned
   Object
   (serialize-instance [_ _ instance]
-    (->> (into {} instance)
+    (->> (dissoc instance :created_at :updated_at)
+         (into {})                                 ; if it's a record type like CardInstance we need to convert it to a regular map or filter-vals won't work
          (m/filter-vals (complement delay?))))
   (revert-to-revision [entity id serialized-instance]
     (m/mapply upd entity id serialized-instance))


2 subscribers seems like a good default.

--- src/onyx/static/default_vals.clj
+++ src/onyx/static/default_vals.clj
@@ -29,7 +29,7 @@
    :onyx.messaging.aeron/embedded-driver? true
    :onyx.messaging.aeron/offer-idle-strategy :high-restart-latency
    :onyx.messaging.aeron/poll-idle-strategy :high-restart-latency
-   :onyx.messaging.aeron/subscriber-count 4
+   :onyx.messaging.aeron/subscriber-count 2
    :onyx.messaging.netty/thread-pool-sizes 1
    :onyx.messaging.netty/connect-timeout-millis 1000
    :onyx.messaging.netty/pending-buffer-size 10000


remove unused require

remove unused require

--- src/onyx_java/wrapper/entity.clj
+++ src/onyx_java/wrapper/entity.clj
@@ -1,6 +1,5 @@
 (ns onyx-java.wrapper.entity
-    (:gen-class)
-    (:require [onyx-java.utils.object :as o]))
+    (:gen-class))

 (defn add-parameter-factory [object-name object-map]


cleaning up build option correction a bit

still a bunch of work to be done here, this code can be reduced and
simplified a good bit, just have to check downstream expectations

--- sidecar/src/figwheel_sidecar/config.clj
+++ sidecar/src/figwheel_sidecar/config.clj
@@ -8,6 +8,12 @@
   (let [f (io/file fpath)]
     (when-let [dir (.getParentFile f)] (.mkdirs dir))))

+(defn get-build-options
+  ([build]
+   (or (:build-options build) (:compiler build) {}))
+  ([build key]
+   (get (get-build-options build) key)))
+
 (defn ensure-output-dirs* [{:keys [build-options compiler]}]
   (let [{:keys [output-to]} (or build-options compiler)]
     (when output-to
@@ -16,7 +22,8 @@
 (defn optimizations-none?
   "returns true if a build has :optimizations set to :none"
   [build]
-  (= :none (get-in build [:compiler :optimizations])))
+  (let [opt (get-build-options build :optimizations)]
+    (or (nil? opt) (= :none opt))))

 ;; checking to see if output dir is in right directory
 (defn norm-path
@@ -75,22 +82,8 @@
 (defn check-for-valid-options
   "Check for various configuration anomalies."
   [{:keys [http-server-root] :as opts} print-warning build']
-  (let [build-options (:compiler build')
-        opts? (and (not (nil? build-options)) (optimizations-none? build'))
-        out-dir? (output-dir-in-resources-root? build-options opts)]
-    ;; this is now a warning
-    (when (and
-           print-warning
-           (not out-dir?)
-           (:output-dir build-options))
-      (println
-       (str
-          "Figwheel Config Warning (in project.clj) -- \n"
-          "Your build :output-dir is not in a resources directory.\n"
-          "If you are serving your assets (js, css, etc.) with Figwheel,\n"
-          "they must be on the resource path for the server.\n"
-          (str "Your :output-dir should match this pattern: " (make-serve-from-display opts))))
-      (newline))
+  (let [build-options (get-build-options build')
+        opts? (and (not (nil? build-options)) (optimizations-none? build'))]
     (map
      #(str "Figwheel Config Error (in project.clj) - " %)
      (filter identity
@@ -133,9 +126,19 @@
                   module-map))
     module-map))

+(defn opt-none? [{:keys [optimizations]}]
+  (or (nil? optimizations) (= optimizations :none)))
+
+;; TODO this is a hack need to check all the places that I'm checking for
+;; :optimizations :none and check for nil? or :none
+(defn default-optimizations-to-none [build-options]
+  (if (opt-none? build-options)
+    (assoc build-options :optimizations :none)
+    build-options))
+
 (defn sane-output-to-dir [{:keys [output-to output-dir] :as options}]
   (letfn [(parent [fname] (if-let [p (.getParent (io/file fname))] (str p "/") ""))]
-    (if (and (= (:optimizations options) :none)
+    (if (and #_(opt-none? options)
              (or (nil? output-dir) (nil? output-to)))
       (if (and (nil? output-dir) (nil? output-to))
         (assoc options :output-to "main.js" :output-dir "out")
@@ -145,18 +148,20 @@
       options)))

 (comment
-  (sane-output-to-dir {:output-dir "yes"})
+  (default-optimizations-to-none {:optimizations :simple})
+
+  (sane-output-to-dir {:output-dir "yes" })

   (sane-output-to-dir {:output-to "yes.js"})

   (sane-output-to-dir {:output-dir "yes/there"})

-  (sane-output-to-dir {:output-to "outer/yes.js"})
-
+  (sane-output-to-dir {:output-to "outer/yes.js"})
   )

 (defn fix-build-options [build-options]
   (->> build-options
+    (default-optimizations-to-none)
     (apply-to-key normalize-dir :output-dir)
     (sane-output-to-dir)
     (apply-to-key namify-module-entries :modules)
@@ -167,10 +172,19 @@
     (assoc opts :id (name (gensym "build_needs_id_")))
     (assoc opts :id (name (:id opts)))))

-(defn fix-build [opts]
-  (-> opts
+(defn move-compiler-to-build-options [build]
+  (if (and (not (:build-options build))
+           (:compiler build))
+    (-> build
+      (assoc :build-options (:compiler build))
+      (dissoc :compiler))
+    build))
+
+(defn fix-build [build]
+  (-> build
     ensure-id
-    (update-in [(if (:build-options opts) :build-options :compiler)] fix-build-options)))
+    move-compiler-to-build-options
+    (update-in [:build-options] fix-build-options)))

 (defn fix-builds [builds]
   (mapv fix-build builds))


That's not where the expected v goes

That's not where the expected v goes

--- test/icecap/async_util_test.clj
+++ test/icecap/async_util_test.clj
@@ -31,8 +31,7 @@

 (deftest <!!?-tests
   (testing "take a value"
-    (is (= (<!!? (go 1 2 3))
-           3)))
+    (is (= 3 (<!!? (go 1 2 3)))))
   (testing "raise an exc"
     (is (thrown-with-msg? AssertionError #"Assert failed: false"
                           (<!!? (go-catch (assert false)))))))
@@ -41,8 +40,7 @@
   (testing "take a value"
     (let [inner-chan (a/to-chan [1 2 3])
           outer-chan (go (<!? inner-chan))]
-      (is (= (<!! outer-chan)
-             1))))
+      (is (= 1 (<!! outer-chan)))))
   (testing "raise an exc"
     (let [err-chan (go-catch (assert false))
           <!?-chan (go-catch (<!? err-chan))]


this should fix allen's test

this should fix allen's test

--- test/metabase/api/user_test.clj
+++ test/metabase/api/user_test.clj
@@ -122,21 +122,24 @@

 ;; ## PUT /api/user/:id/password
 ;; Test that a User can change their password
-(expect-eval-actual-first (sel :one :fields [Session :id] (order :created_at :desc)) ; get the latest Session from the DB
-  (let [password {:old "password"
-                  :new "new_password"}
-        {:keys [email id] :as user} (create-user :password (:old password))
-        creds {:old {:password (:old password)
-                     :email email}
-               :new {:password (:new password)
-                     :email email}}]
-    ;; Check that creds work
-    (metabase.http-client/client :post 200 "session" (:old creds))
-    ;; Change the PW
-    (metabase.http-client/client (:old creds) :put 200 (format "user/%d/password" id) {:password (:new password)
-                                                                                :old_password (:old password)})
-    ;; Old creds should no longer work
-    (assert (= (metabase.http-client/client :post 400 "session" (:old creds))
-               "password mismatch"))
-    ;; New creds *should* work
-    (metabase.http-client/client :post 200 "session" (:new creds))))
+(let [user-last-name (random-name)]
+  (expect-eval-actual-first
+      (let [{user-id :id} (sel :one User :last_name user-last-name)]
+        (sel :one :fields [Session :id] :user_id user-id (order :created_at :desc))) ; get the latest Session for this User
+    (let [password {:old "password"
+                    :new "new_password"}
+          {:keys [email id] :as user} (create-user :password (:old password) :last_name user-last-name)
+          creds {:old {:password (:old password)
+                       :email email}
+                 :new {:password (:new password)
+                       :email email}}]
+      ;; Check that creds work
+      (metabase.http-client/client :post 200 "session" (:old creds))
+      ;; Change the PW
+      (metabase.http-client/client (:old creds) :put 200 (format "user/%d/password" id) {:password (:new password)
+                                                                                :old_password (:old password)})
+      ;; Old creds should no longer work
+      (assert (= (metabase.http-client/client :post 400 "session" (:old creds))
+                 "password mismatch"))
+      ;; New creds *should* work
+      (metabase.http-client/client :post 200 "session" (:new creds)))))


Retry metric now only sent for input tasks

--- test/onyx/metrics/send_test.clj
+++ test/onyx/metrics/send_test.clj
@@ -61,9 +61,7 @@
     ["monitoring-config" ":out"]
     ["monitoring-config" ":inc"]

-    ["retry_segment_rate_1s" "onyx" ":in" "test-workflow"]
-    ["retry_segment_rate_1s" "onyx" ":out" "test-workflow"]
-    ["retry_segment_rate_1s" "onyx" ":inc" "test-workflow"]})
+    ["retry_segment_rate_1s" "onyx" ":in" "test-workflow"]})

 (deftest metrics-test
   (doseq [sender [;:onyx.lifecycle.metrics.websocket/websocket-sender


Util doesn't need a 0 window.

Util doesn't need a 0 window.

--- test/onyx/peer/hornetq_util.clj
+++ test/onyx/peer/hornetq_util.clj
@@ -40,7 +40,6 @@
 (defn read! [config queue-name n echo]
   (let [tc (TransportConfiguration. (.getName NettyConnectorFactory) config)
         locator (HornetQClient/createServerLocatorWithoutHA (into-array [tc]))
-        _ (.setConsumerWindowSize locator 0)
         session-factory (.createSessionFactory locator)
         session (.createTransactedSession session-factory)]


[WIP] cast-all testing

[WIP] cast-all testing

--- test/semantic_csv/core_test.clj
+++ test/semantic_csv/core_test.clj
@@ -30,7 +30,7 @@
              [["# a comment"]])))))

-(deftest casting-test
+(deftest cast-with-test
   (let [data [["this" "that"]
               ["1" "y"]]]
     (testing "should work with mappify"
@@ -50,3 +50,24 @@
       (is (= (->> data
                   (cast-with {0 ->int} {:ignore-first true}))
              [["1" "this"] [2 "that"]])))))
+
+
+(deftest cast-all-test
+  (let [data [["this" "that"]
+              ["1" "2"]]]
+    (testing "should work with mappify"
+      (is (= (->> data
+                  mappify
+                  (cast-all ->int)
+                  first)
+             {:this 1 :that 2})))
+    (testing "should work with :ignore-first"
+      (is (= (->> data
+                  (cast-all ->int {:ignore-first true}))
+             [["this" "that"] [1 2]])))
+    (testing "should work with :only"
+      (is (= (->> data
+                  mappify
+                  (cast-all ->int {:only :that})
+                  first)
+             {:this "1" :that 2})))))


don't keywordize keys for host->cluster which is a string map (#1630)

--- waiter/integration/waiter/token_request_test.clj
+++ waiter/integration/waiter/token_request_test.clj
@@ -48,6 +48,7 @@
         cluster-calculator-config (-> settings-json
                                       (get-in [:token-config :cluster-calculator])
                                       (update :kind keyword)
+                                      (update-in [:configured :host->cluster] walk/stringify-keys)
                                       (as-> $ (update-in $ [(:kind $) :factory-fn] symbol)))
         cluster-calculator (utils/create-component cluster-calculator-config
                                                    :context {:default-cluster default-cluster})]


Give it a unique class so we can track clicks in mixpanel.

--- src-cljs/frontend/components/aside.cljs
+++ src-cljs/frontend/components/aside.cljs
@@ -133,7 +133,8 @@
 (defn project-settings-nav-items [data owner]
   (let [navigation-data (:navigation-data data)]
     [{:type :heading :title "Project Settings"}
-     {:type :subpage :href (routes/v1-org-settings navigation-data) :title "Org Settings"}
+     {:type :subpage :href (routes/v1-org-settings navigation-data) :title "Org Settings"
+      :class "project-settings-to-org-settings"}
      {:type :subpage :href "edit" :title "Overview" :subpage :overview}
      {:type :heading :title "Tweaks"}
      {:type :subpage :href "#parallel-builds" :title "Adjust Parallelism" :subpage :parallel-builds}
@@ -178,7 +179,7 @@

                 :subpage
                 [:a.aside-item {:href (:href item)
-                                :class (when (= subpage (:subpage item)) "active")}
+                                :class [(when (= subpage (:subpage item)) "active") (:class item)]}
                  (:title item)]

                 ))]])))))


add link inside dummy chat text to autofill ping

--- src-cljs/frontend/components/aside.cljs
+++ src-cljs/frontend/components/aside.cljs
@@ -45,11 +45,13 @@
     (render [_]
       (let [{:keys [cast!]} (om/get-shared owner)
             chats (ds/touch-all '[:find ?t :where [?t :chat/body]] @db)
-            dummy-chat {:chat/body (str "Welcome to Precursor! "
-                                        "Create fast prototypes and share your url to collaborate. "
-                                        "Chat "
-                                        (str "@" (str/lower-case chat-bot))
-                                        " for help.")
+            dummy-chat {:chat/body [:span "Welcome to Precursor! "
+                                          "Create fast prototypes and share your url to collaborate. "
+                                          "Chat "
+                                          [:a {:on-click #(cast! :aside-user-clicked {:id-str (str/lower-case chat-bot)})
+                                               :role "button"}
+                                           (str "@" (str/lower-case chat-bot))]
+                                          " for help."]
                         :chat/color "#00b233"
                         :session/uuid chat-bot
                         :server/timestamp (js/Date. 0)}]
@@ -66,7 +68,8 @@
              (html [:div.message {:key (:db/id chat)}
                     [:span {:style {:color (or (:chat/color chat) (str "#" id))}}
                      name]
-                    (str " " (:chat/body chat))]))]
+                    " "
+                    (:chat/body chat)]))]
           [:form {:on-submit #(do (cast! :chat-submitted)
                                   false)
                   :on-key-down #(when (and (= "Enter" (.-key %))


Remove webserver from master

Remove webserver from master

--- src/edge/webserver.clj
+++ src/edge/webserver.clj
@@ -1,16 +0,0 @@
-;; Copyright © 2016, JUXT LTD.
-
-(ns edge.webserver
-  (:require
-   [aleph.http :as http]
-   [bidi.ring :refer [make-handler redirect]]
-   [hiccup.core :refer [html]]
-   [clojure.core.async :refer [chan >!! mult tap close! go go-loop <! >! timeout]]
-   [clojure.java.io :as io]
-   [clojure.tools.logging :refer :all]
-   [com.stuartsierra.component :refer [Lifecycle using]]
-   [schema.core :as s]
-   [yada.yada :refer [yada resource]]))
-
-;; TODO: Create a Webserver record here
-


handle known className attr variants in defstyled

--- src/cljss/core.clj
+++ src/cljss/core.clj
@@ -92,10 +92,12 @@
                                (map meta)
                                flatten
                                set)
-               className  (:className props)
-               className  (str (when className (str className " ")) var-class)
-               props      (assoc props :className className)
-               props      (apply dissoc props (concat attrs meta-attrs))]
+               className  (-> props (select-keys [:className :class :class-name]) vals (filter identity))
+               className  (str (when (seq className)
+                                 (str (cstr/join " " className) " "))
+                               var-class)
+               props      (apply dissoc props (concat attrs meta-attrs [:class :class-name :className]))
+               props      (assoc props :className className)]
            (create-element props children))))))

 (defn- keyframes-styles [idx styles]


Sort reserved-names list for easier reading

--- src/clojars/db.clj
+++ src/clojars/db.clj
@@ -12,16 +12,61 @@
            (java.sql Timestamp)))

 (def reserved-names
-  #{"clojure" "clojars" "clojar" "register" "login"
-    "pages" "logout" "password" "username" "user"
-    "repo" "repos" "jar" "jars" "about" "help" "doc"
-    "docs" "images" "js" "css" "maven" "api"
-    "download" "create" "new" "upload" "contact" "terms"
-    "group" "groups" "browse" "status" "blog" "search"
-    "email" "welcome" "devel" "development" "test" "testing"
-    "prod" "production" "admin" "administrator" "root"
-    "webmaster" "profile" "dashboard" "settings" "options"
-    "index" "files" "releases" "snapshots"})
+  #{"about"
+    "admin"
+    "administrator"
+    "api"
+    "blog"
+    "browse"
+    "clojar"
+    "clojars"
+    "clojure"
+    "contact"
+    "create"
+    "css"
+    "dashboard"
+    "devel"
+    "development"
+    "doc"
+    "docs"
+    "download"
+    "email"
+    "files"
+    "group"
+    "groups"
+    "help"
+    "images"
+    "index"
+    "jar"
+    "jars"
+    "js"
+    "login"
+    "logout"
+    "maven"
+    "new"
+    "options"
+    "pages"
+    "password"
+    "prod"
+    "production"
+    "profile"
+    "register"
+    "releases"
+    "repo"
+    "repos"
+    "root"
+    "search"
+    "settings"
+    "snapshots"
+    "status"
+    "terms"
+    "test"
+    "testing"
+    "upload"
+    "user"
+    "username"
+    "webmaster"
+    "welcome"})

 (defn get-time []
   (Timestamp. (System/currentTimeMillis)))


Move highlighting so that the :_content field can be highlighted.

--- src/clucy/core.clj
+++ src/clucy/core.clj
@@ -137,24 +137,26 @@

 (defn- document->map
   "Turn a Document object into a map."
-  [document]
-  (with-meta
-    (-> (into {}
-              (for [f (.getFields document)]
-                [(keyword (.name f)) (.stringValue f)]))
-        (dissoc :_content))
-    (-> (into {}
-              (for [f (.getFields document)]
-                [(keyword (.name f))
-                 {:indexed (.isIndexed f)
-                  :stored (.isStored f)
-                  :tokenized (.isTokenized f)}]))
-        (dissoc :_content))))
+  ([document]
+     (document->map document identity))
+  ([document highlighter]
+     (with-meta
+       (-> (into {}
+                 (for [f (.getFields document)]
+                   [(keyword (.name f)) (.stringValue f)]))
+           highlighter
+           (dissoc :_content))
+       (-> (into {}
+                 (for [f (.getFields document)]
+                   [(keyword (.name f))
+                    {:indexed (.isIndexed f)
+                     :stored (.isStored f)
+                     :tokenized (.isTokenized f)}]))
+           (dissoc :_content)))))

 (defn- make-highlighter
   "Create a highlighter function which will take a map and return the map with
-highlighted results appended. Highlighting is configured by passing the config
-map."
+highlighted results appended."
   [query searcher config]
   (if config
     (let [indexReader (.getIndexReader searcher)
@@ -193,7 +195,7 @@
               highlighter (make-highlighter query searcher highlight)]
           (doall
            (for [hit (.scoreDocs hits)]
-             (highlighter (document->map (.doc searcher (.doc hit)))))))))))
+             (document->map (.doc searcher (.doc hit)) highlighter))))))))

 (defn search-and-delete
   "Search the supplied index with a query string and then delete all


explain what clicking does

explain what clicking does

--- src-cljs/frontend/components/aside.cljs
+++ src-cljs/frontend/components/aside.cljs
@@ -30,7 +30,7 @@
           ;;  (common/icon :users)
           ;;  [:span "Collaborators"]]
           (let [show-mouse? (get-in app [:subscribers client-id :show-mouse?])]
-            [:button {:title "You're viewing this document. Try inviting others."
+            [:button {:title "You're viewing this document. Try inviting others. Click to toggle sharing your mouse position."
                       :on-click #(put! controls-ch [:show-mouse-toggled {:client-uuid client-id :show-mouse? (not show-mouse?)}])}
              [:object
               (common/icon :user (when show-mouse? {:path-props
@@ -39,7 +39,7 @@
               [:span "You"]]])
           (for [[id {:keys [show-mouse?]}] (dissoc (:subscribers app) client-id)
                 :let [id-str (apply str (take 6 id))]]
-            [:button {:title "An anonymous user is viewing this document. Click to show their mouse."
+            [:button {:title "An anonymous user is viewing this document. Click to toggle showing their mouse position."
                       :on-click #(put! controls-ch [:show-mouse-toggled {:client-uuid id :show-mouse? (not show-mouse?)}])}
              (common/icon :user (when show-mouse? {:path-props {:style {:stroke (str "#" id-str)}}}))
              [:span id-str]])


Add dev-time middleware for new URLs

Add dev-time middleware for new URLs

--- src/frontend/proxy.clj
+++ src/frontend/proxy.clj
@@ -58,7 +58,25 @@
      :headers headers
      :body body}))

-(defn wrap-handler [handler options]
+;; When developing a new page, the URL may not be recognized by the backend yet.
+;; That makes it impossible to develop against production. When that happens,
+;; add the URL (path) to this set (eg, "/projects"). The proxy will fetch
+;; /dashboard from the backend instead, which will load the frontend app.
+;; Meanwhile, the browser will see your new URL, so the frontend will dispatch
+;; on that.
+;;
+;; This is for development only. Do not commit code with values in this set.
+;; Instead, add the route to the backend. (And while you're there, add it to the
+;; nginx config if necessary.)
+(def new-urls #{})
+
+(defn with-new-url-mapping [handler]
+  (fn [req]
+    (handler (cond-> req
+               (contains? new-urls (:uri req))
+               (assoc :uri "/dashboard")))))
+
+(defn with-proxy [handler options]
   (fn [req]
     (or (when (and (contains? #{:get :head} (:request-method req))
                    (nil? (:body req)))
@@ -71,3 +89,8 @@
                    (fn [response]
                      (let [rewrite (if (:error response) rewrite-error rewrite-success)]
                        (send! channel (rewrite response)))))))))
+
+(defn wrap-handler [handler options]
+  (-> handler
+      (with-proxy options)
+      with-new-url-mapping))


star dots, last move

star dots, last move

--- src/gobanbot/image.clj
+++ src/gobanbot/image.clj
@@ -14,13 +14,23 @@
 (defn xy-to-circle [xy color]
   (let [style (if (= color "b")
                 {:fill :black}
-                {:stroke :black :fill :white :width 1})]
+                {:stroke :black :fill :white :width 3})]
     [:circle style (vec (map #(-> % (* cell-size) (+ cell-size)) xy)) (* 0.45 cell-size)]))

 (defn get-stones [moves]
   (map (fn [{:keys [mv color]}]
          (xy-to-circle (mv-to-xy mv) color))
     moves))
+
+(defn get-last-move [{:keys [mv color] :as move}]
+  (if move
+    (let [xy (mv-to-xy mv)
+          style (case color
+                  "b" {:stroke :white :fill :black :width 3}
+                  "w" {:stroke :black :fill :white :width 3})]
+      [[:circle style
+               (vec (map #(-> % (* cell-size) (+ cell-size)) xy))
+               (* 0.3 cell-size)]])))

 (defn get-hlines [size]
   (map
@@ -41,6 +51,15 @@
              (-> i (+ 97) char str)])
     (range size)))

+(defn get-stars [size]
+  (map (fn [xy] [:circle {:fill :black}
+         (vec (map #(-> % (* cell-size) (+ cell-size)) xy))
+         (* 0.1 cell-size)])
+    (case size
+      9 [[2 2] [2 6] [6 2] [6 6] [4 4]]
+      13 [[2 2] [2 6] [2 10] [6 2] [6 6] [6 10] [10 2] [10 6] [10 10]]
+      19 [[3 3] [3 9] [3 15] [9 3] [9 9] [9 15] [15 3] [15 9] [15 15]])))
+
 (defn get-vtext [size]
   (map
     (fn [i] [:text {:font-family "sans-serif" :font-size 72 :x 10 :y (+ 122 (* i cell-size))}
@@ -52,9 +71,11 @@
     (svg/render-png (vec (concat [:dali/page]
                                  (get-hlines (:size game))
                                  (get-vlines (:size game))
+                                 (get-stars (:size game))
                                  (get-htext (:size game))
                                  (get-vtext (:size game))
-                                 (get-stones (:moves game))))
+                                 (get-stones (:moves game))
+                                 (get-last-move (-> game :moves last))))
                     (str "resources/" f-n))
     f-n))


Type hint some calls to avoid reflection.

--- src/cavm/h2.clj
+++ src/cavm/h2.clj
@@ -185,7 +185,7 @@
   (dorun (map #(aset out (% 1) (aget in (% 0))) mapping))
   out)

-(defn bytes-to-floats [barr]
+(defn bytes-to-floats [^bytes barr]
   (let [bb (java.nio.ByteBuffer/allocate (alength barr))
         fb (.asFloatBuffer bb)
         out (float-array (quot (alength barr) 4))]
@@ -193,7 +193,7 @@
     (.get fb out)
     out))

-(defn floats-to-bytes [farr]
+(defn floats-to-bytes [^floats farr]
   (let [bb (java.nio.ByteBuffer/allocate (* (alength farr) 4))
         fb (.asFloatBuffer bb)]
     (.put fb farr)


Add some comments in 'newest-voom-ver-by-spec.

--- src/leiningen/voom.clj
+++ src/leiningen/voom.clj
@@ -478,13 +478,18 @@
         :when (or (= found-path path) (nil? path))
         found-branch (origin-branches gitdir)
         :when (or (= found-branch branch) (nil? branch))
-        :let [not-not-tags (set (mapcat #(:refs (parse-sha-refs %))
+        :let [;; All the tags NOT accessible via this branch (we will exclude them):
+              not-not-tags (set (mapcat #(:refs (parse-sha-refs %))
                                         (:lines (git {:gitdir gitdir} "log" "--pretty=format:%H,%cd,%p,%d" "--all"
                                                      "--simplify-by-decoration" "-m" (str "^origin/" found-branch)))))
+              ;; yes-yes-tags are the matching tags reachable via this branch:
               yes-yes-tags (set/difference tags not-not-tags)
               tags-with-parents (remove #(.endsWith ^String % "--no-parent") yes-yes-tags)
               tags-here-with-parents (filter #(= found-path (:path (parse-tag %))) tags-with-parents)
               neg-tags (map #(str "^" % "^") tags-here-with-parents)
+              ;; All commits on the current branch more recent than
+              ;; (and including) the most recent tag matching our
+              ;; version spec:
               commits
               , (map
                  parse-sha-refs
@@ -496,8 +501,14 @@
           reflist (filter #(and
                             (= (str proj-name) (:proj %))
                             (= found-path (:path %))) (map parse-tag refs))]
+      ;; Walk forward through time, looking for when the next commit
+      ;; is one too far (meaning: we have no further commits to
+      ;; consider or the project at this path has changed version or
+      ;; project name):
       (some (fn [[current next-commit]]
               (when (or (= :end next-commit)
+                        ;; Find if any of the refs of this commit are
+                        ;; voom tags at the same path:
                         (some #(let [t (parse-tag %)]
                                  (and
                                   (= "voom" (:prefix t))


More robust 'fetch-all for offline or incorrect repo paths.

--- src/leiningen/voom.clj
+++ src/leiningen/voom.clj
@@ -221,7 +221,15 @@
      (doseq [^File d dirs]
        (let [repo (-> (remotes d) :origin :fetch)]
          (println "Fetching:" repo (print-str (list (.getName d))))
-         (git {:gitdir d} "fetch")))))
+         (try
+           (git {:gitdir d} "fetch")
+           (catch clojure.lang.ExceptionInfo e
+             (let [data (ex-data e)]
+               (if (:git data)
+                 (println (str (.getMessage e) "\n"
+                               (pr-str (select-keys data [:git :exit])) "\n"
+                               (:err data)))
+                 (throw e)))))))))

 (defn find-project
   [pgroup pname candidate]


added deps task to make sure the specified scala libraries are in maven local repository.

--- src/leiningen/zinc.clj
+++ src/leiningen/zinc.clj
@@ -2,6 +2,7 @@
   (:require [leiningen.classpath :as classpath]
             [leiningen.core.main :as main]
             [leiningen.core.project :as project]
+            [leiningen.deps :as deps]
             [leiningen.help :as help]
             [clojure.tools.namespace.track :as track]
             [zinc.core :as core]
@@ -183,10 +184,11 @@
     ([project]
       (let [profile (or (:zinc (:profiles project)) (zinc-profile project))
             project (project/merge-profiles project [profile])]
-        (zinc-compile project)(zinc-test-compile project)))
+        (deps/deps project)(zinc-compile project)(zinc-test-compile project)))
     ([project subtask & options]
       (let [profile (or (:zinc (:profiles project)) (zinc-profile project))
             project (project/merge-profiles project [profile])]
+        (deps/deps project)
         (case subtask
           "zinc-compile" (zinc-compile project)
           "zinc-test-compile" (zinc-test-compile project)


Change cell size, remove top level styles

--- src/gol/styles.clj
+++ src/gol/styles.clj
@@ -2,26 +2,11 @@
   (:require [garden.def :refer [defstyles]]
             [garden.def :refer [defrule defkeyframes]]
             [garden.units :refer [px percent s]]
-            [garden.color :refer [hex->rgb rgba rgb]]
-  )
-)
+            [garden.color :refer [hex->rgb rgba rgb]]))

-
-(def cell-size 12)
-
+(def cell-size 20)

 (defstyles styles
-  [:html {
-    :height (percent 100) }]
-
-  [:body {
-    :display "table"
-    :min-width (px 980)
-    :width (percent 100)
-    :height (percent 100)
-    :margin 0
-    :background-color (hex->rgb "#fdfdfd") }]
-
   [:#app {
     :display "table-cell"
     :vertical-align "middle"
@@ -70,5 +55,4 @@
           :content "\"\""}
           [:& ^:prefix {
             :border-radius (percent 50)
-            :box-shadow [[0 0 (px 3) (rgba 0 0 0 0.5)]] }] ]]]]
-)
+            :box-shadow [[0 0 (px 3) (rgba 0 0 0 0.5)]] }] ]]]])


service labels 0.x -> 3.x

service labels 0.x -> 3.x

--- src/cljs/swarmpit/component/service/form_labels.cljs
+++ src/cljs/swarmpit/component/service/form_labels.cljs
@@ -1,7 +1,6 @@
 (ns swarmpit.component.service.form-labels
   (:require [material.component :as comp]
-            [material.component.form :as form]
-            [material.component.list-table-form :as list]
+            [material.component.list.edit :as list]
             [swarmpit.component.state :as state]
             [swarmpit.ajax :as ajax]
             [swarmpit.routes :as routes]
@@ -14,45 +13,43 @@

 (def form-state-cursor (conj state/form-state-cursor :labels))

-(def headers [{:name  "Name"
-               :width "35%"}
-              {:name  "Value"
-               :width "35%"}])
-
-(defn- form-name [value index label-names]
-  (comp/autocomplete
-    {:name          (str "form-name-text-" index)
-     :key           (str "form-name-text-" index)
-     :value         value
-     :onUpdateInput #(state/update-item index :name % form-value-cursor)
-     :fullWidth     true
-     :searchText    value
-     :dataSource    label-names}))
+(defn- form-name [value index]
+  (comp/text-field
+    {:fullWidth       true
+     :label           "Name"
+     :key             (str "form-label-name-" index)
+     :value           value
+     :required        true
+     :variant         "outlined"
+     :InputLabelProps {:shrink true}
+     :onChange        #(state/update-item index :name (-> % .-target .-value) form-value-cursor)}))

 (defn- form-value [value index]
-  (list/textfield
-    {:name     (str "form-value-text-" index)
-     :key      (str "form-value-text-" index)
-     :value    value
-     :onChange (fn [_ v]
-                 (state/update-item index :value v form-value-cursor))}))
+  (comp/text-field
+    {:fullWidth       true
+     :label           "Value"
+     :key             (str "form-label-value-" index)
+     :value           value
+     :required        true
+     :variant         "outlined"
+     :InputLabelProps {:shrink true}
+     :onChange        #(state/update-item index :value (-> % .-target .-value) form-value-cursor)}))

-(defn- render-labels
-  [item index data]
-  (let [{:keys [name
-                value]} item]
-    [(form-name name index data)
-     (form-value value index)]))
+(def form-metadata
+  [{:name      "Name"
+    :primary   true
+    :key       [:name]
+    :render-fn (fn [value _ index] (form-name value index))}
+   {:name      "Value"
+    :key       [:value]
+    :render-fn (fn [value _ index] (form-value value index))}])

 (defn- form-table
-  [labels label-names]
-  (form/form
-    {}
-    (list/table-raw headers
-                    labels
-                    label-names
-                    render-labels
-                    (fn [index] (state/remove-item index form-value-cursor)))))
+  [labels names]
+  (list/responsive
+    form-metadata
+    labels
+    (fn [index] (state/remove-item index form-value-cursor))))

 (defn- add-item
   []
@@ -70,5 +67,5 @@
   (let [{:keys [names]} (state/react form-state-cursor)
         labels (state/react form-value-cursor)]
     (if (empty? labels)
-      (form/value "No labels defined for the service.")
+      (html [:div "No labels defined for the service."])
       (form-table labels names))))


adding explicit :autoload client option

adding explicit :autoload client option

--- support/src/figwheel/client.cljs
+++ support/src/figwheel/client.cljs
@@ -166,7 +166,9 @@
     (go
      (cond
       (reload-file-state? msg-names opts)
-      (<! (heads-up/flash-loaded))
+      (if (:autoload opts)
+        (<! (heads-up/flash-loaded))
+        (<! (heads-up/clear)))

       (compile-refail-state? msg-names)
       (do
@@ -263,6 +265,8 @@
    :on-compile-fail default-on-compile-fail
    :on-compile-warning default-on-compile-warning

+   :autoload true
+
    :debug false

    :heads-up-display true
@@ -288,6 +292,9 @@
                                   :file-reloader-plugin
                                   :comp-fail-warning-plugin
                                   :repl-plugin])
+               base)
+        base (if (false? (:autoload system-options))
+               (dissoc base :file-reloader-plugin)
                base)]
     (if (and (:heads-up-display system-options)
              (utils/html-env?))


unread result is limited to 30 exercises

--- src/ontrail/unread.clj
+++ src/ontrail/unread.clj
@@ -24,7 +24,7 @@
   (sort-by :lastModifiedDate time/after? (filter identity (map find-exercise (get-oids user)))))

 (defn comments-all [user]
-  (ex/decorate-results user (take 100 (get-unread-objs user))))
+  (ex/decorate-results user (take 30 (get-unread-objs user))))

 (defn is-own? [user ex]
   (or (= user (:user ex))


Ensure timer trigger is compatible with cljs.

--- src/onyx/triggers.cljc
+++ src/onyx/triggers.cljc
@@ -58,7 +58,9 @@
   [{:keys [trigger/period] :as trigger}
    [_ fire-time]
    {:keys [event-type] :as state-event}]
-  (let [fire? (or (> (System/nanoTime) fire-time)
+  (let [fire? (or (> #?(:clj (System/nanoTime))
+                     #?(:cljs (now))
+                     fire-time)
                   (boolean (#{:job-completed :recovered} event-type)))]
     [fire? (if fire? (next-fire-time trigger) fire-time)]))


small graph fixes

small graph fixes

--- src/pc/views/admin.clj
+++ src/pc/views/admin.clj
@@ -20,6 +20,7 @@
         times (take-while #(time/before? % (time/plus now (time/days 1)))
                           (iterate #(clj-time.core/plus % (clj-time.core/days 1))
                                    earliest))
+
         user-counts (map (partial count-users db) times)
         users-per-day (map (fn [a b] (- b a)) (cons 0 user-counts) user-counts)
         width 1000
@@ -27,10 +28,10 @@
         x-tick-width (/ 1000 (count times))

         max-users-per-day (apply max users-per-day)
-        y-tick-width (/ 500 (+ max-users-per-day (* 0.10 max-users-per-day)))
+        y-tick-width (/ 500 max-users-per-day)

         max-users (apply max user-counts)
-        y-cumulative-tick-width (/ 500 (+ max-users (* 0.10 max-users)))
+        y-cumulative-tick-width (/ 500 max-users)
         padding 20]
     (list
      [:svg {:width 1200 :height 600}


Fix bugs on socket and subscribe functions.

--- src/postal/client.cljs
+++ src/postal/client.cljs
@@ -139,7 +139,7 @@
                         opts))))

 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; EventSource
+;; Socket
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

 (defn socket
@@ -147,22 +147,26 @@
    (socket client dest nil nil))
   ([client dest data]
    (socket client dest data nil))
-  ([client dest data {:keys [params] :or {params {}}}]
-   (let [req (prepare-request client data :get params)
+  ([client dest data {:keys [params _type] :or {params {} _type :socket}}]
+   (let [frame (encode {:data data :dest dest :type _type})
+         req (prepare-request client frame :get params)
          uri (Uri. (:url req))]
      (.setQuery uri (:query-string req))
      (.setScheme uri (if (= (.getScheme uri) "http") "ws" "wss"))
-     (let [ws (WebSocket. (.toString uri))
+     (let [ws (WebSocket. false)
            timer (Timer. 5000)
            busin (s/bus)
            streamin (s/filter #(not= (:type %) :ping) busin)
            busout (s/bus)]
        (letfn [(on-ws-message [event]
-                 (let [frame (decode (.-data event))]
+                 (let [frame (decode (.-message event))]
                    (s/push! busin frame)))
                (on-ws-error [event]
                  (s/error! busin event)
                  (.close ws))
+               (on-ws-closed [event]
+                 (s/end! busout)
+                 (s/end! busin))
                (on-timer-tick [_]
                  (let [frame {:type :ping}]
                    (s/push! busout frame)))
@@ -171,12 +175,17 @@
                    (.send ws data)))
                (on-busout-end []
                  (.close ws))]
+
          (s/on-end busout on-busout-end)
          (s/on-value busout on-busout-value)

          (events/listen ws EventType.MESSAGE on-ws-message)
          (events/listen ws EventType.ERROR on-ws-error)
+         (events/listen ws EventType.CLOSED on-ws-closed)
          (events/listen timer Timer.TICK on-timer-tick)
+
+         (.start timer)
+         (.open ws (.toString uri))

          [streamin busout])))))

@@ -186,7 +195,7 @@
   ([client dest data]
    (subscribe client dest data nil))
   ([client dest data {:keys [params] :or {params {}} :as opts}]
-   (let [[in out] (socket client dest data opts)
+   (let [[in out] (socket client dest data (assoc opts :_type :subscribe))
          bus (s/bus)]
      (s/subscribe in #(s/push! bus %) #(s/error! bus %) #(s/end! bus))
      (s/on-end bus #(s/end! out))


Change normalise-element logic

Change normalise-element logic

--- src/pump/template.cljs
+++ src/pump/template.cljs
@@ -31,19 +31,22 @@
 (defn parse-tag
   [tag]
   (if (fn? tag)
-    [:custom tag nil nil]
+    [:custom tag nil]
     (let [[tag id class] (next (re-matches re-tag (name tag)))]
-      [:vanilla (aget (.-DOM js/React) tag) id class])))
+      [:vanilla
+       (aget (.-DOM js/React) tag)
+       {:id (or id nil)
+        :className (if class (string/replace class #"\." " "))}])))

 (def attr-mapping
   {:class :className
    :for :htmlFor})

-(defn normalize-attributes
-  [attrs]
-  (into {} (map
-            (fn [[k v]] [(dash-to-camel-name (attr-mapping k k)) v])
-            attrs)))
+(defn normalize-into
+  [tag-attrs attrs]
+  (into tag-attrs (map
+                   (fn [[k v]] [(dash-to-camel-name (attr-mapping k k)) v])
+                   attrs)))

 (defn exclude-empty
   [attrs]
@@ -54,14 +57,12 @@
   [[tag & content]]
   (when (not (or (keyword? tag) (symbol? tag) (string? tag) (fn? tag)))
     (throw (str tag " is not a valid element name.")))
-  (let [[tag-type tag id class] (parse-tag tag)
-        tag-attrs      {:id (or id nil)
-                        :className (if class (string/replace class #"\." " "))}
+  (let [[tag-type tag tag-attrs] (parse-tag tag)
         map-attrs      (first content)]
     (if (map? map-attrs)
-      [tag-type tag (merge tag-attrs (if (= tag-type :vanilla)
-                                       (normalize-attributes map-attrs)
-                                       map-attrs))
+      [tag-type tag (if (= tag-type :vanilla)
+                      (normalize-into tag-attrs map-attrs)
+                      map-attrs)
        (next content)]
       [tag-type tag tag-attrs content])))


Wrap all values that implements IParamType to param instance on IExecute...

... and IFetch implementations.

--- src/suricatta/impl.clj
+++ src/suricatta/impl.clj
@@ -128,10 +128,9 @@

   clojure.lang.PersistentVector
   (execute [^PersistentVector sqlvec ^Context ctx]
-    (let [^DSLContext context   (proto/get-context ctx)
-          ^Query query (.query context
-                               (first sqlvec)
-                               (into-array Object (rest sqlvec)))]
+    (let [^DSLContext context (proto/get-context ctx)
+          ^Query query        (->> (into-array Object (map wrap-if-need (rest sqlvec)))
+                                   (.query context (first sqlvec)))]
       (.execute context query)))

   suricatta.types.Deferred
@@ -180,7 +179,7 @@
   PersistentVector
   (fetch [^PersistentVector sqlvec ^Context ctx opts]
     (let [^DSLContext context (proto/get-context ctx)
-          ^ResultQuery query (->> (into-array Object (rest sqlvec))
+          ^ResultQuery query (->> (into-array Object (map wrap-if-need (rest sqlvec)))
                                   (.resultQuery context (first sqlvec)))]
       (-> (.fetch context query)
           (result->vector opts))))


transport: force timeout value

transport: force timeout value

--- src/warp/transport.clj
+++ src/warp/transport.clj
@@ -48,7 +48,7 @@
 (defn make-pipeline
   [initial-pipeline]
   (-> initial-pipeline
-      (.addBefore "handler"   "timeout"    (pipeline/read-timeout))
+      (.addBefore "handler"   "timeout"    (pipeline/read-timeout 30))
       (.addBefore "timeout"   "length-in"  (pipeline/length-decoder))
       (.addBefore "length-in" "length-out" (pipeline/length-encoder))))


Vähemmän request logitusta

Vähemmän request logitusta

--- mtg-pairings-server/src/clj/mtg_pairings_server/server.clj
+++ mtg-pairings-server/src/clj/mtg_pairings_server/server.clj
@@ -24,14 +24,23 @@
         {:status 500
          :body   (.getMessage e)}))))

+(def ^:private log-blacklist
+  [#"^.*\.(ico|png|jpg|js|css|woff2|txt|map)$"
+   #"^/chsk$"])
+
+(defn ^:private logged? [uri]
+  (not-any? #(re-matches % uri) log-blacklist))
+
 (defn wrap-request-log
   [handler]
   (fn [request]
-    (let [response (handler request)]
-      (log/info (:remote-addr request)
-                (-> request :request-method name string/upper-case)
-                (:uri request)
-                (:status response))
+    (let [response (handler request)
+          uri (:uri request)]
+      (when (logged? uri)
+        (log/info (get-in request [:headers "x-real-ip"] (:remote-addr request))
+                  (-> request :request-method name string/upper-case)
+                  uri
+                  (:status response)))
       response)))

 (defn wrap-allow-origin
@@ -49,8 +58,8 @@
                           (.writeString generator (str c))))
   (hs/run-server
     (-> handler
-      wrap-json-with-padding
-      wrap-request-log
-      wrap-allow-origin
-      wrap-errors)
+        wrap-json-with-padding
+        wrap-request-log
+        wrap-allow-origin
+        wrap-errors)
     server-properties))


Fix the (let [a b] ;comment\n) bug.

Fix the (let [a b] ;comment\n) bug.

--- src/zprint/zprint.cljc
+++ src/zprint/zprint.cljc
@@ -1683,18 +1683,19 @@
 (declare precede-w-nl)

 (defn fzprint-flow-seq
-  "Take a seq of a zloc, created by (zmap identity zloc) and return
-  a style-vec of the result.  Either it fits on one line, or it is
-  rendered on multiple lines.  You can force multiple lines with
-  force-nl?. If you want it to do less than everything in the
-  original zloc, modify the result of (zmap identity zloc) to just
-  contain what you want to print. ind is either a single indent,
-  or a seq of indents, one for each element in zloc-seq.  Don't
-  concatenate an indent/newline on to the beginning of the output
-  from this routine.  Let this routine do it for you, as it needs
-  to know one is there in order to properly deal with any newlines
-  in the actual stream.  Else you will get two where you only should
-  have one."
+  "Takes zloc-seq, a seq of a zloc, created by (zmap identity zloc),
+  and returns a style-vec of the result.  Either it fits on one
+  line, or it is rendered on multiple lines.  You can force multiple
+  lines with force-nl?. If the seq is empty, returns :noseq, which
+  is what you give concat-no-nil if you want this to just disappear.
+  If you want it to do less than everything in the original zloc,
+  modify the result of (zmap identity zloc) to just contain what
+  you want to print. ind is either a single indent, or a seq of
+  indents, one for each element in zloc-seq.  Don't concatenate an
+  indent/newline on to the beginning of the output from this routine.
+  Let this routine do it for you, as it needs to know one is there
+  in order to properly deal with any newlines in the actual stream.
+  Else you will get two where you only should have one."
   ([options ind zloc-seq force-nl? nl-first?]
    (dbg options "fzprint-flow-seq: count zloc-seq:" (count zloc-seq))
    (let [coll-print (fzprint-seq options ind zloc-seq)
@@ -1703,16 +1704,17 @@
                     (interpose [[" " :none :whitespace]] coll-print))
          _ (log-lines options "fzprint-flow-seq:" ind one-line)
          one-line-lines (style-lines options ind one-line)]
-     (dbg-form options
-               "fzprint-flow-seq: exit:"
-               (if (and (not force-nl?) (fzfit-one-line options one-line-lines))
-                 one-line
-                 (apply concat-no-nil
-                   (precede-w-nl ind coll-print (not nl-first?)))))))
+     (dbg-form
+       options
+       "fzprint-flow-seq: exit:"
+       (if (and (not force-nl?) (fzfit-one-line options one-line-lines))
+         one-line
+         (if (not (empty? coll-print))
+           (apply concat-no-nil (precede-w-nl ind coll-print (not nl-first?)))
+           :noseq)))))
   ([options ind zloc-seq] (fzprint-flow-seq options ind zloc-seq nil nil))
   ([options ind zloc-seq force-nl?]
    (fzprint-flow-seq options ind zloc-seq force-nl? nil)))
-

 (defn fzprint-hang-one
   "Try out the given zloc, and if it fits on the current line, just
@@ -3113,15 +3115,13 @@
                                                   fn-style
                                                   arg-1-indent)
                                   r-str-vec)
-      (= len 1) #_(concat-no-nil l-str-vec
-                               ; Not clear if this is necessary
-                               pre-arg-1-style-vec
-                               (fzprint* roptions one-line-ind arg-1-zloc)
-                               pre-arg-2-style-vec
-                               r-str-vec)
-       (concat-no-nil l-str-vec
-			       (fzprint-flow-seq roptions one-line-ind zloc-seq nil nil)
-                               r-str-vec)
+      (= len 1)
+	; While len is one, don't assume that there is actually only one
+	; thing to print and use fzprint*.  len only counts the non-comment
+	; and non-nl elements, and there might be other things to print.
+	(concat-no-nil l-str-vec
+		       (fzprint-flow-seq roptions one-line-ind zloc-seq nil nil)
+		       r-str-vec)
       ; In general, we don't have a fn-style if we have less than 3 elements.
       ; However, :binding is allowed with any number up to this point, so we
       ; have to check here.  :binding is actually allowed with at least two
@@ -3143,17 +3143,18 @@
                          (fzprint* loptions (inc ind) arg-1-zloc)
                          pre-arg-2-style-vec
                          binding-style-vec
-                         (if (> len 2)
-                           (concat-no-nil ; here we use options, because
-                                          ; fzprint-flow-seq
-                                          ; will sort it out
-                             (fzprint-flow-seq options
-                                               (+ indent ind)
-                                               (get-zloc-seq-right second-data)
-                                               :force-nl
-                                               :newline-first)
-                             r-str-vec)
-                           r-str-vec)))
+			 (concat-no-nil
+			   ; Here we use options, because fzprint-flow-seq
+			   ; will sort it out.  It will also handle an
+			   ; empty zloc-seq by returning :noseq, so we
+			   ; don't have to check for (> len 2) before
+			   ; we call it.
+			   (fzprint-flow-seq options
+					     (+ indent ind)
+					     (get-zloc-seq-right second-data)
+					     :force-nl
+					     :newline-first)
+			   r-str-vec)))
       (= fn-style :pair-fn)
         (let [zloc-seq-right-first (get-zloc-seq-right first-data)
               zloc-count (count zloc-seq)]


don't need phrasal true/false

don't need phrasal true/false

--- src/babel/english/lab.cljc
+++ src/babel/english/lab.cljc
@@ -27,11 +27,7 @@
                        :sem {:pred :be-called
                              :subj {:pred :top}
                              :iobj {:pred :luisa}}
-                       :subcat []}
-              :comp {:phrasal true}
-              :head {:phrasal true
-                     :head {:phrasal false}
-                     :comp {:phrasal false}}}]
+                       :subcat []}}]
     (repeatedly
      #(println
        (morph (binding [babel.generate/println? false


Add property tests for opening blocks.

Add property tests for opening blocks.

--- src/blocks/store/tests.clj
+++ src/blocks/store/tests.clj
@@ -2,10 +2,11 @@
   "Suite of tests to verify that a given block store implementation conforms to
   the spec."
   (:require
-    [alphabase.bytes :as bytes]
+    [alphabase.bytes :refer [random-bytes]]
     [alphabase.hex :as hex]
     [blocks.core :as block]
     [blocks.store.util :as util]
+    [byte-streams :as bytes :refer [bytes=]]
     [clojure.java.io :as io]
     [clojure.test :refer :all]
     [clojure.test.check :as check]
@@ -22,7 +23,7 @@
   "Creates a new block with random content at most `max-size` bytes long."
   [max-size]
   (block/read!
-    (bytes/random-bytes (inc (rand-int max-size)))
+    (random-bytes (inc (rand-int max-size)))
     (rand-nth (keys digest/functions))))

@@ -78,14 +79,23 @@
         gen-block-key (gen/elements (keys blocks))
         gen-block-val (gen/elements (vals blocks))]
     (gen/one-of
-      [(gen-op :stat          gen-block-key)
-       (gen-op :list          (gen-list-opts blocks))
-       (gen-op :get           gen-block-key)
-       (gen-op :put!          gen-block-val)
-       (gen-op :delete!       gen-block-key)
-       (gen-op :get-batch     (gen/not-empty (gen/set gen-block-key)))
-       (gen-op :put-batch!    (gen/not-empty (gen/set gen-block-val)))
-       (gen-op :delete-batch! (gen/not-empty (gen/set gen-block-key)))])))
+      [(gen-op :stat             gen-block-key)
+       (gen-op :list             (gen-list-opts blocks))
+       (gen-op :get              gen-block-key)
+       (gen-op :put!             gen-block-val)
+       (gen-op :delete!          gen-block-key)
+       (gen-op :get-batch        (gen/not-empty (gen/set gen-block-key)))
+       (gen-op :put-batch!       (gen/not-empty (gen/set gen-block-val)))
+       (gen-op :delete-batch!    (gen/not-empty (gen/set gen-block-key)))
+       (gen-op :open-block       gen-block-key)
+       (gen-op :open-block-range (gen/fmap
+                                   (fn [[id a b]]
+                                     (if (< a b)
+                                       [id a b]
+                                       [id b a]))
+                                   (gen/tuple gen-block-key
+                                              gen/nat
+                                              gen/nat)))])))

@@ -95,11 +105,16 @@
   "Applies an operation to the store by using the op keyword to resolve a method
   in the `blocks.core` namespace. Returns the result of calling the method."
   [store [op-key args]]
-  (let [var-name (symbol (name op-key))
-        method (ns-resolve 'blocks.core var-name)
-        form-str (pr-str (list (symbol "blocks" (str var-name)) 'store args))]
-    ;(println ">>" form-str)
-    (testing form-str
+  ;(println ">>" op-key (pr-str args))
+  (case op-key
+    :open-block
+      (block/get store args)
+
+    :open-block-range
+      (block/get store (first args))
+
+    (let [var-name (symbol (name op-key))
+          method (ns-resolve 'blocks.core var-name)]
       (method store args))))

@@ -168,7 +183,22 @@

     :delete-batch!
       (let [contained-ids (keep (set args) (keys model))]
-        (is (= (set contained-ids) result)))))
+        (is (= (set contained-ids) result)))
+
+    :open-block
+      (if-let [block (get model args)]
+        (is (bytes= (.open (.content block)) (block/open result)))
+        (is (nil? result)))
+
+    :open-block-range
+      (let [[id start end] args]
+        (if-let [block (get model id)]
+          (is (bytes= (@#'blocks.core/bounded-input-stream
+                        (.open (.content block)) start end)
+                      (block/open result
+                                  (min start (:size block))
+                                  (min end   (:size block)))))
+          (is (nil? result))))))

 (defn- update-model


Set the extent of region-before

Set the extent of region-before

to avoid rendering warnings

--- src/catalog/layout/fop.clj
+++ src/catalog/layout/fop.clj
@@ -10,6 +10,11 @@
            javax.xml.transform.sax.SAXResult
            javax.xml.transform.stream.StreamSource
            [org.apache.fop.apps FopFactory MimeConstants]))
+
+(def ^:private region-body-margin-top 15)
+
+(defn- to-mm [n]
+  (format "%smm" n))

 (defn simple-page-master
   [{:keys [master-name page-height page-width
@@ -25,8 +30,10 @@
                            :margin-top margin-top
                            :margin-left margin-left
                            :margin-right margin-right}
-   [:fo:region-body {:margin-top "15mm"}]
-   [:fo:region-before {:region-name (format "xsl-region-before-%s" master-name)}]])
+   [:fo:region-body {:margin-top (to-mm region-body-margin-top)}]
+   [:fo:region-before {:region-name (format "xsl-region-before-%s" master-name)
+                       ;; extent should be smaller than margin-top of region-body
+                       :extent (to-mm (dec region-body-margin-top))}]])

 (defn heading [h hash opts]
   [:fo:block


Allow TB signature

Allow TB signature

for tactile books

--- src/catalog/validation.clj
+++ src/catalog/validation.clj
@@ -24,7 +24,7 @@

 (def BrailleGrade (s/enum :kurzschrift :vollschrift :schwarzschrift))

-(def SignatureRE #"(DS |GDB |BG |ED |BM |BK |PS|DY|GD)\d{4,6}|LUD \d{1,3}|BK \d{3}|VI \d{1,3}")
+(def SignatureRE #"(DS |GDB |BG |ED |BM |BK |PS|DY|GD)\d{4,6}|LUD \d{1,3}|BK \d{3}|VI \d{1,3}|TB \d{1,3}")

 (def SignatureTuple
   [(s/one SignatureRE "signature")


fix email sending

fix email sending

--- src/chat/server/invite.clj
+++ src/chat/server/invite.clj
@@ -81,7 +81,7 @@

 (defn invite-message
   [invite]
-  (let [accept-link ""]
+  (let [accept-link (make-invite-link invite)]
     {:text (str (invite :inviter-email) " has invited to join the " (invite :group-name)
                 " group on chat.leanpixel.com.\n\n"
                 "Go to " accept-link " to accept.")
@@ -96,7 +96,9 @@
   [invite]
   (http/post "https://api.mailgun.net/v3/chat.leanpixel.com/messages"
              {:basic-auth ["api" (env :mailgun-password)]
-              :form-params (merge {:to (invite :invitee-email)}
+              :form-params (merge {:to (invite :invitee-email)
+                                   :from "noreply@chat.leanpixel.com"
+                                   :subject "Join the conversation"}
                                   (invite-message invite))}))

 (defn register-page


Add db/sync to all read operations

Add db/sync to all read operations

--- src/kmg/domain.clj
+++ src/kmg/domain.clj
@@ -88,15 +88,21 @@
 (defn recommendation-data [db rid]
   {:recommendation (entity db rid) :media (entity db (media-id-by-recommendation-id db rid))})

+(defn with-syncronized-db-do [f]
+  @(d/sync (conn))
+  (f))
+
 (defn recommendations [user]
-  (let [db (db)
-        recommend-ids (take 4 (recommendation-ids db user))]
-    (map #(recommendation-data db %) recommend-ids)))
+  (with-syncronized-db-do
+    (fn [] (let [db (db)
+                 recommend-ids (take 4 (recommendation-ids db user))]
+    (map #(recommendation-data db %) recommend-ids)))))

 (defn recommendations-completed [user]
-  (let [db (db)
-        recommend-ids (take 10 (recommendations-completed-by-user db user))]
-    (map #(recommendation-data db %) recommend-ids)))
+  (with-syncronized-db-do
+    (fn [] (let [db (db)
+                 recommend-ids (take 10 (recommendations-completed-by-user db user))]
+    (map #(recommendation-data db %) recommend-ids)))))

 ;;(recommendations "user1")
 ;;(recommendations "user2")