Usage stats cleanup

Usage stats cleanup

--- src/metabase/util/stats.clj
+++ src/metabase/util/stats.clj
@@ -3,11 +3,29 @@
   (:require [clojure.tools.logging :as log]
             [clj-http.client :as client]
             [toucan.db :as db]
+            [metabase.api.session :as session-api]
             [metabase.config :as config]
-            (metabase.models [field :as field]
+            [metabase.driver :as driver]
+            [metabase.email :as email]
+            [metabase.integrations.slack :as slack]
+            (metabase.models [card :refer [Card]]
+                             [card-label :refer [CardLabel]]
+                             [collection :refer [Collection]]
+                             [dashboard :refer [Dashboard]]
+                             [dashboard-card :refer [DashboardCard]]
+                             [database :refer [Database]]
+                             [field :refer [Field]]
                              [humanization :as humanization]
-                             [table :as table]
-                             [setting :as setting])
+                             [label :refer [Label]]
+                             [metric :refer [Metric]]
+                             [permissions-group :refer [PermissionsGroup]]
+                             [pulse :refer [Pulse]]
+                             [pulse-card :refer [PulseCard]]
+                             [pulse-channel :refer [PulseChannel]]
+                             [query-execution :refer [QueryExecution]]
+                             [segment :refer [Segment]]
+                             [table :refer [Table]]
+                             [user :refer [User]])
             [metabase.public-settings :as public-settings]
             [metabase.util :as u]))

@@ -18,16 +36,14 @@
    The goal is to be able to get a rough sense for how many different hosts are throwing a specific error/event."
   (hash (str (java.net.InetAddress/getLocalHost))))

-
-(defn- anon-tracking-enabled?
-  "To avoid a circular reference"
-  []
-  (require 'metabase.public-settings)
-  (resolve 'metabase.public-settings/anon-tracking-enabled))
+(defn- one-if
+  "Return `1` if CONDITION is truthy, otherwise return `0`."
+  [condition]
+  (if condition 1 0))

 (defn- bin-micro-number
-  "Return really small bin number. Assumes positive inputs"
+  "Return really small bin number. Assumes positive inputs."
   [x]
   (case x
     0 "0"
@@ -37,119 +53,119 @@

 (defn- bin-small-number
-  "Return small bin number. Assumes positive inputs"
+  "Return small bin number. Assumes positive inputs."
   [x]
   (cond
-    (= 0 x) "0"
-    (<= 1 x 5) "1-5"
-    (<= 6 x 10) "6-10"
+    (= 0 x)      "0"
+    (<= 1 x 5)   "1-5"
+    (<= 6 x 10)  "6-10"
     (<= 11 x 25) "11-25"
-    (> x 25) "25+"))
+    (> x 25)     "25+"))

 (defn- bin-medium-number
-  "Return medium bin number. Assumes positive inputs"
+  "Return medium bin number. Assumes positive inputs."
   [x]
   (cond
-    (= 0 x) "0"
-    (<= 1 x 5) "1-5"
-    (<= 6 x 10) "6-10"
-    (<= 11 x 25) "11-25"
-    (<= 26 x 50) "26-50"
-    (<= 51 x 100) "51-100"
+    (= 0 x)        "0"
+    (<= 1 x 5)     "1-5"
+    (<= 6 x 10)    "6-10"
+    (<= 11 x 25)   "11-25"
+    (<= 26 x 50)   "26-50"
+    (<= 51 x 100)  "51-100"
     (<= 101 x 250) "101-250"
-    (> x 250) "250+"))
+    (> x 250)      "250+"))

 (defn- bin-large-number
-  "Return large bin number. Assumes positive inputs"
+  "Return large bin number. Assumes positive inputs."
   [x]
   (cond
-    (= 0 x) "0"
-    (< x 1) "< 1"
-    (<= 1 x 10) "1-10"
-    (<= 11 x 50) "11-50"
-    (<= 51 x 250) "51-250"
-    (<= 251 x 1000) "251-1000"
+    (= 0 x)           "0"
+    (< x 1)           "< 1"
+    (<= 1 x 10)       "1-10"
+    (<= 11 x 50)      "11-50"
+    (<= 51 x 250)     "51-250"
+    (<= 251 x 1000)   "251-1000"
     (<= 1001 x 10000) "1001-10000"
-    (> x 10000) "10000+"))
+    (> x 10000)       "10000+"))

 (defn- value-frequencies
-  "go through a bunch of maps and count the frequency a given key's values"
+  "Go through a bunch of maps and count the frequency a given key's values."
   [many-maps k]
   (frequencies (map k many-maps)))

 (defn- histogram
-  "Bin some frequencies using a passed in binning function"
+  "Bin some frequencies using a passed in BINNING-FN."
   [binning-fn many-maps k]
   (frequencies (map binning-fn (vals (value-frequencies many-maps k)))))

