Fetch DOI more robust.

Fetch DOI more robust.

--- src/chronograph/mdapi.clj
+++ src/chronograph/mdapi.clj
@@ -95,24 +95,26 @@
   ; Do each member in background concurrently
   (locking *out* (prn "Member id" member-id))
   (let [works-url (str members-endpoint "/" member-id "/works" \? (client/generate-query-string {:sample sample-size :rows sample-size}))
-        works-results (try-try-again {:sleep 5000 :tries :unlimited}
+        works-results
+        (try-try-again {:sleep 5000 :tries :unlimited}
                #(client/get works-url {:as :json}))
         works (-> works-results :body :message :items)
         dois (map :DOI works)
         domains (mapcat
                   (fn [doi]
                     (let [url (str "http://dx.doi.org/" doi)
-                          result (try-try-again {:sleep 1000 :tries 2}
-                             #(client/get url))
+                          result (try (try-try-again {:sleep 1000 :tries 2}
+                                       #(client/get url))
+                                   (catch Exception _ nil))
                           ; drop first, it's always "dx.doi.org"
                           redirects (rest (:trace-redirects result))
-                          all-domains (map (fn [url]
-                                          (let [host (.getHost (new java.net.URL url))
-                                                [subdomain true-domain etld] (util/get-main-domain host)
-                                                domain-part (str true-domain "." etld)]
-                                              domain-part)) redirects)
-                          all-domains (into #{} all-domains)]
-                      all-domains))
+                          all-domains (when result (into #{}
+                                                         (map (fn [url]
+                                                          (let [host (.getHost (new java.net.URL url))
+                                                                [subdomain true-domain etld] (util/get-main-domain host)
+                                                                domain-part (str true-domain "." etld)]
+                                                              domain-part)) redirects)))]
+                      (or all-domains [])))
                   dois)
         unique-domains (into #{} domains)]
     (locking *out* (prn "Domains for member" member-id "original" (count domains) "unique:" unique-domains "from" dois))


Implement Draggable Morphs

Implement Draggable Morphs

--- src-cljs/cljs_workspace/om_draggable.cljs
+++ src-cljs/cljs_workspace/om_draggable.cljs
@@ -41,7 +41,7 @@
         [new-pos-x, new-pos-y] [(+ (old-pos :x) delta-x) (+ (old-pos :y) delta-y)]]
     (when (= (@app :id) @clicked-morph)
       (swap! prev-cursor-pos #(identity [(.-clientX e) (.-clientY e)]))
-      (om/update! app [:morph :Position] {:x new-pos-x :y new-pos-y}))))
+      (om/update! app [:morph :Position] {:x new-pos-x :y new-pos-y} :update))))

 (defn stop-dragging [e app]
   (swap! clicked-morph #(identity nil))


Uncomment *cljs-warn-on-undeclared*.

Uncomment *cljs-warn-on-undeclared*.

--- src/clj/cljs/compiler.clj
+++ src/clj/cljs/compiler.clj
@@ -64,7 +64,7 @@
 ")

 (defn confirm-var-exists [env prefix suffix]
-  (when true ;;*cljs-warn-on-undeclared*
+  (when *cljs-warn-on-undeclared*
     (let [crnt-ns (-> env :ns :name)]
       (when (= prefix crnt-ns)
         (when-not (-> @namespaces crnt-ns :defs suffix)


output cleanup, remove {} from do

output cleanup, remove {} from do

--- src/clj/cljs/compiler.clj
+++ src/clj/cljs/compiler.clj
@@ -62,8 +62,7 @@
 (defn emit-block
   [context statements ret]
   (if statements
-    (let [body (str "\t" (apply str (interpose "\t" (map emits statements)))
-                    "\t" (emits ret))]
+    (let [body (str (apply str (map emits statements)) (emits ret))]
       (print body))
     (emit ret)))

@@ -86,7 +85,7 @@
   (let [context (:context env)]
     (if (= :expr context)
       (print (str "(cljs.core.truth_(" (emits test) ")?" (emits then) ":" (emits else) ")"))
-      (print (str "if(cljs.core.truth_(" (emits test) "))\n\t" (emits then) " else\n\t" (emits else) "\n")))))
+      (print (str "if(cljs.core.truth_(" (emits test) "))\n{" (emits then) "} else\n{" (emits else) "}\n")))))

 (defmethod emit :def
   [{:keys [name init env]}]
@@ -109,11 +108,11 @@
 (defmethod emit :do
   [{:keys [statements ret env]}]
   (let [context (:context env)]
-    (when (and statements (= :expr context)) (print "(function ()"))
-    (when statements (print "{\n"))
+    (when (and statements (= :expr context)) (print "(function (){"))
+    ;(when statements (print "{\n"))
     (emit-block context statements ret)
-    (when statements (print "}"))
-    (when (and statements (= :expr context)) (print ")()"))))
+    ;(when statements (print "}"))
+    (when (and statements (= :expr context)) (print "})()"))))

 (defmethod emit :let
   [{:keys [bindings statements ret env loop]}]


cljs.compiler/compile-file* cljs.analyzer/cache-file needs to set :write

--- src/clj/cljs/compiler.clj
+++ src/clj/cljs/compiler.clj
@@ -1052,7 +1052,7 @@
                       (let [{:keys [output-dir cache-analysis]} opts]
                         (when (and (true? cache-analysis) output-dir)
                           (ana/write-analysis-cache ns-name
-                            (ana/cache-file src output-dir)))
+                            (ana/cache-file src output-dir :write)))
                         ret))))))))))))

 (defn requires-compilation?


Commit semi-working click updates, preparatory to starting a regression-testing branch.

--- src/cljs/primes/core.cljs
+++ src/cljs/primes/core.cljs
@@ -84,7 +84,8 @@

 (def app-state (atom {:title "Integer composite groups"
-                      :up-to 10}))
+                      :up-to 10
+                      :groups (nums/group-signatures 10)}))

 (defn title [app]
@@ -95,6 +96,7 @@
   "Extend the range of numbers we are looking at"
   [app]
   (om/transact! app :up-to #(nums/ceil (* % 1.5)))
+  (om/update! app :groups (nums/group-signatures (:up-to @app))))

 (defn numseq [app]
@@ -118,28 +120,6 @@
                 (if expanded "EXPANDED" "NOT EXPANDED"))))))

-(defn group-view-new
-  "Render the contents of one group (set) of numbers."
-  [app owner]
-  (let [signature [1 1]
-        numbers [4 5 6 7 8 9 10 "...dummy data..."]]
-    (reify
-      om/IInitState
-      (init-state [_]
-        {:expanded false})
-      om/IRenderState
-      (render-state [_ {:keys [expanded]}]
-        (dom/li nil
-                (dom/b nil
-                       (str/join ", " signature))
-                " [" (nums/vector-magnitude signature) "]"
-                (dom/br nil)
-                (count numbers) ": " (+ 3 4 )
-                (dom/span #js {:onClick (fn [e] (om/set-state! owner :expanded (not expanded)))}
-                           (dom/small nil (if expanded
-                                            (dom/i nil (str/join ", " numbers))
-                                            "CLICK TO EXPAND"))))))))
-
 (defn group-view
   "Render the contents of one group (set) of numbers."
   [[signature numbers] owner]
@@ -154,7 +134,31 @@
               " [" (nums/vector-magnitude signature) "]"
               (dom/br nil)
               (count numbers) ": "
-              (dom/small nil (dom/i nil (str/join ", " numbers)))))))
+              (dom/span #js {:onClick (fn [e] (om/set-state! owner :expanded (not expanded)))}
+                        (dom/small nil
+                                   (dom/i nil
+                                          (if expanded
+                                            (str/join ", " numbers)
+                                            "{Click to expand}"))))))))
+
+
+(defn group-view-wrapper
+  "Render the contents of one group (set) of numbers."
+  [app owner]
+  (let [[signature numbers] (first (:groups app))]
+    (group-view [signature numbers] owner)))
+
+(defn group-view-wrapper2
+  "Render the contents of one group (set) of numbers."
+  [app-group owner]
+  (let [[signature numbers] (first app-group)]
+    (group-view [signature numbers] owner)))
+
+(defn group-view-wrapper3
+  "Render the contents of one group (set) of numbers."
+  [app-group owner]
+  (let [[signature numbers] app-group]
+    (group-view [signature numbers] owner)))

 (defn groups-view
@@ -167,10 +171,18 @@
                (om/build title app)
                (om/build numseq app)
                (om/build counter-view app {})
+               (dom/div nil "Uses wrapper, works")
                (dom/ul nil
-                      (om/build group-view-new app {}))
+                       (om/build group-view-wrapper app))
+               (dom/div nil "Uses wrapper2, works")
+               (dom/ul nil
+                       (om/build group-view-wrapper2 (:groups app)))
+               (dom/div nil "Uses wrapper3, fails")
+               (dom/ul nil
+                       (om/build group-view-wrapper3 (first (:groups app))))
+               (dom/div nil "Build-all, fails")
                (apply dom/ul nil
-                      (om/build-all group-view (nums/group-signatures (:up-to app))))))))
+                      (om/build-all group-view (:groups app)))))))

 (om/root groups-view


`next-slide` implementation with `om/update!`

--- src/cljs/slides/core.cljs
+++ src/cljs/slides/core.cljs
@@ -14,7 +14,13 @@
         (dom/div #js {:className "slide-content banner"}
           (dom/h1 #js {} (:title model)))))))

-(defn next-slide [e model f])
+(defn next-slide [e model f]
+  (let [slides (:slides @model)
+        current-pos (:index @model)
+        upcoming-pos (f current-pos)]
+    (.preventDefault e)
+    (when (get slides upcoming-pos)
+      (om/update! model :index upcoming-pos))))

 (defn app [model owner]
   (reify


update writer docstring

update writer docstring

--- src/cognitect/transit.clj
+++ src/cognitect/transit.clj
@@ -144,7 +144,10 @@

    :handlers - a map of types to WriteHandler instances, they are merged
    with the default-handlers and then with the default handlers
-   provided by transit-java."
+   provided by transit-java.
+
+   :transform - a function of one argument that will transform values before
+   they are written."
   ([out type] (writer out type {}))
   ([^OutputStream out type {:keys [handlers transform]}]
      (if (#{:json :json-verbose :msgpack} type)


@jwilger's version of future-fact

@jwilger's version of future-fact

--- src/midje/sweet.clj
+++ src/midje/sweet.clj
@@ -42,3 +42,4 @@
 (defmacro pending-fact [& forms] nil)
 (defmacro future-fact [& forms] nil)
 (defmacro incipient-fact [& forms] nil)
+(defmacro antiterminologicaldisintactitudinarian-fact [& forms] nil)


Formatting.

Formatting.

--- src/datascript/query.cljs
+++ src/datascript/query.cljs
@@ -424,8 +424,7 @@

     '[*] ;; pattern
       (lookup-pattern context clause (fn [datoms]
-        (callback (update-in context [:rels] collapse-rels datoms))
-        ))))
+        (callback (update-in context [:rels] collapse-rels datoms))))))

 ;TODO not really sure it is valid to replace all these context's with @context's, but it seems to work
 (defn resolve-clause [context clause callback]


Don't setup log in client either.

Don't setup log in client either.

--- src/onyx/system.clj
+++ src/onyx/system.clj
@@ -24,7 +24,7 @@

 (def development-components [:logging-config :log])

-(def client-components [:logging-config :log])
+(def client-components [:log])

 (def peer-components [:log :messenger-buffer :messenger :acking-daemon :virtual-peer])

@@ -82,8 +82,7 @@
 (defn onyx-client
   [config]
   (map->OnyxClient
-   {:logging-config (logging-config/logging-configuration (:logging config))
-    :log (component/using (zookeeper config) [:logging-config])}))
+   {:log (zookeeper config)}))

 (defn onyx-peer
   [config]


Enable anchor links by default

Enable anchor links by default

--- src/io/perun/markdown.clj
+++ src/io/perun/markdown.clj
@@ -37,7 +37,8 @@
   (->> opts
        (merge {:autolinks true
                :strikethrough true
-               :fenced-code-blocks true})
+               :fenced-code-blocks true
+               :extanchorlinks true})
        (filter val)
        keys
        (map extensions)


Working

Working

--- src/mail_sieve_e/core.clj
+++ src/mail_sieve_e/core.clj
@@ -101,9 +101,9 @@
                   (recur))
                 (.close sock)))))))
     (go-loop []
-      (when-not running?
-        (.close server-socket))
-      (recur))
+      (if-not running?
+        (.close server-socket)
+        (recur)))
     {:server-socket server-socket
      :running running?
      :connected connected}))
