(PCP-737) Handle events on stale controller connections too

A recent commit made sure events on stale connection are handled gracefully.
(A stale connection meaning a connection which is not present in the broker's
inventory any longer.) But it failed to address similar problem on controller
connections which are kept in a separate inventory / registry.
So this commit makes sure even events on stale controller connections are
handled gracefully.

--- src/puppetlabs/pcp/broker/core.clj
+++ src/puppetlabs/pcp/broker/core.clj
@@ -590,39 +590,48 @@
    whitelist :- #{s/Str}
    client :- Client
    message :- Message]
-  (let [uri (ws->uri client)
-        connection (get-controller broker uri)
-        message (assoc-when message :sender uri :target "pcp:///server")
-        message-data (merge (connection/summarize connection) (summarize message))]
-    (time!
-     (:on-message (:metrics broker))
+  (let [uri (ws->uri client)]
+    (if-let [connection (get-controller broker uri)]
+      (let [message (assoc-when message :sender uri :target "pcp:///server")
+            message-data (merge (connection/summarize connection) (summarize message))]
+        (time!
+         (:on-message (:metrics broker))
+          (sl/maplog :trace {:type :controller-message-trace
+                             :uri uri
+                             :rawmsg message}
+                     ;; 0 : uri
+                     ;; 1 : raw message
+                     #(i18n/trs "Received PCP message from {0}: {1}"
+                       (:uri %) (:rawmsg %)))
+          (cond
+            ;; only accept messages from the sender
+            (not (authenticated? message connection))
+            (do
+              (log-access :warn (assoc message-data :accessoutcome "AUTHENTICATION_FAILURE"))
+              (send-error-message message (i18n/trs "Message not authenticated.") connection))
+
+            ;; deny messages unless in `whitelist`
+            (not (contains? whitelist (:message_type message)))
+            (do
+              (log-access :warn (assoc message-data :accessoutcome "AUTHORIZATION_FAILURE"))
+              ;; TODO(ale): use 'unauthorized' in version 2
+              (send-error-message message (i18n/trs "Message not authorized.") connection))
+
+            :else
+            (do
+              (log-access :info (assoc message-data :accessoutcome "AUTHORIZATION_SUCCESS"))
+              (if (= (:target message) "pcp:///server")
+                (process-server-message! broker message connection)
+                (deliver-message broker message connection))))))
       (sl/maplog :trace {:type :controller-message-trace
                          :uri uri
+                         :remoteaddress (ws->remote-address client)
                          :rawmsg message}
-                 ;; 0 : uri
-                 ;; 1 : raw message
-                 #(i18n/trs "Received PCP message from {0}: {1}"
-                   (:uri %) (:rawmsg %)))
-      (cond
-        ;; only accept messages from the sender
-        (not (authenticated? message connection))
-        (do
-          (log-access :warn (assoc message-data :accessoutcome "AUTHENTICATION_FAILURE"))
-          (send-error-message message (i18n/trs "Message not authenticated.") connection))
-
-        ;; deny messages unless in `whitelist`
-        (not (contains? whitelist (:message_type message)))
-        (do
-          (log-access :warn (assoc message-data :accessoutcome "AUTHORIZATION_FAILURE"))
-          ;; TODO(ale): use 'unauthorized' in version 2
-          (send-error-message message (i18n/trs "Message not authorized.") connection))
-
-        :else
-        (do
-          (log-access :info (assoc message-data :accessoutcome "AUTHORIZATION_SUCCESS"))
-          (if (= (:target message) "pcp:///server")
-            (process-server-message! broker message connection)
-            (deliver-message broker message connection)))))))
+                 ;; 0 : uri of connection
+                 ;; 1 : remote address of connection
+                 ;; 2 : raw message
+                 #(i18n/trs "Ignoring message received on stale controller connection {0} {1}: {2}"
+                            (:uri %) (:remoteaddress %) (:rawmsg %))))))

 (defn maybe-purge-clients!
   "After having slept for the grace period, if all controllers are still


(PDB-3935) warn-retirements: check option via contains? not get-in

--- src/puppetlabs/puppetdb/config.clj
+++ src/puppetlabs/puppetdb/config.clj
@@ -337,14 +337,14 @@
   process if a [global] url-prefix is found."
   [config-data]

-  (doseq [[section opt :as path] [[:command-processing :max-frame-size]
-                                  [:command-processing :memory-usage]
-                                  [:command-processing :store-usage]
-                                  [:command-processing :temp-usage]
-                                  [:database :classname]
-                                  [:database :subprotocol]
-                                  [:global :catalog-hash-conflict-debugging]]]
-    (when (get-in config-data path)
+  (doseq [[section opt] [[:command-processing :max-frame-size]
+                         [:command-processing :memory-usage]
+                         [:command-processing :store-usage]
+                         [:command-processing :temp-usage]
+                         [:database :classname]
+                         [:database :subprotocol]
+                         [:global :catalog-hash-conflict-debugging]]]
+    (when (contains? (config-data section) opt)
       (utils/println-err
        (trs "The [{0}] {1} config option has been retired and will be ignored."
             (name section) (name opt)))))


Fix paths to vexflow items

Fix paths to vexflow items

--- src/cljs/daveconservatoire/site/ui/vexflow.cljs
+++ src/cljs/daveconservatoire/site/ui/vexflow.cljs
@@ -52,8 +52,8 @@

 (defn render-score [{:keys [::bars ::width ::height ::clef ::scale ::backend]} container]
   (let [Renderer (gobj/getValueByKeys js/window #js ["Vex" "Flow" "Renderer"])
-        Stave (gobj/getValueByKeys js/window #js ["Vex" "Stave"])
-        StaveNote (gobj/getValueByKeys js/window #js ["Vex" "StaveNote"])
+        Stave (gobj/getValueByKeys js/window #js ["Vex" "Flow" "Stave"])
+        StaveNote (gobj/getValueByKeys js/window #js ["Vex" "Flow" "StaveNote"])
         renderer (Renderer. container (backend-renderer backend))
         ctx (js-call renderer "getContext")
         scale (or scale 1)


Tweaked function calls after removing duplicate function in datetime ns

--- src/clj/forma/hadoop/jobs/cdm.clj
+++ src/clj/forma/hadoop/jobs/cdm.clj
@@ -97,7 +97,7 @@
         (o/clean-probs ?prob-series nodata :> ?clean-series)
         (first-hit thresh ?clean-series :> ?first-hit-idx)
         (+ start-period ?first-hit-idx :> ?period)
-        (date/convert-period-res tres tres-out ?period :> ?period-new-res)
+        (date/shift-resolution tres tres-out ?period :> ?period-new-res)
         (- ?period-new-res epoch :> ?rp)
         (min-period ?rp :> ?p)
         (r/modis->latlon ?sres ?modh ?modv ?s ?l :> ?lat ?lon)
@@ -126,7 +126,7 @@
         (o/clean-probs ?prob-series nodata :> ?clean-series)
         (first-hit thresh ?clean-series :> ?first-hit-idx)
         (+ start-period ?first-hit-idx :> ?period)
-        (date/convert-period-res tres tres-out ?period :> ?period-new-res)
+        (date/shift-resolution tres tres-out ?period :> ?period-new-res)
         (- ?period-new-res epoch :> ?rp)
         (min-period ?rp :> ?p)
         (:trap (hfs-seqfile "s3n://formatemp/output/spark-trapped")))))
@@ -150,7 +150,7 @@
         (o/clean-probs ?prob-series nodata :> ?clean-series)
         (first-hit thresh ?clean-series :> ?first-hit-idx)
         (+ ?start-idx ?first-hit-idx :> ?period)
-        (date/convert-period-res t-res t-res-out ?period :> ?period-new-res)
+        (date/shift-resolution t-res t-res-out ?period :> ?period-new-res)
         (- ?period-new-res epoch :> ?cdm-period)
         (date/period->datetime t-res-out ?period-new-res :> ?date-str)
         (c/count ?count))))


implement Dedication Ceremony and Heritage Committee

--- src/clj/game/cards-operations.clj
+++ src/clj/game/cards-operations.clj
@@ -175,6 +175,12 @@
    "Cyberdex Trial"
    {:effect (effect (purge))}

+   "Dedication Ceremony"
+   {:prompt "Choose a faceup card"
+    :choices {:req rezzed?}
+    :msg (msg "place 3 advancement tokens on " (card-str state target))
+    :effect (effect (add-prop :corp target :advance-counter 3 {:placed true}))}
+
    "Defective Brainchips"
    {:events {:pre-damage {:req (req (= target :brain)) :msg "to do 1 additional brain damage"
                           :once :per-turn :effect (effect (damage-bonus :brain 1))}}}
@@ -224,6 +230,15 @@
                             (system-msg (str "adds " (:title target) " to the top of the Stack")))
             :unsuccessful {:msg "take 1 bad publicity"
                            :effect (effect (gain :corp :bad-publicity 1))}}}
+
+   "Heritage Committee"
+   {:effect (effect (draw 3)
+                    (resolve-ability
+                      {:prompt "Choose a card in HQ to put on top of R&D"
+                       :choices (req (:hand corp)) :not-distinct true
+                       :msg "draw 3 cards and add 1 card from HQ to the top of R&D"
+                       :effect (effect (move target :deck {:front true}))}
+                     card nil))}

    "Housekeeping"
    {:events {:runner-install {:req (req (= side :runner))


fix for alt art cards

fix for alt art cards

the cards are in the :cards collection multiple times
so take the one with the alt art image, if possible

--- src/cljs/netrunner/gameboard.cljs
+++ src/cljs/netrunner/gameboard.cljs
@@ -151,14 +151,25 @@
 (defn create-span [item]
   (if-let [class (anr-icons item)]
     [:span {:class (str "anr-icon " class)}]
-  (if-let [[title code] (extract-card-info item)]
+  (if-let [[title code] (extract-card-info item)]
     [:span {:class "fake-link"
             :on-mouse-enter #(put! zoom-channel {:code code})
             :on-mouse-leave #(put! zoom-channel false)} title]
   [:span item])))

+(defn get-alt-art [[title cards]]
+  (let [s (sort-by #(not= (:setname %) "Alternates") cards)]
+    {:title title :code (:code (first s))}))
+
+(defn prepare-cards []
+ (->> (:cards @app-state)
+      (group-by :title)
+      (map get-alt-art)))
+
+;;(def prepared-cards (memoize prepare-cards))
+
 (defn add-image-codes [text]
-  (reduce #(.replace %1 (js/RegExp. (str "\\b" (:title %2) "\\b") "g") (str "[" (:title %2) "~"(:code %2) "]")) text (:cards @app-state)))
+  (reduce #(.replace %1 (js/RegExp. (str "\\b" (:title %2) "\\b") "g") (str "[" (:title %2) "~"(:code %2) "]")) text (prepare-cards)))

 (defn get-message-parts [text]
   (let [with-image-codes (add-image-codes (if (nil? text) "" text))]


fix 24/7 News Cycle so Breaking News tags will stick at turn end

--- src/clj/game/cards-operations.clj
+++ src/clj/game/cards-operations.clj
@@ -10,7 +10,7 @@
                                            (= (first (:zone %)) :scored)
                                            (:abilities %))}
                       :msg (msg "trigger the \"when scored\" ability of " (:title target))
-                      :effect (effect (card-init target))}
+                      :effect (effect (resolve-ability (dissoc (card-def target) :end-turn) card nil))}
                     card nil)))}

    "Accelerated Diagnostics"


Fixed issue with last-time-ms.

Fixed issue with last-time-ms.

--- src/cljc/com/lemondronor/pid.cljc
+++ src/cljc/com/lemondronor/pid.cljc
@@ -33,10 +33,11 @@
 (defn pid
   ([state]
    (-> state
-       (assoc :i-term 0 :last-input 0 :last-time-ms 0 :last-value 0)
+       (assoc :i-term 0 :last-input 0 :last-time-ms nil :last-value 0)
        (set-tunings (:kp state) (:ki state) (:kd state))))
   ([state time-ms value]
-   (if (>= (- time-ms (:last-time-ms state)) (:period-ms state))
+   (if (or (nil? (:last-time-ms state))
+           (>= (- time-ms (:last-time-ms state)) (:period-ms state)))
      (let [{:keys [set-point kp kd ki i-term last-input bounds]} state
            [in-min in-max out-min out-max] bounds
            value (scale (clamp value in-min in-max) in-min in-max -1.0 1.0)


added inifinity bucket for that stuff that is older than dirt also initially limiting the album count for renderring to the most recent 500

--- src/cljs/apollo/client/pages.cljs
+++ src/cljs/apollo/client/pages.cljs
@@ -73,7 +73,8 @@
                    {:date (-> 6 t/months t/ago t/at-midnight) :label "4 - 6 Months"}
                    {:date (-> 1 t/years t/ago t/at-midnight) :label "7 months -  Year"}
                    {:date (-> 3 t/years t/ago t/at-midnight) :label "1 - 3 Years"}
-                   {:date (-> 5 t/years t/ago t/at-midnight) :label "4 - 5 Years"}])
+                   {:date (-> 5 t/years t/ago t/at-midnight) :label "4 - 5 Years"}
+                   {:date (-> 100 t/years t/ago t/at-midnight) :label "6+ years"}])

 (defn date-to-range-val [d]
   (:date (first (filter (fn [x] (or (t/after? d (:date x)) (t/= d (:date x)))) ageing-range))))
@@ -87,16 +88,18 @@
   (om/component
    (html
     [:span
-    [:h2 (date-to-label bucket-date)]
-    (om/build albums/album-list-partial {:artist nil :albums albums})
-    [:hr]])))
+       [:h2 (date-to-label bucket-date)]
+       (om/build albums/album-list-partial {:artist nil :albums albums})
+       [:hr]])))

 (defn view-recently-added [data owner]
   (reify
     om/IRender
     (render [this]
       (let [buckets (group-by
-                     (fn [x] (date-to-range-val (c/from-long (x "last_modified"))))
+                     (fn [x]
+                       (let [d (x "last_modified")]
+                         (date-to-range-val (c/from-long d))))
                      (take 500 (:albums data)))]
         (html [:div.browse
                (om/build nav/main-nav data)


popup-tour mostly finished

popup-tour mostly finished

--- src/cljs/cljs_repl_web/views.cljs
+++ src/cljs/cljs_repl_web/views.cljs
@@ -4,7 +4,8 @@
             [re-frame.core :refer [subscribe dispatch]]
             [re-com.core :refer [md-icon-button h-box v-box box gap button input-text
                                  popover-content-wrapper popover-anchor-wrapper hyperlink-href
-                                 popover-tooltip title label scroller line modal-panel]]
+                                 popover-tooltip title label scroller line modal-panel align-style
+                                 make-tour start-tour make-tour-nav p]]
             [re-com.box :refer [flex-child-style]]
             [re-com.util :refer [px]]
             [clairvoyant.core :refer-macros [trace-forms]]
@@ -18,6 +19,49 @@
             [re-complete.core :as re-complete]))

 ;; (set! re-com.box/debug true)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;      Tour          ;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(def tour
+  (make-tour [:step1 :step2 :step3 :step4 :step5 :step6 :step7]))
+
+(def tour-steps
+  {:step1 {:title "Tour 1 of 7"
+           :body "Start"}
+   :step2 {:title "Tour 2 of 7"
+           :body "Reset"}
+   :step3 {:title "Tour 3 of 7"
+           :body "Clear"}
+   :step4 {:title "Tour 4 of 7"
+           :body "Create Gist"}
+   :step5 {:title "Tour 5 of 7"
+           :body "Clear examples"}
+   :step6 {:title "Tour 6 of 7"
+           :body "Switch input mode"}
+   :step7 {:title "Tour 7 of 7"
+           :body "Console"}})
+
+(defn create-tour-step
+  ([step position anchor]
+   (create-tour-step step position anchor nil))
+  ([step position anchor style]
+   (let [step-keyword (keyword (str "step" step))]
+     [popover-anchor-wrapper
+      :showing? (step-keyword tour)
+      :position position
+      :anchor anchor
+      :popover [popover-content-wrapper
+                :showing? (:step2 tour)
+                :position position
+                :width    "250px"
+                :title    [:strong (get-in tour-steps [step-keyword :title])]
+                :body     [:div (get-in tour-steps [step-keyword :body])
+                           [make-tour-nav tour]]]
+      :style  (if style
+                style
+                (align-style :align-self :end))])))

 ;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;;      Buttons       ;;;
@@ -128,18 +172,27 @@
         showing? (subscribe [:gist-showing?])
         media-query (subscribe [:media-query-size])]
     (fn []
-      [popover-anchor-wrapper
-       :showing? showing?
-       :position (gist-position media-query)
-       :anchor   [md-icon-button
-                  :md-icon-name "zmdi-github"
-                  :on-click #(dispatch [:show-gist-login])
-                  :class "cljs-btn"
-                  :size (if-not (= :medium @media-query) :regular :smaller)
-                  :tooltip "Create Gist"
-                  :tooltip-position (if-not (= :narrow @media-query) :left-center :above-center)
-                  :disabled? @can-dump-gist?]
-       :popover  [gist-login-dialog-body]])))
+      (if @showing?
+        [popover-anchor-wrapper
+         :showing? showing?
+         :position (gist-position media-query)
+         :anchor   [md-icon-button
+                    :md-icon-name "zmdi-github"
+                    :on-click #(dispatch [:show-gist-login])
+                    :class "cljs-btn"
+                    :size (if-not (= :medium @media-query) :regular :smaller)
+                    :tooltip "Create Gist"
+                    :tooltip-position (if-not (= :narrow @media-query) :left-center :above-center)
+                    :disabled? @can-dump-gist?]
+         :popover  [gist-login-dialog-body]]
+        (create-tour-step 4 :below-center [md-icon-button
+                                           :md-icon-name "zmdi-github"
+                                           :on-click #(dispatch [:show-gist-login])
+                                           :class "cljs-btn"
+                                           :size (if-not (= :medium @media-query) :regular :smaller)
+                                           :tooltip "Create Gist"
+                                           :tooltip-position (if-not (= :narrow @media-query) :left-center :above-center)
+                                           :disabled? @can-dump-gist?])))))

 (defn cljs-buttons
   "Return a vector of components containing the cljs console buttons.
@@ -158,38 +211,39 @@
                           (swap! modes rest)
                           next-mode))]
     (fn cljs-buttons-form2 []
-      (let [children [[md-icon-button
-                       :md-icon-name "zmdi-delete"
-                       :on-click #(dispatch [:reset-console-items :cljs-console])
-                       :class "cljs-btn"
-                       :size (if-not (= :medium @media-query) :regular :smaller)
-                       :tooltip "Reset"
-                       :tooltip-position (if-not (= :narrow @media-query) :left-center :above-center)
-                       :disabled? (not @console-created?)]
-                      [md-icon-button
-                       :md-icon-name "zmdi-format-clear-all"
-                       :on-click #(dispatch [:clear-console-items :cljs-console])
-                       :class "cljs-btn"
-                       :size (if-not (= :medium @media-query) :regular :smaller)
-                       :tooltip "Clear"
-                       :tooltip-position (if-not (= :narrow @media-query) :left-center :above-center)
-                       :disabled? (not @console-created?)]
+      (let [children [(create-tour-step 2 :below-center
+                                        [md-icon-button
+                                         :md-icon-name "zmdi-delete"
+                                         :on-click #(dispatch [:reset-console-items :cljs-console])
+                                         :class "cljs-btn"
+                                         :size (if-not (= :medium @media-query) :regular :smaller)
+                                         :tooltip "Reset"
+                                         :tooltip-position (if-not (= :narrow @media-query) :left-center :above-center)
+                                         :disabled? (not @console-created?)])
+                      (create-tour-step 3 :below-center [md-icon-button
+                                                         :md-icon-name "zmdi-format-clear-all"
+                                                         :on-click #(dispatch [:clear-console-items :cljs-console])
+                                                         :class "cljs-btn"
+                                                         :size (if-not (= :medium @media-query) :regular :smaller)
+                                                         :tooltip "Clear"
+                                                         :tooltip-position (if-not (= :narrow @media-query) :left-center :above-center)
+                                                         :disabled? (not @console-created?)])
                       [gist-login-dialog]
-                      [md-icon-button
-                       :md-icon-name "zmdi-stop"
-                       :on-click #(dispatch [:clear-console-queued-forms :cljs-console])
-                       :class "cljs-btn"
-                       :size (if-not (= :medium @media-query) :regular :smaller)
-                       :tooltip "Clear examples"
-                       :tooltip-position (if-not (= :narrow @media-query) :left-center :above-center)
-                       :disabled? (not @example-mode?)]
-                      [md-icon-button
-                       :md-icon-name "zmdi-keyboard"
-                       :on-click #(dispatch [:switch-console-mode (get-next-mode)])
-                       :class "cljs-btn"
-                       :size (if-not (= :medium @media-query) :regular :smaller)
-                       :tooltip "Switch input mode"
-                       :tooltip-position (if-not (= :narrow @media-query) :left-center :above-center)]]]
+                      (create-tour-step 5 :below-center [md-icon-button
+                                                         :md-icon-name "zmdi-stop"
+                                                         :on-click #(dispatch [:clear-console-queued-forms :cljs-console])
+                                                         :class "cljs-btn"
+                                                         :size (if-not (= :medium @media-query) :regular :smaller)
+                                                         :tooltip "Clear examples"
+                                                         :tooltip-position (if-not (= :narrow @media-query) :left-center :above-center)
+                                                         :disabled? (not @example-mode?)])
+                      (create-tour-step 6 :below-center [md-icon-button
+                                                         :md-icon-name "zmdi-keyboard"
+                                                         :on-click #(dispatch [:switch-console-mode (get-next-mode)])
+                                                         :class "cljs-btn"
+                                                         :size (if-not (= :medium @media-query) :regular :smaller)
+                                                         :tooltip "Switch input mode"
+                                                         :tooltip-position (if-not (= :narrow @media-query) :left-center :above-center)])]]
         (if-not (= :narrow @media-query)
           [v-box
            :gap "8px"
@@ -566,12 +620,23 @@
   (let [media-query (subscribe [:media-query-size])
         console (console/console console-key opts)]
     (fn repl-component-form2 []
-      (let [children [[cljs-buttons]
+      (let [children [(create-tour-step 1
+                                        :above-center
+                                        [button
+                                         :label    "Start Tour!"
+                                         :on-click #(start-tour tour)
+                                         :style    {:font-weight "bold" :color "yellow"}
+                                         :class    "btn-info"]
+                                        {:width     "34px"
+                                         :font-size "26px"
+                                         :position  "absolute"
+                                         :top       "240px"
+                                         :left      "250px"})
+                      [cljs-buttons]
                       [box
                        :size "0 0 auto"
-                       :child [console]]
-                      [re-complete/completions console-key #(do (dispatch [:console-set-autocompleted-text console-key])
-                                                                (dispatch [:focus-console-editor console-key]))]]]
+                       :child
+                       (create-tour-step 7 :above-center [console])]]]
         (if (= :narrow @media-query)
           [v-box
            :size "1 1 auto"


Rewrite throttling

Rewrite throttling

--- src/cljs/clojuredocs/widgets.cljs
+++ src/cljs/clojuredocs/widgets.cljs
@@ -298,29 +298,6 @@
   (navigate-to (:href ac-result))
   false)

-;; from https://github.com/swannodette/async-tests
-
-(defn throttle
-  ([source msecs]
-     (throttle (chan) source msecs))
-  ([c source msecs]
-     (go
-       (loop [state ::init last nil cs [source]]
-         (let [[_ sync] cs]
-           (let [[v sc] (alts! cs)]
-             (condp = sc
-               source (condp = state
-                        ::init (do (>! c v)
-                                   (recur ::throttling last
-                                     (conj cs (timeout msecs))))
-                        ::throttling (recur state v cs))
-               sync (if last
-                      (do (>! c last)
-                          (recur state nil
-                            (conj (pop cs) (timeout msecs))))
-                      (recur ::init last (pop cs))))))))
-     c))
-
 (defn maybe-nav [e app ac-results]
   (when app
     (let [ctrl? (.-ctrlKey e)
@@ -341,17 +318,17 @@
         (when (not (= identity f))
           false)))))

+(defn throttle [ms f]
+  (let [timer (atom nil)]
+    (fn [e]
+      (.persist e)
+      (js/clearTimeout @timer)
+      (reset! timer (js/setTimeout #(f e) ms)))))
+
 (defn quick-search [{:keys [highlighted-index loading? ac-results] :as app} owner]
   (reify
-    om/IWillMount
-    (will-mount [_]
-      (let [text-chan (or (om/get-state owner :text-chan) (chan))
-            internal-text-chan (chan)
-            throttled (throttle internal-text-chan 250)]
-        (pipe throttled text-chan)
-        (om/set-state! owner :internal-text-chan internal-text-chan)))
     om/IRenderState
-    (render-state [this {:keys [internal-text-chan text]}]
+    (render-state [this {:keys [text-chan text]}]
       (dom/form {:class "search" :autoComplete "off"
                  ;; the search widget should prob not need to know about
                  ;; autocomplete results (or act on them)
@@ -360,7 +337,7 @@
                     :placeholder "Looking for? (ctrl-s)"
                     :name "query"
                     :autoComplete "off"
-                    :on-input #(put-text % internal-text-chan owner)
+                    :on-input (throttle 200 #(put-text % text-chan owner))
                     :on-key-down #(maybe-nav % app ac-results)})))))

 (defn ac-results [{:keys [highlighted-index ac-results]
@@ -392,13 +369,6 @@
                      :as app}
                     owner]
   (reify
-    om/IWillMount
-    (will-mount [_]
-      (let [text-chan (or (om/get-state owner :text-chan) (chan))
-            internal-text-chan (chan)
-            throttled (throttle internal-text-chan 250)]
-        (pipe throttled text-chan)
-        (om/set-state! owner :internal-text-chan internal-text-chan)))
     om/IDidUpdate
     (did-update [_ prev-props prev-state]
       (when (and (not= (:highlighted-index prev-props)
@@ -406,7 +376,7 @@
                  (> (count ac-results) 0))
         (anim/scroll-into-view (om/get-node owner (:highlighted-index app)) {:pad 30})))
     om/IRenderState
-    (render-state [this {:keys [internal-text-chan text]}]
+    (render-state [this {:keys [text-chan text]}]
       (dom/form {:class "search"
                  :autoComplete "off"
                  :on-submit #(search-submit (nth ac-results highlighted-index))}
@@ -415,7 +385,7 @@
                     :name "query"
                     :autoComplete "off"
                     :autoFocus "autofocus"
-                    :on-input #(put-text % internal-text-chan owner)
+                    :on-input (throttle 200 #(put-text % text-chan owner))
                     :on-key-down #(maybe-nav % app ac-results)})
         (dom/ul {:class "ac-results"}
           (map-indexed


Use byddy.crypto utils function for get a byte array from string on make-secret-key function.

--- src/clojure/buddy/crypto/keys.clj
+++ src/clojure/buddy/crypto/keys.clj
@@ -1,10 +1,11 @@
 (ns buddy.crypto.keys
+  (:require [buddy.crypto.core :refer [str->bytes]])
   (:import java.security.Key))

 (defn make-secret-key
   "Generates a Key instance from given raw string key."
   [^String skey]
-  (let [rawkey (.getBytes skey "UTF-8")]
+  (let [rawkey (str->bytes skey)]
     (proxy [Key] []
       (getFormat [] nil)
       (getEncoded [] rawkey)


Java 12

Java 12

--- src/clojure/nossal/shop/spec.cljc
+++ src/clojure/nossal/shop/spec.cljc
@@ -40,7 +40,7 @@
 (s/def ::images (s/coll-of uri? :kind vector? :distinct true :into []))
 (s/def ::characteristics (s/and
                           (s/map-of ::name ::description)
-                          #(instance? PersistentTreeMap %)))
+                          #(instance? clojure.lang.PersistentTreeMap %)))

 (s/def ::variant (s/keys :req [::id
                                ::name
@@ -67,7 +67,7 @@
                          :opt-un [::variants]))
 (s/def ::products (s/and
                    (s/map-of ::id ::product)
-                   #(instance? PersistentTreeMap %)))
+                   #(instance? clojure.lang.PersistentTreeMap %)))

 (s/def ::basket-item (s/keys :req-un [::product ::quantity]))
 (s/def ::basket-itens (s/coll-of ::basket-item :kind vector? :distinct true :into []))


Refactorint rest-api-test, added tests for get-running-jobs etc.

--- test/emender_jenkins/rest_api_test.clj
+++ test/emender_jenkins/rest_api_test.clj
@@ -643,12 +643,55 @@

 (def building-jobs-jenkins-response
-    (str
-    "{\"_class\":\"hudson.model.ListView\","
-    "\"jobs\":["
-        "{\"_class\":\"hudson.model.FreeStyleProject\",\"name\":\"test-Example_Documentation-1.0-Guide-en-US (preview)\",\"url\":\"http://10.20.30.40:8080/job/test-Example_Documentation-1.0-Guide-en-US%20(preview)/\",\"buildable\":true,\"color\":\"yellow_anime\",\"lastSuccessfulBuild\":{\"_class\":\"hudson.model.FreeStyleBuild\",\"description\":\"Total: 4  Passed: 1  Failed: 3\"},\"scm\":{\"_class\":\"hudson.plugins.git.GitSCM\",\"userRemoteConfigs\":[{\"url\":\"git@git.domain.name:example-documentation/guide.git\"}]}},"
-        "{\"_class\":\"hudson.model.FreeStyleProject\",\"name\":\"test-Example_Documentation-1.0-Guide-en-US (stage)\",\"url\":\"http://10.20.30.40:8080/job/test-Example_Documentation-1.0-Guide-en-US%20(stage)/\",\"buildable\":true,\"color\":\"yellow_anime\",\"lastSuccessfulBuild\":{\"_class\":\"hudson.model.FreeStyleBuild\",\"description\":\"Total: 4  Passed: 1  Failed: 3\"},\"scm\":{\"_class\":\"hudson.plugins.git.GitSCM\",\"userRemoteConfigs\":[{\"url\":\"git@git.domain.name:example-documentation/guide.git\"}]}}"
-        "]}"))
+    (str "{\"_class\":\"hudson.model.ListView\","
+          "\"jobs\":["
+          "{\"_class\":\"hudson.model.FreeStyleProject\",\"name\":\"test-Example_Documentation-1.0-Guide-en-US (preview)\",\"url\":\"http://10.20.30.40:8080/job/test-Example_Documentation-1.0-Guide-en-US%20(preview)/\",\"buildable\":true,\"color\":\"yellow_anime\",\"lastSuccessfulBuild\":{\"_class\":\"hudson.model.FreeStyleBuild\",\"description\":\"Total: 4  Passed: 1  Failed: 3\"},\"scm\":{\"_class\":\"hudson.plugins.git.GitSCM\",\"userRemoteConfigs\":[{\"url\":\"git@git.domain.name:example-documentation/guide.git\"}]}},"
+          "{\"_class\":\"hudson.model.FreeStyleProject\",\"name\":\"test-Example_Documentation-1.0-Guide-en-US (stage)\",\"url\":\"http://10.20.30.40:8080/job/test-Example_Documentation-1.0-Guide-en-US%20(stage)/\",\"buildable\":true,\"color\":\"yellow_anime\",\"lastSuccessfulBuild\":{\"_class\":\"hudson.model.FreeStyleBuild\",\"description\":\"Total: 4  Passed: 1  Failed: 3\"},\"scm\":{\"_class\":\"hudson.plugins.git.GitSCM\",\"userRemoteConfigs\":[{\"url\":\"git@git.domain.name:example-documentation/guide.git\"}]}}"
+          "]}"))
+
+(def jobs-in-queue-jenkins-response
+    (str "{\"_class\":\"hudson.model.Queue\","
+          "\"items\":["
+             "{\"_class\":\"hudson.model.Queue$BlockedItem\",\"task\":{\"_class\":\"hudson.model.FreeStyleProject\",\"name\":\"test-Example_Documentation-1.0-Guide-en-US (preview)\"}}"
+             "{\"_class\":\"hudson.model.Queue$BlockedItem\",\"task\":{\"_class\":\"hudson.model.FreeStyleProject\",\"name\":\"test-Example_Documentation-1.0-Guide-en-US (stage)  \"}}"
+         "]}"))
+
+(def read-currently-building-jobs-expected-result
+   [{"_class" "hudson.model.FreeStyleProject",
+     "name" "test-Example_Documentation-1.0-Guide-en-US (preview)",
+     "url"
+     "http://10.20.30.40:8080/job/test-Example_Documentation-1.0-Guide-en-US%20(preview)/",
+     "buildable" true,
+     "color" "yellow_anime",
+     "lastSuccessfulBuild"
+     {"_class" "hudson.model.FreeStyleBuild",
+      "description" "Total: 4  Passed: 1  Failed: 3"},
+      "scm"
+     {"_class" "hudson.plugins.git.GitSCM",
+      "userRemoteConfigs"
+      [{"url" "git@git.domain.name:example-documentation/guide.git"}]}}
+    {"_class" "hudson.model.FreeStyleProject",
+     "name" "test-Example_Documentation-1.0-Guide-en-US (stage)",
+     "url"
+     "http://10.20.30.40:8080/job/test-Example_Documentation-1.0-Guide-en-US%20(stage)/",
+     "buildable" true,
+     "color" "yellow_anime",
+     "lastSuccessfulBuild"
+     {"_class" "hudson.model.FreeStyleBuild",
+      "description" "Total: 4  Passed: 1  Failed: 3"},
+     "scm"
+     {"_class" "hudson.plugins.git.GitSCM",
+      "userRemoteConfigs"
+      [{"url" "git@git.domain.name:example-documentation/guide.git"}]}}])
+
+(deftest test-read-queue-info-from-jenkins
+    "Check the function emender-jenkins.rest-api/read-queue-info-from-jenkins."
+    (testing "the function emender-jenkins.rest-api/read-queue-info-from-jenkins."
+    (with-redefs [jenkins-api/get-command (fn [url] jobs-in-queue-jenkins-response)]
+        (is (= (read-queue-info-from-jenkins "url")
+             [{"_class" "hudson.model.Queue$BlockedItem" "task" {"_class" "hudson.model.FreeStyleProject" "name" "test-Example_Documentation-1.0-Guide-en-US (preview)"}}
+              {"_class" "hudson.model.Queue$BlockedItem" "task" {"_class" "hudson.model.FreeStyleProject" "name" "test-Example_Documentation-1.0-Guide-en-US (stage)  "}}]
+    )))))

 (deftest test-read-building-jobs-from-jenkins
     "Check the function emender-jenkins.rest-api/read-building-jobs-from-jenkins."
@@ -698,32 +741,7 @@
         (let [request {:configuration {:jenkins {:currently-building-view "Building"
                                              :jenkins-url "http://10.20.30.40:8080/"}}}]
             (is (= (read-currently-building-jobs request)
-               [{"_class" "hudson.model.FreeStyleProject",
-                 "name" "test-Example_Documentation-1.0-Guide-en-US (preview)",
-                 "url"
-                 "http://10.20.30.40:8080/job/test-Example_Documentation-1.0-Guide-en-US%20(preview)/",
-                 "buildable" true,
-                 "color" "yellow_anime",
-                 "lastSuccessfulBuild"
-                 {"_class" "hudson.model.FreeStyleBuild",
-                  "description" "Total: 4  Passed: 1  Failed: 3"},
-                  "scm"
-                 {"_class" "hudson.plugins.git.GitSCM",
-                  "userRemoteConfigs"
-                  [{"url" "git@git.domain.name:example-documentation/guide.git"}]}}
-                {"_class" "hudson.model.FreeStyleProject",
-                 "name" "test-Example_Documentation-1.0-Guide-en-US (stage)",
-                 "url"
-                 "http://10.20.30.40:8080/job/test-Example_Documentation-1.0-Guide-en-US%20(stage)/",
-                 "buildable" true,
-                 "color" "yellow_anime",
-                 "lastSuccessfulBuild"
-                 {"_class" "hudson.model.FreeStyleBuild",
-                  "description" "Total: 4  Passed: 1  Failed: 3"},
-                 "scm"
-                 {"_class" "hudson.plugins.git.GitSCM",
-                  "userRemoteConfigs"
-                  [{"url" "git@git.domain.name:example-documentation/guide.git"}]}}])))))
+                    read-currently-building-jobs-expected-result)))))

 (deftest test-get-currently-building-jobs
     "Check the function emender-jenkins.rest-api/get-currently-building-jobs."
@@ -747,21 +765,10 @@
                      :command "currently_building_jobs"
                      :message "Can not read Jenkins view"}))))))

-(def jobs-in-queue-jenkins-response
-    (str "{\"_class\":\"hudson.model.Queue\","
-          "\"items\":["
-             "{\"_class\":\"hudson.model.Queue$BlockedItem\",\"task\":{\"_class\":\"hudson.model.FreeStyleProject\",\"name\":\"test-Example_Documentation-1.0-Guide-en-US (preview)\"}}"
-             "{\"_class\":\"hudson.model.Queue$BlockedItem\",\"task\":{\"_class\":\"hudson.model.FreeStyleProject\",\"name\":\"test-Example_Documentation-1.0-Guide-en-US (stage)  \"}}"
-         "]}"))
-
-(deftest test-read-queue-info-from-jenkins
-    "Check the function emender-jenkins.rest-api/read-queue-info-from-jenkins."
-    (testing "the function emender-jenkins.rest-api/read-queue-info-from-jenkins."
-    (with-redefs [jenkins-api/get-command (fn [url] jobs-in-queue-jenkins-response)]
-        (is (= (read-queue-info-from-jenkins "url")
-             [{"_class" "hudson.model.Queue$BlockedItem" "task" {"_class" "hudson.model.FreeStyleProject" "name" "test-Example_Documentation-1.0-Guide-en-US (preview)"}}
-              {"_class" "hudson.model.Queue$BlockedItem" "task" {"_class" "hudson.model.FreeStyleProject" "name" "test-Example_Documentation-1.0-Guide-en-US (stage)  "}}]
-    )))))
+(def read-jobs-in-queue-expected-result
+    [{"_class" "hudson.model.Queue$BlockedItem" "task" {"_class" "hudson.model.FreeStyleProject" "name" "test-Example_Documentation-1.0-Guide-en-US (preview)"}}
+    {"_class" "hudson.model.Queue$BlockedItem" "task" {"_class" "hudson.model.FreeStyleProject" "name" "test-Example_Documentation-1.0-Guide-en-US (stage)  "}}]
+)

 (deftest test-read-queue-info-from-jenkins-negative
     "Check the function emender-jenkins.rest-api/read-queue-info-from-jenkins."
@@ -823,3 +830,65 @@
                      :command "jobs_in_queue"
                      :message "Can not read Jenkins queue"}))))))

+(deftest test-prepare-jobs-in-queue
+    "Check the function emender-jenkins.rest-api/prepare-jobs-in-queue."
+    (testing "the function emender-jenkins.rest-api/prepare-jobs-in-queue."
+        (let [items (-> (json/read-str jobs-in-queue-jenkins-response) (get "items"))]
+            (is (= (prepare-jobs-in-queue items)
+                   [{"queuePos" 1
+                     "jobName" "test-Example_Documentation-1.0-Guide-en-US (preview)"
+                     "state"   "QUEUED"}
+                    {"queuePos" 2
+                     "jobName" "test-Example_Documentation-1.0-Guide-en-US (stage)  "
+                     "state"   "QUEUED"}])))))
+
+(deftest test-prepare-building-jobs
+    "Check the function emender-jenkins.rest-api/prepare-building-jobs."
+    (testing "the function emender-jenkins.rest-api/prepare-building-jobs."
+    (with-redefs [jenkins-api/get-command (fn [all-jobs-url] building-jobs-jenkins-response)]
+        (let [request {:configuration {:jenkins {:currently-building-view "Building"
+                                             :jenkins-url "http://10.20.30.40:8080/"}}}]
+            (is (= (prepare-building-jobs (read-currently-building-jobs request))
+               [{"state"   "BUILDING"
+                 "jobName" "test-Example_Documentation-1.0-Guide-en-US (preview)"}
+                {"state"   "BUILDING"
+                 "jobName" "test-Example_Documentation-1.0-Guide-en-US (stage)"}]))))))
+
+(deftest test-create-running-jobs-response
+    "Check the function emender-jenkins.rest-api/create-running-jobs-response."
+    (testing "the function emender-jenkins.rest-api/create-running-jobs-response."
+    (with-redefs [jenkins-api/get-command (fn [all-jobs-url] building-jobs-jenkins-response)]
+        (let [request       {:configuration {:jenkins {:currently-building-view "Building"
+                                                      :jenkins-url "http://10.20.30.40:8080/"}}}
+              jobs-in-queue (-> (json/read-str jobs-in-queue-jenkins-response) (get "items"))
+              building-jobs (read-currently-building-jobs request)]
+            (is (= (create-running-jobs-response jobs-in-queue building-jobs)
+                  [{"queuePos" 1, "jobName" "test-Example_Documentation-1.0-Guide-en-US (preview)", "state" "QUEUED"}
+                   {"queuePos" 2, "jobName" "test-Example_Documentation-1.0-Guide-en-US (stage)  ", "state" "QUEUED"}
+                   {"state" "BUILDING", "jobName" "test-Example_Documentation-1.0-Guide-en-US (preview)"}
+                   {"state" "BUILDING", "jobName" "test-Example_Documentation-1.0-Guide-en-US (stage)"}]))))))
+
+(deftest test-get-running-jobs
+    "Check the function emender-jenkins.rest-api/get-running-jobs."
+    (testing "the function emender-jenkins.rest-api/get-running-jobs."
+    (with-redefs [read-jobs-in-queue           (fn [request] read-jobs-in-queue-expected-result)
+                  read-currently-building-jobs (fn [request] read-currently-building-jobs-expected-result)]
+        (let [request       {:configuration {:jenkins {:currently-building-view "Building"
+                                                      :jenkins-url "http://10.20.30.40:8080/"}}}]
+             (is (= (get-running-jobs request)
+                    {:status 200
+                     :headers {"Content-Type" "application/json"}
+                     :body "[{\"queuePos\":1,\"jobName\":\"test-Example_Documentation-1.0-Guide-en-US (preview)\",\"state\":\"QUEUED\"},{\"queuePos\":2,\"jobName\":\"test-Example_Documentation-1.0-Guide-en-US (stage)  \",\"state\":\"QUEUED\"},{\"state\":\"BUILDING\",\"jobName\":\"test-Example_Documentation-1.0-Guide-en-US (preview)\"},{\"state\":\"BUILDING\",\"jobName\":\"test-Example_Documentation-1.0-Guide-en-US (stage)\"}]"}))))))
+
+(deftest test-get-running-jobs-negative
+    "Check the function emender-jenkins.rest-api/get-running-jobs."
+    (testing "the function emender-jenkins.rest-api/get-running-jobs."
+    (with-redefs [read-jobs-in-queue           (fn [request] nil)
+                  read-currently-building-jobs (fn [request] nil)]
+        (let [request       {:configuration {:jenkins {:currently-building-view "Building"
+                                                      :jenkins-url "http://10.20.30.40:8080/"}}}]
+             (is (= (get-running-jobs request)
+                    {:status 500
+                     :headers {"Content-Type" "application/json"}
+                     :body "{\"status\":\"error\",\"command\":\"running_jobs\",\"message\":\"Can not read Jenkins queue and\\/or selected view\"}"}))))))
+


fix test

fix test

--- test/meo/client_store_search_test.cljc
+++ test/meo/client_store_search_test.cljc
@@ -47,7 +47,7 @@
                                     :put-fn        (fn [_])
                                     :msg-payload   {:query-id :query-1}})
           updated-query (second send-to-self)
-          expected-query (assoc-in (update-in st/open-tasks-query [:n] + 15) [:incremental] true)]
+          expected-query (assoc-in (update-in st/open-tasks-query [:n] + 25) [:incremental] true)]
       (testing
         "send properly updated query, with increased number of results"
         (is (= updated-query


Send a notification to Change service when follow-ups are created or completed.

--- src/oc/storage/api/entries.clj
+++ src/oc/storage/api/entries.clj
@@ -195,12 +195,10 @@
             entry (:existing-entry ctx)
             user (:user ctx)
             follow-ups (:follow-ups ctx)
-            updated-entry (entry-res/add-follow-ups! conn entry follow-ups user)
-            entry-with-comments (assoc entry :existing-comments (entry-res/list-comments-for-entry conn (:uuid entry)))]
+            updated-entry (entry-res/add-follow-ups! conn entry follow-ups user)]
     (do
-      ;; TODO: Trigger notifications for created follow-ups
-      ;; (when (and (seq? follow-ups) (any? follow-ups)))
       (timbre/info "Follow-ups created for entry:" entry-for)
+      (notification/send-trigger! (notification/->trigger :update org board {:old entry :new updated-entry} user nil))
       {:updated-entry (api-common/rep updated-entry)})
     (do
       (timbre/error "Failed creating follow-ups for entry:" entry-for) false)))
@@ -212,11 +210,10 @@
             entry (:existing-entry ctx)
             follow-up (:existing-follow-up ctx)
             user (:user ctx)
-            updated-entry (entry-res/complete-follow-up! conn entry follow-up user)
-            entry-with-comments (assoc entry :existing-comments (entry-res/list-comments-for-entry conn (:uuid entry)))]
+            updated-entry (entry-res/complete-follow-up! conn entry follow-up user)]
     (do
-      ;; TODO: Trigger notifications for completed follow-up
       (timbre/info "Follow-up marked complete for entry:" entry-for)
+      (notification/send-trigger! (notification/->trigger :update org board {:old entry :new updated-entry} user nil))
       {:updated-entry (api-common/rep updated-entry)})
     (do
       (timbre/error "Failed marking complete follow-up for entry:" entry-for) false)))


Review tasks in order.

Review tasks in order.

--- test/onyx/log/generative_peer_join.clj
+++ test/onyx/log/generative_peer_join.clj
@@ -182,6 +182,31 @@
    (is (= (map count (vals (get (:allocations replica) job-1-id))) [1 1 1]))
    (is (= (map count (vals (get (:allocations replica) job-2-id))) [1 1 1]))))

+(checking
+ "Checking Balanced allocation causes peers to be evenly over tasks"
+ 10
+ [{:keys [replica log peer-choices]}
+  (log-gen/apply-entries-gen
+   (gen/return
+    {:replica {:job-scheduler :onyx.job-scheduler/balanced
+               :messaging {:onyx.messaging/impl :dummy-messenger}}
+     :message-id 0
+     :entries (assoc (generate-join-entries (generate-peer-ids 7))
+                :job-1 [(api/create-submit-job-entry job-1-id
+                                                     peer-config
+                                                     job-1
+                                                     (planning/discover-tasks (:catalog job-1) (:workflow job-1)))]
+                :job-2 [(api/create-submit-job-entry job-2-id
+                                                     peer-config
+                                                     job-2
+                                                     (planning/discover-tasks (:catalog job-2) (:workflow job-2)))])
+     :log []
+     :peer-choices []}))]
+ (let [j1-allocations (map (fn [t] (get-in replica [:allocations job-1-id t])) (get-in replica [:tasks job-1-id]))
+       j2-allocations (map (fn [t] (get-in replica [:allocations job-2-id t])) (get-in replica [:tasks job-2-id]))]
+   (is (= (map count j1-allocations) [2 1 1]))
+   (is (= (map count j2-allocations) [1 1 1]))))
+
 (deftest balanced-allocations
   (checking
    "Checking balanced allocation causes peers to be evenly split"


Used balanced task scheduling for test

Used balanced task scheduling for test

--- test/onyx/log/generative_peer_join.clj
+++ test/onyx/log/generative_peer_join.clj
@@ -466,8 +466,8 @@
               (assoc :job-1 {:queue [(api/create-submit-job-entry
                                        job-1-id
                                        peer-config
-                                       job-1-pct-tasks
-                                       (planning/discover-tasks (:catalog job-1-pct-tasks) (:workflow job-1-pct-tasks)))]})
+                                       job-1
+                                       (planning/discover-tasks (:catalog job-1) (:workflow job-1)))]})
               (assoc :leave-1 {:queue [{:fn :leave-cluster :args {:id :p1}}]})
               (assoc :leave-2 {:queue [{:fn :leave-cluster :args {:id :p2}}]}))
           :log []


Modernize source shape tests.

Modernize source shape tests.

--- test/parkour/mapreduce/source_test.clj
+++ test/parkour/mapreduce/source_test.clj
@@ -3,12 +3,12 @@
             [clojure.core.reducers :as r]
             [parkour (conf :as conf) (fs :as fs) (wrapper :as w)
              ,       (mapreduce :as mr) (graph :as pg)]
-            [parkour.io (dsink :as dsink) (seqf :as seqf)]
+            [parkour.io (dsink :as dsink) (seqf :as seqf) (text :as text)]
             [parkour.test-helpers :as th])
   (:import [org.apache.hadoop.io Text LongWritable NullWritable]
            [org.apache.hadoop.mapreduce Mapper]))

-(use-fixtures :once th/config-fixture)
+(use-fixtures :each th/config-fixture)

 (def base-data
   [["a" 1] ["a" 2] ["b" 3] ["c" 4] ["c" 5] ["c" 6] ["d" 7]])
@@ -20,27 +20,19 @@

 (defn reducer
   [shapef mapf transf input]
-  (let [shapef (resolve shapef)
-        mapf (resolve mapf)
-        transf (resolve transf)]
-    (->> (shapef input)
-         (mapf transf)
-         (r/map pr-str)
-         (mr/sink-as :keys))))
+  (->> (shapef input) (mapf transf) (r/map pr-str) (mr/sink-as :keys)))

 (defn run-test-source
   [shapef mapf transf]
-  (let [inpath (doto (fs/path "tmp/input") fs/path-delete)
-        outpath (doto (fs/path "tmp/output") fs/path-delete)
-        dseq (dsink/with-dseq (seqf/dsink [Text LongWritable] inpath)
-               input-data)]
-    (-> (pg/input dseq)
-        (pg/map Mapper)
-        (pg/partition [Text LongWritable])
-        (pg/reduce #'reducer shapef mapf transf)
-        (pg/output (seqf/dsink [Text NullWritable] outpath))
-        (pg/execute (th/config) "test-source")
-        (->> first (r/map (comp read-string w/unwrap first)) (into [])))))
+  (-> (seqf/dsink [Text LongWritable])
+      (dsink/with-dseq input-data)
+      (pg/input)
+      (pg/map Mapper)
+      (pg/partition [Text LongWritable])
+      (pg/reduce #'reducer shapef mapf transf)
+      (pg/output (text/dsink))
+      (pg/fexecute (th/config) "test-source")
+      (->> (r/map read-string) (into []))))

 (defn into-vec [coll] (into [] coll))
 (defn into-seq [coll] (into [] (seq coll)))
@@ -49,58 +41,58 @@

 (deftest test-keys
   (let [expected ["a" "a" "b" "c" "c" "c" "d"]]
-    (is (= expected (run-test-source `mr/keys `r/map `identity)))
-    (is (= expected (run-test-source `mr/keys `map `identity)))))
+    (is (= expected (run-test-source #'mr/keys #'r/map #'identity)))
+    (is (= expected (run-test-source #'mr/keys #'map #'identity)))))

 (deftest test-vals
   (let [expected [1 2 3 4 5 6 7]]
-    (is (= expected (run-test-source `mr/vals `r/map `identity)))
-    (is (= expected (run-test-source `mr/vals `map `identity)))))
+    (is (= expected (run-test-source #'mr/vals #'r/map #'identity)))
+    (is (= expected (run-test-source #'mr/vals #'map #'identity)))))

 (deftest test-keyvals
   (let [expected base-data]
-    (is (= expected (run-test-source `mr/keyvals `r/map `identity)))
-    (is (= expected (run-test-source `mr/keyvals `map `identity)))))
+    (is (= expected (run-test-source #'mr/keyvals #'r/map #'identity)))
+    (is (= expected (run-test-source #'mr/keyvals #'map #'identity)))))

 (deftest test-keygroups
   (let [expected ["a" "b" "c" "d"]]
-    (is (= expected (run-test-source `mr/keygroups `r/map `identity)))
-    (is (= expected (run-test-source `mr/keygroups `map `identity)))))
+    (is (= expected (run-test-source #'mr/keygroups #'r/map #'identity)))
+    (is (= expected (run-test-source #'mr/keygroups #'map #'identity)))))

 (deftest test-valgroups
   (let [expected [[1 2] [3] [4 5 6] [7]]]
-    (is (= expected (run-test-source `mr/valgroups `r/map `into-vec)))
-    (is (= expected (run-test-source `mr/valgroups `r/map `into-seq)))
-    (is (= expected (run-test-source `mr/valgroups `map `into-vec)))
-    (is (= expected (run-test-source `mr/valgroups `map `into-seq)))))
+    (is (= expected (run-test-source #'mr/valgroups #'r/map #'into-vec)))
+    (is (= expected (run-test-source #'mr/valgroups #'r/map #'into-seq)))
+    (is (= expected (run-test-source #'mr/valgroups #'map #'into-vec)))
+    (is (= expected (run-test-source #'mr/valgroups #'map #'into-seq)))))

 (deftest test-keyvalgroups
   (let [expected [["a" [1 2]] ["b" [3]] ["c" [4 5 6]] ["d" [7]]]]
-    (is (= expected (run-test-source `mr/keyvalgroups `r/map `into-vec')))
-    (is (= expected (run-test-source `mr/keyvalgroups `r/map `into-seq')))
-    (is (= expected (run-test-source `mr/keyvalgroups `map `into-vec')))
-    (is (= expected (run-test-source `mr/keyvalgroups `map `into-seq')))))
+    (is (= expected (run-test-source #'mr/keyvalgroups #'r/map #'into-vec')))
+    (is (= expected (run-test-source #'mr/keyvalgroups #'r/map #'into-seq')))
+    (is (= expected (run-test-source #'mr/keyvalgroups #'map #'into-vec')))
+    (is (= expected (run-test-source #'mr/keyvalgroups #'map #'into-seq')))))

 (deftest test-keykeyvalgroups
   (let [expected [["a" [["a" 1] ["a" 2]]]
                   ["b" [["b" 3]]]
                   ["c" [["c" 4] ["c" 5] ["c" 6]]]
                   ["d" [["d" 7]]]]]
-    (is (= expected (run-test-source `mr/keykeyvalgroups `r/map `into-vec')))
-    (is (= expected (run-test-source `mr/keykeyvalgroups `r/map `into-seq')))
-    (is (= expected (run-test-source `mr/keykeyvalgroups `map `into-vec')))
-    (is (= expected (run-test-source `mr/keykeyvalgroups `map `into-seq')))))
+    (is (= expected (run-test-source #'mr/keykeyvalgroups #'r/map #'into-vec')))
+    (is (= expected (run-test-source #'mr/keykeyvalgroups #'r/map #'into-seq')))
+    (is (= expected (run-test-source #'mr/keykeyvalgroups #'map #'into-vec')))
+    (is (= expected (run-test-source #'mr/keykeyvalgroups #'map #'into-seq')))))

 (deftest test-keykeygroups
   (let [expected [["a" ["a" "a"]] ["b" ["b"]] ["c" ["c" "c" "c"]] ["d" ["d"]]]]
-    (is (= expected (run-test-source `mr/keykeygroups `r/map `into-vec')))
-    (is (= expected (run-test-source `mr/keykeygroups `r/map `into-seq')))
-    (is (= expected (run-test-source `mr/keykeygroups `map `into-vec')))
-    (is (= expected (run-test-source `mr/keykeygroups `map `into-seq')))))
+    (is (= expected (run-test-source #'mr/keykeygroups #'r/map #'into-vec')))
+    (is (= expected (run-test-source #'mr/keykeygroups #'r/map #'into-seq')))
+    (is (= expected (run-test-source #'mr/keykeygroups #'map #'into-vec')))
+    (is (= expected (run-test-source #'mr/keykeygroups #'map #'into-seq')))))

 (deftest test-keysgroups
   (let [expected [["a" "a"] ["b"] ["c" "c" "c"] ["d"]]]
-    (is (= expected (run-test-source `mr/keysgroups `r/map `into-vec)))
-    (is (= expected (run-test-source `mr/keysgroups `r/map `into-seq)))
-    (is (= expected (run-test-source `mr/keysgroups `map `into-vec)))
-    (is (= expected (run-test-source `mr/keysgroups `map `into-seq)))))
+    (is (= expected (run-test-source #'mr/keysgroups #'r/map #'into-vec)))
+    (is (= expected (run-test-source #'mr/keysgroups #'r/map #'into-seq)))
+    (is (= expected (run-test-source #'mr/keysgroups #'map #'into-vec)))
+    (is (= expected (run-test-source #'mr/keysgroups #'map #'into-seq)))))


Make an err chan. Close peer on shutdown.

--- src/onyx/peer/virtual_peer.clj
+++ src/onyx/peer/virtual_peer.clj
@@ -7,10 +7,11 @@
             [onyx.peer.task-lifecycle :refer [task-lifecycle]]))

 (defn payload-loop [id sync queue payload-ch shutdown-ch status-ch dead-ch pulse opts]
-  (let [complete-ch (chan 1)]
+  (let [complete-ch (chan 1)
+        err-ch (chan 1)]
     (loop [pipeline nil]
-      (when-let [[v ch] (alts!! [shutdown-ch complete-ch payload-ch] :priority true)]
-        (when-not (nil? pipeline)
+      (when-let [[v ch] (alts!! [shutdown-ch err-ch complete-ch payload-ch] :priority true)]
+        (when (and (not (nil? pipeline)) (not= ch err-ch))
           (component/stop pipeline))

         (cond (nil? v) (extensions/delete sync (:node pulse))
@@ -26,8 +27,7 @@
                 (<!! status-ch)

                 (let [new-pipeline (task-lifecycle id payload sync queue payload-ch complete-ch opts)]
-                  (recur (component/start new-pipeline))))
-              :else (recur nil))))
+                  (recur (component/start new-pipeline)))))))
     (>!! dead-ch true)))

 (defrecord VirtualPeer [opts]


Add cut handler to read-only cell

Add cut handler to read-only cell

--- src/reabledit/cells/read_only.cljs
+++ src/reabledit/cells/read_only.cljs
@@ -10,5 +10,6 @@
       {:type "text"
        :value ""
        :on-key-down #(if (= (.-keyCode %) 13) (.stopPropagation %))
-       :on-copy #(util/set-clipboard-data % v)}]
+       :on-copy #(util/set-clipboard-data % v)
+       :on-cut #(util/set-clipboard-data % v)}]
      [:span.reabledit-read-only-cell__view v]]))


Allow the camera functions to take the camera object directly

--- src/play_clj/core_graphics.clj
+++ src/play_clj/core_graphics.clj
@@ -269,9 +269,10 @@
   `(u/call! ^PerspectiveCamera (or (:camera ~screen) ~screen) ~k ~@options))

 (defn size!
-  [{:keys [^OrthographicCamera camera]} width height]
-  (assert camera)
-  (.setToOrtho camera false width height))
+  [screen width height]
+  (let [^OrthographicCamera camera (or (:camera screen) screen)]
+    (assert camera)
+    (.setToOrtho camera false width height)))

 (defn height!
   [screen new-height]
@@ -282,22 +283,25 @@
   (size! screen new-width (* new-width (/ (game :height) (game :width)))))

 (defn x!
-  [{:keys [^Camera camera]} x]
-  (assert camera)
-  (set! (. (. camera position) x) x)
-  (.update camera))
+  [screen x]
+  (let [^Camera camera (or (:camera screen) screen)]
+    (assert camera)
+    (set! (. (. camera position) x) x)
+    (.update camera)))

 (defn y!
-  [{:keys [^Camera camera]} y]
-  (assert camera)
-  (set! (. (. camera position) y) y)
-  (.update camera))
+  [screen y]
+  (let [^Camera camera (or (:camera screen) screen)]
+    (assert camera)
+    (set! (. (. camera position) y) y)
+    (.update camera)))

 (defn z!
-  [{:keys [^Camera camera]} z]
-  (assert camera)
-  (set! (. (. camera position) z) z)
-  (.update camera))
+  [screen z]
+  (let [^Camera camera (or (:camera screen) screen)]
+    (assert camera)
+    (set! (. (. camera position) z) z)
+    (.update camera)))

 (defn position!
   ([screen x y]


Provide default position/size values when drawing and improve step! function

--- src/play_clj/core_graphics.clj
+++ src/play_clj/core_graphics.clj
@@ -182,8 +182,9 @@
   (.draw object batch 1))

 (defmethod draw-entity! :texture
-  [[^SpriteBatch batch {:keys [^TextureRegion object x y width height]}]]
-  (assert (and object x y width height))
+  [[^SpriteBatch batch {:keys [^TextureRegion object x y width height]
+                        :or {x 0 y 0 width 0 height 0}}]]
+  (assert object)
   (.draw batch object (float x) (float y) (float width) (float height)))

 (defn draw! [{:keys [renderer] :as screen} entities]
@@ -218,15 +219,18 @@
     (render! screen)
     (draw! screen entities)))

+; physics
+
 (defn step!
-  [{:keys [world time-step velocity-iterations position-iterations]
-    :or {time-step (/ 1 60) velocity-iterations 10 position-iterations 10}}
-   entities]
-  (assert world)
-  (cond
-    (isa? (type world) World)
-    (.step ^World world time-step velocity-iterations position-iterations))
-  entities)
+  ([{:keys [world time-step velocity-iterations position-iterations]
+     :or {time-step (/ 1 60) velocity-iterations 10 position-iterations 10}}]
+    (assert world)
+    (cond
+      (isa? (type world) World)
+      (.step ^World world time-step velocity-iterations position-iterations)))
+  ([screen entities]
+    (step! screen)
+    entities))

 ; cameras


remove unnecessary absolute path to ruby

--- src/devops_101_pipeline/steps.clj
+++ src/devops_101_pipeline/steps.clj
@@ -43,8 +43,8 @@
 (defn deploy [s3-address build-id ctx]
   (let [basedir (prepare-deploy-scripts)]
     (shell/bash ctx basedir
-                (str "/usr/local/bin/ruby deploy-new-app-server.rb " s3-address " " build-id)
-                (str "/usr/local/bin/ruby retire-old-app-server.rb " build-id))))
+                (str "ruby deploy-new-app-server.rb " s3-address " " build-id)
+                (str "ruby retire-old-app-server.rb " build-id))))

 (defn deploy-step [{s3-address :s3-address build-id :build-id} ctx]
   (deploy s3-address build-id ctx))


Fix reason code bug in rebalancer

Fix reason code bug in rebalancer

--- scheduler/src/cook/mesos/rebalancer.clj
+++ scheduler/src/cook/mesos/rebalancer.clj
@@ -311,7 +311,7 @@
               [[:generic/ensure task-eid :instance/status (d/entid db :instance.status/running)]
                [:generic/atomic-inc job-eid :job/preemptions 1]
                [:instance/update-state task-eid :instance.status/failed]
-               [:instance/reason-code task-eid reason-preempted-by-rebalancer]
+               [:db/add task-eid :instance/reason-code reason-preempted-by-rebalancer]
                [:db/add task-eid :instance/preempted? true]]))
           (catch Throwable e
             (log/warn e "Failed to transact preemption")))


fix build log update for UI

fix build log update for UI

--- src/main/shadow/cljs/devtools/server/worker.clj
+++ src/main/shadow/cljs/devtools/server/worker.clj
@@ -160,9 +160,8 @@
         (not timing-id)
         (update state :log conj (build-log/event->str event))

-        ;; not interested :enter after the fact
-        ;; (= :enter timing)
-        ;; (update state :active assoc timing-id (assoc event ::m/msg (build-log/event->str event)))
+        (= :enter timing)
+        (update state :active assoc timing-id (assoc event ::m/msg (build-log/event->str event)))

         (= :exit timing)
         (-> state


adding reservation

adding reservation

--- src/aws/provider.clj
+++ src/aws/provider.clj
@@ -55,8 +55,9 @@
    "creates instance from aws"
    [{:keys [aws machine] :as spec} endpoint]
    {:pre [(creation-keys aws)]}
-   (let [inst (merge (dissoc aws :volumes) {:image-id (image-id machine)})]
-     (get-in (with-ctx ec2/run-instances inst) [:instances 0 :instance-id])))
+   (let [inst (merge (dissoc aws :volumes) {:image-id (image-id machine)})
+         {:keys [reservation]} (with-ctx ec2/run-instances inst)]
+     (get-in reservation  [:instances 0 :instance-id])))

 (defconstrainedrecord Instance [endpoint spec user]
   "An Ec2 instance"


cleanup JSON response

cleanup JSON response

--- src/babel/reader.clj
+++ src/babel/reader.clj
@@ -88,20 +88,20 @@
                    :body (write-str {:message "Unexpected internal error. Sorry: hopefully a human will work on it."})})

                 true
-                (do (log/info (str "returning normal response:"
-                                   "'" (:source gcacs) "'"
-                                   " -> " (:targets gcacs) "; spec:" target_spec))
-                    {:status 200
-                     :body
-                     (write-str
-                      (merge
-                       {:real-gcacs gcacs}
-                       {:source source
-                        :source-locale source-locale
-                        :target target
-                        :target-local target-locale
-                        :target_spec target_spec
-                        :target-spec target_spec}))}))))))
+                (let [source (:source gcacs)
+                      targets (:targets gcacs)]
+                  (log/info (str "returning normal response:"
+                                 "'" source "'"
+                                 " -> " targets "; spec:" target_spec))
+                  {:status 200
+                   :body
+                   (write-str
+                    {:source source
+                     :source-locale source-locale
+                     :targets targets
+                     :target-local target-locale
+                     :target_spec target_spec
+                     :target-spec target_spec})}))))))

 (defn generate-question-and-correct-set-dynamic [target-spec
                                                  source-language source-locale


cleanup

cleanup

--- src/babel/reader.clj
+++ src/babel/reader.clj
@@ -4,21 +4,39 @@
    [babel.directory :refer [models models2]]
    [babel.generate :refer [generate]]
    [babel.korma :as korma :refer [convert-keys-from-string-to-keyword init-db read-array]]
+   [cljstache.core :as cljstache]
    [clojure.string :as string]
    [clojure.data.json :as json :refer [read-str write-str]]
+   [clojure.java.io :as io]
    [clojure.tools.logging :as log]
    [compojure.core :as compojure :refer [GET PUT POST DELETE ANY]]
    [dag_unify.core :as unify :refer [dissoc-paths get-in ref? strip-refs unify]]
-   [korma.core :as db]])
-
-;; Configure database's 'expression' table to find the expressions.
-;; requires Postgres 9.4 or higher for JSONb operator '@>' support.
-
-;; TODO: calling functions in here 'generate-X' is misleading
-;; since they are querying a table to find sentences, not generating sentences from scratch.
-(declare generate-question-and-correct-set)
-(declare id2expression)
+   [korma.core :as db]
+   [ring.util.response :as resp]])
+
+(declare generate-question-and-correct-set-dynamic)
 (declare json-read-str)
+
+(defn render-page
+  "Pass in the template name (a string, sans its .mst filename extension),
+  the data for the page (a map), and a list of partials (keywords)
+  corresponding to like-named template filenames (e.g. [:header :footer]
+  correspond to the template files header.mst and footer.mst, respectively.)"
+  [template data partials]
+  (try
+    (cljstache/render-resource
+     (str "public/mst/" template ".mst")
+     data
+     (reduce (fn [accum pt] ;; "pt" is the name (as a keyword) of the partial.
+               (assoc accum pt (slurp (io/resource (str "public/mst/"
+                                                        (name pt)
+                                                        ".mst")))))
+             {}
+             partials))
+    (catch Exception e
+      (str "could not render template: '" template "' - check for existence of:

public/mst/"
+           template ".mst
"))))
+

 ;; web service that translates babel.reader's API and an HTTP client.
 ;; http://localhost:3001/reader?target_spec={%22root%22:{%22italiano%22:{%22italiano%22:%22scrivere%22}}%20%22synsem%22:%20{%22sem%22:%20{%22tense%22:%22past%22,%20%22aspect%22:%22perfect%22}}}
@@ -36,40 +54,13 @@
                                (if-let [target_spec (get (:query-params request) "target_spec")]
                                  target_spec "{}"))
                   gcacs (try
-                          (generate-question-and-correct-set
+                          (generate-question-and-correct-set-dynamic
                            target_spec
                            source source-locale
                            target target-locale)
                           (catch Exception e
                             {:exception (str e)}))]
-              (write-str gcacs))})
-;                          :target_spec target_spec
-;                          ;; TODO: eventually add :source-v2
-;                          :targets (get-in gcacs [:targets])
-;                          :targets-v2 (get-in gcacs [:targets-v2])}))})
-
-      (GET "/:expr" request
-           (let [expr (:expr (:route-params request))]
-             (log/debug (str "expr(1):" expr))
-             (log/debug (str "expr(2):" (Integer. expr)))
-             {:status 200
-              :headers {"Content-Type" "application/json;charset=utf-8"}
-              :body (write-str (id2expression (Integer. expr)))}))))
-
-(defn generate-using-db [spec source-language target-language]
-  (let [spec (unify spec
-                    {:synsem {:subcat '()}})]
-    (log/debug (str "(generate-using-db): spec:" spec))
-    (generate spec source-language target-language)))
-
-(defn id2expression [id]
-  (let [results (db/exec-raw [(str "SELECT structure
-                                      FROM expression
-                                     WHERE id=?")
-                              [id]]
-                             :results)]
-    (if (not (empty? results))
-      (json-read-str (.getValue (:structure (first results)))))))
+              (write-str gcacs))})))

 (defn generate-question-and-correct-set-dynamic [target-spec
                                                  source-language source-locale


use a-tik to modulate note idx changes

use a-tik to modulate note idx changes

--- src/overtone/examples/timing/internal_metro.clj
+++ src/overtone/examples/timing/internal_metro.clj
@@ -83,7 +83,7 @@
   (let [tik   (impulse rate)
         a-tik (pulse-divider tik arp-div)
         b-tik (pulse-divider tik beat-div)
-        cnt   (mod (pulse-count tik) (buf-frames buf))
+        cnt   (mod (pulse-count a-tik) (buf-frames buf))
         note  (buf-rd:kr 1 notes-b cnt)
         freq  (midicps note)
         snd   (white-noise)


Limit the number of items in a collection to display, in case of infinite lists

--- src/io/aviso/twixt/exceptions.clj
+++ src/io/aviso/twixt/exceptions.clj
@@ -48,6 +48,18 @@
                   ))
          ]))))

+(defn- seq->markup [coll]
+  ;; Since *print-length* is normally nil, we provide an actual limit
+  (let [limit (or *print-length* 10)
+        values (take (inc limit) coll)
+        trimmed (if (<= (count values) limit)
+                  values
+                  (concat
+                    (take limit values)
+                    ["..."]))]
+    (for [v trimmed]
+      [:li (to-markup v)])))
+
 (extend-type Sequential
   MarkupGeneration
   (to-markup
@@ -55,9 +67,7 @@
     (html
       (if (empty? coll)
         [:em "none"]
-        [:ul
-         (for [v coll] [:li (to-markup v)])
-         ]))))
+        [:ul (seq->markup coll)]))))

 (extend-type Map
   MarkupGeneration


Fix test failing on Clojure 1.2.0/1.2.1 due to ordering of attributes

--- src/test/clojure/clojure/data/xml/test_emit.clj
+++ src/test/clojure/clojure/data/xml/test_emit.clj
@@ -36,12 +36,14 @@
     (is (= expect (emit-str deep-tree)))))

 (deftest mixed-quotes
-  (is (= (str "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
-              "<mixed double=\""double"quotes"here"\""
-              " single=\"'single'quotes'here\"></mixed>")
-         (emit-str (element :mixed
-                                {:single "'single'quotes'here"
-                                 :double "\"double\"quotes\"here\""})))))
+  (is (= (lazy-parse*
+          (str "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+               "<mixed double=\""double"quotes"here"\""
+               " single=\"'single'quotes'here\"></mixed>"))
+         (lazy-parse*
+          (emit-str (element :mixed
+                             {:single "'single'quotes'here"
+                              :double "\"double\"quotes\"here\""}))))))

 ;; TODO add an indentation test once we figure out how to indent portably across JREs


more idiomatic? but i do love update and assoc-or...

--- src/cake/project.clj
+++ src/cake/project.clj
@@ -3,7 +3,7 @@
         [cake.file :only [file global-file]]
         [cake.ant :only [fileset-seq]]
         [clojure.string :only [join]]
-        [cake.utils.useful :only [assoc-or update merge-in tap]])
+        [cake.utils.useful :only [update merge-in tap]])
   (:import [java.io File]))

 (defn- make-url [file]
@@ -29,7 +29,7 @@
     (eval-in cl '(do (require 'cake)
                      (require 'bake.io)
                      (require 'bake.reload)
-                     (require 'clojure.main)))
+                     (require 'clojure.main)))
     cl))

 (defn reload! []
@@ -123,18 +123,15 @@
   (let [artifact (name project-name)
         artifact-version (str artifact "-" version)]
     (-> opts
-        (assoc :artifact-id  artifact
-               :group-id     (group project-name)
-               :aot          (or (:aot opts) (:namespaces opts))
-               :version      version
-               :context      (symbol (or (:context opts) "dev"))
-               :jar-name     (or (:jar-name opts) artifact-version)
-               :war-name     (or (:war-name opts) artifact-version)
-               :uberjar-name (or (:uberjar-name opts) (str artifact-version "-standalone")))
-        (assoc-or :dependencies (:deps opts))
-        (assoc-or :ext-depencencies (:dev-deps opts))
-        (assoc-or :dev-dependencies (:dev-deps opts))
-        (update :dependencies     dep-map)
-        (update :ext-dependencies dep-map)
-        (update :dev-dependencies dep-map)
-        (assoc-or :name artifact))))
+        (assoc :artifact-id      artifact
+               :group-id         (group project-name)
+               :version          version
+               :name             (or (:name opts) artifact)
+               :aot              (or (:aot opts) (:namespaces opts))
+               :context          (symbol (or (:context opts) "dev"))
+               :jar-name         (or (:jar-name opts) artifact-version)
+               :war-name         (or (:war-name opts) artifact-version)
+               :uberjar-name     (or (:uberjar-name opts) (str artifact-version "-standalone"))
+               :dependencies     (dep-map (or (:dependencies     opts) (:deps     opts)))
+               :dev-dependencies (dep-map (or (:dev-dependencies opts) (:dev-deps opts)))
+               :ext-dependencies (dep-map (or (:ext-dependencies opts) (:ext-deps opts)))))))


documentation

documentation

--- src/babel/generate.cljc
+++ src/babel/generate.cljc
@@ -52,6 +52,23 @@
         max-depth (or max-depth max-total-depth)]
     (log/debug (str "generate-all:" depth "/" max-depth ":" (spec-info spec)))
     (->>
+
+     ;; 1. Generate 'lightning bolts':
+     ;;
+     ;;
+     ;;   H        H    H
+     ;;    \      /      \
+     ;;     H    H        H        ...
+     ;;    /      \        \
+     ;;   H       ..        ..
+     ;;    \
+     ;;     ..
+     ;;
+     ;; Each bolt is a tree with only one child per parent: the head child.
+     ;; Each head child may be a leaf or
+     ;; otherwise has a child with the same two options (leaf or a head child),
+     ;; up to the maximum depth.
+     ;; Complements get filled in later, at step 3.
      (lightning-bolts model spec depth max-depth)

      ;; 2. debug logging.
@@ -89,6 +106,7 @@
                          (assoc-in {} path trellis))
                        (zipmap paths trellis)))))

+     ;; 6. Remove fails. (TODO: consider whether this can be removed)
      (remove (fn [tree-parts]
                (some #(= :fail %) tree-parts)))

@@ -98,6 +116,7 @@
                       (unify-and-log a b model))
                     tree-parts)))

+     ;; 8. Remove fails again. (TODO: consider whether this can be removed)
      (remove #(= :fail %))

      ;; 9. Apply model's defaults, if any, to each tree.


not sorting keys of comps-map

not sorting keys of comps-map

--- src/babel/generate.cljc
+++ src/babel/generate.cljc
@@ -205,7 +205,7 @@
   (log/debug (str "generate2: spec: " spec))
   (mapcat (fn [bolt]
             (let [comps-map (comp-paths-to-bolts-map bolt model depth max-total-depth)
-                  comp-paths (sort (keys comps-map))
+                  comp-paths (keys comps-map)
                   comp-bolts (map #(get comps-map %)
                                   comp-paths)]
               ;; filter by the following constraint:


seems like (reduce (concat)) causes sequences to become eager, so back to mapcat.

--- src/babel/generate.cljc
+++ src/babel/generate.cljc
@@ -87,28 +87,27 @@
 head of its parent. generate (above) 'decorates' each returned lightning bolt
 of this function with complements."
   (if (or (vector? spec) (seq? spec))
-    (reduce concat (pmap (fn [each-spec]
-                           (lightning-bolt grammar lexicon each-spec depth index morph total-depth))
-                         spec))
+    (mapcat (fn [each-spec]
+              (lightning-bolt grammar lexicon each-spec depth index morph total-depth))
+            spec)
     (do
       (log/debug (str "lightning-bolt(depth=" depth ", total-depth=" total-depth "): sem:" (strip-refs (get-in spec [:synsem :sem]))))
       (let [morph (if morph morph (fn [input] (get-in input [:rule] :default-morph-no-rule)))
             depth (if depth depth 0)
             parents (filter #(not (fail? %)) (pmap (fn [rule] (unifyc spec rule)) grammar))]
         (let [lexical ;; 1. generate list of all phrases where the head child of each parent is a lexeme.
-              (reduce concat
-                      (pmap (fn [parent]
-                              (if (= false (get-in parent [:head :phrasal] false))
-                                (let [candidate-lexemes (get-lex parent :head index spec)]
-                                  (over/overh parent
-                                              (pmap copy (lazy-shuffle candidate-lexemes))))))
-                            parents))
+              (mapcat (fn [parent]
+                        (if (= false (get-in parent [:head :phrasal] false))
+                          (let [candidate-lexemes (get-lex parent :head index spec)]
+                            (over/overh parent
+                                        (mapfn copy (lazy-shuffle candidate-lexemes))))))
+                            parents)
               phrasal ;; 2. generate list of all phrases where the head child of each parent is itself a phrase.
               (if (< depth max-total-depth)
-                (reduce concat (pmap (fn [parent]
-                                       (over/overh parent (lightning-bolt grammar lexicon (get-in parent [:head])
-                                                                          (+ 1 depth) index morph (+ 1 total-depth))))
-                                     parents)))]
+                (mapcat (fn [parent]
+                          (over/overh parent (lightning-bolt grammar lexicon (get-in parent [:head])
+                                                             (+ 1 depth) index morph (+ 1 total-depth))))
+                        parents))]
           (if (lexemes-before-phrases total-depth)
             (lazy-cat lexical phrasal)
             (lazy-cat phrasal lexical)))))))


simply use (shuffle) rather than (lazy-shuffle)

--- src/babel/generate.cljc
+++ src/babel/generate.cljc
@@ -30,7 +30,6 @@
 (declare exception)
 (declare find-comp-paths-in)
 (declare lazy-mapcat)
-(declare lazy-shuffle)
 (declare lexemes-before-phrases)
 (declare lightning-bolts)
 (declare generate-all)
@@ -105,7 +104,7 @@
         ;; this is the relative depth; that is, the depth from the top of the current lightning bolt.
         ;; total-depth, on the other hand, is the depth all the way to the top of the entire
         ;; expression, which might involve several parent lightning bolts.
-        parents (lazy-shuffle (candidate-parents grammar spec))]
+        parents (shuffle (candidate-parents grammar spec))]
     (let [lexical ;; 1. generate list of all phrases where the head child of each parent is a lexeme.
           (when (= false (get-in spec [:head :phrasal] false))
             (lazy-mapcat
@@ -127,7 +126,7 @@
                                                    subset))))

                  (log/trace (str "trying overh with parent: " (:rule parent) " and head constraints: " (get-in parent [:head])))
-                 (let [result (over/overh parent (lazy-shuffle subset))]
+                 (let [result (over/overh parent (shuffle subset))]
                    (when (not (empty? subset))
                      (log/trace (str "lightning-bolts:  surviving candidate heads: " (count subset) " -(unify)-> " (count result))))

@@ -244,7 +243,7 @@
                                           complement-candidate-lexemes))))

         bolt-child-synsem (get-in bolt (concat path [:synsem]))
-        lexical-complements (lazy-shuffle
+        lexical-complements (shuffle
                              (filter (fn [lexeme]
                                        (and (not-fail? (unify (get-in lexeme [:synsem] :top)
                                                               bolt-child-synsem))))
@@ -387,9 +386,6 @@
                     (string/join "," (map :rule result))))
     result))

-(defn lazy-shuffle [seq]
-  (lazy-seq (shuffle seq)))
-
 (defn exception [error-string]
   #?(:clj
      (throw (Exception. (str ": " error-string))))


add collapsing of filled rows

add collapsing of filled rows


Parser cleanup

Parser cleanup

--- src/main/clojure/fleet/parser.clj
+++ src/main/clojure/fleet/parser.clj
@@ -1,28 +1,20 @@
 (ns fleet.parser
   (:use
-    [clojure.contrib def]
-    [fleet.util])
+    [clojure.contrib def])
   (:require
-    [clojure.contrib.str-utils2 :as su]
     [clojure.zip :as z])
   (:import
     [java.util.regex Pattern]))

 ;;;;;;;;;; lexer ;;;;;;;;;;

-(defn- make-token-regex
-  [tokens]
-  (Pattern/compile (str "^(.*?)(" (su/join "|" (map escape-regex tokens)) ")") Pattern/DOTALL))
-
 (defvar- token-regexs {
-  true (make-token-regex [")>" "\">"])
-  false (make-token-regex ["<(" "<\""])})
+  true  (Pattern/compile (str "^(.*?)(\\)>|\">)") Pattern/DOTALL)
+  false (Pattern/compile (str "^(.*?)(<\\(|<\")") Pattern/DOTALL)})

 (defn- token-seq
   [input]
-  (loop [input input
-         mode false
-         ast []]
+  (loop [input input, mode false, ast []]
     (let [found (re-find (re-matcher (token-regexs mode) input))
           [pair text token] (or found [input input nil])
           ast (if (empty? text) ast (conj ast text))]
@@ -33,17 +25,13 @@
 ;;;;;;;;;; parser ;;;;;;;;;;

 (defvar- consumers {
-  true {
-    ")>"  (fn [token loc] [false (-> loc z/up z/up)])
-    "\">" (fn [token loc] [false (-> loc (z/append-child [:tpl []]) z/down z/rightmost z/down z/rightmost)])
-    :text (fn [token loc] [true  (-> loc (z/append-child [:clj token]))])
-    }
-  false {
-    "<\"" (fn [token loc] [true  (-> loc z/up z/up)])
-    "<("  (fn [token loc] [true  (-> loc (z/append-child [:embed []]) z/down z/rightmost z/down z/rightmost)])
-    :text (fn [token loc] [false (-> loc (z/append-child [:text token]))])
-    }
-  })
+  ")>"  (fn [_ loc] [false (-> loc z/up z/up)])
+  "<\"" (fn [_ loc] [true  (-> loc z/up z/up)])
+  "<("  (fn [_ loc] [true  (-> loc (z/append-child [:embed []]) z/down z/rightmost z/down z/rightmost)])
+  "\">" (fn [_ loc] [false (-> loc (z/append-child [:tpl   []]) z/down z/rightmost z/down z/rightmost)])
+  :text {
+    true  (fn [token loc] [true  (-> loc (z/append-child [:clj token]))])
+    false (fn [token loc] [false (-> loc (z/append-child [:text token]))])}})

 (defn- make-ast
   [tokens]
@@ -52,8 +40,7 @@
          loc (z/vector-zip [])]
     (if (first tokens)
       (let [token (first tokens)
-            consumers (consumers mode)
-            consumer (consumers token (consumers :text))
+            consumer (consumers token ((consumers :text) mode))
             [mode loc] (consumer token loc)]
         (recur (rest tokens) mode loc))
       (first (z/root loc)))))


normalize token addresses

normalize token addresses

Signed-off-by: yenda <96f164ad4d9b2b0dacf8ebee2bb1eeb3aa69adf1@status.im>

--- src/status_im/ethereum/tokens.cljs
+++ src/status_im/ethereum/tokens.cljs
@@ -74,7 +74,7 @@
                     :decimals 18}
                    {:symbol   :MKR
                     :name     "MKR"
-                    :address  "0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2"
+                    :address  "0x9f8f72aa9304c8b593d555f12ef6589cc3a579a2"
                     :decimals 18}
                    {:symbol   :EOS
                     :name     "EOS"
@@ -82,7 +82,7 @@
                     :decimals 18}
                    {:symbol   :OMG
                     :name     "OMGToken"
-                    :address  "0xd26114cd6EE289AccF82350c8d8487fedB8A0C07"
+                    :address  "0xd26114cd6ee289accf82350c8d8487fedb8a0c07"
                     :decimals 18}
                    {:symbol   :PPT
                     :name     "Populous Platform"
@@ -90,7 +90,7 @@
                     :decimals 8}
                    {:symbol   :REP
                     :name     "Reputation"
-                    :address  "0x1985365e9f78359a9B6AD760e32412f4a445E862"
+                    :address  "0x1985365e9f78359a9b6ad760e32412f4a445e862"
                     :decimals 18}
                    {:symbol   :POWR
                     :name     "PowerLedger"
@@ -98,23 +98,23 @@
                     :decimals 6}
                    {:symbol   :PAY
                     :name     "TenX Pay Token"
-                    :address  "0xB97048628DB6B661D4C2aA833e95Dbe1A905B280"
+                    :address  "0xb97048628db6b661d4c2aa833e95dbe1a905b280"
                     :decimals 18}
                    {:symbol   :VRS
                     :name     "Veros"
-                    :address  "0x92E78dAe1315067a8819EFD6dCA432de9DCdE2e9"
+                    :address  "0x92e78dae1315067a8819efd6dca432de9dcde2e9"
                     :decimals 6}
                    {:symbol   :GNT
                     :name     "Golem Network Token"
-                    :address  "0xa74476443119A942dE498590Fe1f2454d7D4aC0d"
+                    :address  "0xa74476443119a942de498590fe1f2454d7d4ac0d"
                     :decimals 18}
                    {:symbol   :SALT
                     :name     "Salt"
-                    :address  "0x4156D3342D5c385a87D264F90653733592000581"
+                    :address  "0x4156d3342d5c385a87d264f90653733592000581"
                     :decimals 8}
                    {:symbol   :BNB
                     :name     "BNB"
-                    :address  "0xB8c77482e45F1F44dE1745F52C74426C631bDD52"
+                    :address  "0xb8c77482e45f1f44de1745f52c74426c631bdd52"
                     :decimals 18}
                    {:symbol   :BAT
                     :name     "Basic Attention Token"
@@ -124,10 +124,10 @@
                     :name     "Kyber Network Crystal"
                     :address  "0xdd974d5c2e2928dea5f71b9825b8b646686bd200"
                     :decimals 18}
-                   {:symbol               :DGD
-                    :name                 "Digix DAO"
-                    :address              "0xe0b7927c4af23765cb51314a0e0521a9645f0e2a"
-                    :decimals             9
+                   {:symbol   :DGD
+                    :name     "Digix DAO"
+                    :address  "0xe0b7927c4af23765cb51314a0e0521a9645f0e2a"
+                    :decimals 9
                     :skip-decimals-check? true}
                    {:symbol   :AE
                     :name     "Aeternity"
@@ -175,7 +175,7 @@
                     :decimals 8}
                    {:symbol   :ICN
                     :name     "ICONOMI"
-                    :address  "0x888666CA69E0f178DED6D75b5726Cee99A87D698"
+                    :address  "0x888666ca69e0f178ded6d75b5726cee99a87d698"
                     :decimals 18}
                    {:symbol   :WTC
                     :name     "Walton Token"
@@ -195,11 +195,11 @@
                     :decimals 18}
                    {:symbol   :MTL
                     :name     "Metal"
-                    :address  "0xF433089366899D83a9f26A773D59ec7eCF30355e"
+                    :address  "0xf433089366899d83a9f26a773d59ec7ecf30355e"
                     :decimals 8}
                    {:symbol   :PPP
                     :name     "PayPie"
-                    :address  "0xc42209aCcC14029c1012fB5680D95fBd6036E2a0"
+                    :address  "0xc42209accc14029c1012fb5680d95fbd6036e2a0"
                     :decimals 18}
                    {:symbol   :LINK
                     :name     "ChainLink Token"
@@ -211,24 +211,24 @@
                     :decimals 18}
                    {:symbol   :ANT
                     :name     "Aragon Network Token"
-                    :address  "0x960b236A07cf122663c4303350609A66A7B288C0"
+                    :address  "0x960b236a07cf122663c4303350609a66a7b288c0"
                     :decimals 18}
                    {:symbol   :MGO
                     :name     "MobileGo Token"
-                    :address  "0x40395044Ac3c0C57051906dA938B54BD6557F212"
+                    :address  "0x40395044ac3c0c57051906da938b54bd6557f212"
                     :decimals 8}
                    {:symbol   :MCO
                     :name     "Monaco"
                     :address  "0xb63b606ac810a52cca15e44bb630fd42d8d1d83d"
                     :decimals 8}
-                   {:symbol               :LRC
-                    :name                 "loopring"
-                    :address              "0xEF68e7C694F40c8202821eDF525dE3782458639f"
-                    :decimals             18
+                   {:symbol   :LRC
+                    :name     "loopring"
+                    :address  "0xef68e7c694f40c8202821edf525de3782458639f"
+                    :decimals 18
                     :skip-decimals-check? true}
                    {:symbol   :ZSC
                     :name     "Zeus Shield Coin"
-                    :address  "0x7A41e0517a5ecA4FdbC7FbebA4D4c47B9fF6DC63"
+                    :address  "0x7a41e0517a5eca4fdbc7fbeba4d4c47b9ff6dc63"
                     :decimals 18}
                    {:symbol   :DATA
                     :name     "Streamr DATAcoin"
@@ -240,7 +240,7 @@
                     :decimals 18}
                    {:symbol   :WINGS
                     :name     "WINGS"
-                    :address  "0x667088b212ce3d06a1b553a7221E1fD19000d9aF"
+                    :address  "0x667088b212ce3d06a1b553a7221e1fd19000d9af"
                     :decimals 18}
                    {:symbol   :EDG
                     :name     "Edgeless"
@@ -248,7 +248,7 @@
                     :decimals 0}
                    {:symbol   :MLN
                     :name     "Melon Token"
-                    :address  "0xBEB9eF514a379B997e0798FDcC901Ee474B6D9A1"
+                    :address  "0xbeb9ef514a379b997e0798fdcc901ee474b6d9a1"
                     :decimals 18}
                    {:symbol   :MDA
                     :name     "Moeda Loyalty Points"
@@ -356,7 +356,7 @@
                     :decimals 18}
                    {:symbol   :٨
                     :name     "Dentacoin"
-                    :address  "0x08d32b0da63e2C3bcF8019c9c5d849d7a9d791e6"
+                    :address  "0x08d32b0da63e2c3bcf8019c9c5d849d7a9d791e6"
                     :decimals 0}
                    {:symbol   :EDO
                     :name     "Eidoo Token"
@@ -388,11 +388,11 @@
                     :decimals 18}
                    {:symbol   :STX
                     :name     "Stox"
-                    :address  "0x006BeA43Baa3f7A6f765F14f10A1a1b08334EF45"
+                    :address  "0x006bea43baa3f7a6f765f14f10a1a1b08334ef45"
                     :decimals 18}
                    {:symbol   :XAUR
                     :name     "Xaurum"
-                    :address  "0x4DF812F6064def1e5e029f1ca858777CC98D2D81"
+                    :address  "0x4df812f6064def1e5e029f1ca858777cc98d2d81"
                     :decimals 8}
                    {:symbol   :VIB
                     :name     "Vibe"
@@ -400,7 +400,7 @@
                     :decimals 18}
                    {:symbol   :PRG
                     :name     "PRG"
-                    :address  "0x7728dFEF5aBd468669EB7f9b48A7f70a501eD29D"
+                    :address  "0x7728dfef5abd468669eb7f9b48a7f70a501ed29d"
                     :decimals 6}
                    {:symbol   :DPY
                     :name     "Delphy Token"
@@ -420,7 +420,7 @@
                     :decimals 8}
                    {:symbol   :SPANK
                     :name     "SPANK"
-                    :address  "0x42d6622deCe394b54999Fbd73D108123806f6a18"
+                    :address  "0x42d6622dece394b54999fbd73d108123806f6a18"
                     :decimals 18}
                    {:symbol   :BRLN
                     :name     "Berlin Coin"
@@ -453,17 +453,17 @@
                    ;; app.
                    {:symbol   :Centra
                     :name     "Centra token"
-                    :address  "0x96A65609a7B84E8842732DEB08f56C3E21aC6f8a"
+                    :address  "0x96a65609a7b84e8842732deb08f56c3e21ac6f8a"
                     :decimals 18
                     :hidden?  true}
                    {:symbol   :ROL
                     :name     "DICE"
-                    :address  "0x2e071D2966Aa7D8dECB1005885bA1977D6038A65"
+                    :address  "0x2e071d2966aa7d8decb1005885ba1977d6038a65"
                     :decimals 16
                     :hidden?  true}
                    {:symbol   :ATM
                     :name     "Attention Token of Media"
-                    :address  "0x9B11EFcAAA1890f6eE52C6bB7CF8153aC5d74139"
+                    :address  "0x9b11efcaaa1890f6ee52c6bb7cf8153ac5d74139"
                     :decimals 8
                     :hidden?  true}
                    ;; NOTE(goranjovic): the following tokens are collectibles
@@ -474,7 +474,7 @@
                    {:symbol  :EMONA
                     :nft?    true
                     :name    "EtheremonAsset"
-                    :address "0xB2c0782ae4A299f7358758B2D15dA9bF29E1DD99"}
+                    :address "0xb2c0782ae4a299f7358758b2d15da9bf29e1dd99"}
                    {:symbol  :STRK
                     :nft?    true
                     :name    "CryptoStrikers"
@@ -493,7 +493,7 @@
                     :symbol   :STT
                     :decimals 18
                     ;;NOTE(goranjovic): intentionally checksummed for purposes of testing
-                    :address  "0xc55cF4B03948D7EBc8b9E8BAD92643703811d162"}
+                    :address  "0xc55cf4b03948d7ebc8b9e8bad92643703811d162"}
                    {:name     "Handy Test Token"
                     :symbol   :HND
                     :decimals 0


Clean up metrics integration

Clean up metrics integration

--- src/beehive/metrics.clj
+++ src/beehive/metrics.clj
@@ -16,6 +16,7 @@
   (:require [beehive.utils :as utils]
             [beehive.enums :as enums])
   (:import (beehive.java EmptyEnum)
+           (net.uncontended.precipice.metrics Metrics)
            (net.uncontended.precipice.metrics.counts PartitionedCount
                                                      NoOpCounter
                                                      TotalCounts
@@ -35,45 +36,34 @@
   (when-let [metric (get key->enum metric)]
     (.getCount counter metric)))

+(defn decorate-counts [^Metrics precipice-metrics]
+  (let [key->enum (enums/enum-class-to-keyword->enum
+                    (.getMetricClazz precipice-metrics))]
+    (with-meta
+      (reify
+        CountsView
+        (get-count [this metric]
+          (get-metric-count precipice-metrics metric key->enum)))
+      {:precipice-metrics precipice-metrics})))
+
 (defn no-op-counts
   ([] (no-op-counts EmptyEnum))
   ([^Class enum-class]
-   (let [key->enum (enums/enum-class-to-keyword->enum enum-class)
-         metrics (TotalCounts. (NoOpCounter. enum-class))]
-     (with-meta
-       (reify
-         CountsView
-         (get-count [this metric]
-           (get-metric-count metrics metric key->enum)))
-       {:precipice-metrics metrics}))))
+   (decorate-counts (TotalCounts. (NoOpCounter. enum-class)))))

 (defn count-metrics [^Class enum-class]
   (if-not (identical? enum-class EmptyEnum)
-    (let [key->enum (enums/enum-class-to-keyword->enum enum-class)
-          precipice-metrics (TotalCounts. enum-class)]
-      (with-meta
-        (reify CountsView
-          (get-count [this metric]
-            (get-metric-count precipice-metrics metric key->enum)))
-        {:precipice-metrics precipice-metrics}))
+    (decorate-counts (TotalCounts. enum-class))
     (no-op-counts)))

 (defn rolling-count-metrics
   ([enum-class] (rolling-count-metrics enum-class (* 60 15) 1 :seconds))
   ([^Class enum-class slots-to-track resolution time-unit]
    (if-not (identical? enum-class EmptyEnum)
-     (let [key->enum (enums/enum-class-to-keyword->enum enum-class)
-           precipice-metrics
-           (RollingCounts.
-             enum-class
-             (int slots-to-track)
-             (.toNanos ^TimeUnit (utils/->time-unit time-unit) (long resolution)))]
-       (with-meta
-         (reify
-           CountsView
-           (get-count [this metric]
-             (get-metric-count precipice-metrics metric key->enum)))
-         {:precipice-metrics precipice-metrics}))
+     (let [^TimeUnit time-unit (utils/->time-unit time-unit)
+           nanos-per (.toNanos time-unit (long resolution))]
+       (decorate-counts
+         (RollingCounts. enum-class (int slots-to-track) nanos-per)))
      (no-op-counts))))

 (defprotocol LatencyView
@@ -87,24 +77,24 @@
 (defn- precipice-metrics [enum-class]
   (TotalLatency. (ConcurrentHistogram. enum-class)))

-(defn- decorate-latency [key->enum precipice-metrics]
-  (with-meta
-    (reify
-      LatencyView
-      (get-latency [this metric percentile]
-        (latency-at-percentile precipice-metrics metric percentile key->enum)))
-    {:precipice-metrics precipice-metrics}))
+(defn- decorate-latency [^Metrics precipice-metrics]
+  (let [key->enum (enums/enum-class-to-keyword->enum
+                    (.getMetricClazz precipice-metrics))]
+    (with-meta
+      (reify
+        LatencyView
+        (get-latency [this metric percentile]
+          (latency-at-percentile precipice-metrics metric percentile key->enum)))
+      {:precipice-metrics precipice-metrics})))

 (defn no-op-latency-metrics
   ([] (no-op-latency-metrics EmptyEnum))
   ([^Class enum-class]
-   (let [key->enum (enums/enum-class-to-keyword->enum enum-class)
-         precipice-metrics (TotalLatency. (NoOpLatency. enum-class))]
-     (decorate-latency key->enum precipice-metrics))))
+   (let [precipice-metrics (TotalLatency. (NoOpLatency. enum-class))]
+     (decorate-latency precipice-metrics))))

 (defn latency-metrics [enum-class]
   (if-not (identical? enum-class EmptyEnum)
-    (let [key->enum (enums/enum-class-to-keyword->enum enum-class)
-          precipice-metrics (precipice-metrics enum-class)]
-      (decorate-latency key->enum precipice-metrics))
+    (let [precipice-metrics (precipice-metrics enum-class)]
+      (decorate-latency precipice-metrics))
     (no-op-latency-metrics)))