-(def micro-histogram
-  "Return a histogram for micro numbers"
+(def ^:private micro-histogram
+  "Return a histogram for micro numbers."
   (partial histogram bin-micro-number))

-(def small-histogram
-  "Return a histogram for small numbers"
+(def ^:private small-histogram
+  "Return a histogram for small numbers."
   (partial histogram bin-small-number))

-(def medium-histogram
-  "Return a histogram for medium numbers"
+(def ^:private medium-histogram
+  "Return a histogram for medium numbers."
   (partial histogram bin-medium-number))

-(def large-histogram
-  "Return a histogram for large numbers"
+(def ^:private large-histogram
+  "Return a histogram for large numbers."
   (partial histogram bin-large-number))

 (defn- instance-start-date
   "Pull up the first user account and use that date"
   []
-  (db/select-one-field :date_joined 'User {:order-by [[:date_joined :desc]]}))
+  (db/select-one-field :date_joined User {:order-by [[:date_joined :desc]]}))

 (defn- environment-type
   "Figure out what we're running under"
   []
   (cond
     (= (config/config-str :mb-client) "OSX") :osx
-    (config/config-str :rds-hostname) :elastic-beanstalk
-    (config/config-str :database-url) :heroku ;; Putting this last as 'database-url' seems least specific
-    :default :unknown))
+    (config/config-str :rds-hostname)        :elastic-beanstalk
+    (config/config-str :database-url)        :heroku ;; Putting this last as 'database-url' seems least specific
+    :default                                 :unknown))

 (defn- instance-settings
   "Figure out global info about his instance"
   []
-  {:version               (config/mb-version-info :tag)
-   :running_on            (environment-type)
-   :application_database  (config/config-str :mb-db-type)
-   :check_for_updates     (setting/get :check-for-updates)
-   :site_name             (not= (public-settings/site-name) "Metabase")
-   :report_timezone       (setting/get :report-timezone)
-   :friendly_names        (humanization/enable-advanced-humanization)
-   :email_configured      ((resolve 'metabase.email/email-configured?))
-   :slack_configured      ((resolve 'metabase.integrations.slack/slack-configured?))
-   :sso_configured        (boolean ((resolve 'metabase.api.session/google-auth-client-id)))
-   :instance_started      (instance-start-date)
-   :has_sample_data       (db/exists? 'Database, :is_sample true)})
+  {:version              (config/mb-version-info :tag)
+   :running_on           (environment-type)
+   :application_database (config/config-str :mb-db-type)
+   :check_for_updates    (public-settings/check-for-updates)
+   :site_name            (not= (public-settings/site-name) "Metabase")
+   :report_timezone      (driver/report-timezone)
+   :friendly_names       (humanization/enable-advanced-humanization)
+   :email_configured     (email/email-configured?)
+   :slack_configured     (slack/slack-configured?)
+   :sso_configured       (boolean (session-api/google-auth-client-id))
+   :instance_started     (instance-start-date)
+   :has_sample_data      (db/exists? Database, :is_sample true)})

 ;; util function
-(def add-summaries
+(def ^:private add-summaries
   "add up some dictionaries"
   (partial merge-with +))

 ;; User metrics
 (defn- user-dims
-  "characterize a user record"
+  "Characterize a USER record."
   [user]
-  {:total 1
-   :active (if (:is_active user) 1 0) ;; HOW DO I GET THE LIST OF ALL USERS INCLUDING INACTIVES?
-   :admin (if (:is_superuser user) 1 0)
-   :logged_in (if (nil? (:last_login user)) 0 1)
-   :sso (if (nil? (:google_auth user)) 0 1)})
+  {:total     1
+   :active    (one-if (:is_active user)) ;; HOW DO I GET THE LIST OF ALL USERS INCLUDING INACTIVES?
+   :admin     (one-if (:is_superuser user))
+   :logged_in (one-if (:last_login user))
+   :sso       (one-if (:google_auth user))})

 (defn- user-metrics
-  "Get metrics based on user records
+  "Get metrics based on user records.
   TODO: get activity in terms of created questions, pulses and dashboards"
   []
-  (let [users (db/select ['User :is_active :is_superuser :last_login :google_auth])]
+  (let [users (db/select [User :is_active :is_superuser :last_login :google_auth])]
     {:users (apply add-summaries (map user-dims users))}))

@@ -157,32 +173,31 @@
   "Get metrics based on groups:
   TODO characterize by # w/ sql access, # of users, no self-serve data access"
   []
-  (let [groups (db/select ['PermissionsGroup :id])]
-    {:groups (count groups)}))
+  {:groups (db/count PermissionsGroup)})

 ;; Artifact Metrics
 (defn- question-dims
-  "characterize a saved question
+  "Characterize a saved QUESTION.
   TODO: characterize by whether it has params, # of revisions, created by an admin"
-  [question]
-    {:total 1
-     :native (if (= (:query_type question) "native") 1 0)
-     :gui (if (not= (:query_type question) "native") 1 0)})
+  [{query-type :query_type}]
+    {:total  1
+     :native (one-if (= query-type "native"))
+     :gui    (one-if (not= query-type "native"))})

 (defn- question-metrics
   "Get metrics based on questions
   TODO characterize by # executions and avg latency"
   []
-  (let [questions (db/select ['Card :id :query_type])]
+  (let [questions (db/select [Card :id :query_type])]
     {:questions (apply add-summaries (map question-dims questions))}))

 (defn- dashboard-metrics
   "Get metrics based on dashboards
   TODO characterize by # of revisions, and created by an admin"
   []
-  (let [dashboards (db/select ['Dashboard :id :creator_id])
-        dashcards (db/select ['DashboardCard :id :card_id :dashboard_id])]
-    {:dashboards (count dashboards)
+  (let [dashboards (db/select [Dashboard :id :creator_id])
+        dashcards  (db/select [DashboardCard :id :card_id :dashboard_id])]
+    {:dashboards         (count dashboards)
      :num_dashs_per_user (medium-histogram dashboards :creator_id)
      :num_cards_per_dash (medium-histogram dashcards :dashboard_id)
      :num_dashs_per_card (medium-histogram dashcards :card_id)}))
@@ -191,81 +206,76 @@
   "Get mes based on pulses
   TODO: characterize by non-user account emails, # emails"
   []
-  (let [pulses (db/select ['Pulse :id :creator_id])
-        pulsecards (db/select ['PulseCard :id :card_id :pulse_id])
-        pulsechannels (db/select ['PulseChannel :channel_type :schedule_type])]
-    {:pulses (count pulses)
-     :pulse_types (frequencies (map :channel_type pulsechannels))
-     :pulse_schedules (frequencies (map :schedule_type pulsechannels))
-     :num_pulses_per_user (medium-histogram pulses :creator_id)
-     :num_pulses_per_card (medium-histogram pulsecards :card_id)
-     :num_cards_per_pulses (medium-histogram pulsecards :pulse_id)}))
+  (let [pulses         (db/select [Pulse :id :creator_id])
+        pulse-cards    (db/select [PulseCard :id :card_id :pulse_id])
+        pulse-channels (db/select [PulseChannel :channel_type :schedule_type])]
+    {:pulses               (count pulses)
+     :pulse_types          (frequencies (map :channel_type pulse-channels))
+     :pulse_schedules      (frequencies (map :schedule_type pulse-channels))
+     :num_pulses_per_user  (medium-histogram pulses :creator_id)
+     :num_pulses_per_card  (medium-histogram pulse-cards :card_id)
+     :num_cards_per_pulses (medium-histogram pulse-cards :pulse_id)}))

 (defn- label-metrics
   "Get metrics based on labels"
   []
-  (let [labels (db/select 'Label)
-        cardlabels (db/select ['CardLabel :card_id :label_id])]
-    {:labels (count labels)
-     :num_labels_per_card (micro-histogram cardlabels :card_id)
-     :num_cards_per_label (medium-histogram cardlabels :label_id)}))
+  (let [card-labels (db/select [CardLabel :card_id :label_id])]
+    {:labels              (db/count Label)
+     :num_labels_per_card (micro-histogram card-labels :card_id)
+     :num_cards_per_label (medium-histogram card-labels :label_id)}))

 (defn- collection-metrics
   "Get metrics on collection usage"
   []
-  (let [collections (db/select 'Collection)
-        cards (db/select ['Card :collection_id])]
-    {:collections (count collections)
-     :cards_in_collections (count (filter (comp nil?) (map :collection_id cards)))
+  (let [collections (db/select Collection)
+        cards       (db/select [Card :collection_id])]
+    {:collections              (count collections)
+     :cards_in_collections     (count (filter (comp nil?) (map :collection_id cards)))
      :cards_not_in_collections (count (filter nil? (map :collection_id cards)))
-     :num_cards_per_collection (medium-histogram cards :collection_id)}
-    )
-  )
+     :num_cards_per_collection (medium-histogram cards :collection_id)}))

 ;; Metadata Metrics
 (defn- database-dims
   "characterize a database record"
   [database]
-  {:total 1
-   :analyzed (if (:is_full_sync database) 1 0)})
+  {:total    1
+   :analyzed (one-if (:is_full_sync database))})

 (defn- database-metrics
   "Get metrics based on databases"
   []
-  (let [databases (db/select ['Database :id :is_full_sync])]
+  (let [databases (db/select [Database :id :is_full_sync])]
     {:databases (apply add-summaries (map database-dims databases))}))

 (defn- table-metrics
   "Get metrics based on tables"
   []
-  (let [tables (db/select ['Table :id :db_id :schema])]
-    {:tables (count tables)
+  (let [tables (db/select [Table :id :db_id :schema])]
+    {:tables           (count tables)
      :num_per_database (medium-histogram tables :db_id)
-     :num_per_schema (medium-histogram tables :schema)}))
+     :num_per_schema   (medium-histogram tables :schema)}))

 (defn- field-metrics
   "Get metrics based on fields"
   []
-  (let [fields (db/select ['Field :id :table_id])]
-    {:fields (count fields)
+  (let [fields (db/select [Field :table_id])]
+    {:fields        (count fields)
      :num_per_table (medium-histogram fields :table_id)}))

 (defn- segment-metrics
-  "Get metrics based on segments"
-  []
-  (let [segments (db/select ['Segment :id])]
-    {:segments (count segments)}))
+  "Get metrics based on segments."
+  []
+  {:segments (db/count Segment)})

 (defn- metric-metrics
   "Get metrics based on metrics"
   []
-  (let [metrics (db/select ['Metric :id])]
-    {:metrics (count metrics)}))
+  {:metrics (db/count Metric)})

 (defn- bin-latencies
@@ -279,13 +289,13 @@
 (defn- execution-metrics
   "Get metrics based on executions.
   This should be done in a single pass, as there might
-  be a LOT of query executions in a normal instance
-  TODO: characterize by ad hoc vs cards"
-  []
-  (let [executions (db/select ['QueryExecution :executor_id :running_time :status])]
-    {:executions (count executions)
-     :by_status (frequencies (map :status executions))
-     :num_per_user (large-histogram executions :executor_id)
+  be a LOT of query executions in a normal instance."
+  ;; TODO - This looks dangerous, pulling the entire set of QueryExecutions into memory at once to calculate these metrics (!)
+  []
+  (let [executions (db/select [QueryExecution :executor_id :running_time :status])]
+    {:executions     (count executions)
+     :by_status      (frequencies (map :status executions))
+     :num_per_user   (large-histogram executions :executor_id)
      :num_by_latency (bin-latencies executions)}))

@@ -293,20 +303,20 @@
   "generate a map of the usage stats for this instance"
   []
   (merge (instance-settings)
-           {:uuid anonymous-id :timestamp (new java.util.Date)}
-            {:stats {:user (user-metrics)
-                     :question (question-metrics)
-                     :dashboard (dashboard-metrics)
-                     :database (database-metrics)
-                     :table (table-metrics)
-                     :field (field-metrics)
-                     :pulse (pulse-metrics)
-                     :segment (segment-metrics)
-                     :metric (metric-metrics)
-                     :group (group-metrics)
-                     :label (label-metrics)
-                     :collection (collection-metrics)
-                     :execution (execution-metrics)}}))
+         {:uuid anonymous-id, :timestamp (java.util.Date.)}
+         {:stats {:user       (user-metrics)
+                  :question   (question-metrics)
+                  :dashboard  (dashboard-metrics)
+                  :database   (database-metrics)
+                  :table      (table-metrics)
+                  :field      (field-metrics)
+                  :pulse      (pulse-metrics)
+                  :segment    (segment-metrics)
+                  :metric     (metric-metrics)
+                  :group      (group-metrics)
+                  :label      (label-metrics)
+                  :collection (collection-metrics)
+                  :execution  (execution-metrics)}}))

 (defn- send-stats!
@@ -315,12 +325,11 @@
    (try
       (client/post metabase-usage-url {:form-params stats, :content-type :json, :throw-entire-message? true})
       (catch Throwable e
-       (log/error "Sending usage stats FAILED: " (.getMessage e)))))
+       (log/error "Sending usage stats FAILED:" (.getMessage e)))))

 (defn phone-home-stats!
   "Collect usage stats and phone them home"
   []
-  (when (anon-tracking-enabled?)
-    (let [stats (anonymous-usage-stats)]
-      (send-stats! stats))))
+  (when (public-settings/anon-tracking-enabled)
+    (send-stats! (anonymous-usage-stats))))


Namespace lifecycle data.

Namespace lifecycle data.

--- src/onyx/plugin/datomic.clj
+++ src/onyx/plugin/datomic.clj
@@ -25,26 +25,27 @@

 (defmethod l-ext/inject-lifecycle-resources
   :datomic/load-datoms
-  [_ {:keys [task-map fn-params] :as pipeline}]
+  [_ {:keys [onyx.core/task-map onyx.core/fn-params] :as pipeline}]
   (let [conn (d/connect (:datomic/uri task-map))
         db (d/as-of (d/db conn) (:datomic/t task-map))]
-    {:params [db]}))
+    {:onyx.core/params [db]}))

 (defmethod l-ext/inject-lifecycle-resources
   :datomic/commit-tx
-  [_ {:keys [task-map]}]
+  [_ {:keys [onyx.core/task-map]}]
   {:datomic/conn (d/connect (:datomic/uri task-map))})

 (defmethod l-ext/apply-fn [:input :datomic]
-  [{:keys [task-map] :as pipeline}]
+  [{:keys [onyx.core/task-map] :as pipeline}]
   (let [conn (d/connect (:datomic/uri task-map))
         t (:datomic/t task-map)
         partition (:datomic/partition task-map)
         size (:datomic/datoms-per-segment task-map)
         partitions (partition-all 2 1 (range 0 t size))]
-    {:results (map (fn [[low high]]
-                     {:low low :high (or high t) :partition partition})
-                   partitions)}))
+    {:onyx.core/results
+     (map (fn [[low high]]
+            {:low low :high (or high t) :partition partition})
+          partitions)}))

 (defn load-datoms [db {:keys [low high partition]}]
   (->> (datoms-between db partition low high)
@@ -57,11 +58,11 @@
   {})

 (defmethod l-ext/compress-batch [:output :datomic]
-  [{:keys [decompressed] :as pipeline}]
-  {:compressed decompressed})
+  [{:keys [onyx.core/decompressed] :as pipeline}]
+  {:onyx.core/compressed decompressed})

 (defmethod l-ext/write-batch [:output :datomic]
-  [{:keys [compressed] :as pipeline}]
+  [{:keys [onyx.core/compressed] :as pipeline}]
   @(d/transact (:datomic/conn pipeline) (mapcat :datoms compressed))
-  {:written? true})
+  {:onyx.core/written? true})


Fix extra element in map.

Fix extra element in map.

--- src/onyx_benchmark/peer.clj
+++ src/onyx_benchmark/peer.clj
@@ -43,14 +43,13 @@
   (assoc segment :n (inc n)))

 (defn -main [zk-addr id n-peers & args]
-  (let [peer-config
-        {:zookeeper/address zk-addr
-         :onyx/id id
-         :onyx.messaging/bind-addr "127.0.0.1" (slurp "http://169.254.169.254/latest/meta-data/local-ipv4")
-         :onyx.messaging/peer-ports (vec (range 40000 40200))
-         :onyx.peer/join-failure-back-off 500
-         :onyx.peer/job-scheduler :onyx.job-scheduler/greedy
-         :onyx.messaging/impl :netty}
+  (let [peer-config {:zookeeper/address zk-addr
+                     :onyx/id id
+                     :onyx.messaging/bind-addr (slurp "http://169.254.169.254/latest/meta-data/local-ipv4")
+                     :onyx.messaging/peer-ports (vec (range 40000 40200))
+                     :onyx.peer/join-failure-back-off 500
+                     :onyx.peer/job-scheduler :onyx.job-scheduler/greedy
+                     :onyx.messaging/impl :netty}
         n-peers-parsed (Integer/parseInt n-peers)
         peer-group (onyx.api/start-peer-group peer-config)
         peers (onyx.api/start-peers n-peers-parsed peer-group)]


Constantly is variadic and builds a list

--- src/onyx/messaging/aeron.clj
+++ src/onyx/messaging/aeron.clj
@@ -37,7 +37,7 @@
           external-channel (:external-channel messaging-group)
           short-circuitable? (if (arg-or-default :onyx.messaging/allow-short-circuit? config)
                                (fn [channel] (= channel external-channel))
-                               (constantly false))
+                               (fn [_] false))
           release-ch (chan (sliding-buffer (arg-or-default :onyx.messaging/release-ch-buffer-size config)))
           retry-ch (chan (sliding-buffer (arg-or-default :onyx.messaging/retry-ch-buffer-size config)))
           write-buffer-size (arg-or-default :onyx.messaging.aeron/write-buffer-size config)


Stop closing nil pub.

Stop closing nil pub.

--- src/onyx/messaging/aeron.clj
+++ src/onyx/messaging/aeron.clj
@@ -257,8 +257,8 @@
 (defmethod extensions/close-peer-connection AeronConnection
   [messenger event peer-link]
   (when-let [pub (get-in peer-link [:send-pub :pub])]
-    (.close @pub))
+    (when @pub (.close @pub)))
   (when-let [pub (get-in peer-link [:send-pub :aux-pub])]
-    (.close @pub))
+    (when @pub (.close @pub)))
   (.close (:conn peer-link))
   {})


No longer stick the whole messenger into the virtual peers map as it becomes unprintable because it's cyclic. This will likely exhibit better behaviour when vpeers are not stopped properly.

--- src/onyx/messaging/aeron.clj
+++ src/onyx/messaging/aeron.clj
@@ -44,12 +44,14 @@
           retry-ch (chan (sliding-buffer (arg-or-default :onyx.messaging/retry-ch-buffer-size config)))
           acking-ch (:acking-ch (:acking-daemon component))
           send-idle-strategy (:send-idle-strategy messaging-group)
-          compress-f (:compress-f (:messaging-group peer-group))]
+          compress-f (:compress-f (:messaging-group peer-group))
+          multiplex-id (atom nil)]
       (assoc component
              :messaging-group messaging-group
              :short-circuitable? short-circuitable?
              :publications publications
              :connections connections
+             :multiplex-id multiplex-id
              :virtual-peers virtual-peers
              :send-idle-strategy send-idle-strategy
              :compress-f compress-f
@@ -58,13 +60,14 @@
              :release-ch release-ch
              :retry-ch retry-ch)))

-  (stop [{:keys [id release-ch retry-ch virtual-peers] :as component}]
+  (stop [{:keys [release-ch retry-ch virtual-peers multiplex-id] :as component}]
     (taoensso.timbre/info "Stopping Aeron")
     (try
       ;;; TODO; could handle the inbound-ch in a similar way - rather than using messenger-buffer
       (close! release-ch)
       (close! retry-ch)
-      (swap! virtual-peers dissoc id)
+      (when @multiplex-id
+        (swap! virtual-peers dissoc @multiplex-id))
       (catch Throwable e (fatal e)))
     (assoc component
            :send-idle-strategy nil
@@ -72,12 +75,17 @@
            :publications nil
            :connections nil
            :virtual-peers nil
+           :multiplex-id nil
            :compress-f nil :decompress-f nil
            :inbound-ch nil :release-ch nil :retry-ch nil )))

+(defrecord PeerChannels [acking-ch inbound-ch release-ch retry-ch])
+
 (defmethod extensions/open-peer-site AeronConnection
-  [{:keys [virtual-peers] :as messenger} {:keys [aeron/id]}]
-  (swap! virtual-peers assoc id messenger))
+  [{:keys [virtual-peers multiplex-id acking-ch inbound-ch release-ch retry-ch] :as messenger}
+   {:keys [aeron/id]}]
+  (reset! multiplex-id id)
+  (swap! virtual-peers assoc id (->PeerChannels acking-ch inbound-ch release-ch retry-ch)))

 (def no-op-error-handler
   (reify ErrorHandler
@@ -274,11 +282,11 @@
 (defn choose-id [used]
   (first (clojure.set/difference possible-ids used)))

-;;; Assigns a unique id to each peer so that messages do not need
-;;; to send the entire peer-id in a payload, saving 14 bytes per
-;;; message
 (defmethod extensions/assign-site-resources :aeron
   [replica peer-site peer-sites]
+  ;;; Assigns a unique id to each peer so that messages do not need
+  ;;; to send the entire peer-id in a payload, saving 14 bytes per
+  ;;; message
   (let [used-ids (->> (vals peer-sites)
                       (filter
                         (fn [s]
@@ -305,7 +313,6 @@

 (defrecord AeronPeerConnection [channel id])

-;;;; THIS CAN BE MADE FASTER BY NOT GOING THROUGH PEER-LINK IN OPERATION
 (defmethod extensions/connect-to-peer AeronConnection
   [messenger peer-id event {:keys [aeron/external-addr aeron/port aeron/id]}]
   (->AeronPeerConnection (aeron-channel external-addr port) id))


Check the shutdown? flag in the timeout inner loop

--- src/onyx/metrics/riemann.clj
+++ src/onyx/metrics/riemann.clj
@@ -46,24 +46,25 @@
           (let [events (map metric->riemann-event (read-batch ch batch-size batch-timeout))]
             (when-not (empty? events)
               (loop [sleep 0]
-                ;; Exponential backoff to rate limit errors
-                (when-not (zero? sleep)
-                  (info (format "Message send timeout count %s. Backing off %s." @timeout-count sleep))
-                  (Thread/sleep sleep))
+                (when-not @shutdown?
+                  ;; Exponential backoff to rate limit errors
+                  (when-not (zero? sleep)
+                    (info (format "Message send timeout count %s. Backing off %s." @timeout-count sleep))
+                    (Thread/sleep sleep))

-                (let [result (try
-                               (-> client
-                                   (r/send-events events)
-                                   (deref defaulted-timeout ::timeout))
-                               (catch InterruptedException e
-                                 (.interrupt (Thread/currentThread))
-                                 (throw (RuntimeException. e)))
-                               (catch Throwable e
-                                 (warn e "Lost riemann connection" address port)
-                                 ::exception))]
-                  (when (#{::exception ::timeout} result)
-                    (swap! timeout-count inc)
-                    (recur (next-sleep-time sleep))))))))
+                  (let [result (try
+                                (-> client
+                                    (r/send-events events)
+                                    (deref defaulted-timeout ::timeout))
+                                (catch InterruptedException e
+                                  (.interrupt (Thread/currentThread))
+                                  (throw (RuntimeException. e)))
+                                (catch Throwable e
+                                  (warn e "Lost riemann connection" address port)
+                                  ::exception))]
+                    (when (#{::exception ::timeout} result)
+                      (swap! timeout-count inc)
+                      (recur (next-sleep-time sleep)))))))))
         (finally
           (info "Closing riemann connection.")
           (r/close! client))))))


Don't allow non a-z A-Z 0-9 - chars in asset filenames. Fixes #84

--- src/overtone/libs/asset.clj
+++ src/overtone/libs/asset.clj
@@ -36,12 +36,16 @@
   (let [url (str url)]
     (str (hash url))))

+(defn- safe-path
+  [path]
+  (let [safe (safe-url path)
+        hsh  (url-hash path)]
+    (str safe "--" hsh)))
+
 (defn- cache-dir
   "Returns the name of a directory to cache an asset with the given url."
   [url]
-  (let [safe (safe-url url)
-        hsh  (url-hash url)]
-    (mk-path *cache-root* (str safe "--" hsh))))
+  (mk-path *cache-root* (safe-path url)))

 (defn- mk-cache-dir!
   "Create a new cache dir for the specified url"
@@ -52,14 +56,16 @@
 (defn- fetch-cached-path
   "Returns the path to the cached asset if present, otherwise nil."
   [url name]
-  (let [path (mk-path (cache-dir url) name)]
+  (let [name (safe-path name)
+        path (mk-path (cache-dir url) name)]
     (when (path-exists? path)
       path)))

 (defn- download-and-cache-asset
   "Downloads the file pointed to by url and caches it on the local file system"
   [url name]
-  (let [tmp-dir   (str (mk-tmp-dir!))
+  (let [name      (safe-path name)
+        tmp-dir   (str (mk-tmp-dir!))
         tmp-file  (mk-path tmp-dir name)
         dest-dir  (cache-dir url)
         dest-file (mk-path dest-dir name)]


Version of midi-clj that we currently depend on still expects handler fns to accept two args - msg and ts. Update this when we release a new version of midi-clj

--- src/overtone/studio/midi.clj
+++ src/overtone/studio/midi.clj
@@ -13,7 +13,7 @@

 (defn midi-event
   "Trigger a global midi event."
-  [msg]
+  [msg ts]
   (event [:midi (:command msg)] msg))

 (defn- detect-midi-devices


fix nesting

fix nesting

--- src/pc/models/permission.clj
+++ src/pc/models/permission.clj
@@ -73,13 +73,13 @@
 ;; TODO: figure out how to have only 1 read-api (maybe only send datoms?)
 (defn read-api [db permission]
   (let [doc-id (:db/id (:permission/document-ref permission))
-        cust-email (:cust/email (:permission/cust-ref permission))])
-  (-> permission
-    (select-keys [:permission/permits
-                  :permission/grant-date])
-    (assoc :db/id (web-peer/client-id permission))
-    (cond-> doc-id (assoc :permission/document doc-id)
-            cust-email (assoc :permission/cust cust-email))))
+        cust-email (:cust/email (:permission/cust-ref permission))]
+    (-> permission
+      (select-keys [:permission/permits
+                    :permission/grant-date])
+      (assoc :db/id (web-peer/client-id permission))
+      (cond-> doc-id (assoc :permission/document doc-id)
+              cust-email (assoc :permission/cust cust-email)))))

 (defn find-by-document [db doc]
   (->> (d/q '{:find [?t]


Brought GASR up-to-date with Ekeko's revised handling of arrays (use today's Ekeko commit). All tests green.

--- damp.ekeko.aspectj.plugin/src/damp/ekeko/aspectj.clj
+++ damp.ekeko.aspectj.plugin/src/damp/ekeko/aspectj.clj
@@ -10,7 +10,8 @@
              [xcut :as xcut]
              [weaverworld :as world]
              [assumptions :as assumptions]
-             ]))
+             ])
+  (:import [org.aspectj.weaver.AnnotationAJ]))

 (defn
   make-query-views-aspectj-aware!
@@ -18,6 +19,20 @@
   (intern 'damp.ekeko.gui 'label-provider-class baristaui.views.queryResult.AJDTLabelProvider))

 (make-query-views-aspectj-aware!)
+
+
+(extend-ISupportContains-to-arrays-of-class org.aspectj.weaver.AnnotationAJ)
+(extend-ISupportContains-to-arrays-of-class org.aspectj.weaver.ResolvedMember)
+(extend-ISupportContains-to-arrays-of-class org.aspectj.weaver.ResolvedPointcutDefinition)
+
+(extend-ISupportContains-to-arrays-of-class org.aspectj.weaver.ResolvedType)
+(extend-ISupportContains-to-arrays-of-class org.aspectj.weaver.UnresolvedType)
+(extend-ISupportContains-to-arrays-of-class org.aspectj.weaver.TypeVariable)
+(extend-ISupportContains-to-arrays-of-class org.aspectj.weaver.JoinPointSignature)
+(extend-ISupportContains-to-arrays-of-class org.aspectj.weaver.Member)
+
+
+

 (comment
   ;; Example REPL session


Fix modal-panel not picking up prop changes

https://github.com/Day8/re-com/pull/34

--- src/re_com/modal_panel.cljs
+++ src/re_com/modal_panel.cljs
@@ -23,30 +23,29 @@
       :or   {wrap-nicely? true backdrop-color "black" backdrop-opacity 0.6}
       :as   args}]
   {:pre [(validate-args-macro modal-panel-args-desc args "modal-panel")]}
-  (fn []
-    [:div
-     (merge {:class  (str "rc-modal-panel display-flex " class)    ;; Containing div
-             :style (merge {:position "fixed"
-                            :left     "0px"
-                            :top      "0px"
-                            :width    "100%"
-                            :height   "100%"}
-                           style)}
-            attr)
-     [:div
-      {:style    {:position         "fixed"           ;; Backdrop
-                  :width            "100%"
-                  :height           "100%"
-                  :background-color backdrop-color
-                  :opacity          backdrop-opacity
-                  :z-index          1020
-                  :pointer-events   "none"}           ;; TODO: trying to prevent change of focus under the bwhen clicking on backdrop (also with the on-click below). Remove!
-       :on-click #(do (println "stopping propagation") (.preventDefault %) (.stopPropagation %))
-       }]
-     [:div
-      {:style (merge {:margin  "auto"                 ;; Child
-                      :z-index 1020}
-                     (when wrap-nicely? {:background-color "white"
-                                         :padding          "16px"
-                                         :border-radius    "6px"}))}
-      child]]))
+  [:div
+   (merge {:class  (str "rc-modal-panel display-flex " class)    ;; Containing div
+           :style (merge {:position "fixed"
+                          :left     "0px"
+                          :top      "0px"
+                          :width    "100%"
+                          :height   "100%"}
+                         style)}
+          attr)
+   [:div
+    {:style    {:position         "fixed"           ;; Backdrop
+                :width            "100%"
+                :height           "100%"
+                :background-color backdrop-color
+                :opacity          backdrop-opacity
+                :z-index          1020
+                :pointer-events   "none"}           ;; TODO: trying to prevent change of focus under the bwhen clicking on backdrop (also with the on-click below). Remove!
+     :on-click #(do (println "stopping propagation") (.preventDefault %) (.stopPropagation %))
+     }]
+   [:div
+    {:style (merge {:margin  "auto"                 ;; Child
+                    :z-index 1020}
+                   (when wrap-nicely? {:background-color "white"
+                                       :padding          "16px"
+                                       :border-radius    "6px"}))}
+    child]])


Update->story.

Update->story.

--- src/oc/storage/lib/email.clj
+++ src/oc/storage/lib/email.clj
@@ -7,7 +7,7 @@
             [oc.storage.resources.common :as common-res]))

 (def EmailTrigger
-  {:type (schema/enum "update")
+  {:type (schema/enum "story")
    :to [schema/Str]
    :subject schema/Str
    :note schema/Str
@@ -18,23 +18,23 @@
    :logo-url (schema/maybe schema/Str)
    :origin-url schema/Str
    :currency schema/Str
-   :entries [common-res/UpdateEntry]
+   :entries [common-res/StoryEntry]
    :created-at lib-schema/ISO8601})

-(defn ->trigger [org-slug update origin-url user]
-  {:type "update"
-   :to (vec (:to update))
-   :subject (:subject update)
-   :note (:note update)
+(defn ->trigger [org-slug story origin-url user]
+  {:type "story"
+   :to (vec (:to story))
+   :subject (:subject story)
+   :note (:note story)
    :reply-to (:email user)
-   :slug (:slug update)
+   :slug (:slug story)
    :org-slug org-slug
    :origin-url origin-url
-   :org-name (:org-name update)
-   :logo-url (:logo-url update)
-   :currency (:currency update)
-   :entries (:entries update)
-   :created-at (:created-at update)})
+   :org-name (:org-name story)
+   :logo-url (:logo-url story)
+   :currency (:currency story)
+   :entries (:entries story)
+   :created-at (:created-at story)})

 (defn send-trigger! [trigger]
   (timbre/info "Email request to:" config/aws-sqs-email-queue "\n" (dissoc trigger :entries))


kibit comment happiness

kibit comment happiness

--- src/open_company/lib/bot.clj
+++ src/open_company/lib/bot.clj
@@ -72,6 +72,6 @@

   (send-trigger! {:abc :d})

-  (-> @(slack :users.list {:token tkn}) :body)
+  (:body @(slack :users.list {:token tkn}))

   )


tidy docstrings

tidy docstrings

--- src/overtone/algo/chance.clj
+++ src/overtone/algo/chance.clj
@@ -16,13 +16,13 @@
   (take n (shuffle col)))

 (defn weighted-choose
-  "Returns an element from list vals based on the corresponding probabilities
-  list. The length of vals and probabilities should be similar and the sum
-  of all the probabilities should be 1. It is also possible to pass a map of
-  val -> prob pairs as a param.
+  "Returns an element from list vals based on the corresponding
+  probabilities list. The length of vals and probabilities should be
+  similar and the sum of all the probabilities should be 1. It is also
+  possible to pass a map of val -> prob pairs as a param.

-  The following will return one of the following vals with the corresponding
-  probabilities:
+  The following will return one of the following vals with the
+  corresponding probabilities:
   1 -> 50%
   2 -> 30%
   3 -> 12.5%
@@ -61,8 +61,9 @@
            (recur (rest summed)))))))

 (defn weighted-coin
-  "Returns true or false. Probability of true is weighted by n which should be
-   within the range 0 - 1. n will be truncated to range 0 - 1 if it isn't"
+  "Returns true or false. Probability of true is weighted by n which
+   should be within the range 0 - 1. n will be truncated to range 0 - 1
+   if it isn't"
   [n]
   (let [n (float n)
         n (if (< n 0) 0 n)


Added number? function

Added number? function

--- base/general.clj
+++ base/general.clj
@@ -1,6 +1,12 @@
 (in-ns 'clojure)

 (defn include?
-  "Returns true if x is included in coll."
+  "Returns true if x is contained in coll, else false."
   [x coll]
     (some (partial = x) coll))
+
+(defn number?
+  "Returns true if an Clojure number type."
+  [x]
+  (or (instance? clojure.lang.FixNum x)
+      (instance? clojure.lang.DoubleNum x)))


tell touch-enabled devices how to open the radial menu

--- src-cljs/frontend/components/aside.cljs
+++ src-cljs/frontend/components/aside.cljs
@@ -15,9 +15,11 @@
   (reify
     om/IInitState
     (init-state [_]
-      {:listener-key (.getNextUniqueId (.getInstance IdGenerator))})
+      {:listener-key (.getNextUniqueId (.getInstance IdGenerator))
+       :touch-enabled? false})
     om/IDidMount
     (did-mount [_]
+      (om/set-state! owner :touch-enabled? (.hasOwnProperty js/window "ontouchstart"))
       (d/listen! (om/get-shared owner :db)
                  (om/get-state owner :listener-key)
                  (fn [tx-report]
@@ -42,7 +44,11 @@
     (render [_]
       (let [{:keys [cast!]} (om/get-shared owner)
             chats (ds/touch-all '[:find ?t :where [?t :chat/body]] @db)
-            dummy-chat {:chat/body "Welcome to Precursor! Right-click on the canvas to access tools and share your url to collaborate."
+            dummy-chat {:chat/body (str "Welcome to Precursor! "
+                                        (if (om/get-state owner :touch-enabled?)
+                                          "Tap and hold on the canvas to access tools"
+                                          "Right-click on the canvas to access tools")
+                                        "  and share your url to collaborate.")
                         :chat/color "#00b233"
                         :session/uuid "Danny"
                         :server/timestamp (js/Date. 0)}]


fix pricing url

fix pricing url

--- src-cljs/frontend/components/outer.cljs
+++ src-cljs/frontend/components/outer.cljs
@@ -308,7 +308,7 @@
               "That's why we built lightweight collaboration tools, to help your team communicate effectively. "
               "Solve problems with your team in real time. "]
              [:div.calls-to-action
-              [:a.bubble-button {:href "pricing"}
+              [:a.bubble-button {:href "/pricing"}
                [:span "See our team pricing."]]]]
             [:div.feature.art-visible.content
              [:div.feature-story


Turn macro into function

Turn macro into function

--- src/play_clj/core_global.clj
+++ src/play_clj/core_global.clj
@@ -16,21 +16,21 @@
       `(Color. ^Color (utils/gdx-static-field :graphics :Color ~(first args)))
       `(Color. ~@args)))

-(defn game*
+(defmacro bitmap-font
+  [& options]
+  `(BitmapFont. ~@options))
+
+(defn game
   [key]
   (case key
-    :width `(.getWidth (Gdx/graphics))
-    :height `(.getHeight (Gdx/graphics))
-    :fps `(.getFramesPerSecond (Gdx/graphics))
-    :is-fullscreen? `(.isFullscreen (Gdx/graphics))
-    :is-touched? `(.isTouched (Gdx/input))
-    :x `(.getX (Gdx/input))
-    :y `(.getY (Gdx/input))
+    :width (.getWidth (Gdx/graphics))
+    :height (.getHeight (Gdx/graphics))
+    :fps (.getFramesPerSecond (Gdx/graphics))
+    :is-fullscreen? (.isFullscreen (Gdx/graphics))
+    :is-touched? (.isTouched (Gdx/input))
+    :x (.getX (Gdx/input))
+    :y (.getY (Gdx/input))
     nil))
-
-(defmacro game
-  [key]
-  `~(game* key))

 ; input


Go ahead and :use speclj in those tests instead of just :require

--- spec/frereth_server/authentication_spec.clj
+++ spec/frereth_server/authentication_spec.clj
@@ -1,54 +1,66 @@
 (ns frereth-server.authentication-spec
-  (:require [speclj.core :as spec]
-            [frereth-server.authentication :as auth]
+  (:require [frereth-server.authentication :as auth]
             [frereth-server.config :as config]
             [frereth-server.system :as sys]
             [zguide.zhelpers :as mq])
+  (:use [speclj.core :as spec])
   (:gen-class))

 (let [world (atom nil)
       client (atom nil)]

-  (spec/describe "Validate authentication"
-                 (spec/before-all
-                  (println "Preparing")
-                  (reset! world (sys/init)))
+  (describe "Check authentication"
+            (before-all
+             (println "Preparing")
+             (reset! world (sys/init)))

-                 (spec/after-all
-                  (println "Ending")
-                  ;; Next line is causing an NPE. WTF?
-                  (if-let [client @client]
-                    (do (.close @client)
-                        (reset! client nil))
-                    (println "NULL client. Huh?"))
+            (after-all
+             (println "Ending")
+             (if-let [client @client]
+               (do (.close @client)
+                   (reset! client nil))
+               (println "NULL client. Huh?"))

-                  (reset! world nil))
+             (reset! world nil))

-                 (spec/before
-                  (println "\tTesting...")
-                  (swap! world sys/start)
-                  (reset! client (let [ctx (@world :network-context)
-                                       s (mq/socket @ctx mq/req)
-                                       address (format
-                                                "tcp://127.0.0.1:%d"
-                                                config/auth-port)]
-                                   (mq/connect s address)
-                                   s)))
+            (before
+             (println "\tTesting...")
+             (swap! world sys/start)
+             (reset! client (let [ctx (@world :network-context)
+                                  s (mq/socket @ctx mq/req)
+                                  address (format
+                                           "tcp://127.0.0.1:%d"
+                                           config/auth-port)]
+                              (mq/connect s address)
+                              s)))

-                 (spec/after
-                  (println "\t...Tested")
-                  (swap! world sys/stop))
+            (after
+             (println "\t...Tested")
+             (swap! world sys/stop))

-                 (spec/it "Kill"
-                          (spec/should= "K" (#'auth/dispatch "dieDieDIE!!")))
+            (it "Kill"
+                (should= "K" (#'auth/dispatch "dieDieDIE!!")))

-                 (spec/it "Kill Message"
-                          (reset! (:done @world) true)
-                          (let [auth-thread (:authentication-thread world)]
-                            (mq/send @client "dieDieDIE!!")
-                            (let [response (mq/recv-str @client)]
-                              (spec/should= "K" response)
-                              (.join @auth-thread 50)
-                              (spec/should (not (.isAlive @auth-thread))))))))
+            (it "Kill Message"
+                (reset! (:done @world) true)
+                (let [auth-thread (:authentication-thread world)]
+                  (mq/send @client "dieDieDIE!!")
+                  (let [response (mq/recv-str @client)]
+                    (should= "K" response)
+                    (.join @auth-thread 50)
+                    (should (not (.isAlive @auth-thread))))))

-(spec/run-specs)
+            (it "Basic Login Sequence"
+                ;; This is trickier than I realized.
+                ;; I really want to send a multi-part message.
+                ;; Something along these lines:
+                ;; 1) ib <user-id>
+                ;; 2) me-wantz-play <protocol versions client understands>
+                ;; 3) <signature>
+                ;; That approach seems like it will just make
+                ;; life simpler from any angle that comes to mind.
+                ;; Dispatcher gets more complicated,but that isn't
+                ;; a big deal.
+                (should false))))
+
+(run-specs)


Keep repair/break of systems in-frequent.

--- src/startrek/enterprise.clj
+++ src/startrek/enterprise.clj
@@ -63,7 +63,7 @@
 (defn enterprise-update [game-state]
   (when (empty? (get-in @game-state [:current-klingons]))
     (repair-damage game-state (get-in @game-state [:enterprise]))
-    (when (<= (gen-double) 0.8)
+    (when (<= (gen-double) 0.2)
       (let [system (get-system (:enterprise @game-state))]
         (if (>= (gen-double) 0.5)
           (do


added comment about return values from mutations in stock Om

--- src/devguide/untangled_devguide/M30_Advanced_Mutation.cljs
+++ src/devguide/untangled_devguide/M30_Advanced_Mutation.cljs
@@ -55,7 +55,10 @@
   IMPORTANT: The general interaction with the world requires integration of external data (often in a tree format) with
   your app database (normalized graph of maps/vectors). As a result, you almost always want an Om-managed query when
   integrating data, so that the result is normalized. This is also why mutations don't have return values: there is
-  no query to use to merge such a result.
+  no query to use to merge such a result (in stock Om Next you
+  could override merge to try to address this, but we feel that
+  creates a concentration of cross-cutting concerns in `merge` with
+  little practical benefit).

   ### Creating Components *Just* For Their Queries


Fixed Atom feed with proper escaping

Fixed Atom feed with proper escaping

--- src/statuses/views/atom.clj
+++ src/statuses/views/atom.clj
@@ -1,5 +1,6 @@
 (ns statuses.views.atom
-  (:require [statuses.backend.time :as time]))
+  (:require [statuses.backend.time :as time]
+            [hiccup.util :as util]))

@@ -18,7 +19,7 @@
                 [{:keys [id author text time]}]
                 [:entry
                  [:title (str "Posted by @" author)]
-                 [:summary text]
+                 [:summary (util/escape-html text)]
                  [:id id]
                  [:published (time/time-to-rfc3339 time)]
                  [:link {:href (str base-uri "/statuses/updates/" id) }]]) items))))


Define test-helper custom-config-fixtureer.

--- spec/incise/test_helpers.clj
+++ spec/incise/test_helpers.clj
@@ -6,3 +6,7 @@
                               ~custom-config))]
      ~@body))

+(defn custom-config-fixturer [& {:as config}]
+  (fn [f]
+    (with-custom-config config
+      (f))))


adding a header to the frontend layout

adding a header to the frontend layout

--- src-cljs/bitfondue/core.cljs
+++ src-cljs/bitfondue/core.cljs
@@ -18,8 +18,16 @@
                    (sort-by :created_on))]
      [:li (:title item)])])

+(defn header
+  []
+  [:nav.navbar.navbar-default
+   [:div.container-fluid
+    [:div.navbar-header
+     [:a.navbar-brand "bitfondue"]]]])
+
 (defn layout
   []
+  [header]
   [:div
    [chunks]])


center the login form

center the login form

--- src-cljs/bitfondue/core.cljs
+++ src-cljs/bitfondue/core.cljs
@@ -76,7 +76,7 @@
   [layout [:h1 "About"]])

 (def login-form
-  [:div.col-md-6
+  [:div.col-md-offset-3.col-md-6
    [:h1 "Login"]
    [:br]
    [:form


fix line tool shortcut

fix line tool shortcut

--- src-cljs/frontend/state.cljs
+++ src-cljs/frontend/state.cljs
@@ -24,7 +24,7 @@
    :keyboard-shortcuts {:select #{"v"}
                         :circle #{"l"}
                         :rect #{"m"}
-                        :line #{"/"}
+                        :line #{"\\"}
                         :pen #{"n"}
                         :text #{"t"}
                         :undo #{"meta+z" "ctrl+z"}


Split the bash into more actions, for more granular output

--- src/circle/backend/project/circle.clj
+++ src/circle/backend/project/circle.clj
@@ -2,6 +2,7 @@
   (:require [circle.backend.nodes :as nodes])
   (:require [circle.backend.nodes.circle :as circle])
   (:use [circle.backend.build :only (build extend-group-with-revision)])
+  (:use [circle.backend.action.dns :only (update-record)])
   (:use [circle.backend.action.nodes :only (start-nodes stop-nodes)])
   (:use [circle.backend.action.vcs :only (checkout)])
   (:use [circle.backend.action.bash :only (bash)])
@@ -36,10 +37,11 @@
           :group circle/circle-group
           :actions [(start-nodes)
                     (checkout)
-                    (bash [(lein deps)
-                           (export "CIRCLE_ENV=production")
-                           (lein daemon start ":web")
-                           (sudo "/etc/init.d/nginx" :start)])
+                    (bash [(lein deps)])
+                    (bash [(export "CIRCLE_ENV=production")
+                           (export "SWANK=true")
+                           (lein daemon start ":web")])
+                    (bash [(sudo "/etc/init.d/nginx" :start)])
                     (tag-revision)
                     (lb/add-instances)
                     (lb/wait-for-healthy)


better expressions

better expressions


Confirmed: defbufferop not causing problems

--- src/clj/forma/hadoop/jobs/scatter.clj
+++ src/clj/forma/hadoop/jobs/scatter.clj
@@ -405,6 +405,12 @@
 ;; (local-beta-generator (forma-run-parameters "500-16"))
 ;; (use 'forma.hadoop.jobs.scatter)

+(defn my-info-mat
+  [feature-mat]
+  (let [fm (log/to-double-matrix feature-mat)
+        tp (.transpose fm)]
+    (vec (.toArray (.mmul tp fm)))))
+
 (defbufferop [eco-bufferop [r c m]]
   [tuples]
   (let [val-mat      (map second tuples)
@@ -412,14 +418,24 @@
         feature-mat  (map log/unpack-feature-vec val-mat neighbor-mat)]
     [[(first feature-mat)]]))

+(defbufferop [info-matrix-bufferop [r c m]]
+  [tuples]
+  (let [val-mat      (map second tuples)
+        neighbor-mat (map last tuples)
+        feature-mat  (map log/unpack-feature-vec val-mat neighbor-mat)]
+    [[(first (last (repeatedly 1 #(my-info-mat feature-mat))))]]))
+
 (defn buffer-generator
   "query to return the beta vector associated with an ecoregion"
   [{:keys [t-res est-start ridge-const convergence-thresh max-iterations]} src]
   (let [first-idx (date/datetime->period t-res est-start)]
     (<- [?beta]
         (src ?hansen ?val ?neighbor-val)
-        (eco-bufferop [ridge-const convergence-thresh max-iterations]
-                                ?hansen ?val ?neighbor-val :> ?beta)
+        ;;        (eco-bufferop [ridge-const convergence-thresh max-iterations]
+        ;;              ?hansen ?val ?neighbor-val :> ?beta)
+        (info-matrix-bufferop [ridge-const convergence-thresh max-iterations]
+                      ?hansen ?val ?neighbor-val :> ?beta)
+
         (:distinct false))))

 (defmain run-buffer-generator
@@ -430,4 +446,10 @@
               ([]
                  (?- (hfs-seqfile out-path :sinkmode :replace)
                      (buffer-generator est-map
-                                            (hfs-seqfile in-path)))))))+                                       (hfs-seqfile in-path)))))))
+
+(comment
+  (let [src (hfs-seqfile "s3n://formaresults/ecofeaturemat")]
+  (??<- [?count]
+        (src ?hansen ?val ?neighbor)
+        (c/count ?count))))


clean-up unused atom when source is drained

--- src/cljc/commos/delta/compscribe.cljc
+++ src/cljc/commos/delta/compscribe.cljc
@@ -378,6 +378,7 @@
           (if (nil? v)
             (do
               (run! close! @chs)
+              (reset! chs nil)
               (recur cache
                      false))
             (do (when-let [chs (seq @chs)]


small bug fixed by escaping quotes

small bug fixed by escaping quotes

--- src/cljs/cljspazzer/client/pages.cljs
+++ src/cljs/cljspazzer/client/pages.cljs
@@ -92,7 +92,7 @@
         album-count (count albums)
         active-album (:active-album data)
         artist-image (utils/format "/api/artists/%s/image?force-fetch=1" (utils/encode active-artist))
-        artist-image-url (utils/format "url('%s')" artist-image)]
+        artist-image-url (utils/format "url(\"%s\")" artist-image)]
     (html
      [:div.browse
       (nav-partial)


tweak duration format....b/c

tweak duration format....b/c

--- src/cljs/cljspazzer/client/pages.cljs
+++ src/cljs/cljspazzer/client/pages.cljs
@@ -49,7 +49,7 @@
         seconds (rem r 60)]
     (if (> hours 0)
     (utils/format "%i:%02i:%02i" hours minutes seconds)
-    (utils/format "%02i:%02i" minutes seconds))))
+    (utils/format "%i:%02i" minutes seconds))))

 (defn track-detail [track]
   (let [t (track "track")


fixed menu selected cursor

fixed menu selected cursor

--- src/cljs/swarmpit/component/menu.cljs
+++ src/cljs/swarmpit/component/menu.cljs
@@ -125,7 +125,7 @@
             (fn [menu-item]
               (let [icon (:icon menu-item)
                     name (:name menu-item)
-                    selected (= name domain)]
+                    selected (string/includes? domain name)]
                 (if (some? icon)
                   (drawer-item name icon opened selected)
                   (drawer-category name opened)))) menu))))))


Add dummy indented code

Add dummy indented code

--- src/day8/re_frame_10x/view/event.cljs
+++ src/day8/re_frame_10x/view/event.cljs
@@ -49,6 +49,48 @@

 (defn event-code []
   (let [code-traces      @(rf/subscribe [:code/current-code])
+        code-traces      (list
+                           {:title ":event/handler",
+                            :id    1,
+                            :code  [{:form         'dissoc
+                                     :result       dissoc
+                                     :indent-level 1}
+                                    {:form         'todos
+                                     :result       {3 {:id 3, :title "abc", :done false},
+                                                    4 {:id 4, :title "abc", :done true},
+                                                    5 {:id 5, :title "def", :done true},
+                                                    6 {:id 6, :title "abc", :done false},
+                                                    7 {:id 7, :title "add", :done false}}
+                                     :indent-level 1}
+                                    {:form         'todos
+                                     :result       {3 {:id 3, :title "abc", :done false},
+                                                    4 {:id 4, :title "abc", :done true},
+                                                    5 {:id 5, :title "def", :done true},
+                                                    6 {:id 6, :title "abc", :done false},
+                                                    7 {:id 7, :title "add", :done false}}
+                                     :indent-level 4}
+                                    {:form   '(vals todos)
+                                     :result '({:id 3, :title "abc", :done false},
+                                                {:id 4, :title "abc", :done true},
+                                                {:id 5, :title "def", :done true},
+                                                {:id 6, :title "abc", :done false},
+                                                {:id 7, :title "add", :done false})
+                                     :indent-level 3}
+                                    {:form '(filter :done)
+                                     :result '({:id 4 :title "abc" :done true}
+                                                {:id 5 :title "def" :done true})
+                                     :indent-level 2}
+                                    {:form '(map :id)
+                                     :result '(4 5)
+                                     :indent-level 1}
+                                    {:form '(reduce dissoc todos)
+                                     :result {3 {:id 3, :title "abc", :done false},
+                                              6 {:id 6, :title "abc", :done false},
+                                              7 {:id 7, :title "add", :done false}}}]
+                            :form  '(->> (vals todos)
+                                         (filter :done)
+                                         (map :id)
+                                         (reduce dissoc todos))})
         highlighted-form @(rf/subscribe [:code/highlighted-form])
         debug?           @(rf/subscribe [:settings/debug?])]
     [rc/v-box
@@ -94,7 +136,7 @@
                             ^{:key (random-uuid)}
                             [rc/v-box
                              :class "code-fragment"
-                             :style {:margin-left (str (* 9 (dec (:indent-level line))) "px")}
+                             :style {:margin-left (str (* 9 (:indent-level line)) "px")}
                              :attr {:on-mouse-enter #(do (rf/dispatch [:code/hover-form (:form line)])
                                                          true)
                                     :on-mouse-leave #(do (rf/dispatch [:code/exit-hover-form (:form line)])


more defrecord benchmarks

more defrecord benchmarks

--- benchmark/cljs/benchmark_runner.cljs
+++ benchmark/cljs/benchmark_runner.cljs
@@ -164,22 +164,22 @@
       sym 'foo]
   (simple-benchmark [coll {:foo 1 :bar 2}] (kw coll) 1000000)
   (simple-benchmark [coll {'foo 1 'bar 2}] (sym coll) 1000000))
-(defrecord Foo [bar baz])
-(simple-benchmark [coll (Foo. 1 2)] (:bar coll) 1000000)
-(simple-benchmark [coll {:foo 1 :bar 2}] (assoc coll :baz 3) 100000)
-(simple-benchmark [coll {'foo 1 'bar 2}] (assoc coll 'baz 3) 100000)
-(simple-benchmark [coll {:foo 1 :bar 2}] (assoc coll :foo 2) 100000)
-(simple-benchmark [coll {'foo 1 'bar 2}] (assoc coll 'foo 2) 100000)
 (simple-benchmark [coll {:foo 1 :bar 2}]
                   (loop [i 0 m coll]
                     (if (< i 100000)
                       (recur (inc i) (assoc m :foo 2))
                       m))
                   1)
-(simple-benchmark [coll {'foo 1 'bar 2}]
+
+(defrecord Foo [bar baz])
+(simple-benchmark [coll (Foo. 1 2)] (:bar coll) 1000000)
+(simple-benchmark [coll (Foo. 1 2)] (-lookup coll :bar) 1000000)
+(simple-benchmark [coll (Foo. 1 2)] (assoc coll :bar 2) 1000000)
+(simple-benchmark [coll (Foo. 1 2)] (assoc coll :baz 3) 1000000)
+(simple-benchmark [coll (Foo. 1 2)]
                   (loop [i 0 m coll]
-                    (if (< i 100000)
-                      (recur (inc i) (assoc m 'foo 2))
+                    (if (< i 1000000)
+                      (recur (inc i) (assoc m :bar 2))
                       m))
                   1)
 (println)


throw exception if translation fails

throw exception if translation fails

--- src/babel/english/writer.clj
+++ src/babel/english/writer.clj
@@ -77,8 +77,7 @@
                                          ;; of what the (process) command did.
                                          (log/debug (str "process result:" result)))
                                        (catch Exception e
-                                         (cond
-                                           true
+                                         (let [catch-and-log-error false]
                                            (log/error (str "Could not translate source expression: "
                                                            "'" (get source-expression :surface) "'"
                                                            " from language: '" source-language-short-name
@@ -89,8 +88,11 @@
                                                            "'; source semantics:'"
                                                            (strip-refs (get-in source-expression [:structure :synsem :sem]))
                                                            "'" " ; exception: " e))
-                                           false
-                                           (throw e))))))))))
+                                           (cond
+                                             catch-and-log-error
+                                             (log/info (str "ignoring above error and continuing."))
+                                             true
+                                             (throw e)))))))))))
                        source-expressions))))

 (defn all [ & [count]]


Fixed attempt to send a blank xboxapi-key. But the SSL still doesn't work. :(

--- src/bltool/data/xboxlive.clj
+++ src/bltool/data/xboxlive.clj
@@ -9,7 +9,7 @@
 (register-flags ["--xbox-name" "Xbox Live GamerTag"]
   ["--xbox-360-platform" "Platform string to use for Xbox 360 games (recommended: 360, Xbox, XBLA, XNA, XbxGoD)" :default "360"]
   ["--xbox-one-platform" "Platform string to use for Xbox One games (recommended: XBO, Xbox, XbxGoD)" :default "XBO"]
-  ["--xboxapi-key" "Alternative API key to use for xboxapi.com web service" :default ""])
+  ["--xboxapi-key" "Alternative API key to use for xboxapi.com web service"])

 (def default-xboxapi-key "0c713775210b93e6beafd29d1c9b627c0e75f531")

@@ -36,7 +36,7 @@
 (defn- xboxapi-request
   [url]
   (let [keytouse
-    (if (:xboxapi-key *opts*) (:xboxapi-key *opts*) (default-xboxapi-key))
+    (if (:xboxapi-key *opts*) (:xboxapi-key *opts*) default-xboxapi-key)
   reply (http/get url { :headers {"X-AUTH" keytouse} :throw-exceptions false :accept :json })]
     (if (= (get (reply :headers) "x-ratelimit-remaining") 0) (throw+ "Xboxapi.com free access overloaded, try again in an hour or so.")
        reply)))


Added code to create dependencies for embedded objects.

--- src/blutwurst/jsonschema.clj
+++ src/blutwurst/jsonschema.clj
@@ -35,8 +35,16 @@
 (defn- determine-nullabilty [schema res]
  (assoc res :columns (mapv (partial determine-nullability-for-column schema) (:columns res))))

+(defn- create-dependency-for-aggregate-property [prop]
+ {:target-schema nil :target-name (if (nil? (get (second prop) "title")) (first prop) (get (second prop) "title"))
+     :dependency-name nil :links {(first prop) :embedded}}
+)
+
 (defn- extract-dependencies [schema res]
- res)
+ (let [aggregate-properties (filter #(= "object" (get (second %) "type")) (get schema "properties"))
+       aggregate-dependencies (mapv create-dependency-for-aggregate-property aggregate-properties)]
+   (assoc res :dependencies aggregate-dependencies)
+ ))

 (defn- find-child-schemas [schema]
  (let [aggregate-properties (filter #(= "object" (get (second %) "type")) (get schema "properties"))]


docstring: accessor not only retrieves but can preprocess

--- src/blx/sortable/matcher.clj
+++ src/blx/sortable/matcher.clj
@@ -8,8 +8,8 @@
   as a vector of match-steps that produce and refine the match. A step is a map
   with the following keys:

-    - `:accessor` is a function `item -> Maybe d` that is called to retrieve from
-      the item whatever data is used by the matching step.
+    - `:accessor` is a function `item -> Maybe d` that is called on the item to
+      retrieve and preprocess whatever data is used by the matcher.
     - `:matcher-maker` is a function `[source-item] -> (r, d -> Maybe r)` that,
       when called with the collection of source items to be matched against,
       returns a matcher function that, given the result of the previous matcher


calling handler in event -> :dispatch effect

--- src/braid/client/events.cljs
+++ src/braid/client/events.cljs
@@ -9,9 +9,6 @@
             [braid.client.xhr :refer [edn-xhr]]
             [braid.client.state.helpers :as helpers]
             [braid.client.dispatcher :refer [dispatch!]]))
-; XXX
-(defn handler [& args]
-  (ex-info "Turn this into a fx with :dispatch" {:args args}))

 (defn name->open-tag-id
   "Lookup tag by name in the open group"
@@ -169,13 +166,12 @@
     (sync/chsk-send! [:braid.server/show-thread thread-id])
     (helpers/show-thread state thread-id)))

-(reg-event-db
+(reg-event-fx
   :unsub-thread
-  (fn [state [_ data]]
+  (fn [cofx [_ data]]
     ; TODO
     (sync/chsk-send! [:braid.server/unsub-thread (data :thread-id)])
-    ; TODO
-    (handler state [:hide-thread {:thread-id (data :thread-id) :local-only? true}])))
+    {:dispatch [:hide-thread {:thread-id (data :thread-id) :local-only? true}]}))

 (reg-event-db
   :create-tag
@@ -296,20 +292,18 @@
           true (on-success))))
     state))

-(reg-event-db
+(reg-event-fx
   :add-notification-rule
-  (fn [state [_ rule]]
+  (fn [{state :db :as cofx} [_ rule]]
     (let [current-rules (get (helpers/get-user-preferences state) :notification-rules [])]
-      ; TODO
-      (handler state [:set-preference [:notification-rules (conj current-rules rule)]]))))
+      {:dispatch [:set-preference [:notification-rules (conj current-rules rule)]]})))

 (reg-event-db
   :remove-notification-rule
-  (fn [state [_ rule]]
+  (fn [{state :db :as cofx} [_ rule]]
     (let [new-rules (->> (get (helpers/get-user-preferences state) :notification-rules [])
                          (into [] (remove (partial = rule))))]
-      ; TODO
-      (handler state [:set-preference [:notification-rules new-rules]]))))
+      {:dispatch [:set-preference [:notification-rules new-rules]]})))

 (reg-event-db
   :set-search-results
@@ -419,15 +413,14 @@
   (fn [state [_ thread-id]]
     (helpers/focus-thread state thread-id)))

-(reg-event-db
+(reg-event-fx
   :clear-inbox
-  (fn [state [_ _]]
-    (->> (helpers/get-open-threads state)
-         (map :id)
-         (reduce (fn [state id]
-                   ; TODO
-                   (handler state [:hide-thread {:thread-id id :local-only? false}]))
-                 state))))
+  (fn [{state :db :as cofx} [_ _]]
+    {:dispatch-n
+     (into ()
+           (comp (map :id)
+                 (map (fn [id] [:hide-thread {:thread-id id :local-only? false}])))
+           (helpers/get-open-threads state))}))

 (reg-event-db
   :invite
@@ -537,14 +530,13 @@
           (on-complete bot))))
     state))

-(reg-event-db
+(reg-event-fx
   :create-upload
-  (fn [state [_ {:keys [url thread-id group-id]}]]
+  (fn [{state :db :as cofx} [_ {:keys [url thread-id group-id]}]]
     ; TODO
     (sync/chsk-send! [:braid.server/create-upload
                       (schema/make-upload {:url url :thread-id thread-id})])
-    ; TODO
-    (handler state [:new-message {:content url :thread-id thread-id :group-id group-id}])))
+    {:dispatch [:new-message {:content url :thread-id thread-id :group-id group-id}]}))

 (reg-event-db
   :get-group-uploads
@@ -670,9 +662,9 @@
   :notify-if-client-out-of-date
   (fn [state [_ server-checksum]]
     (if (not= (aget js/window "checksum") server-checksum)
-      ; TODO
-      (handler state [:display-error [:client-out-of-date "Client out of date - please refresh" :info]])
-      state)))
+      {:dispatch [:display-error
+                  [:client-out-of-date "Client out of date - please refresh" :info]]}
+      {})))

 (reg-event-db
   :set-init-data


add `shouldComponentUpdate` to protocols

--- src/cellophane/protocols.clj
+++ src/cellophane/protocols.clj
@@ -11,6 +11,7 @@
   (-render [this] "must return a valid ReactDOMElement."))

 (defprotocol IReactLifecycle
+  (shouldComponentUpdate [this next-props next-state])
   (initLocalState [this])
   (componentWillReceiveProps [this next-props])
   (componentWillUpdate [this next-props next-state])


Force chunk values to be a vector.

Force chunk values to be a vector.

--- src/clj/forma/source/hdf.clj
+++ src/clj/forma/source/hdf.clj
@@ -184,7 +184,7 @@
         ret (int-array (* width height))]
     (.ReadRaster band 0 0 width height ret)
     (map-indexed (fn [idx xs]
-                   [idx xs])
+                   [idx (vec xs)])
                  (partition chunk-size ret))))

 ;; ### Metadata Parsing


Add default exception handler.

Add default exception handler.

--- src/clj/kixi/hecuba/main.clj
+++ src/clj/kixi/hecuba/main.clj
@@ -44,4 +44,7 @@
     (when (:help opts)
       (println banner)
       (System/exit 0))
+
+    (kixi/install-default-exception-handler)
+
     (alter-var-root #'kixi/system (fn [_] (component/start (build-application opts))))))


create dev page template

create dev page template

--- src/clj/lesezeichen/core.clj
+++ src/clj/lesezeichen/core.clj
@@ -23,7 +23,7 @@

 (deftemplate auth-success-page
   (io/resource "public/index.html")
-  [email token]
+  [email]
   [:#center-container] (content (auth-jumbo email))
   [:#js-files] (substitute (html [:script {:src "js/auth.js" :type "text/javascript"}])))

@@ -41,10 +41,10 @@
 (deftemplate dev-page
   (io/resource "public/index.html")
   [build]
-  [:#goog-base-js] (set-attr :id (str "js/compiled/" (-> build symbol str) "/out/base.js"))
-  [:#main-js] (set-attr :id (str "js/compiled/" (-> build symbol str) "/main.js"))
-  [:#js-require] (substitute [:script {:type "text/javascript"}
-                              (str "goog.require(' lesezeichen." (-> build symbol str) ".core');")]))
+  [:#goog-base-js] (set-attr :src (str "js/compiled/" (name build) "/out/goog/base.js"))
+  [:#main-js] (set-attr :src (str "js/compiled/" (name build) "/main.js"))
+  [:#js-require] (substitute (html [:script {:type "text/javascript"}
+                                 (str "goog.require('lesezeichen." (name build) ".core');")])))

 (defn fetch-url [url]
@@ -103,10 +103,10 @@
   (GET "/bookmark/ws" [] bookmark-handler)
   (GET "/*" {{token :auth email :email} :params}
        (if (or token email)
-         (auth-success-page email)
+         (dev-page :auth)
          (if (= (:build @server-state) :prod)
            (static-page)
-           (io/resource "public/index.html")))))
+           (dev-page :client)))))

 (defn read-config [state path]
@@ -151,4 +151,5 @@

   (get-all-users (:conn @server-state))

+
 )


Modified doctype removal regex to allow the use of single quotes.

--- src/clj/salava/badge/svg.clj
+++ src/clj/salava/badge/svg.clj
@@ -12,7 +12,7 @@
     :else (get-in assertion [:verify :url])))

 (defn remove-doctype [xml]
-  (string/replace xml #"<!DOCTYPE((.|\n|\r)*?)\">" ""))
+  (string/replace xml #"<!DOCTYPE((.|\n|\r)*?)(\"|')>" ""))

 (defn get-assertion-from-svg [svg-file]
   (try+


Several isa? calls had wrong arg order.

Several isa? calls had wrong arg order.

--- src/clj_ns_browser/utils.clj
+++ src/clj_ns_browser/utils.clj
@@ -190,7 +190,7 @@
   Note that input is a var - if you want to input a name-string or -symbol, use:
   (atom? (resolve-fqname n))"
   [v]
-  (isa? clojure.lang.Atom (type v)))
+  (isa? (type v) clojure.lang.Atom))

 (defn multimethod?
@@ -198,7 +198,7 @@
   Note that input is a var - if you want to input a name-string or -symbol, use:
   (multimethod? (resolve-fqname n))"
   [o]
-  (isa? clojure.lang.MultiFn (type o)))
+  (isa? (type o) clojure.lang.MultiFn))

 (defn var-multimethod?
@@ -214,7 +214,7 @@
   Note that input is a var - if you want to input a name-string or -symbol, use:
   (protocol? (resolve-fqname n))"
   [v]
-  (and (var? v) (isa? clojure.lang.PersistentArrayMap (type @v)) (:on-interface @v) true))
+  (and (var? v) (isa? (type @v) clojure.lang.PersistentArrayMap) (:on-interface @v) true))

 (defn deftype?
@@ -254,7 +254,7 @@
   Note that input is a name referring to a namespace - if you want to input a name-string or -symbol, use:
   (namespace? (resolve-fqname n))"
   [maybe-ns]
-  (isa? clojure.lang.Namespace (type maybe-ns)))
+  (isa? (type maybe-ns) clojure.lang.Namespace))

 ;; Two convenience function for clojure.tools.trace


Tweak jfx

Tweak jfx

--- src/clj_simple_chart/jfx.clj
+++ src/clj_simple_chart/jfx.clj
@@ -53,6 +53,14 @@
         (update-zoom-and-resize! 1.0)

         (and (.isControlDown v)
+             (= (.getText v) "2"))
+        (update-zoom-and-resize! 0.5)
+
+        (and (.isControlDown v)
+             (= (.getText v) "5"))
+        (update-zoom-and-resize! 0.6)
+
+        (and (.isControlDown v)
              (= (.getCode v) KeyCode/W))
         (update-zoom-and-resize! (/ @window-width @input-width))

@@ -78,18 +86,6 @@
   (cond (and (.isControlDown v)
              (= (.getText v) "0"))
         (update-zoom-and-resize! 1.0)
-
-        (and (.isControlDown v)
-             (= (.getCode v) KeyCode/W))
-        (update-zoom-and-resize! (/ @window-width @input-width))
-
-        (and (.isControlDown v)
-             (= (.getCode v) KeyCode/MINUS))
-        (update-zoom-and-resize! (- @zoom zoom-delta))
-
-        (and (.isControlDown v)
-             (= (.getCode v) KeyCode/EQUALS))
-        (update-zoom-and-resize! (+ @zoom zoom-delta))

         :else (do #_(println "unhandled" v))))


Fix function name on core.

Fix function name on core.

--- src/cljs/openslack/core.cljs
+++ src/cljs/openslack/core.cljs
@@ -27,7 +27,7 @@
 ;;   :load-warninged-code false
 ;; })

-(defn- start-roster-watcher
+(defn- initialize-roster
   [client]
   (go-loop []
     (let [mroster (<! (xmpp/get-roster client))]


introduce strategies for ai - possibility to have a cheating ai

--- src/cljs/triboard/ai/ai.cljs
+++ src/cljs/triboard/ai/ai.cljs
@@ -11,23 +11,23 @@
 ;; Private
 ;; -----------------------------------------

-;; TODO - Blue score + min-max modification for AI Aliance
+(defprotocol AIStrategy
+  (summarize-score [this scores] "Extract data from the score to compare")
+  (maximizing-turn? [this turn] "Indicates whether we are in min or max"))

 (defn- make-ai
-  [board player]
-  {:player player})
+  [player]
+  (reify AIStrategy
+    (summarize-score [_ scores] (get scores player))
+    (maximizing-turn? [_ turn] (= (:player turn) player))
+    ))

-(defn- summarize-score
-  [ai scores]
-  (get scores (:player ai))
-  ;; (+ (:red scores) (:green scores)) ;; Aligned against player
-  )
-
-(defn- maximizing-turn?
-  [ai turn]
-  (= (:player ai) (:player turn))
-  ;; (not= :blue (:player turn)) ;; Aligned against player
-  )
+(defn- make-cheating-ai
+  [player]
+  (reify AIStrategy
+    (summarize-score [_ scores] (+ (:red scores) (:green scores)))
+    (maximizing-turn? [_ turn] (not= (:player turn) :blue))
+    ))

 ;; -----------------------------------------

@@ -75,7 +75,7 @@
 (defn- play-best-move
   [game]
   (let [turn (game/current-turn game)
-        ai (make-ai (:board turn) (:player turn))]
+        ai (make-ai (:player turn))]
     (:game
       (min-max-step-by
         :score ai turn


Protect checker-makers from folded-prerequisites

--- src/midje/midje_forms/recognizing.clj
+++ src/midje/midje_forms/recognizing.clj
@@ -1,7 +1,8 @@
 ;; -*- indent-tabs-mode: nil -*-

 (ns midje.midje-forms.recognizing
-  (:use midje.util.form-utils)
+  (:use midje.util.form-utils
+        [midje.checkers.defining :only [checker? checker-makers]])
   (:require [midje.util.wrapping :as wrapping])
   (:require [midje.util.unify :as unify])
   (:require [clojure.zip :as zip]))
@@ -80,11 +81,13 @@
 ;; Note that folded prerequisites are in semi-sweet-style. (That is, they can only
 ;; be recognized after sweet style has been converted to semi-sweet.)

+(def special-forms '[quote fn let])

 (defn- mockable-function-symbol? [loc]
   (let [symbol (zip/node loc)]
-    (not (or (= 'quote symbol)
-             (:midje/checker (meta (resolve symbol)))))))
+    (not (or (some #{symbol} special-forms)
+             (some #{symbol} checker-makers)
+             (checker? (resolve symbol))))))

 (defn looks-like-a-function-call? [loc first-symbol-validity-test]
   (when-let [tree (and loc (zip/node loc))]


CMR-5848 Move test to more appropriate namespace.

--- system-int-test/test/cmr/system_int_test/ingest/provider_cmr_only_client_id_test.clj
+++ system-int-test/test/cmr/system_int_test/ingest/provider_cmr_only_client_id_test.clj
@@ -123,30 +123,4 @@
       (assert-ingest-success #'ingest/delete-concept concept "Virtual-Product-Service")
       (index/wait-until-indexed)
       (is (= 0 (:hits (search/find-refs :granule {:granule-ur (:granule-ur granule)
-                                                  :page-size 50}))))))
-  (testing "ingest with Virtual-Product-Service with a umm-json granule"
-    (let [psa1 (data-umm-cmn/additional-attribute {:Name "source_granule_ur" :DataType "STRING" :Description "Test"})
-          collection (d/ingest-umm-spec-collection "GES_DISC" (data-umm-c/collection
-                                                                {:EntryTitle "OMI/Aura Surface UVB Irradiance and Erythemal Dose Daily L3 Global 1.0x1.0 deg Grid V003 (OMUVBd) at GES DISC"
-                                                                 :ShortName "OMUVBd_ErythemalUV"
-                                                                 :AdditionalAttributes [psa1]
-                                                                 :Version "003"}))
-          concept (-> (dg/granule-with-umm-spec-collection
-                       collection
-                       (:concept-id collection)
-                       {:granule-ur "Gran1"
-                        :provider-id "GES_DISC"
-                        :collection-ref (umm-g/map->CollectionRef {:entry-title "OMI/Aura Surface UVB Irradiance and Erythemal Dose Daily L3 Global 1.0x1.0 deg Grid V003 (OMUVBd) at GES DISC"})})
-                      (d/item->concept {:format :umm-json
-                                        :version "1.4"}))]
-      (ingest/clear-caches)
-      (assert-ingest-success #'ingest/validate-concept concept "Virtual-Product-Service")
-      (assert-ingest-success #'ingest/ingest-concept concept "Virtual-Product-Service")
-      (index/wait-until-indexed)
-      (is (= 1 (:hits (search/find-refs :granule {:granule-ur (:granule-ur "Gran1")
                                                   :page-size 50})))))))
-
-      ; (assert-ingest-success #'ingest/delete-concept concept "Virtual-Product-Service")
-      ; (index/wait-until-indexed)
-      ; (is (= 0 (:hits (search/find-refs :granule {:granule-ur (:granule-ur "Gran1")
-      ;                                             :page-size 50})))))))


a working figwheel main

a working figwheel main

--- figwheel-main/src/figwheel/main.clj
+++ figwheel-main/src/figwheel/main.clj
@@ -8,8 +8,13 @@
    [cljs.cli :as cli]
    [cljs.repl]
    [cljs.env]
+   [cljs.analyzer :as ana]
+   [cljs.analyzer.api :as ana-api]
    [cljs.build.api :as bapi]
-   [hawk.core :as hawk]))
+   [hawk.core :as hawk])
+  (:import
+   [java.io StringReader]))
+

 ;; TODO
 ;; builds
@@ -72,7 +77,29 @@
                     (f (cons e @events))))))
       (assoc ctx :collector collector))))

-#_ (reset-watch!)
+(defn file-suffix [file]
+  (last (string/split (.getName (io/file file)) #"\.")))
+
+(defn suffix-filter [suffixes]
+  (fn [_ {:keys [file]}]
+    (and file
+         (.isFile file)
+         (not (.isHidden file))
+         (suffixes (file-suffix file))
+         (not (#{\. \#} (first (.getName file)))))))
+
+#_((suffix-filter #{"clj"}) nil {:file (io/file "project.clj")})
+
+(defn watch [inputs opts cenv]
+  (prn "Called Watch!!!")
+  (add-watch! (-> opts meta :build-id (or :dev))
+              {:paths (if (coll? inputs) inputs [inputs])
+               :filter (suffix-filter #{"cljs" "clj" "cljc"})
+               :handler (throttle
+                         50
+                         (fn [evts]
+                           (let [inputs (if (coll? inputs) (apply bapi/inputs inputs) inputs)]
+                             (figwheel.core/build inputs opts cenv))))}))

 (defn- watch-opt
   [cfg path]
@@ -93,9 +120,7 @@
   (assoc-in cfg [::options-meta :figwheel] (not= bl "false")))

 (defn build-opt [cfg bn]
-  (assoc-in cfg [::options-meta :build-name] )
-
-  )
+  (assoc-in cfg [::options-meta :build-name] bn))

 (def figwheel-commands
   {:init {["-w" "--watch"]
@@ -113,236 +138,24 @@
 (alter-var-root #'cli/default-commands cli/add-commands
                 figwheel-commands)

-;; ------------------------------------------------------------
-;; CLJS Main Argument manipulation
-;; ------------------------------------------------------------
-
-;; let's just insert a processing step at the end of inits only
-
-(defn main-arg? [[arg val]]
-  (cli/dispatch? cli/default-commands :main arg))
-
-;; TODO test this thoroughly
-
-(defn split-main-cli [args]
-  (if-let [args
-           (re-matches
-            #"(?i)(-c|--compile)\s(\S+)\s(?:(-r|--repl)|(-s|--serve)\s(\S+))\s(.*)"
-            (string/join " " (flatten args)))]
-    [(partition-all 2 (filter some? (take 5 (rest args))))
-     (string/split (last args) #"\s")]
-    (if (#{"-r" "--repl" "-h" "--help" "-?"} (ffirst args)) ;; no arg main flag
-      [[[(ffirst args)]]
-       (rest (flatten args))]
-      (let [[main-arg r] (split-with main-arg? args)]
-        [main-arg (flatten r)]))))
-
-#_(split-main-cli (partition-all 2 (string/split "-m a b c"  #"\s")))
-
-#_(cljs.main/-main)
-;; TODO need to allow for things that take no args instead of partition 2
-(defn split-args [normalized]
-  (let [main-arg? #(cli/dispatch? cli/default-commands :main (first %))
-        [init-args args] (split-with (complement main-arg?) (partition-all 2 normalized))
-        [main-args cli-args] (split-main-cli args)]
-    {:init (vec init-args)
-     :main (vec main-args)
-     :app-main-cli  cli-args}))
-
-(defn assemble-args [{:keys [init main app-main-cli]}]
-  (concat (flatten init) (flatten main) app-main-cli))
-
-(defn default-repl-env [{:keys [init] :as args}]
-  (if-let [[f v] (first (filter #(#{"-re" "--repl-env"} (first %))
-                                init))]
-    (cond-> args
-      (= v "figwheel")
-      (assoc ::figwheel-repl true))
-    (-> args
-        (update :init #(cons ["-re" "figwheel"] %))
-        (assoc ::figwheel-repl true))))
-
-(defn index-of-compiler-options [{:keys [init]}]
-  (let [[pre post] (split-with (complement #(#{"-co" "--compile"} (first %)))
-                               init)]
-    (if (empty? post) nil (count pre))))
-
-#_(index-of-compiler-option (split-args test-args))
-
-(defn get-options [sargs]
-  (when-let [idx (index-of-compiler-options sargs)]
-    (read-string (second ((vec (:init sargs)) idx)))))
-
-(defn update-options [sargs f]
-  (update sargs :init
-          (fn [inits]
-            (if-let [idx (index-of-compiler-options sargs)]
-              (update (vec inits)
-                      idx (fn [[flag options]]
-                            [flag (pr-str (f (read-string options)))]))
-              (vec (cons ["-co" (pr-str (f {}))]
-                         inits))))))
-
-#_(update-options (split-args test-args) (fn [options]
-                                         (assoc options :hi 1)))
-
-#_(get-options (split-args test-args))
-
-(defn has-arg? [init-or-main-arg-list flag]
-  (->> init-or-main-arg-list
-       reverse
-       (filter #(flag (first %)))
-       first))
-
-(defn get-arg [init-or-main-arg-list flag]
-  (second (has-arg? init-or-main-arg-list flag)))
-
-(defn figwheel-adjust-options [sargs]
-  (update-options
-   sargs
-   #(update % :preloads
-            (fn [p]
-              (vec (distinct (concat p '[figwheel.repl.preload figwheel.core])))))))
-
-(defn opt-none? [{:keys [init] :as sargs}]
-  (let [opt (first (filter some? [(get-arg init #{"-O" "--optimizations"})
-                                 (:optimizations (get-options sargs))]))]
-    (or (nil? opt) (#{"none" :none} opt))))
-
-(defn output-to [{:keys [init] :as sargs}]
-  (first (filter some? [(get-arg init #{"-o" "--output-to"})
-                        (:output-to (get-options sargs))])))
-
-(defn target [{:keys [init] :as sargs}]
-  (first (filter some? [(get-arg init #{"-t" "--target"})
-                        (:target (get-options sargs))])))
-
-(defn figwheel-mode? [sargs]
-  (boolean
-   (and (not= "false" (get-arg (:init sargs) #{"-fw" "--figwheel"}))
-       (opt-none? sargs)
-       (get-arg (:init sargs) #{"-w" "--watch"})
-       (get-arg (:main sargs) #{"-c" "--compile"}))))
-
-
-
-
-;; -b build
-;; defaults to watch and compile with repl
-;; output-to
-
-
-#_(assemble-args (process-args test-args))
-
-#_(opt-none? (split-args test-args))
-#_(figwheel-mode? (split-args test-args))
-
-#_(has-arg? (:init (split-args test-args))
-            #{"-re" "--repl-env"})
-;; TODO --figwheel true
-
-;; figwheel mode
-;; :and
-;; - not --figwheel false
-;; - build opt is nil or :none
-;; - watching is enabled
-
-;; adjustments for figwheel mode
-
-
-
-;; figwheel server is started
-;; :or
-;; - in figwheel-mode
-;; - -r and figwheel repl env
-;; - -serve
-
-;; when server is started always remove serve
-
-;; where to call figwheel.core/start
-;; when figwheel-mode call start with seperate repl-env
-
-(defn start-server? [sargs]
-  (or (figwheel-mode? sargs)
-      (get-arg (:init sargs) #{"-r" "--repl"})
-      (get-arg (:init sargs) #{"-s" "--serve"})))
-
-;; figwheel server gets its port from repl config or serve config, or default
-;; if -r arg repl config if --serve arg server config, or default
-(defn server-host-port [sargs]
-  (let [{:keys [host port] :as res}
-        (if-let [host-port (get-arg (:main sargs) #{"-s" "--serve"})]
-          (let [[host port] (string/split host-port #":")
-                host (if (string/blank? host) nil host)
-                port (Integer/parseInt port)]
-            {:host host :port port})
-          (if (and (has-arg? (:main sargs) #{"-r" "--repl"})
-                   (::figwheel-repl sargs))
-            (let [host (get-arg (:init sargs) #{"-H" "--host"})
-                  port (get-arg (:init sargs) #{"-p" "--port"})]
-              (cond-> {}
-                host (assoc :host host)
-                port (assoc :port (Integer/parseInt port))))))]
-    (cond-> {:port figwheel.repl/default-port}
-      host (assoc :host host)
-      port (assoc :port port))))
-
-(defn- norm [args] (cljs.main/normalize (cli/normalize cli/default-commands args)))
-
-(defn process-args [args]
-  (-> args
-      norm
-      split-args
-      default-repl-env
-      (#(if (figwheel-mode? %) (assoc % ::figwheel-mode? true) %))
-      (#(if (opt-none? %) (assoc % ::opt-none? true) %))
-      (#(if (start-server? %) (assoc % ::start-server? true) %))
-      (#(if (::figwheel-mode? %) (figwheel-adjust-options %) %))
-      (#(if (and (::figwheel-mode? %)
-                 (has-arg? (:main %) #{"-r" "--repl"}))
-          (update % :init (fn [init] (conj (vec init) ["-e" "(figwheel.core/start-from-repl)"])))
-          %))
-      (#(if (::start-server? %) (assoc % ::host-port (server-host-port %)) %))
-      ))
-
-#_(process-args test-args)
-
 ;; TODO
 ;; -b build flag
 ;; -bb background-build flag

 ;; TODO dev only
-(def test-args [#_"--wow" #_"1" "-co" "{:aot-cache false :asset-path \"out\" :preloads [figwheel.repl.preload figwheel.core] :closure-defines {figwheel.repl/connect-url \"ws://localhost:[[client-port]]/figwheel-connect\"}}" #_"-re" #_"figwheel" "--port" "9501" "--watch" "src" "--watch" "wow" "-d" "target/public/out" "-o" "target/public/out/mainer.js"  "-e" "(figwheel.core/start-from-repl)" "-c" "exproj.core" "-r" "-s"  "a" "b" "c" "d"])
-
-
-#_(figwheel-mode? (split-args test-args))
-
-(defn file-suffix [file]
-  (last (string/split (.getName (io/file file)) #"\.")))
-
-(defn suffix-filter [suffixes]
-  (fn [_ {:keys [file]}]
-    (and file
-         (.isFile file)
-         (not (.isHidden file))
-         (suffixes (file-suffix file))
-         (not (#{\. \#} (first (.getName file)))))))
-
-#_((suffix-filter #{"clj"}) nil {:file (io/file "project.clj")})
-
-(defn watch [inputs opts cenv]
-  (prn "Called Watch!!!")
-  (add-watch! (-> opts meta :build-id (or :dev))
-              {:paths (if (coll? inputs) inputs [inputs])
-               :filter (suffix-filter #{"cljs" "clj" "cljc"})
-               :handler (throttle
-                         50
-                         (fn [evts]
-                           (let [inputs (if (coll? inputs) (apply bapi/inputs inputs) inputs)]
-                             (figwheel.core/build inputs opts cenv))))}))
-
-(def default-output-dir (.getPath (io/file "target" "public" "out")))
-(def default-output-to  (.getPath (io/file "target" "public" "out" "main.js")))
+
+(def default-output-dir (.getPath (io/file "target" "public" "cljs-out")))
+(def default-output-to  (.getPath (io/file "target" "public" "cljs-out" "main.js")))
+
+(defn figure-default-asset-path [repl-options options]
+  (let [{:keys [output-dir]} options
+        stack-options (:ring-stack-options repl-options)]
+    ;; if you have configured your static resources you are on your own
+    (when (and
+           (not (:asset-path options))
+           (not (contains? stack-options :static)))
+      (last (string/split (or output-dir default-output-dir)
+                          #"[\/\\]public[\/\\]")))))

 (defn default-compile
   [repl-env {:keys [ns args options ::options-meta] :as cfg}]
@@ -356,8 +169,13 @@
                    (symbol ns)
                    (:main options))
         figwheel-mode? (and (:figwheel options-meta true)
-                            (:watch opts)
-                            (= :none (:optimizations opts :none)))
+                            (:watch options)
+                            (= :none (:optimizations options :none)))
+        _ (prn :figwheel-mode figwheel-mode?)
+        cfg      (if figwheel-mode?
+                   (#'cljs.cli/eval-opt cfg "(figwheel.core/start-from-repl)")
+                   cfg)
+
         opts     (as->
                    (merge
                      #_(select-keys env-opts
@@ -368,8 +186,8 @@
                    (cond-> opts
                      (not (:output-to opts))
                      (assoc :output-to default-output-to)
-                     (= :advanced (:optimizations opts))
-                     (dissoc :browser-repl)
+                     (and (not (:asset-path opts)) (figure-default-asset-path env-opts opts))
+                     (assoc :asset-path (figure-default-asset-path env-opts opts))
                      (not (:output-dir opts))
                      (assoc :output-dir default-output-dir)
                      figwheel-mode?
@@ -377,17 +195,18 @@
                              (fn [p]
                                (vec (distinct
                                      (concat p '[figwheel.repl.preload figwheel.core])))))
-                     #_(not (contains? opts :aot-cache))
-                     #_(assoc :aot-cache true)))
-        convey   (into [:output-dir] cljs.repl/known-repl-opts)
+                     (not (contains? opts :aot-cache))
+                     (assoc :aot-cache false)))
+        convey   (into [:output-dir :output-to] cljs.repl/known-repl-opts)
         cfg      (update cfg :options merge (select-keys opts convey))
         cfg      (update cfg :options dissoc :watch)
+
         source   (when (and (= :none (:optimizations opts :none)) main-ns)
                    (:uri (bapi/ns->location main-ns)))
         cenv     (cljs.env/default-compiler-env)]
+
     (cljs.env/with-compiler-env cenv
-      [opts options-meta]
-      #_(if-let [path (:watch opts)]
+      (if-let [path (:watch opts)]
         (do
           (bapi/build (if (coll? path)
                         (apply bapi/inputs path)
@@ -398,34 +217,44 @@
                  (dissoc opts :watch)
                  cenv))
         (bapi/build source opts cenv))
-      #_(when repl?
+      (when repl?
         (#'cli/repl-opt repl-env args cfg))
-      #_(when serve?
-        (#'cli/serve-opt repl-env args cfg)))))
-
-#_(merge (select-keys repl-env [:port
-                                :host
-                                :output-to
-                                :ring-handler
-                                :ring-server
-                                :ring-server-options
-                                :ring-stack
-                                :ring-stack-options])
-         (select-keys opts [:target
-                            :output-to]))
+      (when (or serve? figwheel-mode?)
+        ;; what to do when the repl isn't a figwheel repl here?
+        ;; in the case where it isn't the repl we will need to start the server
+        ;; directly, so perhaps start the server directly regardless
+
+        ;; use repl to start server and setup environment for figwheel to operate in
+        (let [re-opts (merge (:repl-env-options cfg)
+                             (select-keys opts [:output-dir :output-to]))
+              renv (apply repl-env (mapcat identity re-opts))]
+          (binding [cljs.repl/*repl-env* renv]
+            (cljs.repl/-setup renv (:options cfg))
+            ;; TODO is this better than a direct call?
+            ;; I don't think so
+            (when figwheel-mode?
+              (cljs.repl/evaluate-form renv
+                                       "<cljs repl>"
+                                       (assoc (ana/empty-env)
+                                              :ns (ana/get-namespace ana/*cljs-ns*))
+                                       ;; todo allow opts to be added here
+                                       (ana-api/forms-seq (StringReader. "(figwheel.core/start-from-repl)"))))
+            (when-let [server @(:server repl-env)]
+              (.join server))))))))

 (def server (atom nil))
+
+(def ^:dynamic *config*)

 ;; TODO figwheel.core start when not --repl
 (defn -main [& args]
-  (let [sargs (process-args args)
-        forward-args (assemble-args sargs)]
-    (clojure.pprint/pprint forward-args)
+  (let [[pre post] (split-with (complement #{"-re" "--repl-env"}) args)
+        args (if (empty? post) (concat ["-re" "figwheel" ] args) args)]
     (with-redefs [cljs.cli/default-compile default-compile]
-      (apply cljs.main/-main forward-args))))
+      (apply cljs.main/-main args))))

 (def args
-  (concat ["-co" "{:aot-cache false :asset-path \"out\"}" "--figwheel" "false"]
+  (concat ["-co" "{:aot-cache false :asset-path \"out\"}" "-e" "(figwheel.core/start-from-repl)"]
           (string/split "-w src -d target/public/out -o target/public/out/mainer.js -c exproj.core -r" #"\s")))

 #_(apply -main args)


Update eastwood

Update eastwood

--- roles/clojure/files/profiles.clj
+++ roles/clojure/files/profiles.clj
@@ -9,7 +9,7 @@

         :plugins [[cider/cider-nrepl "0.7.0-SNAPSHOT"]
                   [codox "0.6.6"]
-                  [jonase/eastwood "0.1.1"]
+                  [jonase/eastwood "0.1.4"]
                   [lein-ancient "0.5.4"]
                   [lein-cljsbuild "1.0.0"]
                   [lein-clojars "0.9.1"]


Make sure doc is available in the REPL

Make sure doc is available in the REPL

--- roles/clojure/files/profiles.clj
+++ roles/clojure/files/profiles.clj
@@ -22,7 +22,7 @@

         :injections [(require
                       '[alembic.still :refer [distill]]
-                      '[clojure.repl :refer [source]]
+                      '[clojure.repl :refer [doc source]]
                       '[clojure.tools.namespace.repl :as repl]
                       '[criterium.core :refer [bench quick-bench]]
                       'spyscope.core)]


Fix abs-plugin-test/abs-merge-test

Fix abs-plugin-test/abs-merge-test

--- src/onyx/messaging/atom_messenger.clj
+++ src/onyx/messaging/atom_messenger.clj
@@ -39,7 +39,7 @@
              (apply f (switch-peer m (:peer-id messenger)) args)))))

 (defrecord AtomMessenger
-  [peer peer-id immutable-messenger]
+  [peer peer-id messages immutable-messenger]
   component/Lifecycle

   (start [component]
@@ -105,7 +105,9 @@

   (receive-messages
     [messenger batch-size]
-    (assoc messenger :messages (update-messenger-atom! messenger m/receive-messages batch-size)))
+    (assoc messenger
+           :messages
+           (:messages (update-messenger-atom! messenger m/receive-messages batch-size))))

   (send-segments
     [messenger messages task-slots]


more macro expansion

more macro expansion

--- src/clj/algorithms_clj/macro_initiation.clj
+++ src/clj/algorithms_clj/macro_initiation.clj
@@ -41,12 +41,20 @@
 (defmacro add-m-3
   "Summing two integers known at compile time"
   [a b]
-  ;; TODO - How to get rid of eval??? constexpr
   (eval `(+ ~a ~b)))

 (defmacro add-m-4
+  "Summing two integers known at compile time"
   [a b]
   `(constexpr add ~a ~b))
+
+(defmacro sum-m
+  []
+  (add 1 2))
+
+(def ^:const c1 1)
+(def ^:const c2 2)
+(def ^:const c3 (add 1 2))

 (def x1 1)
 (def x2 2)
@@ -64,12 +72,14 @@
     ;; (println (add-m x y))
     ;; (println (add-m-2 x y))

-    ;; This however works, but only with add-m-2
-    ;; (println (add-m (x1) (x2)))
+    ;; This however works, thanks to eval or custom macro
     (report (add-inline x y))
     (report (add-m-3 x1 x2))
     (report (add-m-4 x1 x2))
-    ))
+    (report (sum-m))
+
+    ;; Up to the JVM to optimize it
+    (report c3)))

 ;; --------------------------------------------------------
@@ -87,7 +97,12 @@
   [coll]
   `(constexpr average ~coll))

-(defmacro coll-m [] [1 2 3 4])
+(defmacro my-average
+  []
+  (average-m [1 2 3 4]))
+
+(def ^:const my-average-2
+  (average-m [1 2 3 4]))

 (defn test-average
   []
@@ -95,9 +110,8 @@
     (report (average coll))
     ;; (println (average-m coll)) ;; Would not compile
     (report (average-m [1 2 3 4]))
-
-    ;; This however works
-    (report (average-m (coll-m)))
+    (report (my-average))
+    (report my-average-2)
     ))