@@ -167,6 +167,7 @@
     (do
       (>!! send-chan 0)
       (reset! (:running server) false)
+      (a/close! send-chan)
       (.close (:server-socket server)))
     (println "Sieve completed!")))

@@ -184,7 +185,8 @@
         (println "Waiting for kill signal...")
         (while (not= 0 (<!! (:in lead)))
           (<!! (timeout 50)))
-        (.close (:socket lead))
+        (do (a/close! (:in lead))
+            (a/close! (:out lead)))
         (println "Done!")))))

 (defn -main


trying some garbage collection of old channels

--- src/mediakeys/sockets.clj
+++ src/mediakeys/sockets.clj
@@ -1,6 +1,6 @@
 (ns mediakeys.sockets
     (:use [mediakeys.utils :only [defcurried dochan]]
-          [clojure.core.async :only [put! chan tap]])
+          [clojure.core.async :only [put! chan close! tap]])
     (:import [org.webbitserver WebSocketHandler]))

 (defcurried send! [c message]
@@ -11,24 +11,44 @@
         (tap mult return)
         return))

+(def channels (atom { }))
+(defn start! [conn channel]
+    (swap! channels assoc conn channel)
+    (print @channels))
+(defn stop! [conn]
+    (close! (@channels conn))
+    (swap! channels dissoc conn)
+    (print @channels))
+
 (defn keypresses [incoming]
     (proxy [WebSocketHandler] []
         (onOpen [c]
-            (dochan (clone incoming) (send! c)))
-        (onClose [c] (println "closed" c))
+            (let [channel (clone incoming)]
+                (dochan channel (send! c))
+                (start! c channel)))
+        (onClose [c]
+            (println "closed" c)
+            (stop! c))
         (onMessage [c j] )))

 (defn controls [new-keys incoming-changes]
     (proxy [WebSocketHandler] []
         (onOpen [c]
-            (dochan (clone incoming-changes) (send! c)))
-        (onClose [c] (println "closed changes" c))
+            (let [channel (clone incoming-changes)]
+                (dochan channel (send! c))
+                (start! c channel)))
+        (onClose [c]
+            (println "closed changes" c)
+            (stop! c))
         (onMessage [c message]
             (put! new-keys message))))

 (defn errors [incoming-errors]
     (proxy [WebSocketHandler] []
         (onOpen [c]
-            (dochan (clone incoming-errors) (send! c)))
-        (onClose [c])
+           (let [channel (clone incoming-errors)]
+                (dochan channel (send! c))
+                (start! c channel)))
+        (onClose [c]
+            (stop! c))
         (onMessage[c j])))


Reorder components

Reorder components

--- src/braid/client/register/views/user.cljs
+++ src/braid/client/register/views/user.cljs
@@ -7,6 +7,39 @@
    [:a.github "Github"]
    [:a.google "Google"]
    [:a.facebook "Facebook"]])
+
+(defn returning-email-field-view []
+  [:div.option.email
+   [:h2 "Email"]
+   [:label
+    [:div.field
+     [:input {:type "email"
+              :placeholder "you@awesome.com"
+              :autocomplete true
+              :autocorrect false
+              :autocapitalize false
+              :spellcheck false
+              :auto-focus true}]]
+    [:div.explanation
+     [:p "Or, login with: "
+      [auth-providers-view]]]]])
+
+(defn password-field-view []
+  [:div.option.password
+   [:h2 "Password"]
+   [:label
+    [:div.field
+     [:input {:type "password"
+              :placeholder "•••••••••••"}]]]
+   [:div.explanation
+    [:p "Don't remember your password?"
+     [:a "Reset it."]]]])
+
+(defn returning-user-view []
+  [:div
+   [:h2 "Log In"]
+   [returning-email-field-view]
+   [password-field-view]])

 (defn new-email-field-view []
   (let [value (subscribe [:register/field-value :email])
@@ -37,43 +70,10 @@
          [:p "Or, register with: "
           [auth-providers-view]]]]])))

-(defn returning-email-field-view []
-  [:div.option.email
-   [:h2 "Email"]
-   [:label
-    [:div.field
-     [:input {:type "email"
-              :placeholder "you@awesome.com"
-              :autocomplete true
-              :autocorrect false
-              :autocapitalize false
-              :spellcheck false
-              :auto-focus true}]]
-    [:div.explanation
-     [:p "Or, login with: "
-      [auth-providers-view]]]]])
-
-(defn password-field-view []
-  [:div.option.password
-   [:h2 "Password"]
-   [:label
-    [:div.field
-     [:input {:type "password"
-              :placeholder "•••••••••••"}]]]
-   [:div.explanation
-    [:p "Don't remember your password?"
-     [:a "Reset it."]]]])
-
 (defn new-user-view []
   [:div
    [:h2 "Create an Account"]
    [new-email-field-view]])
