Start incorporating endpoint responses

Start incorporating endpoint responses

--- src/io/aviso/rook/swagger.clj
+++ src/io/aviso/rook/swagger.clj
@@ -51,38 +51,45 @@
                                    :required :true}))]
     (reduce reducer swagger-object path-ids)))

+(defn reduce-schema-key
+  "Simplifies a key from a schema reducing it to a keyword, and whether the key is required or optional."
+  [schema-key]
+  (cond (s/optional-key? schema-key)
+        [(.k schema-key) false]
+
+        (s/required-key? schema-key)
+        [(.k schema-key) true]
+
+        (keyword? schema-key)
+        [schema-key true]
+
+        :else
+        (throw (RuntimeException. (format "No idea what to do with query schema key %s." schema-key)))))
+
 (defn default-query-params-injector
   "Identifies each query parameter via the :query-schema metadata and injects it."
   [swagger-options swagger-object routing-entry params-key]
   (if-let [schema (-> routing-entry :meta :query-schema)]
     ;; Assumes that the schema is a map.
-    (let [reducer (fn [so [key-id key-schema]]
-                    (cond-let
-                      ;; Just ignore these, they are a convinience for the caller ("be generous in what you accept").
-                      (= s/Any key-id)
-                      so
-
-                      [[k required] (cond (s/optional-key? key-id)
-                                          [(.k key-id) false]
-
-                                          (s/required-key? key-id)
-                                          [(.k key-id) true]
-
-                                          (keyword? key-id)
-                                          [key-id true]
-
-                                          :else
-                                          (throw (ex-info (format "No idea what to do with query schema key %s." key-id)
-                                                          {:routing-entry routing-entry
-                                                           :key-id        key-id
-                                                           :key-schema    key-schema})))]
-
-                      :else
-                      (update-in so params-key
-                                 conj {:name     k
-                                       :in       :query
-                                       :required required})))]
-      (reduce reducer swagger-object schema))
+    (try
+      (let [reducer (fn [so [key-id key-schema]]
+                      (cond-let
+                        ;; Just ignore these, they are a convinience for the caller ("be generous in what you accept").
+                        (= s/Any key-id)
+                        so
+
+                        [[k required] (reduce-schema-key key-id)]
+
+                        :else
+                        (update-in so params-key
+                                   conj {:name     k
+                                         :in       :query
+                                         :required required})))]
+        (reduce reducer swagger-object schema))
+      (catch Exception e
+        (throw (ex-info "Unable to convert routing entry into Swagger data."
+                        routing-entry
+                        e))))
     ; no :query-schema
     swagger-object))

@@ -90,9 +97,11 @@
   [swagger-options schema]
   ;; To be done!
   (medley/remove-vals nil?
-                      {:required   []
-                       :description (-> schema meta :doc)
-                       :properties {}}))
+                      {:required    []
+                       ;; :description is often provided by with-description, which overrides the normal docstring.
+                       :description (or (-> schema meta :description)
+                                        (-> schema meta :doc))
+                       :properties  {}}))

 (defn to-schema-reference
   "Converts a schema to a schema reference; the schema must be named.  Returns a tuple
@@ -137,12 +146,24 @@
     ; no schema:
     swagger-object))

+(defn default-responses-injector
+  "Uses the :responses metadata to identify possible responses."
+  [swagger-options swagger-object routing-entry paths-key]
+  (let [responses (-> routing-entry :meta :responses)
+        reducer (fn [so [status-code schema]]
+                  (let [schema-meta (meta schema)
+                        description (or (:description schema-meta)
+                                        (:doc schema-meta)
+                                        "Documentation not provided.")]
+                    (assoc-in so (concat paths-key [:responses (str status-code)]) {:description description})))]
+    (reduce reducer swagger-object responses)))
+
 (defn default-path-item-object-injector
   "Injects a PathItemObject based on a routing entry.

   The paths-key is a coordinate into the swagger-object where the PathItemObject should be created.

-  Returns the modified swagger-object. "
+  Returns the modified swagger-object."
   [swagger-options swagger-object routing-entry paths-key]
   (let [{endpoint-meta :meta} routing-entry
         swagger-meta (:swagger endpoint-meta)
@@ -152,6 +173,7 @@
         path-params-injector (:path-params-injector swagger-options default-path-params-injector)
         query-params-injector (:query-params-injector swagger-options default-query-params-injector)
         body-params-injector (:body-params-injector swagger-options default-body-params-injector)
+        responses-injector (:responses-injector swagger-options default-responses-injector)
         params-key (concat paths-key ["parameters"])]
     (as-> swagger-object %
           (assoc-in % paths-key
@@ -162,7 +184,7 @@
           (path-params-injector swagger-options % routing-entry params-key)
           (query-params-injector swagger-options % routing-entry params-key)
           (body-params-injector swagger-options % routing-entry params-key)
-          (update-in % params-key #(sort-by :name %)))))
+          (responses-injector swagger-options % routing-entry paths-key))))

 (defn default-route-injector
   "The default route converter.  The swagger-options may contain an override of this function.
@@ -204,17 +226,26 @@
    :path   path
    :meta   endpoint-meta})

+(defn default-configurer
+  "The configurer is passed the final swagger object and can make final changes to it. This implementation
+  does nothing, returning the swagger object unchanged."
+  [swagger-options swagger-object routing-entries]
+  swagger-object)
+
 (defn construct-swagger-object
   "Constructs the root Swagger object from the Rook options, swagger options, and the routing table
   (part of the result from [[construct-namespace-handler]])."
   [swagger-options routing-table]
-  (let [{:keys [skeleton route-converter]
+  (let [{:keys [skeleton route-converter configurer]
          :or   {skeleton        default-swagger-skeleton
-                route-converter default-route-injector}} swagger-options]
-    (->> routing-table
-         vals
-         (apply concat)
-         (map routing-entry->map)
-         ;; Add the :no-swagger meta data to edit it out.
-         (remove #(-> % :meta :no-swagger))
-         (reduce (partial route-converter swagger-options) skeleton))))+                route-converter default-route-injector
+                configurer      default-configurer
+                }} swagger-options
+        routing-entries (->> routing-table
+                             vals
+                             (apply concat)
+                             (map routing-entry->map)
+                             ;; Endpoints with the :no-swagger meta data are ignored.
+                             (remove #(-> % :meta :no-swagger)))]
+    (as-> (reduce (partial route-converter swagger-options) skeleton routing-entries) %
+          (configurer swagger-options % routing-entries))))


print out :none if a ugen's arg has no default

--- src/overtone/sc/ugen/doc.clj
+++ src/overtone/sc/ugen/doc.clj
@@ -12,7 +12,7 @@
   "Returns a string representing the arguments of the ugen spec"
   [spec]
   (let [args (:args spec)
-        name-vals (map #(str (:name %) " " (:default %)) args)
+        name-vals (map #(str (:name %) " " (get % :default ":none")) args)
         line (apply str (interpose ", " name-vals))]
     (str "  [" line "]")))


Add note about Chrome working best.

Add note about Chrome working best.

--- src/klangmeister/ui/view.cljs
+++ src/klangmeister/ui/view.cljs
@@ -36,7 +36,8 @@
   (frame
     [:div
      [:p "Klangmeister is a live coding environment for the browser. It lets you design synthesisers and compose music using
-         computer code - without having to install anything on your own computer."]
+         computer code - without having to install anything on your own computer. Klangmeister works best in Chrome, because
+         the synthesis features that it relies on have patchy support across the other browsers."]
      [:p [:a {:href "https://twitter.com/ctford"} "I"] " recommend starting with the " [:a {:href "/synthesis"} "synthesis tutorial"] "."]]))

 (defn music [handle! state-atom]


Re-add accidentally removed do

Re-add accidentally removed do

--- src/onyx/plugin/datomic.clj
+++ src/onyx/plugin/datomic.clj
@@ -218,15 +218,16 @@
                                              (take read-size
                                                    (seq
                                                      (d/tx-range (d/log conn) tx-index max-tx))))]
-                            (doseq [entry entries]
-                              (>!! ch
-                                   (t/input (java.util.UUID/randomUUID)
-                                            (update (into {} entry)
-                                                    :data (partial map unroll-log-datom)))))
-                            (let [last-t (:t (last entries))
-                                  next-t (inc last-t)]
-                              (if (not= last-t max-tx)
-                                (recur next-t)))
+                            (do
+                              (doseq [entry entries]
+                                (>!! ch
+                                     (t/input (java.util.UUID/randomUUID)
+                                              (update (into {} entry)
+                                                      :data (partial map unroll-log-datom)))))
+                              (let [last-t (:t (last entries))
+                                    next-t (inc last-t)]
+                                (if (not= last-t max-tx)
+                                  (recur next-t))))
                             ;; timeout could be used to backoff here
                             ;; when no entries are read
                             (recur tx-index)))


working on synths

working on synths

--- src/overtone/inst/synth.clj
+++ src/overtone/inst/synth.clj
@@ -3,8 +3,7 @@
         [overtone.sc.machinery.ugen.fn-gen]
         [overtone.studio rig]))

-
-(definst tick [freq 880]
+(definst ticker [freq 880]
   (* (env-gen (perc 0.001 0.01) :action FREE)
      (sin-osc freq)))

@@ -34,6 +33,7 @@
 (definst mooger
   [note 60 amp 0.8
    osc1 0 osc2 1     ; Choose 0 1 2 for saw, sin, or pulse
+   osc1-level 0.5 osc2-level 0.5
    cutoff 500
    attack 0.1 decay 0.1 sustain 0.7 release 0.2
    fattack 0.1 fdecay 0.1 fsustain 0.9 frelease 0.2
@@ -43,8 +43,8 @@
         osc-bank-2 [(saw freq) (sin-osc freq) (pulse freq)]
         amp-env (env-gen (adsr attack decay sustain release) gate :action FREE)
         f-env (env-gen (adsr fattack fdecay fsustain frelease) gate :action FREE)
-        s1 (select osc1 osc-bank-1)
-        s2 (select osc2 osc-bank-2)
+        s1 (* osc1-level (select osc1 osc-bank-1))
+        s2 (* osc2-level (select osc2 osc-bank-2))
         filt (moog-ff (+ s1 s2) (* cutoff f-env) 3)]
     (* amp filt)))

@@ -62,12 +62,14 @@
         echo       (comb-n reverb 0.4 0.3 0.5)]
     (* amp echo)))

-(definst pad [note 60 t 4 amt 0.3 amp 0.8]
+(definst pad [note 60 t 10 amt 0.3 amp 0.8 a 0.4 d 0.5 s 0.8 r 2]
   (let [freq       (midicps note)
-        f-env      (env-gen (perc t t) 1 1 0 1 FREE)
-        src        (saw [freq (* freq (+ 2 (* 0.01 (sin-osc:kr 5 (rand 1.5)))))])
-        signal     (rlpf (* 0.9 src)
-                         (+ (* 0.3 freq) (* f-env 4 freq)) 0.5)
+        lfo        (+ 2 (* 0.01 (sin-osc:kr 5 (rand 1.5))))
+        src        (apply + (saw [freq (* freq lfo)]))
+        env        (env-gen (adsr a d s r) (sin-osc:kr 0.2))
+        f-env      (x-line:kr 0.001 4 t)
+        src        (* env src)
+        signal     (rlpf src (+ (* 0.3 freq) (* f-env 2 freq)) 0.5)
         k          (/ (* 4 amt) (- 1 amt))
         dist       (clip2 (/ (* (+ 1 k) signal) (+ 1 (* k (abs signal))))
                           0.03)]


show first line only in waiting habit

show first line only in waiting habit

--- src/cljs/iwaswhere_web/ui/entry/briefing.cljs
+++ src/cljs/iwaswhere_web/ui/entry/briefing.cljs
@@ -92,7 +92,11 @@
                 ^{:key ts}
                 [:li.habit
                  {:on-click (up/add-search ts tab-group put-fn)}
-                 [:strong (s/replace (:md waiting-habit) "#habit" "")]]))]
+                 [:strong (-> waiting-habit
+                              :md
+                              (s/replace "#habit" "")
+                              s/split-lines
+                              first)]]))]
            [:form.briefing-details
             [:fieldset
              [:legend (or day "date not set")]


bumped up cljs version

bumped up cljs version

--- src/leiningen/new/reagent.clj
+++ src/leiningen/new/reagent.clj
@@ -30,7 +30,7 @@

 (def lib-or-app-dependencies
   "Dependencies for development or as part of an app."
-  '[[org.clojure/clojurescript "0.0-2755" :scope "provided"]
+  '[[org.clojure/clojurescript "0.0-2760" :scope "provided"]
     [com.cemerick/piggieback "0.1.5"]
     [weasel "0.5.0"]
     [ring "1.3.2"]


fix previous commit

fix previous commit

--- src/blind/reader.clj
+++ src/blind/reader.clj
@@ -647,7 +647,7 @@
         (recur (next s) (-> key-vals
                             (conj! (key e))
                             (conj! (val e)))))
-      (persistent! key-vals))))
+      (seq (persistent! key-vals)))))

 (defn- register-gensym [sym]
   (if-not gensym-env


Make dirs-on-classpath* private

Make dirs-on-classpath* private

--- src/refactor_nrepl/util.clj
+++ src/refactor_nrepl/util.clj
@@ -23,7 +23,10 @@
     (.replaceAll path (Pattern/quote "\\") "/")
     path))