-
-(defn returning-user-view []
-  [:div
-   [:h2 "Log In"]
-   [returning-email-field-view]
-   [password-field-view]])

 (defn user-auth-view []
   [:div


Load message by entity-id from search

Load message by entity-id from search

Instead of having elasticsearch index thread-id, just get the entity id
of the messages & use pull-many to get the thread-ids

--- src/braid/server/search/elasticsearch.clj
+++ src/braid/server/search/elasticsearch.clj
@@ -3,6 +3,7 @@
     [braid.server.conf :refer [config]]
     [braid.server.db :as db]
     [clojure.data.json :as json]
+    [datomic.api :as d]
     [org.httpkit.client :as http]))

 (defn elasticsearch-enabled? []
@@ -10,19 +11,22 @@

 (defn search-for
   [{:keys [text group-id user-id]}]
-  (some->
-    @(http/get (str (config :elasticsearch-url)
-                    "/braid-messages/_search")
-       {:body (json/write-str {:query {:match {:content text}}})})
-    :body
-    json/read-str
-    (get-in ["hits" "hits"])
-    (->>
-      (into #{}
-            (comp
-              (map #(get-in % ["_source" "thread-id"]))
-              (map #(java.util.UUID/fromString %))
-              (filter #(= group-id (db/thread-group-id %)))
-              (map (fn [t-id] [t-id (db/thread-newest-message t-id)])))))
-    seq
-    set))
+  (let [resp (->
+               @(http/get (str (config :elasticsearch-url)
+                               ; TODO: page results properly
+                               "/braid-messages/_search?size=500")
+                  {:body (json/write-str {:query {:match {:content text}}})})
+               :body
+               json/read-str
+               (get "hits"))
+        more (- (get resp "total") (count (get resp "hits")))]
+    (->> (get resp "hits")
+         (map #(Long. (get % "_id")))
+         (d/pull-many (d/db db/conn) [{:message/thread [:thread/id]}])
+         (into #{}
+               (comp
+                 (map #(get-in % [:message/thread :thread/id]))
+                 (filter #(= group-id (db/thread-group-id %)))
+                 (map (fn [t-id] [t-id (db/thread-newest-message t-id)]))))
+         seq
+         set)))


assign task prios

assign task prios

--- src/cljs/iwaswhere_web/ui/entry/task.cljs
+++ src/cljs/iwaswhere_web/ui/entry/task.cljs
@@ -17,6 +17,12 @@
             (let [sel (js/parseInt (-> ev .-nativeEvent .-target .-value))
                   follow-up-hrs (when-not (js/isNaN sel) sel)
                   updated (assoc-in entry [:task :follow-up-hrs] follow-up-hrs)]
+              (put-fn [:entry/update-local updated]))))
+        priority-select
+        (fn [entry]
+          (fn [ev]
+            (let [sel (keyword (-> ev .-nativeEvent .-target .-value))
+                  updated (assoc-in entry [:task :priority] sel)]
               (put-fn [:entry/update-local updated]))))]
     (fn [entry put-fn edit-mode?]
       (when (contains? (:tags entry) "#task")
@@ -35,12 +41,24 @@
                       :on-input (input-fn entry :due)
                       :value    (format-time2 (-> entry :task :due))}]
              [:time (format-time (-> entry :task :due))])]
+          [:div
+           [:span " Priority: "]
+           [:select {:value     (get-in entry [:task :priority] "")
+                     :disabled  (not edit-mode?)
+                     :on-change (priority-select entry)}
+            [:option ""]
+            [:option {:value :A} "A"]
+            [:option {:value :B} "B"]
+            [:option {:value :C} "C"]
+            [:option {:value :D} "D"]
+            [:option {:value :E} "E"]]]
           (if-let [follow-up-scheduled (:follow-up-scheduled (:task entry))]
             [:div "Follow-up in " follow-up-scheduled]
             [:div
              [:span "Follow-up after "]
              [:select {:value     (get-in entry [:task :follow-up-hrs] "")
-                       :on-change (follow-up-select entry)}
+                       :on-change (follow-up-select entry)
+                       :disabled  (not edit-mode?)}
               [:option ""]
               [:option {:value 1} "1 hour"]
               [:option {:value 3} "3 hours"]


add arg cardinality to profiling

add arg cardinality to profiling

--- src/com/billpiel/mem_tracer/profiling.clj
+++ src/com/billpiel/mem_tracer/profiling.clj
@@ -5,40 +5,54 @@

 (defn calculate-log-score [])

+(defn merge-metric-values
+  [a b]
+  ((cond (number? a) +
+         (set? a) clojure.set/union
+         :default (throw (Exception. (format "Cant' merge this: '%s'" a))))
+   a b))
+
 (defn merge-fn-metrics
   [& rest]
   (apply merge-with
-         #(merge-with + % %2)
+         #(merge-with merge-metric-values % %2)
          rest))

 (defn finalize-metrics
   [fn-ms]
-  (util/apply-to-map-vals #(merge %
-                                  {:gross-time-avg (/ (:gross-time-sum %)
-                                                      (:count %)
-                                                      1.0)
-                                   :net-time-avg  (/ (:net-time-sum %)
-                                                     (:count %)
-                                                     1.0)})
+  (util/apply-to-map-vals (fn [metrics]
+                            (let [arg-cardinality (-> metrics :arg-set count)
+                                  call-count (:count metrics)
+                                  gross-time-sum (:gross-time-sum metrics)
+                                  repeat-arg-pct (- 1 (/ arg-cardinality
+                                                         call-count
+                                                         1.0))]
+                              (-> metrics
+                                  (dissoc :arg-set)
+                                  (merge {:gross-time-avg (/ gross-time-sum
+                                                             call-count
+                                                             1.0)
+                                          :net-time-avg  (/ (:net-time-sum metrics)
+                                                            call-count
+                                                            1.0)
+                                          :arg-cardinality arg-cardinality
+                                          :repeat-arg-pct repeat-arg-pct
+                                          :gross-of-repeats (* gross-time-sum
+                                                               repeat-arg-pct)}))))
                           fn-ms))

 (defn get-fn-metrics
   [tree]
-  (let [{{:keys [gross-time net-time]} :profiling} tree]
+  (let [{{:keys [gross-time net-time arg-set]} :profiling} tree]
     (apply merge-fn-metrics
            {(-> tree :name keyword)
             {:count 1
              :gross-time-sum gross-time
-             :net-time-sum net-time}}
+             :net-time-sum net-time
+             :arg-set arg-set}}
            (some->> tree
                     :children
                     (map get-fn-metrics)))))
-
-(defn get-fn-metrics-finalized
-  [tree]
-  (-> tree
-      get-fn-metrics
-      finalize-metrics))

 (defn add-durations-to-tree
   [tree]
@@ -56,7 +70,8 @@
            {:children children
             :profiling {:gross-time gross-time
                         :net-time net-time
-                        :kids-time kids-time}})))
+                        :kids-time kids-time
+                        :arg-set #{(:args tree)}}})))

 (defn add-metrics-to-rec
   [rec]


Benchmark tool should accept a directory of sample catalogs

Signed-off-by: Deepak Giridharagopal <d11186354d1ef01ca06ae37d7e23e827da13e85f@puppetlabs.com>

--- src/com/puppetlabs/cmdb/cli/benchmark.clj
+++ src/com/puppetlabs/cmdb/cli/benchmark.clj
@@ -37,12 +37,14 @@
 ;; tick.
 ;;
 (ns com.puppetlabs.cmdb.cli.benchmark
+  (:import (java.io File))
   (:require [clojure.tools.logging :as log]
             [com.puppetlabs.cmdb.catalog :as cat]
             [com.puppetlabs.cmdb.catalog.utils :as catutils]
             [cheshire.core :as json]
             [clj-http.client :as client]
-            [clj-http.util :as util])
+            [clj-http.util :as util]
+            [fs.core :as fs])
   (:use [com.puppetlabs.utils :only (cli! ini-to-map utf8-string->sha1)]
         [com.puppetlabs.cmdb.scf.migrate :only [migrate!]]))

@@ -118,17 +120,32 @@
       (Thread/sleep 10)
       (recur curr-time))))

+(defn associate-catalog-with-host
+  "Takes the given catalog and transforms it to appear related to
+  `hostname`"
+  [hostname catalog]
+  (-> catalog
+      (assoc-in ["data" "name"] hostname)
+      (assoc-in ["data" "resources"] (for [resource (get-in catalog ["data" "resources"])]
+                                       (assoc resource "tags" (conj (resource "tags") hostname))))))
 (defn -main
   [& args]
   (let [[options _] (cli! args
-                          ["-f" "--file" "Path to a sample JSON catalog"]
+                          ["-d" "--dir" "Path to a directory containing sample JSON catalogs"]
                           ["-u" "--url" "URL to REST endpoint for commands"]
                           ["-i" "--runinterval" "What runinterval (in minutes) to use during simulation"]
                           ["-n" "--numhosts" "How many hosts to use during simulation"]
                           ["-rp" "--rand-perc" "What percentage of submitted catalogs are tweaked (int between 0 and 100)"])

-        file        (:file options)
-        catalog     (json/parse-string (slurp file))
+        dir         (:dir options)
+        catalogs    (->> (for [file (fs/list-dir dir)
+                               :let [fname (str dir File/separator file)]]
+                           (try
+                             (json/parse-string (slurp fname))
+                             (catch Exception e
+                               (log/error (format "Error parsing %s; skipping" file)))))
+                         (remove nil?)
+                         (into []))

         nhosts      (:numhosts options)
         hostnames   (into #{} (map #(str "host-" %) (range 1 (Integer/parseInt nhosts))))]
@@ -141,11 +158,7 @@
     (def hosts
       (into [] (map #(agent {:host %,
                              :lastrun (- (System/currentTimeMillis) (rand-int runinterval)),
-                             :catalog (-> catalog
-                                        (assoc-in ["data" "name"] %)
-                                        (assoc-in ["data" "resources"]
-                                                  (for [resource (get-in catalog ["data" "resources"])]
-                                                    (assoc resource "tags" (conj (resource "tags") %)))))})
+                             :catalog (associate-catalog-with-host % (rand-nth catalogs))})
                     hostnames)))

     ;; Loop forever


Added Crate type mappings

Added Crate type mappings

--- src/metabase/driver/crate.clj
+++ src/metabase/driver/crate.clj
@@ -8,9 +8,20 @@
   "Map of Postgres column types -> Field base types.
    Add more mappings here as you come across them."
   [_ column-type]
-  ({:int       :IntegerField
-    :integer   :IntegerField
-    :string    :TextField} column-type))
+  ({:integer   :IntegerField
+    :string    :TextField
+    :boolean   :BooleanField
+    :byte      :UnknownField
+    :short     :UnknownField
+    :long      :BigIntegerField
+    :float     :FloatField
+    :double    :FloatField
+    :ip        :UnknownField
+    :timestamp :DateTimeField
+    :geo_point :UnknownField
+    :geo_shape :UnknownField
+    :
+    } column-type))

 (defrecord CrateDriver []
   Named


Made pulse card container function private

--- src/metabase/pulse/render.clj
+++ src/metabase/pulse/render.clj
@@ -396,7 +396,7 @@
            (number-field? col-2))                                  :bar
       :else                                                        :table)))