-(defn dirs-on-classpath* []
+(defn- dirs-on-classpath*
+  "Return all dirs on classpath, filterout out our inlined deps
+  directory."
+  []
   (->> (cp/classpath)
        (filter fs/directory?)
        (remove #(-> % str (.endsWith "target/srcdeps")))))


Added docstring

Added docstring

--- src/riemann/stackdriver.clj
+++ src/riemann/stackdriver.clj
@@ -8,12 +8,13 @@
 (def gateway-url "https://custom-gateway.stackdriver.com/v1/custom")

 (defn metric-name
-  "Constructs a metric-name for an event."
+  "Constructs a metric name from an event."
   [opts event]
   (let [service ((:name opts) event)]
      (replace service #"\s+" ".")))

 (defn generate-datapoint
+  "Accepts riemann event/events and converts it into equivalent stackdriver datapoint."
   [opts event-or-events]
   (let [events (if (sequential? event-or-events) event-or-events (list event-or-events))]
     (map (fn [event]
@@ -31,7 +32,7 @@
     (client/post uri http-options)))

 (defn stackdriver
-  "Returns a function which accepts an event and sends it to Stackdriver."
+  "Returns a function which accepts an event/events and sends it to Stackdriver."
   [opts]
   (let [ts (atom 0)
         opts (merge {:api-key "stackdriver-api-key"


Don't pass on-save as props to input field.

Fixes #8

--- src/day8/re_frame/trace.cljs
+++ src/day8/re_frame/trace.cljs
@@ -113,17 +113,16 @@
 (defn search-input [{:keys [title on-save on-stop]}]
   (let [val  (r/atom title)
         save #(let [v (-> @val str clojure.string/trim)]
-               (on-save v))]
-    (fn [props]
-      [:input (merge props
-                     {:type        "text"
-                      :value       @val
-                      :auto-focus  true
-                      :on-blur     save
-                      :on-change   #(reset! val (-> % .-target .-value))
-                      :on-key-down #(case (.-which %)
-                                     13 (save)
-                                     nil)})])))
+                (on-save v))]
+    (fn []
+      [:input {:type        "text"
+               :value       @val
+               :auto-focus  true
+               :on-blur     save
+               :on-change   #(reset! val (-> % .-target .-value))
+               :on-key-down #(case (.-which %)
+                               13 (save)
+                               nil)}])))

 (defn render-traces []


Remove unused require

Remove unused require

--- src/time_tracker/config.clj
+++ src/time_tracker/config.clj
@@ -1,8 +1,7 @@
 (ns time-tracker.config
   (:require [clojure.java.io :as io]
             [nomad :refer [defconfig]]
-            [ragtime.jdbc]
-            [ragtime.repl]))
+            [ragtime.jdbc]))

 (defconfig app-config (io/file "config/backend-config.edn"))

@@ -12,3 +11,4 @@
   {:datastore  (ragtime.jdbc/sql-database {:connection-uri (:db-connection-string (app-config))})
    :migrations (ragtime.jdbc/load-resources (:migrations-resource-dir (app-config)))})

+


Story ID: develop Added support for testing the existence of a desired DOM element

--- src/untangled/test/dom.cljs
+++ src/untangled/test/dom.cljs
@@ -90,6 +90,15 @@
     )
   )

+(defn has-element
+  "Same assertion as has-visible-text, but doesn't check the component's innerHTML. Uses find-element to
+  process search-kind and search-param on the given dom, then asserts that the returned element is not nil."
+  [search-kind search-param dom]
+  (if (find-element search-kind search-param dom)
+    (t/do-report {:type :pass})
+    (t/do-report {:type :error :message (str "Could not find element " search-kind " " search-param)
+                  :expected "DOM element" :actual "Nil"})))
+

 (defn has-selected-option [search-type search-value dom-with-select selected-value]
   (if-let [ele (find-element search-type search-value dom-with-select)]


Remove unused metadata from workspace var.

--- src/uxbox/ui/workspace.cljs
+++ src/uxbox/ui/workspace.cljs
@@ -145,7 +145,7 @@
        (when right-sidebar?
          (right-sidebar))]])))