-(defn render-pulse-card-container
+(defn- render-pulse-card-container
   [card content]
   [:a {:href   (card-href card)
        :target "_blank"


Lower case the NUX sections.

Lower case the NUX sections.

--- src/oc/storage/config.clj
+++ src/oc/storage/config.clj
@@ -81,24 +81,24 @@

 (defonce default-board-names #{
   "All-hands"
-  "CEO Update"
+  "CEO update"
   "Competition"
-  "Customer Wins"
+  "Customer wins"
   "Decisions"
   "Design"
   "Engineering"
   "Events"
   "Finances"
-  "Key Metrics"
+  "Key metrics"
   "Kudos"
-  "Lessons Learned"
+  "Lessons learned"
   "Marketing"
   "People"
   "Playbooks"
   "Press"
-  "Product Updates"
+  "Product updates"
   "Sales"
-  "Team and Hiring"
+  "Team and hiring"
   "Week in review"})

 (defonce new-org-board-names #{


Properly categorize dummy options

Properly categorize dummy options

There are some AI options that are dummy. If no attack is found, just
generate random moves, with very low value. The problema was that
aggregating valid attack options with the dummy options would bring that
best options down. This patch makes the joiner ignore dummy options.

--- src/obb_rules/ai/common.cljc
+++ src/obb_rules/ai/common.cljc
@@ -161,6 +161,7 @@
                  (assoc :distance 1)
                  (assoc :actions [action])
                  (assoc :value value)
+                 (assoc :dummy true)
                  (assoc :element-coord target-coord)
                  (assoc :cost mov-cost)))
           actions-and-results))))
@@ -194,6 +195,14 @@
     (let [cost-factor (+ 17 (* 100 (- laws/max-action-points (:cost option))))]
       (- (* (option :value) cost-factor)))
     0))
+
+(defn value-for-join
+  "Gets the value of the option, considering that the option will me merged
+  with another option."
+  [current-option]
+  (if (:dummy current-option)
+    0
+    (:value current-option)))

 (defn join-options
   "Joins the given options on the given board, until the cost is possible"
@@ -213,6 +222,6 @@
           (-> master
               (assoc :board (result/result-board result))
               (assoc :actions (into (master :actions) actions))
-              (update :value + (:value current-option))
+              (update :value + (value-for-join current-option))
               (assoc :cost (+ (master :cost) (current-option :cost))))
           master)))))


Added px and close-button to re-com (and fixed input-text bug re :box-sizing)

--- src/day8/re_frame/trace/utils/re_com.cljs
+++ src/day8/re_frame/trace/utils/re_com.cljs
@@ -3,6 +3,11 @@
   (:require-macros [day8.re-frame.trace.utils.re-com :refer [handler-fn]])
   (:require [reagent.ratom :as reagent :refer [RAtom Reaction RCursor Track Wrapper]]
             [clojure.string :as string]))
+
+(defn px
+  "takes a number (and optional :negative keyword to indicate a negative value) and returns that number as a string with 'px' at the end"
+  [val & negative]
+  (str (if negative (- val) val) "px"))

 (defn deref-or-value-peek
   "Takes a value or an atom
@@ -337,6 +342,7 @@
                          :style       (merge
                                         (flex-child-style "none")
                                         {:height        height
+                                         :box-sizing    "border-box" ;; TODO: Added to override the incorrect default of "content-box" somehow set up by :all unset
                                          :padding-right "12px"} ;; override for when icon exists
                                         style)
                          :placeholder placeholder
@@ -537,6 +543,38 @@
                     :on-click (handler-fn (callback-fn))}
                    label])]]))

+;; Taken from day8.briefly.components.close-button
+(defn close-button
+  []
+  (let [over? (reagent/atom false)]
+    (fn close-button-render
+      [& {:keys [on-click div-size font-size color hover-color tooltip top-offset left-offset style attr]
+          :or   {div-size 16 font-size 16 color "#ccc" hover-color "#999"}}]
+      [box
+       :class "rc-close-button"
+       :style {:display          "inline-block"
+               :position         "relative"
+               :width            (px div-size)
+               :height           (px div-size)}
+       :child [box
+               :style (merge
+                        {:position  "absolute"
+                         :cursor    "pointer"
+                         :font-size (px font-size)
+                         :color     (if @over? hover-color color)
+                         :top       (px (- (/ (- font-size div-size) 2) top-offset)  :negative)
+                         :left      (px (- (/ (- font-size div-size) 2) left-offset) :negative)}
+                        style)
+               :attr  (merge
+                        {:title          tooltip
+                         :on-click       (handler-fn (on-click)
+                                                     (.stopPropagation event))
+                         :on-mouse-enter (handler-fn (reset! over? true))
+                         :on-mouse-leave (handler-fn (reset! over? false))}
+                        attr)
+               ;:child [:i {:class "zmdi zmdi-hc-fw-rc zmdi zmdi-close"}]
+               :child [:span "×"]]])))
+
 (defn css-join [& args]
   "Creates a single string from all passed args, separated by spaces (all args are coerced to strings)
   Very simple, but handy


remove spurious debug statement

remove spurious debug statement

--- src/overtone/sc/mixer.clj
+++ src/overtone/sc/mixer.clj
@@ -14,7 +14,6 @@
 (add-watch master-vol*
            ::update-vol-on-server
            (fn [k r old new-vol]
-             (println "updating volume to " new-vol (main-mixer-group))
              (ctl (main-mixer-group) :master-volume new-vol)))

 (add-watch master-gain*


Allow midi-poly-player to be associated with specific midi devices. Also implement midi-device-keys which returns a sequence of midi device event keys. Fixes #143.

--- src/overtone/studio/midi.clj
+++ src/overtone/studio/midi.clj
@@ -9,7 +9,6 @@
 (defonce midi-devices* (atom {}))
 (defonce midi-control-agents* (atom {}))
 (defonce poly-players* (atom {}))
-(defonce seen-midi-device-keys* (atom #{}))

 (def EXCLUDED-DEVICES #{"Real Time Sequencer" "Java Sound Synthesizer"})

@@ -40,9 +39,7 @@
         dev-event-key (midi-mk-full-device-event-key dev command)]
     (event [:midi command] msg)
     (event (midi-mk-full-control-event-key dev command (:data1 msg)) msg)
-    (event dev-event-key msg)
-    (when-not (get @seen-midi-device-keys* dev-key)
-      (swap! seen-midi-device-keys* conj dev-key))))
+    (event dev-event-key msg)))

 (defn- detect-midi-devices
   "Designed to run periodically and update the midi-devices* atom with
@@ -95,29 +92,40 @@
     (def dinger (midi-poly-player ding))
   "
   ([play-fn] (midi-poly-player play-fn ::midi-poly-player))
-  ([play-fn key]
-     (let [notes*  (atom {})
-           on-key  [key :note-on]
-           off-key [key :note-off]]
-       (on-event [:midi :note-on] (fn [{note :note velocity :velocity}]
-                                    (let [amp (float (/ velocity 127))]
-                                      (swap! notes* assoc note (play-fn :note note :amp amp :velocity velocity))))
+  ([play-fn player-key] (midi-poly-player play-fn [:midi] player-key))
+  ([play-fn device-key player-key]
+     (let [notes*        (atom {})
+           on-event-key  (concat device-key [:note-on])
+           off-event-key (concat device-key [:note-off])
+           on-key        (concat [::midi-poly-player] on-event-key)
+           off-key       (concat [::midi-poly-player] off-event-key)]
+       (on-event on-event-key (fn [{note :note velocity :velocity}]
+                                (let [amp (float (/ velocity 127))]
+                                  (swap! notes* assoc note (play-fn :note note :amp amp :velocity velocity))))
                  on-key)

-       (on-event [:midi :note-off] (fn [{note :note velocity :velocity}]
-                                     (let [velocity (float (/ velocity 127 ))]
-                                       (when-let [n (get @notes* note)]
-                                         (node-control n [:gate 0 :after-touch velocity])
-                                         (swap! notes* dissoc note))))
+       (on-event off-event-key (fn [{note :note velocity :velocity}]
+                                 (let [velocity (float (/ velocity 127 ))]
+                                   (when-let [n (get @notes* note)]
+                                     (node-control n [:gate 0 :after-touch velocity])
+                                     (swap! notes* dissoc note))))
                  off-key)

        ;; TODO listen for '/n_end' event for nodes that free themselves
        ;; before recieving a note-off message.
-       (let [player {:notes* notes*
-                     :on-key on-key
-                     :off-key off-key
-                     :playing? (atom true)}]
-         (swap! poly-players* assoc key player)))))
+       (let [player (with-meta {:notes* notes*
+                                :on-key on-key
+                                :off-key off-key
+                                :device-key device-key
+                                :player-key player-key
+                                :playing? (atom true)}
+                      {:type ::midi-poly-player})]
+         (swap! poly-players* assoc player-key player)))))
+
+(defn midi-device-keys
+  "Return a list of device event keys for the available MIDI devices"
+  []
+  (map midi-mk-full-device-key (vals @midi-devices*)))

 (defn- midi-control-handler
   [state-atom handler mapping msg]
@@ -150,17 +158,19 @@

 (defn midi-player-stop
   ([]
-     (remove-handler [::midi-poly-player :note-on])
-     (remove-handler [::midi-poly-player :note-off]))
+     (remove-handler [::midi-poly-player :midi :note-on])
+     (remove-handler [::midi-poly-player :midi :note-off]))
   ([player-or-key]
      (if (keyword? player-or-key)
        (midi-player-stop (get @poly-players* player-or-key))
-       (do
-         (remove-handler (:on-key player-or-key))
-         (remove-handler (:off-key player-or-key))
-         (reset! (:playing? player-or-key) false)
-         (swap! poly-players* dissoc player-or-key)
-         player-or-key))))
+       (let [player player-or-key]
+         (when-not (= ::midi-poly-player (type player))
+           (throw (IllegalArgumentException. (str "Expected a midi-poly-player. Got: " (prn-str (type player))))))
+         (remove-handler (:on-key player))
+         (remove-handler (:off-key player))
+         (reset! (:playing? player) false)
+         (swap! poly-players* dissoc (:player-key player))
+         player))))

 (defn midi-capture-next-control-input


Exclude range and not from clojure.core.

--- src/pjstadig/es/query.clj
+++ src/pjstadig/es/query.clj
@@ -6,7 +6,8 @@
 ;;;;
 ;;;; This Source Code Form is "Incompatible With Secondary Licenses", as defined
 ;;;; by the Mozilla Public License, v. 2.0.
-(ns pjstadig.es.query)
+(ns pjstadig.es.query
+  (:refer-clojure :exclude [not range]))

 (defn term [field term]
   {:pre [field term]}


Remove unnecessary wrap functions on request handler

--- src/regarde/web.clj
+++ src/regarde/web.clj
@@ -91,10 +91,7 @@
         ;; TODO: heroku config:add SESSION_SECRET=$RANDOM_16_CHARS
         store (cookie/cookie-store {:key (env :session-secret)})]
     (jetty/run-jetty (-> #'app
-                         keyword-params/wrap-keyword-params
-                         params/wrap-params
                          (oauth2-ring/wrap-oauth2 authentication/google-com-oauth2)
-                         session/wrap-session
                          ((if (env :production)
                             wrap-error-page
                             trace/wrap-stacktrace))


Work around kibit issue.

Work around kibit issue.

--- src/oc/storage/api/boards.clj
+++ src/oc/storage/api/boards.clj
@@ -89,19 +89,21 @@
       (assoc :entries entry-reps)))))

 ;; ----- Validations -----
+
 (defn- valid-entry-with-board?
   [conn entry author]
-  (if-let* [entry-uuid (:uuid entry)
-           found-entry (entry-res/get-entry conn entry-uuid)]
-    (merge found-entry entry)
+  (if-let* [status (or (:status entry) "published")
+            entry-uuid (:uuid entry)
+            found-entry (entry-res/get-entry conn entry-uuid)]
+    (merge found-entry (assoc entry :status status))
     (entry-res/->entry conn entry-res/temp-uuid entry author)))

 (defn- valid-new-board? [conn org-slug {board-map :data author :user}]
   (if-let [org (org-res/get-org conn org-slug)]
     (try
       (let [notifications (:private-notifications board-map)
-            entry-data (map #(valid-entry-with-board?
-                               conn (assoc % :status (or (:status %) "published")) author) (:entries board-map))
+            entry-data (map #(valid-entry-with-board? conn % author)
+                          (:entries board-map))
             board-data (-> board-map
                         (dissoc :private-notifications :note)
                         (assoc :entries entry-data))]


Cast template as file

Cast template as file

--- src/sparql_to_csv/cli.clj
+++ src/sparql_to_csv/cli.clj
@@ -59,7 +59,7 @@
     :as params}
    template]
   (validate-params params)
-  (when-not (util/file-exists? template)
+  (when-not (util/file-exists? (io/as-file template))
     (util/die (format "File at %s doesn't exist." template)))
   (let [template' (slurp template)
         piped? (has-input? input)


Removed unnecessary experimental code

Removed unnecessary experimental code

--- src/flatgui/samples/forms/hellowindow.clj
+++ src/flatgui/samples/forms/hellowindow.clj
@@ -13,8 +13,7 @@
             [flatgui.widgets.window :as window]
             [flatgui.widgets.checkbox :as checkbox]
             [flatgui.widgets.label :as label]
-            [flatgui.widgets.panel :as panel]
-            [flatgui.inputchannels.host :as host]))
+            [flatgui.widgets.panel :as panel]))

 (def nogreeting-text "Not now")

@@ -48,19 +47,10 @@
        :position-matrix (m/translation 1.0 0.75)
        :evolvers {:text greeting-evolver}})))

-(fg/defevolverfn :clip-size
-  (if (host/host-event? component)
-    (let [host-size (host/get-host-size component)
-          _ (println "Host-size = " host-size)]
-      (m/defpoint (:w host-size) (:h host-size)))
-    old-clip-size))
-
-
 (def root-panel
   (fg/defcomponent
     panel/panel
     :main
     {:clip-size (m/defpoint 4 2)
-     :background (awt/color 9 17 26)
-     :evolvers {:clip-size clip-size-evolver}}
+     :background (awt/color 9 17 26)}
     hello-window))


Well, that much about 6.11, now moving on. I might get back to this later...

--- src/fpinscala/purely_functional_state.clj
+++ src/fpinscala/purely_functional_state.clj
@@ -409,4 +409,6 @@
     (let [{{{:keys [coins candies]} :val} :next-state} ((state-sequence-fpins (map #(modify-state (step-machine %)) inputs)) (make-state m nil))]
       [coins candies])))
 ;Where as Scala FPINS variant yields proper State[Machine, (Int, Int)], mine returns just desired "yield" output of FPINS solution
-
+;This require revision of map and flatMap functions as well as get-state and set-state, well.. everything in
+;scope of this exercise (6.11)
+


Fix unlisten to work outside of the container.

--- modules/messaging/src/main/clojure/immutant/messaging.clj
+++ modules/messaging/src/main/clojure/immutant/messaging.clj
@@ -226,7 +226,8 @@
    destination before your app is undeployed."
   [listener]
   (when listener
-    (if (instance? java.io.Closeable listener)
+    (if (or (instance? java.io.Closeable listener)
+            (instance? javax.jms.Connection listener))
       (.close listener)
       (let [complete (promise)]
         (.remove listener #(deliver complete %))


Add :none to enumeration of same-site cookie values

--- src/yada/schema.clj
+++ src/yada/schema.clj
@@ -474,7 +474,7 @@
     (s/optional-key :path) (s/pred #(re-matches syn/path %))
     (s/optional-key :secure) s/Bool
     (s/optional-key :http-only) s/Bool
-    (s/optional-key :same-site) (s/enum :strict :lax)}
+    (s/optional-key :same-site) (s/enum :strict :lax :none)}
    CookieConsumer
    NamespacedEntries))


Update reader.clj

Update reader.clj

--- src/yaml/reader.clj
+++ src/yaml/reader.clj
@@ -70,10 +70,3 @@
       (decode (.load (Yaml. constructor) string))
       (catch ComposerException e
         (parse-documents string)))))
-
-(comment
-  (parse-string (slurp "test/fixtures/tags.yaml"))
-
-  (parse-string (slurp "test/fixtures/petstore.yaml"))
-
-  )


Wires format-for-mailgun into post-message

Handles different input to put in expected format for API.

--- src/yuubin/mail.clj
+++ src/yuubin/mail.clj
@@ -28,4 +28,4 @@
   (client/post
     (addr-of mailbox)
     {:basic-auth ["api" key]
-     :form-params (merge (from mailbox) json-msg)}))
+     :form-params (merge (from mailbox) (format-for-mailgun json-msg))}))


refactored interpreter_core

refactored interpreter_core

--- src/push/interpreter/interpreter_core.clj
+++ src/push/interpreter/interpreter_core.clj
@@ -47,6 +47,14 @@
                         "Unknown Push instruction:'" token "'"))))

+(defn- throw-unknown-push-item-error
+  [item]
+  (throw (Exception. (str
+                        "Push Parsing Error: Cannot interpret '"
+                        item
+                        "' as a Push item."))))
+
+
 (defn- add-instruction
   "Takes an Interpreter and an Instruction (record), and adds the
   instruction to the :instructions registry of the interpreter,
@@ -126,30 +134,37 @@
     :else interpreter)))