-(def ^:static workspace
+(def workspace
   (mx/component
    {:render workspace-render
     :transfer-state workspace-transfer-state


Update index catalog code.

Update index catalog code.

--- src/vault/index/catalog.clj
+++ src/vault/index/catalog.clj
@@ -18,14 +18,6 @@
 (defrecord IndexCatalog
   [indexes blob-key])

-; Blob index schema:
-#_
-{:blob      HashID      ; blob hash-id (pk)
- :size      Long        ; blob byte length
- :type      Keyword     ; data type
- :label     String      ; type-specific annotation
- :stored-at DateTime}   ; time added to index
-
 (extend-type IndexCatalog
   store/BlobStore

@@ -34,25 +26,26 @@
     (store/select-ids opts
       ; TODO: this is where being able to do real queries would help;
       ; specifically, for :after and :prefix.
-      (engine/search (get-blob-index this) {} nil)))
+      (engine/search (get-blob-index this) {})))

   (stat
     [this id]
-    (-> (get-blob-index this)
-        (engine/search {:blob id} nil)
-        first))
+    (when id
+      (-> (get-blob-index this)
+          (engine/search {:blob id})
+          first)))

-  (put! [this blob]
-    ; TODO: check whether blob has been seen
-    (when blob
+  (put!
+    [this blob]
+    (when-not (store/stat this (:id blob))
       ; TODO: ensure blob has been parsed?
-      (for [index (vals (:indexes this))]
+      (doseq [index (vals (:indexes this))]
         (when-let [projection (:projection index)]
-          (for [record (projection blob)]
-            (engine/update! index record))))
-      blob)))
+          (doseq [record (projection blob)]
+            (engine/update! index record)))))
+    blob))

 (defn index-catalog


work arround warnings in rrb-vector

work arround warnings in rrb-vector

--- src/main/shadow/build/compiler.clj
+++ src/main/shadow/build/compiler.clj
@@ -1085,8 +1085,18 @@
          ;; sorted by descending length to avoid bailing too early
          ;; some.foo.bar.thing should always hit some.foo.bar and never some.foo if both exist
          cljs-provides
-         (->> cljs
-              (map :ns)
+         (into #{} (map :ns) cljs)
+
+         ;; work around problems where rrb-vector uses direct reference to
+         ;; clojure.core.rrb_vector.rrbt.Vector
+         ;; which will never be found in analyzer data since it should be
+         ;; clojure.core.rrb-vector.rrbt/Vector
+         ;; https://github.com/clojure/core.rrb-vector/blob/88c605a72f1176813ca71d664275d480285f634e/src/main/cljs/clojure/core/rrb_vector/macros.clj#L23-L24
+         ;; only doing this to relax warnings given that this is a probably-wont-fix in CLJS
+         cljs-provides
+         (->> cljs-provides
+              (map comp/munge)
+              (into cljs-provides)
               (sort-by #(-> % str count))
               (reverse)
               (into []))


Inbox: Don't implement ColumnSource for NewDocumentColumn.

--- src-cljs/pepa/workflows/inbox2.cljs
+++ src-cljs/pepa/workflows/inbox2.cljs
@@ -113,16 +113,9 @@

 (declare new-document-ui)

-(defrecord NewDocumentColumnSource [id]
+(defrecord NewDocumentColumn [id]
   SpecialColumn
   (special-column-ui [_] new-document-ui)
-  ColumnSource
-  (column-title [_ _]
-    "Create New Document")
-  (column-header-url [_] nil)
-  (column-pages [_ _] [])
-  (remove-pages! [_ state page-ids]
-    (assert false "Can't remove pages from NewDocumentColumnSource"))
   ColumnDropTarget
   (accept-drop! [_ state new-pages _]
     (go
@@ -269,8 +262,7 @@
                                           source-column
                                           page-ids
                                           0)))}
-     [:header
-      (column-title column state)]
+     [:header nil]
      [:.center
       "Drag pages here or press \"Open to open a file or document"
       [:button {:on-click (fn [e]
@@ -283,7 +275,9 @@
         target  (first (filter #(= (:id %) target) columns))
         source  (first (filter #(= (:id %) source) columns))
         ;; Remove page-ids already in `target'
-        existing-pages (mapv :id (column-pages target state))
+        existing-pages (mapv :id (if (satisfies? ColumnSource target)
+                                   (column-pages target state)
+                                   []))
         pages (into []
                     (comp (remove (set existing-pages))
                           (map page-cache)
@@ -311,7 +305,7 @@
 (defn ^:private make-page-cache [state columns]
   (into {}
         ;; Transducerpower
-        (comp (mapcat #(column-pages % state))
+        (comp (mapcat #(when (satisfies? ColumnSource %) (column-pages % state)))
               (map om/value)
               (map (juxt :id identity)))
         columns))
@@ -366,9 +360,9 @@
       (let [gen (IdGenerator.getInstance)
             columns (for [column columns]
                       (match [column]
-                        [[:document id]] (->DocumentColumnSource (.getNextUniqueId gen) id)
-                        [[:inbox _]]     (->InboxColumnSource (.getNextUniqueId gen))
-                        [[:new-document _]]     (->NewDocumentColumnSource (.getNextUniqueId gen))))]
+                        [[:document id]]    (->DocumentColumnSource (.getNextUniqueId gen) id)
+                        [[:inbox _]]        (->InboxColumnSource (.getNextUniqueId gen))
+                        [[:new-document _]] (->NewDocumentColumn (.getNextUniqueId gen))))]
         (filterv identity columns)))))

 (defn- prepare-columns! [props state owner]


Add default thumbup rection to every entry.

--- src/oc/storage/resources/reaction.clj
+++ src/oc/storage/resources/reaction.clj
@@ -9,11 +9,14 @@
     (if-let [existing-reaction (reactions unicode)]
       ;; have this unicode already, so add this reaction to it
       (assoc reactions unicode (-> existing-reaction
-                                  (update :count inc)
-                                  (update :authors #(conj % author))
-                                  (update :author-ids #(conj % author-id))))
+                                  (update :count + (:count reaction))
+                                  (update :authors #(remove nil? (conj % author)))
+                                  (update :author-ids #(remove nil? (conj % author-id)))))
       ;; haven't seen this reaction unicode before, so init a new one
-      (assoc reactions unicode {:reaction unicode :count 1 :authors [author] :author-ids [author-id]}))))
+      (assoc reactions unicode {:reaction unicode
+                                :count (if author 1 0)
+                                :authors (remove nil? [author])
+                                :author-ids (remove nil? [author-id])}))))

 (defn aggregate-reactions
   "
@@ -21,4 +24,6 @@
   that include the count of how many times reacted and the list of author names and IDs that reacted.
   "
   [entry-reactions]
-  (or (vals (reduce reaction-collapse {} (map #(assoc % :count 1) entry-reactions))) []))+  (let [fixed-entry-reactions (conj (map #(assoc % :count 1) entry-reactions) {:reaction "👍" :count 0})
+        collapsed-reactions (vals (reduce reaction-collapse {} fixed-entry-reactions))]
+    (or collapsed-reactions [])))


Reduce over it.

Reduce over it.

--- src/onyx/peer/pipeline_extensions.clj
+++ src/onyx/peer/pipeline_extensions.clj
@@ -16,10 +16,11 @@
   (:onyx/type (find-task (:catalog event) (:task event))))

 (defn merge-api-levels [f event]
-  (let [x (merge event (f name-dispatch event))
-        x (merge x (f ident-dispatch x))
-        x (merge x (f type-and-medium-dispatch x))]
-    (merge x (f type-dispatch x))))
+  (reduce
+   (fn [result g]
+     (merge result (f g)))
+   event
+   [name-dispatch ident-dispatch type-and-medium-dispatch type-dispatch]))

 (defmulti inject-pipeline-resources
   "Adds keys to the event map. This function is called once


Replace broken swing stuff with working seesaw stuff

Courtesy of @Tcepsa

--- src/overtone/examples/gui/keynome.clj
+++ src/overtone/examples/gui/keynome.clj
@@ -1,41 +1,34 @@
 (ns overtone.examples.gui.keynome
   (:use overtone.live)
-  (:import [java.awt GridLayout Dimension]
-           [java.awt.event ActionListener KeyListener KeyEvent]
-           [javax.swing JFrame JButton JPanel]))
+  (:require [seesaw [core :as sscore]
+                    [keymap :as sskeymap]]))

 (def keyboard
-  (let [cm (keyword ","), sl (keyword "/"), sc (keyword ";"),
-        mi (keyword "-"), lb (keyword "["), rb (keyword "]"),
-        qt (keyword "'")]
-    [:1 :2 :3 :4 :5 :6 :7 :8 :9 :0 mi
-     :q :w :e :r :t :y :u :i :o :p lb
-     :a :s :d :f :g :h :j :k :l sc qt
-     :z :x :c :v :b :n :m cm :. sl rb]))
+  [:1 :2 :3 :4 :5 :6 :7
+   :q :w :e :r :t :y :u
+   :a :s :d :f :g :h :j
+   :z :x :c :v :b :n :m ])

 (defn new-keynome []
-  (let [grid-layout (GridLayout. 4 11)
-        action-map (ref {})
-        buttons (for [kwd keyboard] (JButton. (str kwd)))
-        panel (JPanel.)
-        fire (fn [e am]
-               (let [key (str (.getKeyChar e))
-                     f (@am (keyword key))]
-                 (do (if f (f) (println "key" key "pressed, no action")))))
-        key-listener (proxy [KeyListener] []
-                       (keyPressed [e] (fire e action-map))
-                       (keyReleased [e] nil) (keyTyped [e] nil))
-        frame (JFrame. "kbdnome")]
-    (do (doall (for [b buttons] (do (.add panel b))))
-        (doto panel
-          (.setLayout grid-layout)
-          (.addKeyListener key-listener)
-          (.setFocusable true)
-          (.setFocusTraversalKeysEnabled false))
-        (.add (.getContentPane frame) panel)
-        (doto frame (.pack) (.setVisible true))
-        {:frame frame :action-map action-map
-         :buttons (apply hash-map (interleave keyboard buttons))})))
+  (let [action-map (ref {})
+        click-handler (fn [e]
+                        (let [key (keyword (sscore/config e :text))
+                              f (@action-map key)]
+                          (if f
+                            (f)
+                            (println "Key" key "pressed, no action"))))
+        buttons (for [kwd keyboard]
+                  (let [ b (sscore/button :text (name kwd))]
+                    (sscore/listen b :action click-handler)
+                    b))
+        panel (sscore/grid-panel :rows 4 :columns 7 :hgap 5 :vgap 5 :items buttons)
+        frame (sscore/frame :title "SeeSaw Keynome"
+                            :content panel)]
+    (doseq [btn buttons] (sskeymap/map-key frame (.toUpperCase (sscore/config btn :text)) btn :scope :global))
+    (-> frame sscore/pack! sscore/show!)
+    {:frame frame
+     :action-map action-map
+     :buttons (apply hash-map (interleave keyboard buttons))}))

 (defn set-actions [ & stuff]
   (let [am ((first stuff) :action-map)


Revert to supporting just one changelog per request

--- src/pdok/featured_to_extracts/api.clj
+++ src/pdok/featured_to_extracts/api.clj
@@ -43,7 +43,7 @@
 (def ExtractRequest
   "A schema for a JSON extract request"
   {:dataset                   s/Str
-   :changeLogs                [URI]
+   :changeLog                 URI
    (s/optional-key :format)   (s/enum "csv" "zip")
    :extractTypes              [s/Str]
    (s/optional-key :callback) URI})
@@ -90,7 +90,7 @@
   (let [dataset (:dataset request)
         extract-types (:extractTypes request)
         zipped? (if (nil? (:format request)) true (= (:format request) "zip"))
-        [file err] (download-file (first (:changeLogs request)) zipped?)]
+        [file err] (download-file (:changeLog request) zipped?)]
     (if-not file
       (do
         (swap! stats assoc-in [:processing worker-id] nil)
@@ -99,7 +99,7 @@
                                           (if err err "Something went wrong downloading"))))
       (try
         (with-open [in (io/input-stream file)]
-          (let [_ (log/info "Processing file:" (first (:changeLogs request)))
+          (let [_ (log/info "Processing file:" (:changeLog request))
                 result (core/update-extracts dataset extract-types in)
                 run-stats (merge request result)]
             (swap! stats assoc-in [:processing worker-id] nil)


add scale-to-(width|height)-only routes

add scale-to-(width|height)-only routes

* scale-only-down was removed
* there are two separate resources for scaling down for weight and height

--- src/vignette/http/routes.clj
+++ src/vignette/http/routes.clj
@@ -76,7 +76,7 @@
                   :thumbnail-mode "scale-to-width"
                   :width size-regex}))

-(def scale-only-down-route
+(def scale-to-width-down-route
   (route-compile "/:wikia:image-type/:top-dir/:middle-dir/:original/revision/:revision/:thumbnail-mode/:width"
                  {:wikia wikia-regex
                   :image-type image-type-regex
@@ -84,8 +84,19 @@
                   :middle-dir middle-dir-regex
                   :original original-regex
                   :revision revision-regex
-                  :thumbnail-mode "scale-only-down"
+                  :thumbnail-mode "scale-to-width-down"
                   :width size-regex}))
+
+(def scale-to-height-down-route
+  (route-compile "/:wikia:image-type/:top-dir/:middle-dir/:original/revision/:revision/:thumbnail-mode/:height"
+                 {:wikia wikia-regex
+                  :image-type image-type-regex
+                  :top-dir top-dir-regex
+                  :middle-dir middle-dir-regex
+                  :original original-regex
+                  :revision revision-regex
+                  :thumbnail-mode "scale-to-width-down"
+                  :height size-regex}))

 (defn create-request-handlers
   "Creates request handlers for a given route for GET & HEAD using the given route and
@@ -108,6 +119,8 @@
   [system]
   (flatten
     [(create-request-handlers system scale-to-width-route handle-thumbnail route->thumbnail-auto-height-map)
+     (create-request-handlers system scale-to-width-down-route handle-thumbnail route->thumbnail-auto-height-map)
+     (create-request-handlers system scale-to-height-down-route handle-thumbnail route->thumbnail-auto-width-map)
      (create-request-handlers system window-crop-route handle-thumbnail route->thumbnail-auto-height-map)
      (create-request-handlers system window-crop-fixed-route handle-thumbnail route->thumbnail-map)
      (create-request-handlers system thumbnail-route handle-thumbnail route->thumbnail-map)


add precondition

add precondition

--- src/puppetlabs/trapperkeeper/core.clj
+++ src/puppetlabs/trapperkeeper/core.clj
@@ -172,6 +172,7 @@
   `cli-data` is expected to be a map constructed by parsing the CLI args.
   (see `parse-cli-args`)"
   [cli-data]
+  {:pre [(map? cli-data)]}
   (-> cli-data
       (bootstrap)
       (run-app)))


Add documentation to has-command-prefix method

--- src/yetibot/core/handler.clj
+++ src/yetibot/core/handler.clj
@@ -52,7 +52,9 @@
        ; ensure prefix is actually a command
        (filter #(command? (-> % second second second)))))

-(defn has-command-prefix? [body]
+(defn has-command-prefix?
+  "Returns true if body has an command matching the prefix !"
+  [body]
   (re-find #"^\!(.+)" body))

 (defn handle-raw


Clears input after submit Fixes #10

Clears input after submit
Fixes #10

--- src/todo_mvc/input_todo.cljs
+++ src/todo_mvc/input_todo.cljs
@@ -15,7 +15,8 @@
        [text-input {:style             {:height     58
                                         :font-style (if (zero? (count @state)) "italic" "normal")
                                         :fontSize   16}
-                    :on-submit-editing #(rf/dispatch [:add-todo (.. % -nativeEvent -text)])
+                    :on-submit-editing #(do (rf/dispatch [:add-todo (.. % -nativeEvent -text)])
+                                            (reset! state ""))
                     :on-change-text    #(reset! state (str %))
                     :placeholder       "What needs to be done?"
                     :default-value     @state}]])))


remove unneeded ref to private fn :disappointed_relieved:

--- src/metabase/driver/mongo.clj
+++ src/metabase/driver/mongo.clj
@@ -13,7 +13,7 @@
             [metabase.driver :as driver]
             [metabase.driver.interface :refer :all]
             (metabase.driver.mongo [query-processor :as qp]
-                                   [util :refer [*mongo-connection* with-mongo-connection values->base-type details-map->connection-string]])))
+                                   [util :refer [*mongo-connection* with-mongo-connection values->base-type]])))

 (declare driver)


Fix completion-eval to not bind to namespaces that don't exist.

The `reply.eval-modes.nrepl/completion-eval` function would attempt to
bind `*ns*` to the value inside `current-ns`, which starts out as
`reply.eval-modes.nrepl`, a namespace that exists on the client but
usually doesn't exist on the server.

This patch changes it so that it falls back to the current value of
`*ns*` if the namespace in question doesn't exist.

--- src/clj/reply/eval_modes/nrepl.clj
+++ src/clj/reply/eval_modes/nrepl.clj
@@ -173,7 +173,9 @@
        :session session}
       (binding [*print-length* nil
                 *print-level* nil]
-        (pr-str `(binding [*ns* (the-ns (symbol ~(deref current-ns)))] ~form))))
+        (pr-str `(binding [*ns* (or (find-ns (symbol ~(deref current-ns)))
+                                    *ns*)]
+                   ~form))))
     (read-string @results)))

 (defn poll-for-responses [{:keys [print-out print-err] :as options} connection]


Refresh builder after setting SDK/RoboVM paths

--- src/clojure/nightcode/builders.clj
+++ src/clojure/nightcode/builders.clj
@@ -9,6 +9,8 @@
             [seesaw.color :as color]
             [seesaw.core :as s]))

+(declare show-builder)
+
 ; keep track of open builders

 (def builders (atom {}))
@@ -27,14 +29,16 @@
   (when-let [dir (chooser/choose-file :dir (utils/read-pref :android-sdk)
                                       :selection-mode :dirs-only
                                       :remember-directory? false)]
-    (utils/write-pref :android-sdk (.getCanonicalPath dir))))
+    (utils/write-pref :android-sdk (.getCanonicalPath dir))
+    (show-builder (ui/get-selected-path))))

 (defn set-robovm
   [_]
   (when-let [dir (chooser/choose-file :dir (utils/read-pref :robovm)
                                       :selection-mode :dirs-only
                                       :remember-directory? false)]
-    (utils/write-pref :robovm (.getCanonicalPath dir))))
+    (utils/write-pref :robovm (.getCanonicalPath dir))
+    (show-builder (ui/get-selected-path))))

 (defn eval-in-repl
   [console path timestamp]


db/content.clj: comments

db/content.clj: comments

--- src/org/altlaw/db/content.clj
+++ src/org/altlaw/db/content.clj
@@ -12,6 +12,9 @@

 (defn get-page [path]
   (s3/get-object-string *bucket* (str "www/" path)))
+
+
+;;; Content objects, identified by SHA1 hash

 (defn put-content-string [content metadata]
   (let [hash (DigestUtils/shaHex content)


improve docstring arglists by referring to metro as metro not this

--- src/overtone/music/rhythm.clj
+++ src/overtone/music/rhythm.clj
@@ -8,15 +8,15 @@
   _PROTOCOLS_
   (do
     (defprotocol IMetronome
-      (metro-start [this] [this start-beat]
+      (metro-start [metro] [metro start-beat]
         "Returns the start time of the metronome. Also restarts the metronome at
      'start-beat' if given.")
-      (metro-tick [this]
+      (metro-tick [metro]
         "Returns the duration of one metronome 'tick' in milleseconds.")
-      (metro-beat [this] [this beat]
+      (metro-beat [metro] [metro beat]
         "Returns the next beat number or the timestamp (in milliseconds) of the
      given beat.")
-      (metro-bpm [this] [this new-bpm]
+      (metro-bpm [metro] [metro new-bpm]
         "Get the current bpm or change the bpm to 'new-bpm'."))))

 ; Rhythm
@@ -42,17 +42,17 @@
   IMetronome
   (metro-start [metro] @start)
   (metro-start [metro start-beat]
-    (let [new-start (- (now) (* start-beat (metro-tick this)))]
+    (let [new-start (- (now) (* start-beat (metro-tick metro)))]
       (reset! start new-start)
       new-start))
   (metro-tick  [metro] (beat-ms 1 @bpm))
-  (metro-beat  [metro] (inc (long (/ (- (now) @start) (metro-tick this)))))
-  (metro-beat  [metro b] (+ (* b (metro-tick this)) @start))
+  (metro-beat  [metro] (inc (long (/ (- (now) @start) (metro-tick metro)))))
+  (metro-beat  [metro b] (+ (* b (metro-tick metro)) @start))
   (metro-bpm   [metro] @bpm)
   (metro-bpm   [metro new-bpm]
-    (let [cur-beat (metro-beat this)
+    (let [cur-beat (metro-beat metro)
           new-tick (beat-ms 1 new-bpm)
-          new-start (- (metro-beat this cur-beat) (* new-tick cur-beat))]
+          new-start (- (metro-beat metro cur-beat) (* new-tick cur-beat))]
       (reset! start new-start)
       (reset! bpm new-bpm))
     [:bpm new-bpm])


Implement ordensgruppen import

Implement ordensgruppen import

--- adressverzeichnis/clj-migrate/migrate.clj
+++ adressverzeichnis/clj-migrate/migrate.clj
@@ -11,12 +11,12 @@

 (deps/add-deps
  '{:deps
-   {honeysql/honeysql {:mvn/version "1.0.444"}
+   {com.github.seancorfield/honeysql {:mvn/version "2.1.818"}
     org.clojure/data.csv {:mvn/version "1.0.0"}}})

 (require '[clojure.data.csv :as csv]
-         '[honeysql.core :as sql]
-         '[honeysql.helpers :as helpers])
+         '[honey.sql :as sql]
+         '[honey.sql.helpers :as helpers :refer [select insert-into values from where on-conflict do-nothing]])

 (def path-to-csv (first *command-line-args*))

@@ -183,26 +183,85 @@
        "INSERT INTO public.adressverzeichnis_manuelleberechtigung (" (str/join "," (map name fields)) ", erstellt, veraendert, person_id, organ_id) "
        "VALUES "(str/join ", " values)";"))))

+(defn ordensgruppe-mitgliedschaft-sql [ordensgruppe old-id]
+  (when-not (str/blank? ordensgruppe)
+    (str
+      "INSERT INTO public.adressverzeichnis_amt (erstellt, veraendert, bestaetigt, gruppierung_id, person_id, typ_id)
+       VALUES ('now', 'now', false, "
+      (str/join ","
+        [(str "(SELECT id from public.adressverzeichnis_gruppierung WHERE adressverzeichnis_gruppierung.name = '" ordensgruppe "')")
+         (str "(SELECT id from public.adressverzeichnis_person WHERE adressverzeichnis_person.alte_id = " old-id ")")
+         (str "(SELECT id from public.adressverzeichnis_amttyp WHERE adressverzeichnis_amttyp.name = 'Mitglied')")])
+      ");")))
+
 (defn person-sql [person]
-  (let [person (dissoc person :Gruppe :Älterengemeinschaft :Ordensgruppe :Amt :Ordensamt :Übergeordnetegruppe :Änderungsdatum :Hilfsgruppe
-                      )
-        fields (keys (dissoc person :address :numbers :permissions))
+  (let [person (dissoc person :Gruppe :Älterengemeinschaft  :Amt :Ordensamt :Übergeordnetegruppe :Änderungsdatum :Hilfsgruppe)
+
+        fields (keys (dissoc person :address :numbers :permissions :Ordensgruppe))
         old-id (:alte_id person)]
     (str/join "\n"
      [(str "INSERT INTO adressverzeichnis_person (" (str/join "," (map name fields)) ",erstellt, veraendert) VALUES (" (str/join "," (map #(format-value (get person %)) fields)) ",'now','now');")
       (adress-sql (:address person) old-id)
       (phones-sql (:numbers person) old-id)
       (permissions-sql (:permissions person) old-id)
+      (ordensgruppe-mitgliedschaft-sql (:Ordensgruppe person) old-id)
       ""])))

-(defn persons-sql [persons]
-  (let [persons (map #(dissoc % :Gruppe :ID :Älterengemeinschaft :Ordensgruppe :Amt :Ordensamt :Übergeordnetegruppe :Änderungsdatum :Hilfsgruppe
-                              :address :permissions :numbers) persons)]
-    []))
-
+(defn ordensgruppe-typ [ordensgruppe]
+  (cond
+    (str/includes? ordensgruppe "Konvent") "Konvent"
+    (str/includes? ordensgruppe "Aufbaukollegium") "Aufbaukollegium"
+    (str/includes? ordensgruppe "Kollegium") "Kollegium"))
+
+(defn ordensgruppe-types-sql [ordensgruppe-types]
+  (->
+   (insert-into :public.adressverzeichnis_gruppierungstyp)
+   (values (for [ordensgruppe-typ ordensgruppe-types]
+              {:name ordensgruppe-typ}))))
+
+(defn ordensgruppen-sql [ordensgruppen]
+  (->
+   (insert-into :public.adressverzeichnis_gruppierung)
+   (values
+     (for [{:keys [Ordensgruppe Älterengemeinschaft]} ordensgruppen
+           :when (not (str/blank? Ordensgruppe))]
+       {:name Ordensgruppe
+        :obergruppe_id
+        (when-not (str/blank? Älterengemeinschaft)
+          (-> (select :id)
+              (from :public.adressverzeichnis_gruppierung)
+              (where [:= :name Älterengemeinschaft])))
+        :typ_id
+        (when-let [typ (ordensgruppe-typ Ordensgruppe)]
+          (-> (select :id)
+              (from :public.adressverzeichnis_gruppierungstyp)
+              (where [:= :name typ])))}))))
+
+(defn älterengemeinschaften-sql [älterengemeinschaften]
+  (->
+   (insert-into :public.adressverzeichnis_gruppierung)
+   (values (for [gemeinschaft älterengemeinschaften
+                 :when (not (str/blank? gemeinschaft))]
+             {:name gemeinschaft}))))
+
+
+(defn format-sql [sql-map]
+  (-> sql-map
+   (update :values (fn [values] (map #(assoc % :veraendert "now", :erstellt "now") values)))
+   on-conflict do-nothing ; do-update-set
+   (sql/format {:inline true, :checking :strict})
+   (first)
+   (str ";")))

 (print
-  (str "BEGIN;\n"
-    (str/join "\n"
-      (map (comp person-sql parse-person) old))
-    "\nCOMMIT;"))+  (let [persons (map parse-person old)]
+      (str "BEGIN;\n"
+        (str/join "\n"
+          (concat
+            (map format-sql
+              (let [ordensgruppen (into #{} (map #(select-keys % #{:Ordensgruppe :Älterengemeinschaft})) persons)]
+                [(älterengemeinschaften-sql (set (map :Älterengemeinschaft ordensgruppen)))
+                 (ordensgruppe-types-sql (disj (set (map ordensgruppe-typ (map :Ordensgruppe ordensgruppen))) nil))
+                 (ordensgruppen-sql ordensgruppen)]))
+            (map person-sql persons)))
+        "\nCOMMIT;")))


Refactor retrieving examples

Refactor retrieving examples

--- src/rdf_path_examples/examples.clj
+++ src/rdf_path_examples/examples.clj
@@ -38,6 +38,18 @@
     {:path path
      :vars (extract-vars path)}))

+(defn ^Model retrieve-examples
+  "Retrieve examples of `path` using SPARQL query from `query-template-path`."
+  [^Model path
+   ^String query-template-path
+   {:keys [graph-iri limit sparql-endpoint]}]
+  (let [path-data (preprocess-path path)
+        query (render-file query-template-path
+                           (assoc path-data
+                                  :graph-iri graph-iri
+                                  :limit limit))]
+    (construct-query sparql-endpoint query)))
+
 (defn serialize-examples
   "Serialize path `examples` into JSON-LD Clojure hash-map"
   [^Model examples]
@@ -53,25 +65,18 @@
   (fn [config _] (:selection-method config)))

 (defmethod generate-examples "random"
-  [{:keys [graph-iri limit sparql-endpoint]}
+  [params
    ^Model path]
-  (let [path-data (preprocess-path path)
-        query (render-file "sparql/templates/random.mustache"
-                           (assoc path-data
-                                  :graph-iri graph-iri
-                                  :limit limit))
-        results (construct-query sparql-endpoint query)]
-    (serialize-examples results)))
+  (serialize-examples (retrieve-examples path "sparql/templates/random.mustache" params)))

 (defmethod generate-examples "distinct"
-  [{:keys [graph-iri limit sparql-endpoint]}
+  [{:keys [sampling-factor] :as params}
    ^Model path]
-  (let [path-data (preprocess-path path)
-        query (render-file "sparql/templates/distinct.mustache"
-                           (assoc path-data
-                                  :graph-iri graph-iri
-                                  :limit limit))]))
+  (let [examples (retrieve-examples path
+                                    "sparql/templates/distinct.mustache"
+                                    (update params :limit (partial * sampling-factor)))]
+    ))

 (defmethod generate-examples "representative"
-  [{:keys [graph-iri limit sparql-endpoint]}
+  [{:keys [graph-iri limit sampling-factor sparql-endpoint]}
    ^Model path])


:anon-fn-naming-policy :unmapped

:anon-fn-naming-policy :unmapped

--- cljs/project.clj
+++ cljs/project.clj
@@ -48,18 +48,19 @@
                     "src/common"
                     "src/main"
                     "src/worker"]
-     :compiler     {:main            plastic.main
-                    :closure-defines {"plastic.env.run_worker_on_main_thread" true
-                                      "plastic.env.validate_dbs"              true
-                                      "plastic.env.log_all_dispatches"        true}
-                    :output-to       "../lib/_dev_build/main/plastic.js"
-                    :output-dir      "../lib/_dev_build/main"
-                    :optimizations   :none
-                    :target          :nodejs
-                    :compiler-stats  true
-                    :cache-analysis  true
-                    :figwheel        true
-                    :source-map      true}}
+     :compiler     {:main                  plastic.main
+                    :closure-defines       {"plastic.env.run_worker_on_main_thread" true
+                                            "plastic.env.validate_dbs"              true
+                                            "plastic.env.log_all_dispatches"        true}
+                    :output-to             "../lib/_dev_build/main/plastic.js"
+                    :output-dir            "../lib/_dev_build/main"
+                    :optimizations         :none
+                    :target                :nodejs
+                    :anon-fn-naming-policy :unmapped
+                    :compiler-stats        true
+                    :cache-analysis        true
+                    :figwheel              true
+                    :source-map            true}}
     :main
     {:source-paths ["checkouts/re-frame/src"
                     "checkouts/reagent/src"
@@ -68,15 +69,16 @@
                     "src/dev"
                     "src/common"
                     "src/main"]
-     :compiler     {:main           plastic.main
-                    :output-to      "../lib/_build/main/plastic.js"
-                    :output-dir     "../lib/_build/main"
-                    :optimizations  :none
-                    :target         :nodejs
-                    :compiler-stats true
-                    :cache-analysis true
-                    :figwheel       true
-                    :source-map     true}}
+     :compiler     {:main                  plastic.main
+                    :output-to             "../lib/_build/main/plastic.js"
+                    :output-dir            "../lib/_build/main"
+                    :optimizations         :none
+                    :target                :nodejs
+                    :anon-fn-naming-policy :unmapped
+                    :compiler-stats        true
+                    :cache-analysis        true
+                    :figwheel              true
+                    :source-map            true}}
     :worker
     {:source-paths ["checkouts/re-frame/src"
                     "checkouts/rewrite-cljs/src"
@@ -85,12 +87,13 @@
                     "src/dev"
                     "src/common"
                     "src/worker"]
-     :compiler     {:main           plastic.worker
-                    :output-to      "../lib/_build/worker/plastic.js"
-                    :output-dir     "../lib/_build/worker"
-                    :optimizations  :none
-                    :target         :nodejs
-                    :compiler-stats true
-                    :cache-analysis true
-                    :figwheel       true
-                    :source-map     true}}}})
+     :compiler     {:main                  plastic.worker
+                    :output-to             "../lib/_build/worker/plastic.js"
+                    :output-dir            "../lib/_build/worker"
+                    :optimizations         :none
+                    :target                :nodejs
+                    :anon-fn-naming-policy :unmapped
+                    :compiler-stats        true
+                    :cache-analysis        true
+                    :figwheel              true
+                    :source-map            true}}}})


More docs about handlers

More docs about handlers

--- src/icecap/handlers/core.clj
+++ src/icecap/handlers/core.clj
@@ -7,6 +7,11 @@

 (defmacro defstep
   "Define a step implementation.
+
+  A step implementation is defined by its schema (a map), and a
+  handler (a sequence of forms). The handler forms will have the step
+  being handled injected into it, and should evaluate to a core.async
+  chan.

   The schema does not have to include the step's `:type`; it is
   implicitly added.


Fixed typo.

Fixed typo.

--- indexer-app/src/cmr/indexer/services/index_service.clj
+++ indexer-app/src/cmr/indexer/services/index_service.clj
@@ -528,7 +528,7 @@
 (defmethod delete-concept :service-association
   [context concept-id revision-id options]
   ;; When service association is deleted, we want to re-index the associated collection.
-  ;; This is the same thing we do when a service association is update. So we call the same function.
+  ;; This is the same thing we do when a service association is updated. So we call the same function.
   (index-association-concept context concept-id revision-id options))

 (defn force-delete-all-concept-revision


CMR-6158: fix test that was failing in CI

--- indexer-app/src/cmr/indexer/services/index_service.clj
+++ indexer-app/src/cmr/indexer/services/index_service.clj
@@ -259,10 +259,10 @@
 (defn- collection->suggestion-doc
   "Convert collection concept metadata to UMM-C and pull facet fields
   to be indexed as autocomplete suggestion doc"
-  [context collection]
-  (let [parsed-concept (cp/parse-concept context collection)
-        humanized-fields (humanizer/collection-humanizers-elastic context parsed-concept)
-        suggestion-docs (get-suggestion-docs humanized-fields)]
+  [context collections]
+  (let [parsed-concepts (map #(cp/parse-concept context %) collections)
+        humanized-fields (map #(humanizer/collection-humanizers-elastic context %) parsed-concepts)
+        suggestion-docs (map get-suggestion-docs humanized-fields)]
     (flatten suggestion-docs)))

@@ -284,7 +284,7 @@
 (defn reindex-autocomplete-suggestions
   "Reindexes all autocomplete suggestions in the providers given."
   [context]
-  (let [provider-ids (meta-db/get-providers context)]
+  (let [provider-ids (map :provider-id (meta-db/get-providers context))]
     (reindex-science-keyword-suggestions context)

     (doseq [provider-id provider-ids]


jupyter as functional as before

jupyter as functional as before

--- src/ipython_clojure/core.clj
+++ src/ipython_clojure/core.clj
@@ -150,7 +150,6 @@
                       {:status "ok"
                        :execution_count @execution-count
                        :user_variables {}
-                       :payload [{}]
                        :user_expressions {}}
                       parent-header
                       {:dependencies_met "True"


CMR-6217 updated test name

CMR-6217 updated test name

--- access-control-app/int-test/cmr/access_control/int_test/access_control_group_crud_test.clj
+++ access-control-app/int-test/cmr/access_control/int_test/access_control_group_crud_test.clj
@@ -473,7 +473,7 @@
                                concept_id2)]}
              (test-util/update-group token concept_id3 (assoc group3 :name (:name group2))))))))

-(deftest update-provider-groups
+(deftest update-provider-groups-test
   (let [group1 (test-util/make-group {:name "group1" :provider_id "PROV1"})
         group1a (test-util/make-group {:name "group2" :provider_id "PROV1"})
         group2 (test-util/make-group {:name "group2" :provider_id "PROV2"})


Forgot to commit this: `flatten` in `(->>)`

--- src/clj/kixi/hecuba/api/devices.clj
+++ src/clj/kixi/hecuba/api/devices.clj
@@ -119,13 +119,14 @@
 (defmethod calculated-sensor :default [sensor])

 (defn create-synth-sensors [sensors]
-  (flatten (->> sensors
-                (mapcat (fn [sensor]
-                          (if (= "CUMULATIVE" (:period sensor))
-                            [sensor (ext-type sensor "differenceSeries")] [sensor])))
-                (mapcat (fn [sensor]
-                          (if (= "PULSE" (:period sensor))
-                            [sensor (calculated-sensor sensor)] [sensor]))))))
+  (->> sensors
+       (mapcat (fn [sensor]
+                 (if (= "CUMULATIVE" (:period sensor))
+                   [sensor (ext-type sensor "differenceSeries")] [sensor])))
+       (mapcat (fn [sensor]
+                 (if (= "PULSE" (:period sensor))
+                   [sensor (calculated-sensor sensor)] [sensor])))
+       flatten))

 (defn create-default-sensors
   "Creates default sensors whenever new device is added: *_differenceSeries for CUMULATIVE,


Don't drop a comic from the page-list until it is succesfully received

--- src/cljs/comic_reader/handlers.cljs
+++ src/cljs/comic_reader/handlers.cljs
@@ -11,9 +11,7 @@
                        :as db}]
   (api/get-img-tag site (first page-list))
   (let [{:keys [page-list] :as db}
-        (assoc db
-               :page-list (next page-list)
-               :waiting true)
+        (assoc db :waiting true)
         new-location (assoc location
                             :chapter (inc
                                       (read-string chapter))
@@ -79,9 +77,9 @@
   (rf/register-handler
    :scroll
    (fn [db _]
-     (if (and (not (:waiting db))
-              (= (:page db)
-                 :read))
+     (if (and (= (:page db)
+                 :read)
+              (not (:waiting db)))
        (let [scroll-y (.-scrollY js/window)
              window-height (.-innerHeight js/window)
              screen-bottom (+ scroll-y window-height)
@@ -99,4 +97,5 @@
    (fn [db [_ img-data]]
      (-> db
          (assoc :waiting false)
+         (update-in [:page-list] next)
          (update-in [:comic-imgs] conj img-data)))))


make whole panel header clickable, set default view to none

--- src/cljs/salava/badge/ui/stats.cljs
+++ src/cljs/salava/badge/ui/stats.cljs
@@ -15,28 +15,28 @@
         total-views (reduce #(+ %1 (:reg_count %2) (:anon_count %2)) 0 views)]
     [:div.panel
      [:div.panel-heading
-      [:h3
-       [:a {:href "#" :on-click #(do (.preventDefault %) (reset! visible-area-atom panel-identity))} (t :badge/Badgeviews) ":"] " (" total-views ")"]]
+      [:a {:href "#" :on-click #(do (.preventDefault %) (reset! visible-area-atom panel-identity))}
+       [:h3 (t :badge/Badgeviews) ":" " (" total-views ")"]]]
      (if (= @visible-area-atom panel-identity)
        [:div.panel-body
         [:div {:class "row header"}
          [:div.col-md-12
-           [:div.flip-table
+          [:div.flip-table
            [:div.col-md-6]
-                      [:div.col-md-2 (t :badge/Loggedinusers)]
+           [:div.col-md-2 (t :badge/Loggedinusers)]
            [:div.col-md-2 (t :badge/Anonymoususers)]
            [:div.col-md-2 (t :badge/Latestview)]]]]
-         (into [:div {:class "row body "}]
-               (for [badge-views views
-                     :let [{:keys [id name image_file reg_count anon_count latest_view]} badge-views]]
-                 [:div.col-md-12
-                  [:div.flip-table
+        (into [:div {:class "row body "}]
+              (for [badge-views views
+                    :let [{:keys [id name image_file reg_count anon_count latest_view]} badge-views]]
+                [:div.col-md-12
+                 [:div.flip-table
                   [:div.col-md-1 [:img.badge-icon {:src (str "/" image_file)}]]
                   [:div.col-md-5 [:a {:href "#"
-                                 :on-click #(do
-                                              (mo/open-modal [:badge :info] {:badge-id id})
-                                        ;(b/open-modal id false init-data state)
-                                              (.preventDefault %)) }  name]]
+                                      :on-click #(do
+                                                   (mo/open-modal [:badge :info] {:badge-id id})
+                                                   ;(b/open-modal id false init-data state)
+                                                   (.preventDefault %)) }  name]]
                   [:div.col-md-2 [:label (t :badge/Loggedinusers)] reg_count]
                   [:div.col-md-2 [:label (t :badge/Anonymoususers)]anon_count]
                   [:div.col-md-2 [:label (t :badge/Latestview)] (if latest_view (date-from-unix-time (* 1000 latest_view)))]]]))])]))
@@ -46,8 +46,8 @@
         total-congratulations (->> congratulations (map :congratulation_count) (reduce +))]
     [:div.panel
      [:div.panel-heading
-      [:h3
-       [:a {:href "#" :on-click #(do (.preventDefault %) (reset! visible-area-atom panel-identity))} (t :badge/Congratulations) ":"] " (" total-congratulations ")"]]
+      [:a {:href "#" :on-click #(do (.preventDefault %) (reset! visible-area-atom panel-identity))}
+       [:h3 (t :badge/Congratulations) ":" " (" total-congratulations ")"]]]
      (if (= @visible-area-atom panel-identity)
        [:div.panel-body
         [:table {:class "table" :summary (t :badge/Congratulations)}
@@ -66,7 +66,7 @@
                   [:td.name [:a {:href "#"
                                  :on-click #(do
                                               (mo/open-modal [:badge :info] {:badge-id id})
-                                        ;(b/open-modal id false init-data state)
+                                              ;(b/open-modal id false init-data state)
                                               (.preventDefault %)) } name]]
                   [:td congratulation_count]
                   [:td (if latest_congratulation (date-from-unix-time (* 1000 latest_congratulation)))]]))]])]))
@@ -75,8 +75,8 @@
   (let [panel-identity :issuers]
     [:div.panel
      [:div.panel-heading
-      [:h3
-       [:a {:href "#" :on-click #(do (.preventDefault %) (reset! visible-area-atom panel-identity))} (t :badge/Issuers) ":"] " (" (count issuers) ")"]]
+      [:a {:href "#" :on-click #(do (.preventDefault %) (reset! visible-area-atom panel-identity))}
+       [:h3 (t :badge/Issuers) ":" " (" (count issuers) ")"]]]
      (if (= @visible-area-atom panel-identity)
        (into [:div.panel-body]
              (for [issuer issuers
@@ -87,10 +87,10 @@
                       (for [badge badges
                             :let [{:keys [id image_file name]} badge]]
                         [:a {:href "#"
-                                 :on-click #(do
-                                              (mo/open-modal [:badge :info] {:badge-id id})
-                                        ;(b/open-modal id false init-data state)
-                                              (.preventDefault %)) }
+                             :on-click #(do
+                                          (mo/open-modal [:badge :info] {:badge-id id})
+                                          ;(b/open-modal id false init-data state)
+                                          (.preventDefault %)) }
                          [:img.badge-icon {:src (str "/"  image_file) :title name :alt name}]]))])))]))

 (defn content [state]
@@ -100,12 +100,13 @@
      [m/modal-window]
      [:h1.uppercase-header
       (t :badge/Badgestatistics)]
+     [:p (t :connections/Statisticspageinfo)]
      [:h3 (t :badge/Totalbadges) ": " badge_count " " (t :badge/Expired) ": " expired_badge_count]
      [views-panel badge_views visible-area-atom]
      [congratulations-panel badge_congratulations visible-area-atom]
      [issuers-panel badge_issuers visible-area-atom]]))

-(def initial-state {:visible_area :views
+(def initial-state {:visible_area nil
                     :badge_count nil
                     :expired_badge_count nil
                     :badge_views []


improve the error message when a Closure lib does not exist

--- src/cljs/snapshot/lumo/js_deps.cljs
+++ src/cljs/snapshot/lumo/js_deps.cljs
@@ -57,13 +57,15 @@
 (defn parse-libs
   "Converts a closure lib path into a list of module descriptors."
   [lib]
-  (->> (cp-file-seq lib)
-    (filter #(= ".js" (js/$$LUMO_GLOBALS.path.extname %)))
-    (map (fn [file]
-           (let [source (.-source (js/$$LUMO_GLOBALS.readSource file))]
-             (when-not source
-               (throw (ex-info "The specified closure library does not exist" {:path file})))
-             (assoc (parse-closure-ns source) :file file))))))
+  (into []
+    (comp
+      (filter #(= ".js" (js/$$LUMO_GLOBALS.path.extname %)))
+      (map (fn [file]
+             (if-let [source (some-> (js/$$LUMO_GLOBALS.readSource file)
+                               .-source)]
+               (assoc (parse-closure-ns source) :file file)
+               (throw (ex-info (str "The specified Closure file does not exist: " file) {:path file}))))))
+    (cp-file-seq lib)))

 (defn index-js-libs
   "Indexes all js foreign and closure libs from each deps.cljs on the classpath."
@@ -72,7 +74,9 @@
           (fn [index]
             (reduce (fn [index deps-cljs-str]
                       (let [{:keys [libs foreign-libs]} (r/read-string deps-cljs-str)]
-                        (add-js-libs index (concat foreign-libs (mapcat parse-libs libs)))))
+                        (add-js-libs index (into (vec foreign-libs)
+                                             (mapcat parse-libs)
+                                             libs))))
                     index
                     (js/$$LUMO_GLOBALS.loadUpstreamJsLibs)))))


Add in dsu/t as an alias for dsu/touch+, since it's used so frequently

--- src/shared/dato/db/utils.cljc
+++ src/shared/dato/db/utils.cljc
@@ -76,6 +76,12 @@
   ;; (into {}) makes the map assoc'able, but lacks a :db/id, which is annoying for later lookups.
   (into (select-keys ent [:db/id]) (d/touch ent)))

+(defn t
+  "By default, touch returns a map that can't be assoc'd. Fix it"
+  [ent]
+  ;; (into {}) makes the map assoc'able, but lacks a :db/id, which is annoying for later lookups.
+  (into (select-keys ent [:db/id]) (d/touch ent)))
+
 (defn touch-all
   "Runs the query that returns [[eid][eid]] and returns all entity maps.
    Uses the first DB to look up all entities"


Fixed implementation of concept approximations

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

--- src/conexp/contrib/concept_approximation.clj
+++ src/conexp/contrib/concept_approximation.clj
@@ -14,8 +14,8 @@

 (defn- apprx-handler
   "Special handler for concept approximation exploration."
-  [ctx new-impl new-objs cross-handler]
-  (let [counterexamples (default-handler ctx new-impl)]
+  [ctx known new-impl new-objs cross-handler]
+  (let [counterexamples (default-handler-for-complete-counterexamples ctx known new-impl)]
     (doseq [new-att (map first counterexamples)]
       (let [att-objs (ask (str "Which of the objs " new-objs " definitively has the attribute " new-att "? ")
                           #(read-string (str "#{" (read-line) "}"))
@@ -25,22 +25,21 @@
     counterexamples))

 (defn explore-approximations
-  "Performs concept approximation exploration and returns the final
-  context."
+  "Performs concept approximation exploration and returns the final context."
   [context]
   (let [_                (println "Starting attribute exploration")
-        att-explored-ctx (:context (explore-attributes context)),
+        att-explored-ctx (:context (explore-attributes :context context)),

         _                (println "Starting object exploration")
         new-objects      (difference (objects att-explored-ctx)
                                      (objects context)),
         known-crosses    (atom #{}),
         handler          (fn [ctx known impl]
-                           (apprx-handler ctx impl new-objects
+                           (apprx-handler ctx known impl new-objects
                                           #(swap! known-crosses into %))),
         obj-explored-ctx (dual-context
                           (:context (explore-attributes
-                                     (dual-context context)
+                                     :context (dual-context context)
                                      :handler handler)))]
     (context-subposition
      (context-apposition context obj-explored-ctx)


[clojure] utility fns for starting and stopping dev systems

--- etc/scratch.clj
+++ etc/scratch.clj
@@ -20,7 +20,9 @@
 (R/refresh) - refresh all namespaces
 (scrtach/refresh-all) - refresh all project + dep namespaces
 (R/pp) alias for clojure.pprint/pprint
-(R/list-ns) - find all namespaces in SRC"))
+(R/list-ns) - find all namespaces in SRC
+(R/start-system! 'some.user-ns) - refresh and start a system in some.user-ns
+(R/stop-system! 'some.user-ns) - stop a system in some.user-ns "))

 (defn init! []
   (ns scratch)
@@ -72,4 +74,22 @@
      (printf "end |%s| %s - %sms\n" ~tag   (str (java.time.LocalDateTime/now)) time#)
      return#))

+(defn start-system!
+  "Given a namespace, usually some-service.user, do the following:
+  - refresh
+  - require the user ns
+  - start  system, invoking somer-service.user/start
+  Warning: best if the system is not running, or things will go south"
+  [an-ns]
+  (refresh)
+  (require an-ns)
+  (let [f (ns-resolve an-ns 'start)]
+    (f)))
+
+(defn stop-system!
+  "Given a namespace, usually some-service.user, stop the system"
+  [an-ns]
+  (let [f (ns-resolve an-ns 'stop)]
+    (f)))
+
 (init!)


revised irefweb rules to represent protein interactions

--- kabob-build/src/main/resources/edu/ucdenver/ccp/kabob/build/rules/temp/irefweb/irefweb.clj
+++ kabob-build/src/main/resources/edu/ucdenver/ccp/kabob/build/rules/temp/irefweb/irefweb.clj
@@ -1,166 +1,235 @@

-;; obo/MI_0000 ;psi-mi "molecular interaction"
-;; obo/INO_0000002 ;interaction
-
-;; obo/GO_ ; complex
-
-`{:name "irefweb-interaction-2-proteins"
-  :head ((?/interaction rdfs/subClassOf obo/MI_0000) ;interaction
+`{:name "irefweb-binary-interactions"
+  :description ""
+  :head ((?/interaction rdfs/subClassOf ?/int_type_id) ;interaction
+
+         ;; create subclasses of the proteins
+         (?/protein1_sc rdfs/subClassOf ?/protein1)
+         (?/protein2_sc rdfs/subClassOf ?/protein2)

          (?/r1 rdf/type owl/Restriction)
          (?/r1 owl/onProperty obo/RO_0000057) ; has_participant
-         (?/r1 owl/someValuesFrom ?/protein1)
+         (?/r1 owl/someValuesFrom ?/protein1_sc)

          (?/r2 rdf/type owl/Restriction)
          (?/r2 owl/onProperty obo/RO_0000057) ; has_participant
-         (?/r2 owl/someValuesFrom ?/protein2)
-
-         ;;make the interaction be necessarily part of these 3 restrictions
-         ;;still need to add a sufficient definition
+         (?/r2 owl/someValuesFrom ?/protein2_sc)
+
          (?/interaction rdfs/subClassOf ?/r1)
          (?/interaction rdfs/subClassOf ?/r2))

   :body
-  (;; just look this up once we'll need it later
-   (_/Ftypename kiao/hasTemplate iaoirefweb/IRefWebInteractorType_interactorTypeNameDataField1)
-   (_/Ftypename obo/IAO_0000219 "protein") ; denotes
-   (_/Rtype obo/BFO_0000051 _/Ftypename) ; has_part
-   (_/Rtype kiao/hasTemplate iaoirefweb/IRefWebInteractorTypeSchema1)
-
-
-   ;; find all interactions with 2 partners
-   (_/fvnum kiao/hasTemplate iaoirefweb/IRefWebInteraction_numParticipantsDataField1)
-   ;;(_/fvnum obo/IAO_0000219 ["2" xsd/integer])
-   (_/fvnum obo/IAO_0000219 2) ; denotes
-   (_/interactionrecord obo/BFO_0000051 _/fvnum) ; has_part
-
-   ;; get top record
-   (_/psimi obo/BFO_0000051 _/interactionrecord) ; has_part
-
-   ;;get two distinct interactors
-   (_/psimi obo/BFO_0000051 ?/Rinteractor1) ; has_part
-   (?/Rinteractor1 kiao/hasTemplate iaoirefweb/IRefWebInteractorSchema1)
-   (_/psimi obo/BFO_0000051 ?/Rinteractor2) ; has_part
-   (?/Rinteractor2 kiao/hasTemplate iaoirefweb/IRefWebInteractorSchema1)
-   (!= ?/Rinteractor1 ?/Rinteractor2)
-
-   ;;all two part interactions should be protein and protein but verify
-   ;; reuse type from initial lookup
-   (?/Rinteractor1 obo/BFO_0000051 _/Rtype) ; has_part
-   (?/Rinteractor2 obo/BFO_0000051 _/Rtype) ; has_part
-
-   ;;get the first interactor ID and then BIO entity
-   (?/Rinteractor1 obo/BFO_0000051 _/FID1) ; has_part
-   (_/FID1 kiao/hasTemplate iaoirefweb/IRefWebInteractor_uniqueIdDataField1)
-   (_/FID1 obo/IAO_0000219 _/ID1) ; denotes
-   (_/ID1 obo/IAO_0000219 ?/protein1) ; denotes
-
-   ;;get the second interactor ID and then BIO entity
-   (?/Rinteractor2 obo/BFO_0000051 _/FID2) ; has_part
-   (_/FID2 kiao/hasTemplate iaoirefweb/IRefWebInteractor_uniqueIdDataField1)
-   (_/FID2 obo/IAO_0000219 _/ID2) ; denotes
-   (_/ID2 obo/IAO_0000219 ?/protein2) ; denotes
-   )
-
-
- ;;need a better way to reify / sort the restrictions to form the interaction
-
-  :reify ([?/interaction {:ln (:sha-1 "interaction" ?/r1 ?/r2)
+  ;; get binary interaction records
+  ((?/edge_field kiao/hasTemplate iaoirefweb/IRefWebInteraction_edgeTypeDataField1)
+   (?/edge_field obo/IAO_0000219 "X"@en)   ;; "X" signifies binary interaction
+   (?/interaction_record obo/BFO_0000051 ?/edge_field)  ;; bfo/has_part
+
+   ;; get the unique interaction identifier
+   (?/interaction_record obo/BFO_0000051 ?/interaction_checksum_field) ;; bfo/has_part
+   (?/interaction_checksum_field kiao/hasTemplate iaoirefweb/IRefWebInteraction_checksumInteractionDataField1)
+   (?/interaction_checksum_field obo/IAO_0000219 ?/unique_interaction_id) ;; iao/denotes
+
+   ;; get the interaction type name and ID
+   (?/interaction_record obo/BFO_0000051 ?/interaction_type_record) ;; bfo/has_part
+   (?/interaction_type_record kiao/hasTemplate iaoirefweb/IRefWebInteractionTypeSchema1)
+   (?/interaction_type_record obo/BFO_0000051 ?/int_type_name_field) ;; bfo/has_part
+   (?/int_type_name_field kiao/hasTemplate iaoirefweb/IRefWebInteractionType_interactionTypeNameDataField1)
+   (?/int_type_name_field obo/IAO_0000219 ?/int_type_name) ;; iao/denotes
+   (?/interaction_type_record obo/BFO_0000051 ?/int_type_id_field) ;; bfo/has_part
+   (?/int_type_id_field kiao/hasTemplate iaoirefweb/IRefWebInteractionType_interactionTypeIdDataField1)
+   (?/int_type_id_field obo/IAO_0000219 ?/int_type_id_ice) ;; iao/denotes
+   (?/int_type_id_ice obo/IAO_0000219 ?/int_type_id) ;; iao/denotes
+
+   ;; get the detection method
+   (?/interaction_record obo/BFO_0000051 ?/interaction_detection_method_record) ;; bfo/has_part
+   (?/interaction_detection_method_record kiao/hasTemplate iaoirefweb/IRefWebInteractionDetectionMethodSchema1)
+   (?/interaction_detection_method_record obo/BFO_0000051 ?/detection_method_id_field) ;; bfo/has_part
+   (?/detection_method_id_field kiao/hasTemplate iaoirefweb/IRefWebInteractionDetectionMethod_detectionMethodIdDataField1)
+   (?/detection_method_id_field obo/IAO_0000219 ?/detection_method_id) ;; iao/denotes
+
+   ;; there is a "super" record in IRefWeb that contains references
+   ;; to the interaction record and interactor record(s)
+   (?/super_record obo/BFO_0000051 ?/interaction_record) ;; bfo/has_part
+
+   ;; get the two distinct interactors for this binary interaction
+   (?/super_record obo/BFO_0000051 ?/interactor_record1) ;; bfo/has_part
+   (?/interactor_record1 kiao/hasTemplate iaoirefweb/IRefWebInteractorSchema1)
+   (?/super_record obo/BFO_0000051 ?/interactor_record2) ;; bfo/has_part
+   (?/interactor_record2 kiao/hasTemplate iaoirefweb/IRefWebInteractorSchema1)
+   (!= ?/interactor_record1 ?/interactor_record2)
+
+   ;; get the bioentity (protein) corresponding to interactor 1
+   (?/interactor_record1 obo/BFO_0000051 ?/id_field1) ;; bfo/has_part
+   (?/id_field1 kiao/hasTemplate iaoirefweb/IRefWebInteractor_uniqueIdDataField1)
+   (?/id_field1 obo/IAO_0000219 ?/id1) ;; iao/denotes
+   (?/id1 obo/IAO_0000219 ?/protein1) ;; iao/denotes
+
+   ;; get the bioentity (protein) corresponding to interactor 2
+   (?/interactor_record2 obo/BFO_0000051 ?/id_field2) ;; bfo/has_part
+   (?/id_field2 kiao/hasTemplate iaoirefweb/IRefWebInteractor_uniqueIdDataField1)
+   (?/id_field2 obo/IAO_0000219 ?/id2) ;; iao/denotes
+   (?/id2 obo/IAO_0000219 ?/protein2)) ;; iao/denotes
+
+  ;; we take advantage of the fact that IRefWeb has
+  ;; created a unique id for the interaction. This will allow us to reproducibly create
+  ;; a hash for the interaction that can be matched across records.
+  :reify ([?/interaction {:ln (:sha-1 ?/unique_interaction_id)
                           :ns "kbio" :prefix "I_"}]
           [?/r1 {:ln (:restriction)
                  :ns "kbio" :prefix "R_"}]
           [?/r2 {:ln (:restriction)
-                 :ns "kbio" :prefix "R_"}])
-
-  :options {:magic-prefixes [["franzOption_clauseReorderer" "franz:identity"]]}
- }
-
-`{:name "irefweb-reify-complex-and-interaction"
-  :head ((?/interaction rdfs/subClassOf obo/MI_0000) ;interaction
-         (?/complex rdfs/subClassOf obo/GO_0032991)  ;macromolecular complex
-         (?/interaction kro/resuts_in_the_formation_of ?/complex)
-
-         (?/complexID obo/IAO_0000219 ?/complex) ; complexID denotes complex
-         ;;(?/complexID obo/IAO_0000142 ?/interaction) ;the complex id mentions the interaction? no
-         )
-  :body
-  ((_/Ftypename kiao/hasTemplate iaoirefweb/IRefWebInteractorType_interactorTypeNameDataField1)
-   (_/Ftypename obo/IAO_0000219 "protein complex") ; denotes
-   (_/Rtype obo/BFO_0000051 _/Ftypename) ; has_part
-   (_/Rtype kiao/hasTemplate iaoirefweb/IRefWebInteractorTypeSchema1)
-
-   ;;get all the interactor records that are protein complex stand-ins
-   (?/Rinteractor obo/BFO_0000051 _/Rtype) ; has_part
-
-   ;;get the complex ID
-   (?/Rinteractor obo/BFO_0000051 _/FID1) ; has_part
-   (_/FID1 kiao/hasTemplate iaoirefweb/IRefWebInteractor_uniqueIdDataField1)
-   (_/FID1 obo/IAO_0000219 ?/complexID)) ; denotes
-
-  :reify ([?/interaction {:ln (:sha-1 "interaction" ?/complexID)
-                          :ns "kbio" :prefix "I_"}]
-          [?/complex {:ln (:sha-1 "complex" ?/complexID)
-                      :ns "kbio" :prefix "C_"}])
+                 :ns "kbio" :prefix "R_"}]
+          [?/protein1_sc {:ln (:sha-1 ?/interaction ?/protein1)
+                          :ns "kbio" :prefix "P_"}]
+          [?/protein2_sc {:ln (:sha-1 ?/interaction ?/protein2)
+                          :ns "kbio" :prefix "P_"}])

   :options {:magic-prefixes [["franzOption_clauseReorderer" "franz:identity"]]}
   }

-`{:name "irefweb-complex-and-interaction-participant"
-  :head (;(?/interaction rdfs/subClassOf obo/MI_0000) ;interaction
-         ;(?/complex rdfs/subClassOf obo/GO_0032991)  ;macromolecular complex
+
+`{:name "irefweb-unary-interactions"
+  :description ""
+  :head ((?/interaction rdfs/subClassOf ?/int_type_id) ;interaction
+
+         ;; create subclasses of the single protein involved
+         (?/protein1_sc rdfs/subClassOf ?/protein1)
+
          (?/r1 rdf/type owl/Restriction)
          (?/r1 owl/onProperty obo/RO_0000057) ; has_participant
-         (?/r1 owl/someValuesFrom ?/protein)
-
-         (?/r2 rdf/type owl/Restriction)
-         (?/r2 owl/onProperty obo/BFO_0000051) ; has_part
-         (?/r2 owl/someValuesFrom ?/protein)
-
-         (?/interaction rdfs/subClassOf ?/r1)
-         (?/complex rdfs/subClassOf ?/r2))
-  ;;how to possibly extend these to sufficient definitions?
+         (?/r1 owl/someValuesFrom ?/protein1_sc)
+
+         (?/interaction rdfs/subClassOf ?/r1))

   :body
-  (;; just look this up once we'll need it later
-   (_/FtypenameP kiao/hasTemplate iaoirefweb/IRefWebInteractorType_interactorTypeNameDataField1)
-   (_/FtypenameP obo/IAO_0000219 "protein") ; denotes
-   (_/RtypeP obo/BFO_0000051 _/FtypenameP) ; has_part
-   (_/RtypeP kiao/hasTemplate iaoirefweb/IRefWebInteractorTypeSchema1)
-
-   ;;get the protein complex type
-   (_/FtypenamePC kiao/hasTemplate iaoirefweb/IRefWebInteractorType_interactorTypeNameDataField1)
-   (_/FtypenamePC obo/IAO_0000219 "protein complex")  ; denotes
-   (_/RtypePC obo/BFO_0000051 _/FtypenamePC) ; has_part
-   (_/RtypePC kiao/hasTemplate iaoirefweb/IRefWebInteractorTypeSchema1)
-
-   ;;get all the protein complex interaction records
-   (?/RinteractorPC obo/BFO_0000051 _/RtypePC) ; has_part
-   (_/psimi obo/BFO_0000051 ?/RinteractorPC) ; has_part
-
-   ;;get the one protein mentioned in this record
-   (_/psimi obo/BFO_0000051 ?/RinteractorP) ; has_part
-   (?/RinteractorP obo/BFO_0000051 _/RtypeP) ; has_part
-
-   ;;get the first interactor ID and then BIO entity
-   (?/RinteractorPC obo/BFO_0000051 _/FID1) ; has_part
-   (_/FID1 kiao/hasTemplate iaoirefweb/IRefWebInteractor_uniqueIdDataField1)
-   (_/FID1 obo/IAO_0000219 ?/complexID) ; denotes
-
-   ;;get the second interactor ID and then BIO entity
-   (?/RinteractorP obo/BFO_0000051 _/FID2) ; has_part
-   (_/FID2 kiao/hasTemplate iaoirefweb/IRefWebInteractor_uniqueIdDataField1)
-   (_/FID2 obo/IAO_0000219 _/ID2) ; denotes
-   (_/ID2 obo/IAO_0000219 ?/protein)) ; denotes
-
-  :reify ([?/interaction {:ln (:sha-1 "interaction" ?/complexID)
+  ;; get binary interaction records
+  ((?/edge_field kiao/hasTemplate iaoirefweb/IRefWebInteraction_edgeTypeDataField1)
+   (?/edge_field obo/IAO_0000219 "Y"@en)   ;; "Y" signifies intra-molecular interaction
+   (?/interaction_record obo/BFO_0000051 ?/edge_field)  ;; bfo/has_part
+
+   ;; get the unique interaction identifier
+   (?/interaction_record obo/BFO_0000051 ?/interaction_checksum_field) ;; bfo/has_part
+   (?/interaction_checksum_field kiao/hasTemplate iaoirefweb/IRefWebInteraction_checksumInteractionDataField1)
+   (?/interaction_checksum_field obo/IAO_0000219 ?/unique_interaction_id) ;; iao/denotes
+
+   ;; get the interaction type name and ID
+   (?/interaction_record obo/BFO_0000051 ?/interaction_type_record) ;; bfo/has_part
+   (?/interaction_type_record kiao/hasTemplate iaoirefweb/IRefWebInteractionTypeSchema1)
+   (?/interaction_type_record obo/BFO_0000051 ?/int_type_name_field) ;; bfo/has_part
+   (?/int_type_name_field kiao/hasTemplate iaoirefweb/IRefWebInteractionType_interactionTypeNameDataField1)
+   (?/int_type_name_field obo/IAO_0000219 ?/int_type_name) ;; iao/denotes
+   (?/interaction_type_record obo/BFO_0000051 ?/int_type_id_field) ;; bfo/has_part
+   (?/int_type_id_field kiao/hasTemplate iaoirefweb/IRefWebInteractionType_interactionTypeIdDataField1)
+   (?/int_type_id_field obo/IAO_0000219 ?/int_type_id_ice) ;; iao/denotes
+   (?/int_type_id_ice obo/IAO_0000219 ?/int_type_id) ;; iao/denotes
+
+   ;; get the detection method
+   (?/interaction_record obo/BFO_0000051 ?/interaction_detection_method_record) ;; bfo/has_part
+   (?/interaction_detection_method_record kiao/hasTemplate iaoirefweb/IRefWebInteractionDetectionMethodSchema1)
+   (?/interaction_detection_method_record obo/BFO_0000051 ?/detection_method_id_field) ;; bfo/has_part
+   (?/detection_method_id_field kiao/hasTemplate iaoirefweb/IRefWebInteractionDetectionMethod_detectionMethodIdDataField1)
+   (?/detection_method_id_field obo/IAO_0000219 ?/detection_method_id) ;; iao/denotes
+
+   ;; there is a "super" record in IRefWeb that contains references
+   ;; to the interaction record and interactor record(s)
+   (?/super_record obo/BFO_0000051 ?/interaction_record) ;; bfo/has_part
+
+   ;; there is only one interactor for the unary interaction
+   (?/super_record obo/BFO_0000051 ?/interactor_record1) ;; bfo/has_part
+   (?/interactor_record1 kiao/hasTemplate iaoirefweb/IRefWebInteractorSchema1)
+
+   ;; get the bioentity (protein) corresponding to interactor 1
+   (?/interactor_record1 obo/BFO_0000051 ?/id_field1) ;; bfo/has_part
+   (?/id_field1 kiao/hasTemplate iaoirefweb/IRefWebInteractor_uniqueIdDataField1)
+   (?/id_field1 obo/IAO_0000219 ?/id1) ;; iao/denotes
+   (?/id1 obo/IAO_0000219 ?/protein1)) ;; iao/denotes
+
+  ;; we take advantage of the fact that IRefWeb has
+  ;; created a unique id for the interaction. This will allow us to reproducibly create
+  ;; a hash for the interaction that can be matched across records.
+  :reify ([?/interaction {:ln (:sha-1 ?/unique_interaction_id)
                           :ns "kbio" :prefix "I_"}]
-          [?/complex {:ln (:sha-1 "complex" ?/complexID)
-                      :ns "kbio" :prefix "C_"}]
           [?/r1 {:ln (:restriction)
                  :ns "kbio" :prefix "R_"}]
-          [?/r2 {:ln (:restriction)
-                 :ns "kbio" :prefix "R_"}])
+          [?/protein1_sc {:ln (:sha-1 ?/interaction ?/protein1)
+                          :ns "kbio" :prefix "P_"}])

   :options {:magic-prefixes [["franzOption_clauseReorderer" "franz:identity"]]}
- }
+  }
+
+
+
+`{:name "irefweb-n-ary-interactions"
+  :description "interactions with >2 participants. IRefWeb refers to them as complexes,
+  but these interactions don't necessarily form complexes."
+  :head ((?/interaction rdfs/subClassOf ?/int_type_id) ;interaction
+
+         ;; create subclasses of the proteins
+         (?/protein1_sc rdfs/subClassOf ?/protein1)
+
+         (?/r1 rdf/type owl/Restriction)
+         (?/r1 owl/onProperty obo/RO_0000057) ; has_participant
+         (?/r1 owl/someValuesFrom ?/protein1_sc)
+
+         (?/interaction rdfs/subClassOf ?/r1))
+
+  :body
+  ;; get binary interaction records
+  ((?/edge_field kiao/hasTemplate iaoirefweb/IRefWebInteraction_edgeTypeDataField1)
+   (?/edge_field obo/IAO_0000219 "C"@en)   ;; "C" signifies "complex" in IRefWeb, but really mean n-ary interaction where n>2
+   (?/interaction_record obo/BFO_0000051 ?/edge_field)  ;; bfo/has_part
+
+   ;; get the unique interaction identifier
+   (?/interaction_record obo/BFO_0000051 ?/interaction_checksum_field) ;; bfo/has_part
+   (?/interaction_checksum_field kiao/hasTemplate iaoirefweb/IRefWebInteraction_checksumInteractionDataField1)
+   (?/interaction_checksum_field obo/IAO_0000219 ?/unique_interaction_id) ;; iao/denotes
+
+   ;; get the interaction type name and ID
+   (?/interaction_record obo/BFO_0000051 ?/interaction_type_record) ;; bfo/has_part
+   (?/interaction_type_record kiao/hasTemplate iaoirefweb/IRefWebInteractionTypeSchema1)
+   (?/interaction_type_record obo/BFO_0000051 ?/int_type_name_field) ;; bfo/has_part
+   (?/int_type_name_field kiao/hasTemplate iaoirefweb/IRefWebInteractionType_interactionTypeNameDataField1)
+   (?/int_type_name_field obo/IAO_0000219 ?/int_type_name) ;; iao/denotes
+   (?/interaction_type_record obo/BFO_0000051 ?/int_type_id_field) ;; bfo/has_part
+   (?/int_type_id_field kiao/hasTemplate iaoirefweb/IRefWebInteractionType_interactionTypeIdDataField1)
+   (?/int_type_id_field obo/IAO_0000219 ?/int_type_id_ice) ;; iao/denotes
+   (?/int_type_id_ice obo/IAO_0000219 ?/int_type_id) ;; iao/denotes
+
+   ;; get the detection method
+   (?/interaction_record obo/BFO_0000051 ?/interaction_detection_method_record) ;; bfo/has_part
+   (?/interaction_detection_method_record kiao/hasTemplate iaoirefweb/IRefWebInteractionDetectionMethodSchema1)
+   (?/interaction_detection_method_record obo/BFO_0000051 ?/detection_method_id_field) ;; bfo/has_part
+   (?/detection_method_id_field kiao/hasTemplate iaoirefweb/IRefWebInteractionDetectionMethod_detectionMethodIdDataField1)
+   (?/detection_method_id_field obo/IAO_0000219 ?/detection_method_id) ;; iao/denotes
+
+   ;; there is a "super" record in IRefWeb that contains references
+   ;; to the interaction record and interactor record(s)
+   (?/super_record obo/BFO_0000051 ?/interaction_record) ;; bfo/has_part
+
+   ;; there are two interactors, but one is a place holder that is used to bind
+   ;; multiple records together to form n-ary interactions. The placeholder is
+   ;; identical to the unique interaction ID, so we select the other interactor
+   ;; (which will be linked to a bioentity (protein))
+   (?/super_record obo/BFO_0000051 ?/interactor_record1) ;; bfo/has_part
+   (?/interactor_record1 kiao/hasTemplate iaoirefweb/IRefWebInteractorSchema1)
+
+   ;; get the bioentity (protein) corresponding to interactor 1
+   (?/interactor_record1 obo/BFO_0000051 ?/id_field1) ;; bfo/has_part
+   (?/id_field1 kiao/hasTemplate iaoirefweb/IRefWebInteractor_uniqueIdDataField1)
+   (?/id_field1 obo/IAO_0000219 ?/id1) ;; iao/denotes
+   (!= ?/id1 ?/unique_interaction_id)
+   (?/id1 obo/IAO_0000219 ?/protein1)) ;; iao/denotes
+
+  ;; we take advantage of the fact that IRefWeb has
+  ;; created a unique id for the interaction. This will allow us to reproducibly create
+  ;; a hash for the interaction that can be matched across records.
+  :reify ([?/interaction {:ln (:sha-1 ?/unique_interaction_id)
+                          :ns "kbio" :prefix "I_"}]
+          [?/r1 {:ln (:restriction)
+                 :ns "kbio" :prefix "R_"}]
+          [?/protein1_sc {:ln (:sha-1 ?/interaction ?/protein1)
+                          :ns "kbio" :prefix "P_"}])
+
+  :options {:magic-prefixes [["franzOption_clauseReorderer" "franz:identity"]]}
+  }


Minor tweaks to test code based on pull request feedback

--- test/com/puppetlabs/puppetdb/test/archive.clj
+++ test/com/puppetlabs/puppetdb/test/archive.clj
@@ -17,14 +17,14 @@
         (archive/add-entry tar-writer (:path bazfile) (:content bazfile))
         (archive/add-entry tar-writer (:path blingfile) (:content blingfile))))

-    (let [in-stream (ByteArrayInputStream. (.toByteArray out-stream))]
+    (with-open [in-stream (ByteArrayInputStream. (.toByteArray out-stream))]
       (with-open [tar-reader (archive/tarball-reader in-stream)]
         (testing "should be able to find a specific entry in a tarball"
           (let [bling-entry (archive/find-entry tar-reader (:path blingfile))]
             (is (not (nil? bling-entry)))
             (is (= (:content blingfile) (archive/read-entry-content tar-reader)))))))

-    (let [in-stream (ByteArrayInputStream. (.toByteArray out-stream))]
+    (with-open [in-stream (ByteArrayInputStream. (.toByteArray out-stream))]
       (with-open [tar-reader (archive/tarball-reader in-stream)]
         (let [entry-count (atom 0)]
           (testing "should only contain the expected entries, with expected content"


Rewrite template generator to accept arguments

--- src/leiningen/new/kraken_works.clj
+++ src/leiningen/new/kraken_works.clj
@@ -5,12 +5,27 @@

 (def render (renderer "kraken-works"))

+(def default-options {})
+
+(def valid-options {})
+
+(defn parse-opt [opt]
+  (if-let [opt-map (valid-options opt)]
+    opt-map
+    (main/abort "Invalid option:" opt)))
+
+(defn make-data [name opts]
+  (apply merge
+    {:name name
+     :sanitized (name-to-path name)
+     :env-var-style (-> name name-to-path str/upper-case)}
+    default-options
+    (map parse-opt opts)))
+
 (defn kraken-works
   "FIXME: write documentation"
-  [name]
-  (let [data {:name name
-              :sanitized (name-to-path name)
-              :env-var-style (-> name name-to-path str/upper-case)}]
+  [name & opts]
+  (let [data (make-data name opts)]
     (main/info (str "Generating fresh kraken-works project in directory " (:sanitized data) "/."))

     (main/info (str "TODO: (you probably want to `cd " name "` first)"))
@@ -21,26 +36,27 @@
     (main/info " * `git commit -am \"initial commit\"`")
     (main/info " * push this to github")
     (main/info " * make a Buildkite project")
-    (->files data
-             [".gitignore" (render ".gitignore" data)]
-             ["Dockerfile" (render "Dockerfile" data)]
-             ["{{name}}@.service.template" (render "PROJECT@.service.template" data)]
-             ["docker-compose.yml" (render "docker-compose.yml" data)]
-             ["newrelic.yml" (render "newrelic.yml" data)]
-             ["profiles.clj.sample" (render "profiles.clj.sample" data)]
-             ["project.clj" (render "project.clj" data)]
-             ["README.md" (render "README.md" data)]
-             ["LICENSE" (render "LICENSE" data)]
+    (->> [[".gitignore" (render ".gitignore" data)]
+           ["Dockerfile" (render "Dockerfile" data)]
+           ["{{name}}@.service.template" (render "PROJECT@.service.template" data)]
+           ["docker-compose.yml" (render "docker-compose.yml" data)]
+           ["newrelic.yml" (render "newrelic.yml" data)]
+           ["profiles.clj.sample" (render "profiles.clj.sample" data)]
+           ["project.clj" (render "project.clj" data)]
+           ["README.md" (render "README.md" data)]
+           ["LICENSE" (render "LICENSE" data)]

-             ["script/deploy" (render "script/deploy" data)]
-             ["script/build" (render "script/build" data)]
+           ["script/deploy" (render "script/deploy" data)]
+           ["script/build" (render "script/build" data)]

-             ["resources/config.edn" (render "config.edn" data)]
-             ["resources/schemas/.gitkeep" ""]
-             ["resources/logback.xml" (render "logback.xml" data)]
+           ["resources/config.edn" (render "config.edn" data)]
+           ["resources/schemas/.gitkeep" ""]
+           ["resources/logback.xml" (render "logback.xml" data)]

-             ["src/{{sanitized}}/core.clj" (render "core.clj" data)]
-             ["src/{{sanitized}}/queue.clj" (render "queue.clj" data)]
-             ["src/{{sanitized}}/channels.clj" (render "channels.clj" data)]
-             ["src/{{sanitized}}/handlers.clj" (render "handlers.clj" data)]
-             ["test/{{sanitized}}/handlers_test.clj" (render "handlers_test.clj" data)])))
+           ["src/{{sanitized}}/core.clj" (render "core.clj" data)]
+           ["src/{{sanitized}}/queue.clj" (render "queue.clj" data)]
+           ["src/{{sanitized}}/channels.clj" (render "channels.clj" data)]
+           ["src/{{sanitized}}/handlers.clj" (render "handlers.clj" data)]
+           ["test/{{sanitized}}/handlers_test.clj" (render "handlers_test.clj" data)]]
+         (remove nil?)
+         (apply ->files data))))


add :clj branch tests

add :clj branch tests

--- src/test/compassus/tests.cljc
+++ src/test/compassus/tests.cljc
@@ -57,13 +57,15 @@
   (is (fn? (c/root-class *app*)))
   (is (some? #?(:clj  (-> (c/root-class *app*) meta :component-name)
                 :cljs (.. (c/root-class *app*) -prototype))))
-  #?(:cljs (is (true? (.. (c/root-class *app*) -prototype -om$isComponent)))))
+  #?(:cljs (is (true? (.. (c/root-class *app*) -prototype -om$isComponent)))
+     :clj  (is (string? (-> (c/root-class *app*) meta :component-name)))))

 (deftest test-make-root-class
   (let [root (#'c/make-root-class {:routes {:index Home
                                           :about About}})]
     (is (fn? root))
-    #?(:cljs (is (true? (.. root -prototype -om$isComponent))))
+    #?(:cljs (is (true? (.. root -prototype -om$isComponent)))
+       :clj  (is (string? (-> root meta :component-name))))
     (is (= (om/get-query root)
            [::c/route
             {::c/route-data {:index [:home/title :home/content]


[onyx#681] Re-establish subscriber after conductor timeout

--- src/onyx/messaging/aeron.clj
+++ src/onyx/messaging/aeron.clj
@@ -1,7 +1,7 @@
 (ns ^:no-doc onyx.messaging.aeron
   (:require [clojure.core.async :refer [chan >!! <!! alts!! timeout close! sliding-buffer]]
             [com.stuartsierra.component :as component]
-            [taoensso.timbre :refer [fatal info] :as timbre]
+            [taoensso.timbre :refer [fatal info warn] :as timbre]
             [onyx.messaging.aeron.peer-manager :as pm]
             [onyx.messaging.aeron.publication-manager :as pubm]
             [onyx.messaging.aeron.publication-pool :as pub-pool :refer [get-publication]]
@@ -90,9 +90,6 @@
   (when peer-task-id
     (swap! virtual-peers pm/dissoc peer-task-id)))

-(def no-op-error-handler
-  (reify ErrorHandler
-    (onError [this x] (taoensso.timbre/warn x))))

 (defn fragment-data-handler [f]
   (FragmentAssembler.
@@ -112,10 +109,10 @@
                                                 (.toNanos TimeUnit/MICROSECONDS 10)
                                                 (.toNanos TimeUnit/MICROSECONDS 1000))))

-(defn consumer [handler ^IdleStrategy idle-strategy limit]
+(defn consumer [handler ^IdleStrategy idle-strategy limit shutdown failed]
   (reify Consumer
     (accept [this subscription]
-      (while (not (Thread/interrupted))
+      (while (and (not @shutdown) (not @failed))
         (let [fragments-read (.poll ^Subscription subscription ^FragmentHandler handler ^int limit)]
           (.idle idle-strategy fragments-read))))))

@@ -162,18 +159,33 @@
           (throw (ex-info "Could not deserialize incoming message from Aeron"
                           {:msg-type msg-type})))))

-(defn start-subscriber! [bind-addr port stream-id virtual-peers decompress-f idle-strategy]
-  (let [ctx (-> (Aeron$Context.)
-                (.errorHandler no-op-error-handler))
-        conn (Aeron/connect ctx)
-        channel (aeron-channel bind-addr port)
-        handler (fragment-data-handler
-                  (fn [buffer offset length header]
-                    (handle-message decompress-f virtual-peers buffer offset length header)))
-        subscription (.addSubscription conn channel stream-id)
-        subscriber-fut (future (try (.accept ^Consumer (consumer handler idle-strategy 10) subscription)
-                                    (catch Throwable e (fatal e))))]
-    {:conn conn :subscription subscription :subscriber-fut subscriber-fut}))
+
+(defn start-subscriber! [shutdown bind-addr port stream-id virtual-peers decompress-f idle-strategy]
+  (future
+   (loop []
+     (let [failed (atom false)
+           no-op-error-handler (reify ErrorHandler
+                                 (onError [this x]
+                                   (reset! failed true)))
+           ctx (-> (Aeron$Context.)
+                   (.errorHandler no-op-error-handler))
+           conn (Aeron/connect ctx)
+           channel (aeron-channel bind-addr port)
+           handler (fragment-data-handler
+                    (fn [buffer offset length header]
+                      (handle-message decompress-f virtual-peers buffer offset length header)))
+           subscription (.addSubscription conn channel stream-id)]
+       (try (.accept ^Consumer (consumer handler idle-strategy 10 shutdown failed) subscription)
+            (catch Throwable e
+              (reset! failed true)
+              (warn "Subscriber failed. Restarting." e))
+            (finally
+             (.close subscription)
+             (.close conn))))
+     (when-not @shutdown
+       (info "Subscriber failed. Restarting.")
+       (recur)))
+   (info "Shutting down subscriber.")))

 (defn get-threading-model
   [media-driver]
@@ -209,8 +221,9 @@
           virtual-peers (atom (pm/vpeer-manager))
           publication-pool (component/start (pub-pool/new-publication-pool opts send-idle-strategy))
           subscriber-count (arg-or-default :onyx.messaging.aeron/subscriber-count opts)
+          shutdown (atom false)
           subscribers (mapv (fn [stream-id]
-                              (start-subscriber! bind-addr port stream-id virtual-peers decompress-f receive-idle-strategy))
+                              (start-subscriber! shutdown bind-addr port stream-id virtual-peers decompress-f receive-idle-strategy))
                             (range subscriber-count))]
       (when embedded-driver?
         (.addShutdownHook (Runtime/getRuntime)
@@ -229,18 +242,16 @@
              :virtual-peers virtual-peers
              :compress-f compress-f
              :decompress-f decompress-f
+             :shutdown shutdown
              :port port
              :send-idle-strategy send-idle-strategy
              :subscriber-count subscriber-count
              :subscribers subscribers)))

-  (stop [{:keys [media-driver media-driver-context subscribers publication-pool] :as component}]
+  (stop [{:keys [media-driver media-driver-context subscribers publication-pool shutdown] :as component}]
     (taoensso.timbre/info "Stopping Aeron Peer Group")
     (component/stop publication-pool)
-    (doseq [subscriber subscribers]
-      (future-cancel (:subscriber-fut subscriber))
-      (.close ^Subscription (:subscription subscriber))
-      (.close ^Aeron (:conn subscriber)))
+    (reset! shutdown true)

     (when media-driver (.close ^MediaDriver media-driver))
     (when media-driver-context (.deleteAeronDirectory ^MediaDriver$Context media-driver-context))