+(defn get-stack
+  "A convenience function which returns the named stack from the
+  interpreter"
+  [interpreter stack]
+  (get-in interpreter [:stacks stack]))
+
+
+(defn set-stack
+  "A convenience function which replaces the named stack with the
+  indicated list"
+  [interpreter stack new-value]
+  (assoc-in interpreter [:stacks stack] new-value))
+
+
 (defn push-item
-  "Takes an Interpreter, a stack name and a Clojure expression, and returns the Interpreter with the item pushed onto the specified stack. If the stack doesn't already exist, it is created."
+  "Takes an Interpreter, a stack name and a Clojure expression, and
+  returns the Interpreter with the item pushed onto the specified
+  stack. If the stack doesn't already exist, it is created."
   [interpreter stack item]
   (let [old-stack (get-in interpreter [:stacks stack])]
     (assoc-in interpreter [:stacks stack] (conj old-stack item))))

 (defn load-items
-  "Takes an Interpreter, a stack name, and a seq, and conj'es each item onto the named stack of the interpreter (using Clojure's `into` transducer). Used primarily for loading code onto the :exec stack."
-  [interpreter stack item-list]
-  (let [old-stack (get-in interpreter [:stacks stack])]
-    (assoc-in interpreter [:stacks stack] (into old-stack (reverse item-list)))))
-
-
-(defn get-stack
-  "A convenience function which returns the named stack from the interpreter"
-  [interpreter stack]
-  (get-in interpreter [:stacks stack]))
-
-
-(defn set-stack
-  "A convenience function which replaces the named stack with the indicated list"
-  [interpreter stack new-value]
-  (assoc-in interpreter [:stacks stack] new-value))
+  "Takes an Interpreter, a stack name, and a collection of items. Puts
+  all the items onto the named stack, one at time (probably reversing
+  them along the way."
+  [interpreter stackname item-list]
+  (let [old-stack (get-in interpreter [:stacks stackname])
+        new-stack (into old-stack (reverse item-list))]
+    (set-stack interpreter stackname new-stack)))

 (defn clear-stack
@@ -159,38 +174,44 @@

 (defn boolean?
-  "a checker that returns true if the argument is the literal `true` or the literal `false`"
+  "a checker that returns true if the argument is the literal `true`
+  or the literal `false`"
   [item]
   (or (false? item) (true? item)))

 (defn instruction?
-  "takes an Interpreter and a keyword, and returns true if the keyword is a key of the :instructions registry in that Interpreter instance"
+  "takes an Interpreter and a keyword, and returns true if the keyword
+  is a key of the :instructions registry in that Interpreter instance"
   [interpreter token]
   (contains? (:instructions interpreter) token))

 (defn handle-item
-  "Takes an Interpreter and an item, and either recognizes and invokes a keyword registered in that Interpreter as an instruction, or sends the item to the correct stack (if it exists). Throws an exception if the Clojure expression is not recognized explicitly as a registered instruction or some other kind of Push literal."
+  "Takes an Interpreter and an item, and either recognizes and invokes
+  a keyword registered in that Interpreter as an instruction, or sends
+  the item to the correct stack (if it exists). Throws an exception if
+  the Clojure expression is not recognized explicitly as a registered
+  instruction or some other kind of Push literal."
   [interpreter item]
   (cond
-    (instruction? interpreter item) (execute-instruction interpreter item)
+    (instruction? interpreter item)
+      (execute-instruction interpreter item)
     (integer? item) (push-item interpreter :integer item)
     (boolean? item) (push-item interpreter :boolean item)
     (char? item) (push-item interpreter :char item)
     (float? item) (push-item interpreter :float item)
     (string? item) (push-item interpreter :string item)
     (list? item) (load-items interpreter :exec item)
-    :else (throw
-      (Exception. (str "Push Parsing Error: Cannot interpret '" item "' as a Push item.")))))
+    :else (throw-unknown-push-item-error item)))

 (defn clear-all-stacks
   "removes all items from all stacks in an Interpreter"
   [interpreter]
   (let [stacklist (keys (:stacks interpreter))]
-    (assoc interpreter :stacks (reduce #(assoc %1 %2 '()) {} stacklist))))
-
+    (assoc interpreter :stacks
+      (reduce #(assoc %1 %2 '()) {} stacklist))))

 (defn reset-interpreter
@@ -206,13 +227,16 @@

 (defn increment-counter
-  "takes an Interpreter and increments its :counter (without otherwise changing it)"
+  "takes an Interpreter and increments its :counter (without otherwise
+  changing it)"
   [interpreter]
   (assoc interpreter :counter (inc (:counter interpreter))))

 (defn step
-  "Takes an Interpreter, pops one item off :exec, routes it to the router, increments the counter. If the :exec stack is empty, does nothing."
+  "Takes an Interpreter, pops one item off :exec, routes it to the
+  router, increments the counter. If the :exec stack is empty, does
+  nothing."
   [interpreter]
   (let [old-exec (get-stack interpreter :exec)]
     (if (seq old-exec)


Initialize DB before route handler events are run.

--- examples/todomvc/src/todomvc/core.cljs
+++ examples/todomvc/src/todomvc/core.cljs
@@ -15,6 +15,13 @@
 ;; -- Debugging aids ----------------------------------------------------------
 (devtools/install!)       ;; we love https://github.com/binaryage/cljs-devtools
 (enable-console-print!)   ;; so that println writes to `console.log`
+
+
+;; Put an initial value into app-db.
+;; The event handler for `:initialise-db` can be found in `events.cljs`
+;; Using the sync version of dispatch means that value is in
+;; place before we go onto the next step.
+(dispatch-sync [:initialise-db])

 ;; -- Routes and History ------------------------------------------------------
 ;; Although we use the secretary library below, that's mostly a historical
@@ -42,12 +49,6 @@
 ;;
 (defn ^:export main
   []
-  ;; Put an initial value into app-db.
-  ;; The event handler for `:initialise-db` can be found in `events.cljs`
-  ;; Using the sync version of dispatch means that value is in
-  ;; place before we go onto the next step.
-  (dispatch-sync [:initialise-db])
-
   ;; Render the UI into the HTML's <div id="app" /> element
   ;; The view function `todomvc.views/todo-app` is the
   ;; root view for the entire UI.


my bad.

my bad.

--- resources/leiningen/new/exponent/env/dev/user.clj
+++ resources/leiningen/new/exponent/env/dev/user.clj
@@ -37,4 +37,4 @@
   []
   (ra/stop-figwheel!))

-(start-figwheel)
+(def -main start-figwheel)


[CS] A map is more descriptive

[CS] A map is more descriptive

--- src/vip/data_processor/validation/csv.clj
+++ src/vip/data_processor/validation/csv.clj
@@ -59,7 +59,7 @@
   (let [raw-rows (csv/read-csv file-handle)
         headers (first raw-rows)
         rows (rest raw-rows)]
-    [headers (map (partial zipmap headers) rows)]))
+    {:headers headers :contents (map (partial zipmap headers) rows)}))

 (defn booleanize [field]
   (fn [row] (assoc row field
@@ -86,7 +86,7 @@
         (let [sql-table (get-in ctx [:tables table])
               column-names (sqlite/column-names (:db ctx) (:name sql-table))
               select-columns (fn [row] (select-keys row column-names))
-              [headers contents] (read-csv-with-headers in-file)]
+              {:keys [headers contents]} (read-csv-with-headers in-file)]
           (if (empty? (clojure.set/intersection (set headers) (set column-names)))
             (update-in ctx [:critical filename] conj "No header row")
             (let [transforms (apply comp select-columns row-transform-fns)


Move sort function

Move sort function

--- resources/orthogonal-rpg/core.clj
+++ resources/orthogonal-rpg/core.clj
@@ -36,9 +36,9 @@
                      (prevent-move screen entities)
                      (adjust-times screen))))
          (attack-player)
-         (sort-by :y #(compare %2 %1))
          (play-sounds!)
          (remove #(<= (:health %) 0))
+         (sort-by :y #(compare %2 %1))
          (render! screen)
          (update-screen! screen)))


Fix test.

Fix test.

--- test/hasch/test.cljc
+++ test/hasch/test.cljc
@@ -102,9 +102,8 @@

 (deftest squuid-test
   (testing "Sequential UUID functionality."
-    (is (= (squuid (uuid [1 2 3]))
-           #uuid "5914da46-5c15-555e-a1c8-6166a78fc808"))))
-
+    (is (= (subs (str (squuid (uuid [1 2 3]))) 24)
+           "6166a78fc808"))))

 #_(run-tests)


Implement support for customizing cell views

--- src/reabledit/components.cljs
+++ src/reabledit/components.cljs
@@ -1,6 +1,16 @@
 (ns reabledit.components
   (:require [reabledit.util :as util]
             [reagent.core :as reagent]))
+
+;;
+;; Cell views
+;;
+
+(defn span-view
+  []
+  (fn [v]
+    [:span v]))
+

 ;;
 ;; Cell editors
@@ -38,6 +48,7 @@
         edit? (:edit @state)
         column (nth columns nth-col)
         cursor (reagent/cursor state [:edit :updated (:key column)])
+        view (or (:view column) (span-view))
         editor (or (:editor column) (string-editor))]
     [:td {:class (if selected? "selected")
           :on-click #(util/set-selected! state nth-row nth-col)}


Taking a snapshot of the latest activity before sorting the tabs

See https://app.asana.com/0/50978096561390/62450128772424 for an
explanation

--- src/background/relevance/background.cljs
+++ src/background/relevance/background.cljs
@@ -217,6 +217,10 @@
 (register-handler
   ::on-clicked-button
   (fn [app-state [_ {:keys [tab]}]]
+    ;; Force it to track the time up until now
+    (let [active-tab (:active-tab app-state)]
+      (dispatch [:handle-deactivation active-tab])
+      (dispatch [:handle-activation active-tab]))
     (dispatch [:on-relevance-sort-tabs tab])
     app-state
     ))


Reorganize sub-functions by top-level usage

--- src/clj/comic_reader/sites/manga_fox.clj
+++ src/clj/comic_reader/sites/manga_fox.clj
@@ -77,6 +77,11 @@

 ;;; Real functions

+
+;; ############################################################
+;; ## Get Comic List Functions
+;; ############################################################
+
 (defn manga-url []
   (format (manga-url-format) (root-url)))

@@ -90,6 +95,61 @@
                   {url :href} :attrs}]
   {:name ((link-name-normalize) name)
    :url  ((link-url-normalize)  url)})
+
+(defn comic-link-add-id [{:keys [url] :as comic-map}]
+  (let [[_ data] (re-find (manga-pattern) url)]
+    (assoc comic-map
+           :id data)))
+
+(defn comic-link-normalize [link]
+  (-> link
+      link->map
+      comic-link-add-id))
+
+(defn extract-comics-list [html]
+  (scrape/extract-list html
+                       (comic-list-selector)
+                       comic-link-normalize))
+
+(defn get-comic-list []
+  (-> (manga-list-url)
+      scrape/fetch-url
+      extract-comics-list))
+
+
+;; ############################################################
+;; ## Get Chapter List functions
+;; ############################################################
+
+(defn chapter-link-add-ch-num [{:keys [url]
+                                :as comic-map}]
+  (let [[_ data] (re-find (chapter-number-match-pattern) url)]
+    (assoc comic-map
+           :ch-num (safe-read-string data))))
+
+(defn chapter-link-normalize [link]
+  (-> link
+      link->map
+      chapter-link-add-ch-num))
+
+(defn extract-chapters-list [html comic-url]
+  (scrape/extract-list html
+                       (chapter-list-selector)
+                       chapter-link-normalize))
+
+(defn comic->url [comic-id]
+  (format (comic->url-format) (manga-url) comic-id))
+
+(defn get-chapter-list [comic-id]
+  (let [comic-url (comic->url comic-id)]
+    (-> comic-url
+        scrape/fetch-url
+        (extract-chapters-list comic-url))))
+
+
+;; ############################################################
+;; ## Get Page List functions
+;; ############################################################

 (defn extract-image-tag [html]
   (scrape/extract-image-tag html (image-selector)))
@@ -112,56 +172,16 @@
                          (page-list-selector)
                          normalize)))

-(defn chapter-link-add-ch-num [{:keys [url]
-                            :as comic-map}]
-  (let [[_ data] (re-find (chapter-number-match-pattern) url)]
-    (assoc comic-map
-           :ch-num (safe-read-string data))))
-
-(defn chapter-link-normalize [link]
-  (-> link
-      link->map
-      chapter-link-add-ch-num))
-
-(defn extract-chapters-list [html comic-url]
-  (scrape/extract-list html
-                       (chapter-list-selector)
-                       chapter-link-normalize))
-
-(defn comic-link-add-id [{:keys [url] :as comic-map}]
-  (let [[_ data] (re-find (manga-pattern) url)]
-    (assoc comic-map
-           :id data)))
-
-(defn comic-link-normalize [link]
-  (-> link
-      link->map
-      comic-link-add-id))
-
-(defn extract-comics-list [html]
-  (scrape/extract-list html
-                       (comic-list-selector)
-                       comic-link-normalize))
-
-(defn comic->url [comic-id]
-  (format (comic->url-format) (manga-url) comic-id))
-
-(defn get-comic-list []
-  (-> (manga-list-url)
-      scrape/fetch-url
-      extract-comics-list))
-
-(defn get-chapter-list [comic-id]
-  (let [comic-url (comic->url comic-id)]
-    (-> comic-url
-        scrape/fetch-url
-        (extract-chapters-list comic-url))))
-
 (defn get-page-list [comic-chapter]
   (let [chapter-url (:url comic-chapter)]
     (-> chapter-url
         scrape/fetch-url
         (extract-pages-list chapter-url))))

+
+;; ############################################################
+;; ## Get Image Data functions
+;; ############################################################
+
 (defn get-image-data [comic-id chapter page]
   [])


Changed pushgp params of bioavailability problem to match origin paper.

--- src/clojush/examples/bioavailability.clj
+++ src/clojush/examples/bioavailability.clj
@@ -135,11 +135,9 @@
   :evalpush-limit 500
   :population-size 500
   :max-generations 100
-  :mutation-probability 0.1
-  :crossover-probability 0.8
-  :simplification-probability 0.05
-  :tournament-size 6
-  :trivial-geography-radius 10
+  :mutation-probability 0.09
+  :crossover-probability 0.81
+  :tournament-size 10
   :node-selection-method :size-tournament
   :node-selection-tournament-size 2
   :report-simplifications 0


Doubled max points

Doubled max points

--- src/clojush/problems/synthetic/order.clj
+++ src/clojush/problems/synthetic/order.clj
@@ -43,7 +43,7 @@
     (reset! global-problem-size size)
     (println "problem-size =" size)
     (def argmap
-      {:max-points (* 10 2 size)
+      {:max-points (* 10 4 size)
        :max-genome-size-in-initial-program (* 10 size)
        :error-function order-fitness
        :atom-generators atom-generators


Add :autoconstruction-aware diversification constraint

--- src/clojush/pushgp/genetic_operators.clj
+++ src/clojush/pushgp/genetic_operators.clj
@@ -1109,6 +1109,15 @@
                  (not (:silent instruction-map))))
           (:genome ind))))

+(defn autoconstruction-aware-diversifying?
+  [ind argmap]
+  (assoc ind :diversifying
+    (some (fn [instruction-map]
+            (and (not (:silent instruction-map))
+                 (or (= (:instruction instruction-map) 'genome_autoconstructing)
+                     (= (:instruction instruction-map) 'genome_if_autoconstructing))))
+          (:genome ind))))
+
 (defn diversifying?
   "Returns ind with :diversifying set to true if it staisfies all test
   specified in (:autoconstructive-diversification-test argmap), or false
@@ -1139,6 +1148,7 @@
                 :new-instruction-diversifying new-instruction-diversifying?
                 :new-size-diversifying new-size-diversifying?
                 :checks-autoconstructing checks-autoconstructing-diversifying?
+                :autoconstruction-aware autoconstruction-aware-diversifying?
                 :none (fn [ind argmap] i))
               i
               argmap)


Pass histories of parents to diversification tests, and provide tests that use them

--- src/clojush/pushgp/genetic_operators.clj
+++ src/clojush/pushgp/genetic_operators.clj
@@ -1003,6 +1003,36 @@
            (and (not= pgm parent1-pgm)
                 (not= pgm parent2-pgm)))))

+(defn lineage-behavior-diversifying?
+  [ind argmap]
+  (if (not (:print-history argmap))
+    (throw
+     (Exception.
+      ":print-history must be true for :lineage-behavior diversification test"))
+    (assoc ind :diversifying
+           (let [hist (:parent1-history argmap)]
+             (or (< (count hist) 2)
+                 (apply distinct? hist))))))
+
+(defn new-errors-diversifying?
+  [ind argmap]
+  (if (not (:print-history argmap))
+    (throw
+     (Exception.
+      ":print-history must be true for :new-errors diversification test"))
+    (let [errs (or (:errors ind)
+                   (do
+                     (swap! evaluations-count inc)
+                     (:errors ((:error-function argmap)
+                               {:genome (:genome ind)
+                                :program (translate-plush-genome-to-push-program
+                                          {:genome (:genome ind)}
+                                          argmap)}))))]
+      (assoc ind :diversifying
+             (let [hist (:parent1-history argmap)]
+               (or (< (count hist) 2)
+                   (not (some #{errs} hist))))))))
+
 (defn not-empty-diversifying?
   [ind argmap]
   (do ;#(do (println %) %)
@@ -1766,9 +1796,11 @@
                 :doesnt-clone-genetically doesnt-clone-genetically-diversifying?
                 :child-doesnt-clone child-doesnt-clone-diversifying?
                 :not-a-clone not-a-clone-diversifying?
+                :lineage-behavior lineage-behavior-diversifying?
                 :not-empty not-empty-diversifying?
                 :minimum-genetic-difference minimum-genetic-difference-diversifying?
                 :different-errors different-errors-diversifying?
+                :new-errors new-errors-diversifying?
                 :new-instruction new-instruction-diversifying?
                 :lost-instruction lost-instruction-diversifying?
                 :different-instructions different-instructions-diversifying?
@@ -1811,7 +1843,9 @@
                                    (assoc :parent1-genome parent1-genome)
                                    (assoc :parent2-genome parent2-genome)
                                    (assoc :parent1-errors (:errors parent1))
-                                   (assoc :parent2-errors (:errors parent2))))]
+                                   (assoc :parent2-errors (:errors parent2))
+                                   (assoc :parent1-history (:history parent1))
+                                   (assoc :parent2-history (:history parent2))))]
     (if (:diversifying checked)
       (assoc (make-individual :genome child-genome
                               :errors (:errors checked)


Exclude ctim tutorial from trojan scan (#1300)

Same as https://github.com/advthreat/iroh/commit/2a7bd955aae34d166ec58cb1453fd95e65b9e7d1

[§](#qa) QA
============================

No QA is needed.

[§](#release-notes) Release Notes
=============================================================

```
intern: Exclude ctim tutorial from trojan scan
```

[§](#squashed-commits) Squashed Commits
======================================================================

--- scripts/uberjar-trojan-scan.clj
+++ scripts/uberjar-trojan-scan.clj
@@ -38,6 +38,7 @@
    "org/xerial/snappy/native/Linux/android-arm/libsnappyjava.so"
    "org/xerial/snappy/native/Linux/ppc64le/libsnappyjava.so"
    "org/xerial/snappy/native/Windows/x86/snappyjava.dll"
+   "tutorials/threat-context/*.png" ;; ctim

    ;; :/
    "goog/i18n/datetimepatternsext.js"


Remove jobs-by-user-and-state (#1048)

Remove jobs-by-user-and-state (#1048)

--- scheduler/src/cook/mesos/util.clj
+++ scheduler/src/cook/mesos/util.clj
@@ -471,24 +471,6 @@
            (take limit)
            doall))))

-
-(defn jobs-by-user-and-state
-  "Returns all job entities for a particular user
-   in a particular state.  Unlike get-jobs-by-user-and-state, doesn't
-  impose any other conditions."
-  [db user state pool-name]
-  (let [requesting-default-pool? (pool/requesting-default-pool? pool-name)
-        pool-name' (pool/pool-name-or-default pool-name)]
-    (->> (q '[:find [?j ...]
-              :in $ ?user ?state ?pool-name ?requesting-default-pool
-              :where
-              [?j :job/state ?state]
-              [?j :job/user ?user]
-              [(cook.mesos.pool/check-pool $ ?j :job/pool ?pool-name ?requesting-default-pool)]]
-            db user state pool-name' requesting-default-pool?)
-         (map (partial d/entity db))
-         (map d/touch))))
-
 (timers/deftimer [cook-mesos scheduler get-running-tasks-duration])

 (defn get-running-task-ents
@@ -817,4 +799,4 @@
   "Returns a sequence of date-time values growing over specific period.
    Takes as input the starting value and the growing value, returning a lazy infinite sequence."
   [start ^ReadablePeriod period]
-  (iterate (fn [^DateTime t] (.plus t period)) start))+  (iterate (fn [^DateTime t] (.plus t period)) start))


CMR-7071: Fixed subscription ingest tests failing on master.

--- system-int-test/test/cmr/system_int_test/ingest/subscription_ingest_test.clj
+++ system-int-test/test/cmr/system_int_test/ingest/subscription_ingest_test.clj
@@ -169,32 +169,13 @@

 ;; Verify that the accept header works with returned errors
 (deftest subscription-ingest-with-errors-accept-header-test
-  (testing "json response, with no token"
+  (testing "json response"
     (let [concept-no-metadata (assoc (subscription-util/make-subscription-concept)
                                      :metadata "")
           response (ingest/ingest-concept
                     concept-no-metadata
                     {:accept-format :json
                      :raw? true})
-          {:keys [errors]} (ingest/parse-ingest-body :json response)]
-      (is (re-find #"You do not have permission to perform that action." (first errors)))))
-  (testing "xml response, with no token"
-    (let [concept-no-metadata (assoc (subscription-util/make-subscription-concept)
-                                     :metadata "")
-          response (ingest/ingest-concept
-                    concept-no-metadata
-                    {:accept-format :xml
-                     :raw? true})
-          {:keys [errors]} (ingest/parse-ingest-body :xml response)]
-      (is (re-find #"You do not have permission to perform that action." (first errors)))))
-  (testing "json response"
-    (let [concept-no-metadata (assoc (subscription-util/make-subscription-concept)
-                                     :metadata "")
-          response (ingest/ingest-concept
-                    concept-no-metadata
-                    {:accept-format :json
-                     :raw? true
-                     :token "mock-echo-system-token"})
           {:keys [errors]} (ingest/parse-ingest-body :json response)]
       (is (re-find #"required key \[Name\] not found" (first errors)))))
   (testing "xml response"
@@ -203,8 +184,7 @@
           response (ingest/ingest-concept
                     concept-no-metadata
                     {:accept-format :xml
-                     :raw? true
-                     :token "mock-echo-system-token"})
+                     :raw? true})
           {:keys [errors]} (ingest/parse-ingest-body :xml response)]
       (is (re-find #"required key \[Name\] not found" (first errors))))))


clearing print

clearing print

--- test/celestial/integration/es/systems.clj
+++ test/celestial/integration/es/systems.clj
@@ -18,7 +18,6 @@
   (sys/put "2" redis-ec2-spec)
   (sys/put "3" (assoc redis-ec2-spec :env :prod-1))
   (sys/put "4" redis-prox-spec :flush? true)
-  (println "damn!")
   )

 (defn total [res] (get-in res [:hits :total]))


Pass terminal? fns round, not namespaces.

--- test/kolmogorov_music/test/kolmogorov.clj
+++ test/kolmogorov_music/test/kolmogorov.clj
@@ -60,13 +60,13 @@

 (defn enterprise*
   "Find the first natural number with a complexity greater than f."
-  [expr ns]
+  [expr terminal?]
   (->> (kolmogorov/monocon)
-       (first-that #(more-complex-than? % (kolmogorov/complexity* expr (kolmogorov/relative-to ns))))))
+       (first-that #(more-complex-than? % (kolmogorov/complexity* expr terminal?)))))

 (defmacro enterprise
   [expr]
-  (enterprise* expr *ns*))
+  (enterprise* expr (kolmogorov/relative-to *ns*)))

 (defn yo-dawg []
   (enterprise enterprise))


Allow connector subtype to redefine identifier (#1476)

* Allow connector subtype to redefine identifier

* minor refactor of set-operations

--- cimi-resources/src/com/sixsq/slipstream/ssclj/resources/connector.clj
+++ cimi-resources/src/com/sixsq/slipstream/ssclj/resources/connector.clj
@@ -146,10 +146,19 @@
 ;; use name as the identifier
 ;;

-(defmethod crud/new-identifier resource-name
+(defmulti new-identifier-subtype
+          (fn [resource _] (:cloudServiceType resource)))
+
+(defmethod new-identifier-subtype :default
   [resource resource-name]
   (if-let [new-id (:instanceName resource)]
     (assoc resource :id (str (u/de-camelcase resource-name) "/" new-id))))
+
+
+(defmethod crud/new-identifier resource-name
+  [resource resource-name]
+  (new-identifier-subtype resource resource-name))
+

 ;;; Activate operation

@@ -175,6 +184,7 @@

 ;;; Quarantine operation
+
 (defmulti quarantine-subtype
           (fn [resource _] (:cloudServiceType resource)))

@@ -194,6 +204,9 @@
           (quarantine-subtype request)))
     (catch ExceptionInfo ei
       (ex-data ei))))
+
+
+;;; Describe operation

 (defmethod crud/do-action [resource-url "describe"]
   [{{uuid :uuid} :params :as request}]
@@ -207,6 +220,8 @@
     (catch ExceptionInfo ei
       (ex-data ei))))

+;;; set subtype operations
+
 (defmulti set-subtype-ops
           (fn [resource _] (:cloudServiceType resource)))

@@ -215,9 +230,9 @@
   (crud/set-standard-operations resource request))

 (defmethod crud/set-operations resource-uri
-  [{:keys [id resourceURI username connectorTemplate] :as resource} request]
-  (let [href (str id "/describe")
-        describe-op {:rel (:describe c/action-uri) :href href}]
+  [{:keys [id connectorTemplate] :as resource} request]
+  (let [describe-href (str id "/describe")
+        describe-op {:rel (:describe c/action-uri) :href describe-href}]
     (cond-> (set-subtype-ops resource request)
-            (get connectorTemplate :href) (update-in [:operations] conj describe-op))))
-
+            (:href connectorTemplate) (update-in [:operations] conj describe-op))))
+


SQUASH ME -- improve debug message in fileset commit

--- boot/pod/src/boot/tmpdir.clj
+++ boot/pod/src/boot/tmpdir.clj
@@ -232,10 +232,11 @@
           {:keys [added removed changed]} (diff* prev this [:id :dir])]
       (util/dbug "Committing fileset...\n")
       (doseq [tmpf (set/union (ls removed) (ls changed))
-              :let [prev (get-in prev [:tree (path tmpf)])]]
-        (when (.exists ^File (file prev))
-          (util/dbug "Commit: removing %s %s...\n" (id prev) (path prev))
-          (file/delete-file (file prev))))
+              :let [prev (get-in prev [:tree (path tmpf)])
+                    exists? (.exists ^File (file prev))
+                    op (if exists? "removing" "no-op")]]
+        (util/dbug "Commit: %-8s %s %s...\n" op (id prev) (path prev))
+        (when exists? (file/delete-file (file prev))))
       (let [this (loop [this this
                         [tmpf & tmpfs]
                         (->> (set/union (ls added) (ls changed))


use `:show-sql-fn` from Clj-DBSpec to print SQL

--- src/main/clj/org/bituf/fountain/jdbc.clj
+++ src/main/clj/org/bituf/fountain/jdbc.clj
@@ -14,7 +14,7 @@

 (def ^{:doc "Fountain-JDBC version (only major and minor)"}
-      version [0 1])
+      version [0 2])

 (defn make-sjtspec
@@ -58,7 +58,7 @@
   "Print the SQL statement if the *show-sql* flag is true."
   [sql]
   (when (:show-sql sp/*dbspec*)
-    (println sql)))
+    ((:show-sql-fn sp/*dbspec*) sql)))

 (defmacro with-query-args


Show number of crossings per ordering attempt

--- examples/asoiaf/agot/devcards/agot/cards.cljs
+++ examples/asoiaf/agot/devcards/agot/cards.cljs
@@ -218,18 +218,18 @@
         input->SparseGraph
         ord/SparseGraph->ordered-graphs
         (map ord/OrderedGraph->FlatGraph)
-        (map #(plot % max-slope min-arc-radius layer-sep node-sep char-sep)))))
+        (map #(-> [% (plot % max-slope min-arc-radius layer-sep node-sep char-sep)])))))

 (defn ordering-component
   []
   [:div
    (map-indexed
-    (fn [i {:keys [min-x min-y max-x max-y plots]}]
+    (fn [i [{:keys [crossings]} {:keys [min-x min-y max-x max-y plots]}]]
       (let [width (- max-x min-x)
             height (- max-y min-y)]
         ^{:key (str "ordering-" i)}
         [:div {:style {:margin-bottom "20px"}}
-         [:h3 (inc i) " " (if (even? i) "Forward" "Reverse")]
+         [:h3 (inc i) " " (if (even? i) "Forward" "Reverse") ", " crossings " crossings"]
          [:svg {:viewBox (s/join " " [min-x min-y width height])}
           (map #(let [{:keys [plots character]} %
                       d (s/join " " (map defs/data->path plots))


CMR-4621: Make sure after all retries have been exhausted the request is marked as failed

--- message-queue-lib/src/cmr/message_queue/test/queue_broker_wrapper.clj
+++ message-queue-lib/src/cmr/message_queue/test/queue_broker_wrapper.clj
@@ -183,7 +183,9 @@
         (handler msg)
         (update-message-queue-history broker-wrapper queue-name :process msg :success)
         (catch Exception e
-          (update-message-queue-history broker-wrapper queue-name :process msg :retry)
+          ;; Will return a retry up to the retry count and then a failure afterwards
+          (let [message-state (queue-response->message-state :retry msg)]
+            (update-message-queue-history broker-wrapper queue-name :process msg message-state))
           (throw e))))))

 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;