(PDB-4676) Adjust whitespace in migration 74

This commit adjusts whitespace only in the reports-partitioning function.
The previous commit changed the arity of this function and adjusted how
the migration handled batching.

--- src/puppetlabs/puppetdb/scf/migrate.clj
+++ src/puppetlabs/puppetdb/scf/migrate.clj
@@ -1778,173 +1778,171 @@

 (defn reports-partitioning []
   (jdbc/do-commands
-     ;; detach the sequence so it isn't modified during the migration
-     "ALTER SEQUENCE reports_id_seq OWNED BY NONE"
-
-     "DROP INDEX idx_reports_noop_pending"
-     "DROP INDEX idx_reports_prod"
-     "DROP INDEX idx_reports_producer_timestamp"
-     "DROP INDEX idx_reports_producer_timestamp_by_hour_certname"
-     "DROP INDEX reports_cached_catalog_status_on_fail"
-     "DROP INDEX reports_catalog_uuid_idx"
-     "DROP INDEX reports_certname_idx"
-     "DROP INDEX reports_end_time_idx"
-     "DROP INDEX reports_environment_id_idx"
-     "DROP INDEX reports_hash_expr_idx"
-     "DROP INDEX reports_job_id_idx"
-     "DROP INDEX reports_noop_idx"
-     "DROP INDEX reports_status_id_idx"
-     "DROP INDEX reports_tx_uuid_expr_idx"
-     "ALTER TABLE certnames DROP CONSTRAINT certnames_reports_id_fkey"
-
-     "ALTER TABLE reports DROP CONSTRAINT reports_pkey"
-
-     "ALTER TABLE reports RENAME TO reports_premigrate"
-
-     "CREATE TABLE reports (
-        id bigint NOT NULL,
-        hash bytea NOT NULL,
-        transaction_uuid uuid,
-        certname text NOT NULL,
-        puppet_version text NOT NULL,
-        report_format smallint NOT NULL,
-        configuration_version text NOT NULL,
-        start_time timestamp with time zone NOT NULL,
-        end_time timestamp with time zone NOT NULL,
-        receive_time timestamp with time zone NOT NULL,
-        noop boolean,
-        environment_id bigint,
-        status_id bigint,
-        metrics_json json,
-        logs_json json,
-        producer_timestamp timestamp with time zone NOT NULL,
-        metrics jsonb,
-        logs jsonb,
-        resources jsonb,
-        catalog_uuid uuid,
-        cached_catalog_status text,
-        code_id text,
-        producer_id bigint,
-        noop_pending boolean,
-        corrective_change boolean,
-        job_id text)"
-
-     "CREATE OR REPLACE FUNCTION find_reports_unique_dates()
-     RETURNS TABLE (rowdate TIMESTAMP WITH TIME ZONE)
-     AS $$
-     DECLARE
-     BEGIN
-       EXECUTE 'SET local timezone to ''UTC''';
-       RETURN QUERY SELECT DISTINCT date_trunc('day', producer_timestamp) AS rowdate FROM reports_premigrate;
-     END;
-     $$ language plpgsql;")
-
-   ;; note: the reports table does *not* have an insert trigger because reports relies on the RETURNING *
-   ;; part of the INSERT INTO statement.
-
-   ;; create range of partitioned tables
-
-   (let [now (ZonedDateTime/now)
-         days (range -4 4)]
-     (doseq [day-offset days]
-       (partitioning/create-reports-partition (.plusDays now day-offset))))
-
-   ;; pre-create partitions
-   (log/info (trs "Creating partitions based on unique days in reports"))
-   (let [current-timezone (:current_setting (first (jdbc/query-to-vec "SELECT current_setting('TIMEZONE')")))]
-     (jdbc/call-with-query-rows
-       ["select rowdate from find_reports_unique_dates()"]
-       (fn [rows]
-         (doseq [row rows]
-           (partitioning/create-reports-partition (-> (:rowdate row)
-                                                      (.toInstant))))))
-     (jdbc/do-commands
-       ;; restore the transaction's timezone setting after creating the partitions
-       (str "SET local timezone to '" current-timezone "'")))
-
-   (let [event-count (-> "select count(*) from reports_premigrate"
-                         jdbc/query-to-vec first :count)
-         last-logged (atom (.getTime (java.util.Date.)))
-         reports-migrated (atom 0)]
-     (jdbc/call-with-query-rows
-       ["select * from (
-           select
-             id, transaction_uuid, certname, puppet_version, report_format, configuration_version, start_time, end_time,
-             receive_time, noop, environment_id, status_id, metrics_json, logs_json, producer_timestamp, metrics, logs,
-             resources, catalog_uuid, cached_catalog_status, code_id, producer_id, noop_pending, corrective_change,
-             job_id,
-             row_number() over ( partition by
-                                   certname, puppet_version, report_format, configuration_version, start_time, end_time,
-                                   receive_time, transaction_uuid
-                                 order by receive_time asc )
-           from reports_premigrate) as sub
-         where row_number = 1"]
-       ;; set the FetchSize used by jdbc to avoid any potential OOM errors caused
-       ;; by fetching too many large reports at once
-       {:fetch-size 1}
-       (fn [rows]
-         (let [old-cols [:id :transaction_uuid :certname :puppet_version :report_format
-                         :configuration_version :start_time :end_time :receive_time :noop
-                         :environment_id :status_id :metrics_json :logs_json :producer_timestamp
-                         :metrics :logs :resources :catalog_uuid :cached_catalog_status :code_id
-                         :producer_id :noop_pending :corrective_change :job_id]
-               new-cols (into [:hash] old-cols)
-               update-row (apply juxt (comp sutils/munge-hash-for-storage
-                                            hash/report-identity-hash)
-                                 old-cols)
-               insert->hash (fn [row]
-                              (swap! reports-migrated inc)
-                              (let [updated-row (update-row row)
-                                    table-name (str "reports_" (-> updated-row
-                                                                   (get 15) ;; producer_timestamp
-                                                                   (partitioning/to-zoned-date-time)
-                                                                   (partitioning/date-suffix)))]
-                                (jdbc/insert! table-name new-cols updated-row))
-                              (let [now (.getTime (java.util.Date.))]
-                                (when (> (- now @last-logged) 60000)
-                                  (maplog :info
-                                          {:migration 74 :at @reports-migrated :of event-count}
-                                          #(trs "Migrated {0} of {1} reports" (:at %) (:of %)))
-                                  (reset! last-logged now))))]
-           (run! insert->hash rows)))))
-
-   ;; migrate data
-
-   (jdbc/do-commands
-     ;; attach sequence
-     "ALTER SEQUENCE reports_id_seq OWNED BY reports.id"
-
-     ;; set default value on new table DEFAULT nextval('reports_id_seq'::regclass)
-     "ALTER TABLE reports ALTER COLUMN id SET DEFAULT nextval('reports_id_seq'::regclass)"
-
-     "ALTER TABLE reports ADD CONSTRAINT reports_pkey PRIMARY KEY (id)"
-     "CREATE INDEX idx_reports_noop_pending ON reports USING btree (noop_pending) WHERE (noop_pending = true)"
-     "CREATE INDEX idx_reports_prod ON reports USING btree (producer_id)"
-     "CREATE INDEX idx_reports_producer_timestamp ON reports USING btree (producer_timestamp)"
-     ["CREATE INDEX idx_reports_producer_timestamp_by_hour_certname ON reports USING btree "
-      "  (date_trunc('hour'::text, timezone('UTC'::text, producer_timestamp)), producer_timestamp, certname)"]
-     ["CREATE INDEX reports_cached_catalog_status_on_fail ON reports USING btree"
-      "  (cached_catalog_status) WHERE (cached_catalog_status = 'on_failure'::text)"]
-     "CREATE INDEX reports_catalog_uuid_idx ON reports USING btree (catalog_uuid)"
-     "CREATE INDEX reports_certname_idx ON reports USING btree (certname)"
-     "CREATE INDEX reports_end_time_idx ON reports USING btree (end_time)"
-     "CREATE INDEX reports_environment_id_idx ON reports USING btree (environment_id)"
-     "CREATE UNIQUE INDEX reports_hash_expr_idx ON reports USING btree (encode(hash, 'hex'::text))"
-     "CREATE INDEX reports_job_id_idx ON reports USING btree (job_id) WHERE (job_id IS NOT NULL)"
-     "CREATE INDEX reports_noop_idx ON reports USING btree (noop) WHERE (noop = true)"
-     "CREATE INDEX reports_status_id_idx ON reports USING btree (status_id)"
-     "CREATE INDEX reports_tx_uuid_expr_idx ON reports USING btree (((transaction_uuid)::text))"
-     ["ALTER TABLE reports"
-      "  ADD CONSTRAINT reports_certname_fkey FOREIGN KEY (certname) REFERENCES certnames(certname) ON DELETE CASCADE"]
-     ["ALTER TABLE reports"
-      "  ADD CONSTRAINT reports_env_fkey FOREIGN KEY (environment_id) REFERENCES environments(id) ON DELETE CASCADE"]
-     ["ALTER TABLE reports"
-      "  ADD CONSTRAINT reports_prod_fkey FOREIGN KEY (producer_id) REFERENCES producers(id)"]
-     ["ALTER TABLE reports"
-      "  ADD CONSTRAINT reports_status_fkey FOREIGN KEY (status_id) REFERENCES report_statuses(id) ON DELETE CASCADE"]
-
-     "DROP TABLE reports_premigrate"
-     "DROP FUNCTION find_reports_unique_dates()"))
+   ;; detach the sequence so it isn't modified during the migration
+   "ALTER SEQUENCE reports_id_seq OWNED BY NONE"
+
+   "DROP INDEX idx_reports_noop_pending"
+   "DROP INDEX idx_reports_prod"
+   "DROP INDEX idx_reports_producer_timestamp"
+   "DROP INDEX idx_reports_producer_timestamp_by_hour_certname"
+   "DROP INDEX reports_cached_catalog_status_on_fail"
+   "DROP INDEX reports_catalog_uuid_idx"
+   "DROP INDEX reports_certname_idx"
+   "DROP INDEX reports_end_time_idx"
+   "DROP INDEX reports_environment_id_idx"
+   "DROP INDEX reports_hash_expr_idx"
+   "DROP INDEX reports_job_id_idx"
+   "DROP INDEX reports_noop_idx"
+   "DROP INDEX reports_status_id_idx"
+   "DROP INDEX reports_tx_uuid_expr_idx"
+   "ALTER TABLE certnames DROP CONSTRAINT certnames_reports_id_fkey"
+
+   "ALTER TABLE reports DROP CONSTRAINT reports_pkey"
+
+   "ALTER TABLE reports RENAME TO reports_premigrate"
+
+   "CREATE TABLE reports (
+      id bigint NOT NULL,
+      hash bytea NOT NULL,
+      transaction_uuid uuid,
+      certname text NOT NULL,
+      puppet_version text NOT NULL,
+      report_format smallint NOT NULL,
+      configuration_version text NOT NULL,
+      start_time timestamp with time zone NOT NULL,
+      end_time timestamp with time zone NOT NULL,
+      receive_time timestamp with time zone NOT NULL,
+      noop boolean,
+      environment_id bigint,
+      status_id bigint,
+      metrics_json json,
+      logs_json json,
+      producer_timestamp timestamp with time zone NOT NULL,
+      metrics jsonb,
+      logs jsonb,
+      resources jsonb,
+      catalog_uuid uuid,
+      cached_catalog_status text,
+      code_id text,
+      producer_id bigint,
+      noop_pending boolean,
+      corrective_change boolean,
+      job_id text)"
+
+   "CREATE OR REPLACE FUNCTION find_reports_unique_dates()
+    RETURNS TABLE (rowdate TIMESTAMP WITH TIME ZONE)
+    AS $$
+    DECLARE
+    BEGIN
+      EXECUTE 'SET local timezone to ''UTC''';
+      RETURN QUERY SELECT DISTINCT date_trunc('day', producer_timestamp) AS rowdate FROM reports_premigrate;
+    END;
+    $$ language plpgsql;")
+
+  ;; note: the reports table does *not* have an insert trigger because reports relies on the RETURNING *
+  ;; part of the INSERT INTO statement.
+
+  ;; create range of partitioned tables
+
+  (let [now (ZonedDateTime/now)
+        days (range -4 4)]
+    (doseq [day-offset days]
+      (partitioning/create-reports-partition (.plusDays now day-offset))))
+
+  ;; pre-create partitions
+  (log/info (trs "Creating partitions based on unique days in reports"))
+  (let [current-timezone (:current_setting (first (jdbc/query-to-vec "SELECT current_setting('TIMEZONE')")))]
+    (jdbc/call-with-query-rows
+     ["select rowdate from find_reports_unique_dates()"]
+     (fn [rows]
+       (doseq [row rows]
+         (partitioning/create-reports-partition (-> (:rowdate row)
+                                                    (.toInstant))))))
+    (jdbc/do-commands
+     ;; restore the transaction's timezone setting after creating the partitions
+     (str "SET local timezone to '" current-timezone "'")))
+
+  (let [event-count (-> "select count(*) from reports_premigrate"
+                        jdbc/query-to-vec first :count)
+        last-logged (atom (.getTime (java.util.Date.)))
+        reports-migrated (atom 0)]
+    (jdbc/call-with-query-rows
+      ["select * from (
+          select
+            id, transaction_uuid, certname, puppet_version, report_format, configuration_version, start_time, end_time,
+            receive_time, noop, environment_id, status_id, metrics_json, logs_json, producer_timestamp, metrics, logs,
+            resources, catalog_uuid, cached_catalog_status, code_id, producer_id, noop_pending, corrective_change,
+            job_id,
+            row_number() over ( partition by
+                                  certname, puppet_version, report_format, configuration_version, start_time, end_time,
+                                  receive_time, transaction_uuid
+                                order by receive_time asc )
+          from reports_premigrate) as sub
+        where row_number = 1"]
+      ;; set the FetchSize used by jdbc to avoid any potential OOM errors caused
+      ;; by fetching too many large reports at once
+      {:fetch-size 1}
+      (fn [rows]
+        (let [old-cols [:id :transaction_uuid :certname :puppet_version :report_format
+                        :configuration_version :start_time :end_time :receive_time :noop
+                        :environment_id :status_id :metrics_json :logs_json :producer_timestamp
+                        :metrics :logs :resources :catalog_uuid :cached_catalog_status :code_id
+                        :producer_id :noop_pending :corrective_change :job_id]
+              new-cols (into [:hash] old-cols)
+              update-row (apply juxt (comp sutils/munge-hash-for-storage
+                                           hash/report-identity-hash)
+                                old-cols)
+              insert->hash (fn [row]
+                             (swap! reports-migrated inc)
+                             (let [updated-row (update-row row)
+                                   table-name (str "reports_" (-> updated-row
+                                                                  (get 15) ;; producer_timestamp
+                                                                  (partitioning/to-zoned-date-time)
+                                                                  (partitioning/date-suffix)))]
+                               (jdbc/insert! table-name new-cols updated-row))
+                             (let [now (.getTime (java.util.Date.))]
+                               (when (> (- now @last-logged) 60000)
+                                 (maplog :info
+                                         {:migration 74 :at @reports-migrated :of event-count}
+                                         #(trs "Migrated {0} of {1} reports" (:at %) (:of %)))
+                                 (reset! last-logged now))))]
+          (run! insert->hash rows)))))
+
+  (jdbc/do-commands
+   ;; attach sequence
+   "ALTER SEQUENCE reports_id_seq OWNED BY reports.id"
+
+   ;; set default value on new table DEFAULT nextval('reports_id_seq'::regclass)
+   "ALTER TABLE reports ALTER COLUMN id SET DEFAULT nextval('reports_id_seq'::regclass)"
+
+   "ALTER TABLE reports ADD CONSTRAINT reports_pkey PRIMARY KEY (id)"
+   "CREATE INDEX idx_reports_noop_pending ON reports USING btree (noop_pending) WHERE (noop_pending = true)"
+   "CREATE INDEX idx_reports_prod ON reports USING btree (producer_id)"
+   "CREATE INDEX idx_reports_producer_timestamp ON reports USING btree (producer_timestamp)"
+   ["CREATE INDEX idx_reports_producer_timestamp_by_hour_certname ON reports USING btree "
+    "  (date_trunc('hour'::text, timezone('UTC'::text, producer_timestamp)), producer_timestamp, certname)"]
+   ["CREATE INDEX reports_cached_catalog_status_on_fail ON reports USING btree"
+    "  (cached_catalog_status) WHERE (cached_catalog_status = 'on_failure'::text)"]
+   "CREATE INDEX reports_catalog_uuid_idx ON reports USING btree (catalog_uuid)"
+   "CREATE INDEX reports_certname_idx ON reports USING btree (certname)"
+   "CREATE INDEX reports_end_time_idx ON reports USING btree (end_time)"
+   "CREATE INDEX reports_environment_id_idx ON reports USING btree (environment_id)"
+   "CREATE UNIQUE INDEX reports_hash_expr_idx ON reports USING btree (encode(hash, 'hex'::text))"
+   "CREATE INDEX reports_job_id_idx ON reports USING btree (job_id) WHERE (job_id IS NOT NULL)"
+   "CREATE INDEX reports_noop_idx ON reports USING btree (noop) WHERE (noop = true)"
+   "CREATE INDEX reports_status_id_idx ON reports USING btree (status_id)"
+   "CREATE INDEX reports_tx_uuid_expr_idx ON reports USING btree (((transaction_uuid)::text))"
+   ["ALTER TABLE reports"
+    "  ADD CONSTRAINT reports_certname_fkey FOREIGN KEY (certname) REFERENCES certnames(certname) ON DELETE CASCADE"]
+   ["ALTER TABLE reports"
+    "  ADD CONSTRAINT reports_env_fkey FOREIGN KEY (environment_id) REFERENCES environments(id) ON DELETE CASCADE"]
+   ["ALTER TABLE reports"
+    "  ADD CONSTRAINT reports_prod_fkey FOREIGN KEY (producer_id) REFERENCES producers(id)"]
+   ["ALTER TABLE reports"
+    "  ADD CONSTRAINT reports_status_fkey FOREIGN KEY (status_id) REFERENCES report_statuses(id) ON DELETE CASCADE"]
+
+   "DROP TABLE reports_premigrate"
+   "DROP FUNCTION find_reports_unique_dates()"))

 (def migrations
   "The available migrations, as a map from migration version to migration function."


fix indentation

fix indentation

--- src-cljs/frontend/components/overlay.cljs
+++ src-cljs/frontend/components/overlay.cljs
@@ -231,31 +231,30 @@
             access-grants (ds/touch-all '[:find ?t :in $ ?doc-id :where [?t :access-grant/document ?doc-id]] @db doc-id)
             access-requests (ds/touch-all '[:find ?t :in $ ?doc-id :where [?t :access-request/document ?doc-id]] @db doc-id)]
         (html
-          [:div ; TODO make this a list, or at least get rid of div somehow
-           [:article
-            ; [:h2 "This document is private."]
-            [:h2
-             [:span "This document is "]
-             [:span.privacy-private-word "private."]]
-            [:p.privacy-private-words "It's only visible to users with access."
-             " Email a teammate and notify them to request access."]
-            [:form.menu-invite-form {:on-submit #(do (cast! :permission-grant-submitted)
-                                                     false)
-                                     :on-key-down #(when (= "Enter" (.-key %))
-                                                     (cast! :permission-grant-submitted)
-                                                     false)}
-             [:input {:type "text"
-                      :required "true"
-                      :data-adaptive ""
-                      :value (or permission-grant-email "")
-                      :on-change #(cast! :permission-grant-email-changed {:value (.. % -target -value)})}]
-             [:label {:data-placeholder "Teammate's email"
-                      :data-placeholder-nil "What's your teammate's email?"
-                      :data-placeholder-forgot "Don't forget to submit!"}]]]
-
-           [:div.access-list
-            (for [access-entity (sort-by (comp - :db/id) (concat permissions access-grants access-requests))]
-              (render-access-entity access-entity cast!))]])))))
+         [:div ; TODO make this a list, or at least get rid of div somehow
+          [:article
+           [:h2
+            [:span "This document is "]
+            [:span.privacy-private-word "private."]]
+           [:p.privacy-private-words "It's only visible to users with access."
+            " Email a teammate and notify them to request access."]
+           [:form.menu-invite-form {:on-submit #(do (cast! :permission-grant-submitted)
+                                                    false)
+                                    :on-key-down #(when (= "Enter" (.-key %))
+                                                    (cast! :permission-grant-submitted)
+                                                    false)}
+            [:input {:type "text"
+                     :required "true"
+                     :data-adaptive ""
+                     :value (or permission-grant-email "")
+                     :on-change #(cast! :permission-grant-email-changed {:value (.. % -target -value)})}]
+            [:label {:data-placeholder "Teammate's email"
+                     :data-placeholder-nil "What's your teammate's email?"
+                     :data-placeholder-forgot "Don't forget to submit!"}]]]
+
+          [:div.access-list
+           (for [access-entity (sort-by (comp - :db/id) (concat permissions access-grants access-requests))]
+             (render-access-entity access-entity cast!))]])))))

 (defn public-sharing [app owner]
   (reify


outer plans description update

outer plans description update

--- src-cljs/frontend/components/pricing.cljs
+++ src-cljs/frontend/components/pricing.cljs
@@ -68,7 +68,7 @@
              [:div.row
               [:div.pricing-calculator-controls
                [:div.controls-containers
-                [:h2 "Containers"]
+                [:h2 "LXE Containers"]
                 [:p "All of your containers are shared across your entire organization."]
                 ;;TODO Use frontend.components.shared/styled-range-slider
                 [:div.containers-range {:on-click #(om/set-state! owner :drag-percent (calculate-drag-percent owner %))


Prevent nREPL port files overwriting each other

--- app/dev/nrepl.clj
+++ app/dev/nrepl.clj
@@ -17,7 +17,7 @@
                        #'refactor.nrepl/wrap-refactor
                        #'cemerick.piggieback/wrap-cljs-repl
                        )))]
-    (spit "../.nrepl-port" (:port server))
+    (spit ".nrepl-port" (:port server))
     (println "NREPL port:" (:port server))
     server))


Load clojure.repl when started as interactive repl

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

--- src/scripts/conexp-clj.clj
+++ src/scripts/conexp-clj.clj
@@ -19,7 +19,7 @@
     (use 'conexp.main)
     (load-file (options :load)))
   (when-not (or (options :load))
-    (clojure.main/repl :init #(use 'conexp.main))))
+    (clojure.main/repl :init #(do (use 'conexp.main) (use 'clojure.repl)))))

 ;;


Started out by making tuple generator tests stable and useful.

--- test/blutwurst/tuple_generator_test.clj
+++ test/blutwurst/tuple_generator_test.clj
@@ -5,7 +5,32 @@
             [blutwurst.logging-fixture :refer :all]
             [blutwurst.tuple-generator :refer :all]))

-(use-fixtures :each logging-fixture)
+(def fixed-generators
+  ^{ :private true }
+  [
+   {
+      :name "Random String Generator"
+      :determiner #(= (:type %) "VARCHAR")
+      :generator (fn [x] "asdf")
+   }
+   {
+       :name "Random Integer Generator"
+       :determiner #(= (:type %) "INTEGER")
+       :generator (fn [c] 100)
+   }
+   {
+       :name "Random Decimal Generator"
+       :determiner #(= (:type %) "DECIMAL")
+       :generator (fn [c] 1.7)
+   }
+  ])
+
+(defn predictable-generator-fixture [f]
+ (with-redefs [blutwurst.tuple-generator/value-generation-strategies fixed-generators]
+  (f)
+ ))
+
+(use-fixtures :each logging-fixture predictable-generator-fixture)

 (deftest random-string-test
  (testing "Basic random string generation."
@@ -20,9 +45,10 @@
                       :schema "foo"
                       :columns '({:name "Address1" :type "VARCHAR" :length 20 :nullable false}
                                  {:name "City" :type "VARCHAR" :length 100 :nullable true})
-                      }
-          data (generate-tuples-for-table table-spec 5)]
-      (is (= 2 (count data)))
+                      }]
+      (is (= {:table table-spec
+              :tuples '((("Address1" "asdf") ("City" "asdf")) (("Address1" "asdf") ("City" "asdf")))}
+             (generate-tuples-for-table table-spec 2)))
     )))

 (deftest generate-tuples-from-plan-test
@@ -33,9 +59,12 @@
                           :columns ({:name "Address1" :type "VARCHAR" :length 20 :nullable false}
                                      {:name "ID" :type "INTEGER" :length 3 :nullable true})
                           })
-              data (generate-tuples-for-plan table-spec)]
-          (trace data)
-          (is (= 1 (count data)))
-          (is (= 2 (count (first data))))
+              expected-tuples (repeat 100 '(("Address1" "asdf") ("ID" 100)))
+              ]
+        (is (= `({:table ~(first table-spec)
+                 :tuples ~expected-tuples
+                 })
+                (generate-tuples-for-plan table-spec)
+               ))
       )))
 ; TODO: build a negative test with an unknown data type


setting :visible? to false in a post when unsaving

--- src/saved_for_reddit/reddit-api.cljs
+++ src/saved_for_reddit/reddit-api.cljs
@@ -57,7 +57,13 @@
           error  (:error body)]
       (if (clojure.string/blank? error)
         (do
-          (println body))
+          (println body)
+          ;; set the post visibility to false
+          (swap! saved-for-reddit.core/saved-posts
+                 update-in
+                 [(keyword thing-id)]
+                 #(assoc % :visible? false))
+          )
         (views/handle-error error)))))

 (defn repack-post [p]


Documentation

Documentation

--- ClojureScript/src/goby/core.cljs
+++ ClojureScript/src/goby/core.cljs
@@ -3,95 +3,133 @@
             [clojure.data :as data])
   (:require-macros [goby.macros :refer [reify]]))

-(def env (atom {}))
-
-(def table-view-scroll-positions {:table-view-scroll-position-none   0
-                                  :table-view-scroll-position-top    1
-                                  :table-view-scroll-position-middle 2
-                                  :table-view-scroll-position-bottom 3})
-
-(def table-view-scroll-positions' (set/map-invert table-view-scroll-positions))
-
-(def table-view-row-animations {:table-view-row-animation-fade      0
-                                :table-view-row-animation-right     1
-                                :table-view-row-animation-left      2
-                                :table-view-row-animation-top       3
-                                :table-view-row-animation-bottom    4
-                                :table-view-row-animation-none      5
-                                :table-view-row-animation-middle    6
-                                :table-view-row-animation-automatic 100})
-
-(def table-view-row-animations' (set/map-invert table-view-row-animations))
-
-(def table-view-cell-accessory-types {:table-view-cell-accessory-none                     0
-                                      :table-view-cell-accessory-disclosure-indicator     1
-                                      :table-view-cell-accessory-detail-disclosure-button 2
-                                      :table-view-cell-accessory-checkmark                3
-                                      :table-view-cell-accessory-detail-button            4})
-
-(def table-view-cell-accessory-types' (set/map-invert table-view-cell-accessory-types))
-
-(def table-view-cell-editing-styles {:table-view-cell-editing-style-none   0
-                                     :table-view-cell-editing-style-delete 1
-                                     :table-view-cell-editing-style-insert 2})
-
-(def table-view-cell-editing-styles' (set/map-invert table-view-cell-editing-styles))
-
-(def device-orientations {:device-orientation-unknown              0
-                          :device-orientation-portrait             1
-                          :device-orientation-portrait-upside-down 2
-                          :device-orientation-landscape-left       3
-                          :device-orientation-landscape-right      4
-                          :device-orientation-face-up              5
-                          :device-orientation-face-down            6})
-
-(def device-orientations' (set/map-invert device-orientations))
-
-(def interface-orientations {:interface-orientation-portrait             (:device-orientation-portrait device-orientations)
-                             :interface-orientation-portrait-upside-down (:device-orientation-portrait-upside-down device-orientations)
-                             :interface-orientation-landscape-left       (:device-orientation-landscape-left device-orientations)
-                             :interface-orientation-landscape-right      (:device-orientation-landscape-right device-orientations)})
-
-(def interface-orientations' (set/map-invert interface-orientations))
-
-(def ^:private ui-control-events {:touch-down              (bit-shift-left 1 0)
-                                  :touch-down-repeat       (bit-shift-left 1 1)
-                                  :touch-drag-inside       (bit-shift-left 1 2)
-                                  :touch-drag-outside      (bit-shift-left 1 3)
-                                  :touch-drag-enter        (bit-shift-left 1 4)
-                                  :touch-drag-exit         (bit-shift-left 1 5)
-                                  :touch-up-inside         (bit-shift-left 1 6)
-                                  :touch-up-outside        (bit-shift-left 1 7)
-                                  :touch-cancel            (bit-shift-left 1 8)
-                                  :value-changed           (bit-shift-left 1 12)
-                                  :editing-did-begin       (bit-shift-left 1 16)
-                                  :editing-changed         (bit-shift-left 1 17)
-                                  :editing-did-end         (bit-shift-left 1 18)
-                                  :editing-did-end-on-exit (bit-shift-left 1 19)})
-
-(def ^:private inverted-ui-control-events (set/map-invert ui-control-events))
-
-(def ^:private attributes {:not-applicable 0
-                           :enabled        1
-                           :text           2
-                           :selected       3
-                           :highlighted    4
-                           :hidden         5})
-
-(def ^:private inverted-attributes (set/map-invert attributes))
+(def env "Contains a map of environment values such as whether running a release build, etc." (atom {}))
+
+
+(def table-view-scroll-positions
+  "Defines a map from keywords to `UITableViewScrollPosition` values."
+  {:table-view-scroll-position-none   0
+   :table-view-scroll-position-top    1
+   :table-view-scroll-position-middle 2
+   :table-view-scroll-position-bottom 3})
+
+(def table-view-scroll-positions'
+  "Defines a map from `UITableViewScrollPosition` values to keywords."
+  (set/map-invert table-view-scroll-positions))
+
+(def table-view-row-animations
+  "Defines a map from keywords to `UITableViewRowAnimation` values."
+  {:table-view-row-animation-fade      0
+   :table-view-row-animation-right     1
+   :table-view-row-animation-left      2
+   :table-view-row-animation-top       3
+   :table-view-row-animation-bottom    4
+   :table-view-row-animation-none      5
+   :table-view-row-animation-middle    6
+   :table-view-row-animation-automatic 100})
+
+(def table-view-row-animations'
+  "Defines a map from `UITableViewRowAnimation` values to keywords."
+  (set/map-invert table-view-row-animations))
+
+(def table-view-cell-accessory-types
+  "Defines a map from keywords to `UITableViewAccesoryType` values."
+  {:table-view-cell-accessory-none                     0
+   :table-view-cell-accessory-disclosure-indicator     1
+   :table-view-cell-accessory-detail-disclosure-button 2
+   :table-view-cell-accessory-checkmark                3
+   :table-view-cell-accessory-detail-button            4})
+
+(def table-view-cell-accessory-types'
+  "Defines a map from `UITableViewAccesoryType` values to keywords."
+  (set/map-invert table-view-cell-accessory-types))
+
+(def table-view-cell-editing-styles
+  "Defines a map from keywords to `UITableViewEditingStyle` values."
+  {:table-view-cell-editing-style-none   0
+   :table-view-cell-editing-style-delete 1
+   :table-view-cell-editing-style-insert 2})
+
+(def table-view-cell-editing-styles'
+  "Defines a map from `UITableViewEditingStyle` values to keywords."
+  (set/map-invert table-view-cell-editing-styles))
+
+(def device-orientations
+  "Defines a map from keywords to `UIDeviceOrientation` values."
+  {:device-orientation-unknown              0
+   :device-orientation-portrait             1
+   :device-orientation-portrait-upside-down 2
+   :device-orientation-landscape-left       3
+   :device-orientation-landscape-right      4
+   :device-orientation-face-up              5
+   :device-orientation-face-down            6})
+
+(def device-orientations'
+  "Defines a map from `UIDeviceOrientation` values to keywords."
+  (set/map-invert device-orientations))
+
+(def interface-orientations
+  "Defines a map from keywords to `UIInterfaceOrientation` values."
+  {:interface-orientation-portrait             (:device-orientation-portrait device-orientations)
+   :interface-orientation-portrait-upside-down (:device-orientation-portrait-upside-down device-orientations)
+   :interface-orientation-landscape-left       (:device-orientation-landscape-left device-orientations)
+   :interface-orientation-landscape-right      (:device-orientation-landscape-right device-orientations)})
+
+(def interface-orientations'
+  "Defines a map from `UIInterfaceOrientation` values to keywords."
+  (set/map-invert interface-orientations))
+
+(def ^:private ui-control-events
+  "Defines a map from keywords to `UIControlEvent` values."
+  {:touch-down              (bit-shift-left 1 0)
+   :touch-down-repeat       (bit-shift-left 1 1)
+   :touch-drag-inside       (bit-shift-left 1 2)
+   :touch-drag-outside      (bit-shift-left 1 3)
+   :touch-drag-enter        (bit-shift-left 1 4)
+   :touch-drag-exit         (bit-shift-left 1 5)
+   :touch-up-inside         (bit-shift-left 1 6)
+   :touch-up-outside        (bit-shift-left 1 7)
+   :touch-cancel            (bit-shift-left 1 8)
+   :value-changed           (bit-shift-left 1 12)
+   :editing-did-begin       (bit-shift-left 1 16)
+   :editing-changed         (bit-shift-left 1 17)
+   :editing-did-end         (bit-shift-left 1 18)
+   :editing-did-end-on-exit (bit-shift-left 1 19)})
+
+(def ^:private inverted-ui-control-events
+  "Defines a map from `UIControlEvent` values to keywords."
+  (set/map-invert ui-control-events))
+
+(def ^:private attributes
+  "Defines a map from keywords to `UIAttribute` values."
+  {:not-applicable 0
+   :enabled        1
+   :text           2
+   :selected       3
+   :highlighted    4
+   :hidden         5})
+
+(def ^:private inverted-attributes
+  "Defines a map from `UIAttribute` values to keywords."
+  (set/map-invert attributes))

 (defn- form-events-mask
   [ui-control-events-set]
   (reduce bit-or 0 (map ui-control-events ui-control-events-set)))

-(def fetched-results-change-type {:fetched-results-change-insert 1
-                                  :fetched-results-change-delete 2
-                                  :fetched-results-change-move   3
-                                  :fetched-results-change-update 4})
-
-(def fetched-results-change-type' (set/map-invert fetched-results-change-type))
+(def fetched-results-change-type
+  "Defines a map from keywords to `NSFetchedResultsChangeType` values."
+  {:fetched-results-change-insert 1
+   :fetched-results-change-delete 2
+   :fetched-results-change-move   3
+   :fetched-results-change-update 4})
+
+(def fetched-results-change-type'
+  "Defines a map from `NSFetchedResultsChangeType` values to keywords."
+  (set/map-invert fetched-results-change-type))

 (defprotocol TableViewDelegate
+  "Defines a protocol consistent with `UITableViewDelegate`."

   ;; All methods in this protocol are optional

@@ -153,6 +191,7 @@
   (^:export perform-action-for-row-at-index-path-with-sender [this sel section row sender]))

 (defprotocol TableViewDataSource
+  "Defines a protocol consistent with `UITableViewDataSource`."

   (^:export TableViewDataSource-implements [this])

@@ -172,6 +211,7 @@
   (^:export move-row-at-index-path [this source-section source-row destination-section destination-row]))

 (defprotocol FetchedResultsControllerDelegate
+  "Defines a protocol consistent with `NSFetchedResultsControllerDelegate`."

   (^:export FetchedResultsControllerDelegate-implements [this])

@@ -183,10 +223,14 @@
   (^:export did-change-content [this])
   (^:export section-index-title-for-section-name [this section-name]))

-(defn user-interface-idiom-ipad? []
+(defn user-interface-idiom-ipad?
+  "Returns true iff the interface idiom is iPad."
+  []
   (= "iPad" (:user-interface-idiom @env)))

-(defn reify-fetched-results-controller-delegate [table-view]
+(defn reify-fetched-results-controller-delegate
+  "Provides a refication of `FetchedResultsControllerDelegate` that maniuplates a table-view."
+  [table-view]
   (reify FetchedResultsControllerDelegate

     (did-change-object-at-index-path-for-change-type-new-index-path


core.async: More mapping examples.

core.async: More mapping examples.

--- test/com/nomistech/clojure_the_language/core_async_mapping_etc_test.clj
+++ test/com/nomistech/clojure_the_language/core_async_mapping_etc_test.clj
@@ -15,7 +15,23 @@

 ;;;; ___________________________________________________________________________

-(fact
-  (chan->seq (a/map inc
+(fact "About `a/map`"
+  (chan->seq (a/map (partial * 100)
                     [(a/to-chan (range 5))]))
-  => [1 2 3 4 5])
+  => [0 100 200 300 400])
+
+(fact "About `a/map<` (N.B. This is deprecated)"
+  (chan->seq (a/map< (partial * 100)
+                     (a/to-chan (range 5))))
+  => [0 100 200 300 400])
+
+(fact "About `a/map>` (N.B. This is deprecated)"
+  (let [wrapped-ch  (a/chan)
+        wrapping-ch (a/map> (partial * 100)
+                            wrapped-ch)]
+    (a/go
+      (doseq [i (range 5)]
+        (a/>! wrapping-ch i))
+      (a/close! wrapping-ch))
+    (chan->seq wrapped-ch))
+  => [0 100 200 300 400])


[#670] Removed comments

[#670] Removed comments

--- backend/src/akvo/lumen/admin/add_tenant.clj
+++ backend/src/akvo/lumen/admin/add_tenant.clj
@@ -281,10 +281,7 @@
 (defn -main [url title email]
   (try
     (check-env-vars)
-    (let [;; url (normalize-url url)
-          ;; label (label url)
-          {keys [email label title url]} (conform-input url title email)
-          ]
+    (let [{keys [email label title url]} (conform-input url title email)]
       (setup-database label title)
       (let [user-creds (setup-tenant-in-keycloak label email url)]
         (println "Credentials:")


Make ConnectionPool implement java.io.Closeable

--- src/taoensso/carmine/connections.clj
+++ src/taoensso/carmine/connections.clj
@@ -46,7 +46,9 @@
   (get-conn     [this spec] (.borrowObject pool spec))
   (release-conn [this conn] (.returnObject pool (get-spec conn) conn))
   (release-conn [this conn exception] (.invalidateObject pool (get-spec conn)
-                                                         conn)))
+                                                         conn))
+  java.io.Closeable
+  (close [this] (.close ^ConnectionPool pool)))

 (defn make-new-connection
   "Actually creates and returns a new socket connection."


[#231] Experimental: Add conns instrumentation fn callbacks (@pete-woods)

--- src/taoensso/carmine/connections.clj
+++ src/taoensso/carmine/connections.clj
@@ -36,8 +36,14 @@
           (protocol/with-context this
             (protocol/with-replies
               (taoensso.carmine/ping)))
-          (catch Exception _)))))
-  (close-conn [_] (.close socket)))
+
+          (catch Exception ex
+            (when-let [f (get-in spec [:instrument :on-conn-error])]
+              (f {:spec spec :ex ex})))))))
+
+  (close-conn [_]
+    (when-let [f (get-in spec [:instrument :on-conn-close])] (f {:spec spec}))
+    (.close socket)))

 (defprotocol IConnectionPool
   (get-conn     [this spec])
@@ -99,6 +105,8 @@
                    (BufferedOutputStream. buff-size)))

         db (when (and db (not (zero? db))) db)]
+
+    (when-let [f (get-in spec [:instrument :on-conn-open])] (f {:spec spec}))

     (when (or password db conn-setup-fn)
       (protocol/with-context conn
@@ -150,12 +158,18 @@
     :test-while-idle? (.setTestWhileIdle pool v) ; false
     :time-between-eviction-runs-ms (.setTimeBetweenEvictionRunsMillis pool v) ; -1

+    :instrument nil ; noop (ignore)
+
     (throw (ex-info (str "Unknown pool option: " k) {:option k})))
   pool)

 (def conn-pool
   (enc/memoize_
     (fn [pool-opts]
+
+      (when-let [f (get-in pool-opts [:instrument :on-pool-init])]
+        (f {:pool-opts pool-opts}))
+
       (cond
         (identical? pool-opts :none) (->NonPooledConnectionPool)
         ;; Pass through pre-made pools (note that test reflects):


Log CQL query

Log CQL query

--- src/whisper2cyanite/metric_store.clj
+++ src/whisper2cyanite/metric_store.clj
@@ -105,9 +105,10 @@
       (fetch-series [this tenant rollup period path from to file]
         (try
           (swap! stats-processed inc)
-          (let [series (atom {})]
-            (let [rows (.execute session (format fetch-cql tenant rollup period
-                                                 path from to))
+          (let [series (atom {})
+                cql (format fetch-cql tenant rollup period path from to)]
+            (log/debug "Fetch series CQL:" cql)
+            (let [rows (.execute session cql)
                   first-row (.one rows)]
               (when first-row
                 (loop [row first-row]


Add 10 days to test claim expiration

Add 10 days to test claim expiration

--- src/obb_api/core/auth.clj
+++ src/obb_api/core/auth.clj
@@ -10,7 +10,7 @@
   "Build a claim to sign"
   [user]
   {:iss user
-   :exp (plus (now) (days -1))
+   :exp (plus (now) (days 10))
    :iat (now)})

 (defn token-for


sleep before re-fetching

sleep before re-fetching

--- src/onyx/plugin/kafka.clj
+++ src/onyx/plugin/kafka.clj
@@ -103,9 +103,10 @@
             (loop [ms (kc/messages consumer "onyx" topic kpartition offset fetch-size)
                    head-offset offset]
               (if-not (seq ms)
-                (let [fetched (kc/messages consumer "onyx" topic kpartition head-offset fetch-size)]
+                (do
                   (Thread/sleep empty-read-back-off)
-                  (recur fetched head-offset))
+                  (let [fetched (kc/messages consumer "onyx" topic kpartition head-offset fetch-size)]
+                    (recur fetched head-offset)))
                 (let [message ^KafkaMessage (first ms)
                       next-offset ^int (.offset message)]
                   (>!! ch (assoc (t/input (java.util.UUID/randomUUID)


update length-of-longest-string to deal with empty/nil arg

--- src/overtone/util/doc.clj
+++ src/overtone/util/doc.clj
@@ -17,10 +17,14 @@
       0))

 (defn length-of-longest-string
-  "Returns the length of the longest string/symbol/keyword in list l"
+  "Returns the length of the longest string/symbol/keyword in list l. Returns 0
+  if l is nil or empty"
   [l]
-  (let [longest (last (sort-by #(.length (name %)) l))]
-    (.length (name longest))))
+  (if (or (not l) (empty? l))
+    0
+    (let [longest (last (sort-by #(.length (name %)) l))]
+      (println "longest: " longest ", len: " (.length (name longest)))
+      (.length (name longest)))))

 (defn gen-padding
   "Generates a padding string starting concatting s with len times pad:


Some kv.jdbc.util cleanup. Bumping max pool size.

--- src/poky/kv/jdbc/util.clj
+++ src/poky/kv/jdbc/util.clj
@@ -1,7 +1,9 @@
 (ns poky.kv.jdbc.util
   (:import com.mchange.v2.c3p0.ComboPooledDataSource))

-(def ^:private default-pool-size 3)
+(def ^:private default-min-pool-size 3)
+(def ^:private default-max-pool-size 3)
+(def ^:private default-driver "org.postgresql.Driver")

 (defn create-db-spec
   ([dsn driver]
@@ -18,16 +20,17 @@
       :user user
       :password pass}))
   ([dsn]
-   (create-db-spec dsn "org.postgresql.Driver")))
+   (create-db-spec dsn default-driver)))

 (defn pool
-  [spec &{:keys [min-pool-size] :or {min-pool-size default-pool-size}}]
+  [spec &{:keys [min-pool-size] :or {min-pool-size default-min-pool-size}}]
   (let [cpds (doto (ComboPooledDataSource.)
                (.setDriverClass (:classname spec))
                (.setJdbcUrl (str "jdbc:" (:subprotocol spec) ":" (:subname spec)))
                (.setUser (:user spec))
                (.setPassword (:password spec))
                (.setMinPoolSize min-pool-size)
+               (.setMaxPoolSize default-max-pool-size)
                (.setMaxIdleTimeExcessConnections (* 30 60))
                (.setMaxIdleTime (* 3 60 60)))]
       {:datasource cpds}))


fixing imports

fixing imports

--- src/ppl/views/account.clj
+++ src/ppl/views/account.clj
@@ -8,7 +8,7 @@
   (:require [clj-oauth2.client :as oauth2])
   (:require [ppl.auth :as ppl_auth])
   ;(:require [korma.db :refer [select]])
-  (:use [korma.core :only [select where fields, insert, values]])
+  (:use [korma.core :only [select where fields, insert, values, update, set-fields]])
   ;(:require [ppl.models :refer [users]])
   (:use [ppl.models :only [users]])
   ;(:require [korma.db]
@@ -24,7 +24,7 @@
   (seq (select users (fields :id)(where {:email email}))))

 (defn update-token [id token]
-  (if-not (seq (select users (fields :id)(where {:email email :access_token token})))
+  (if-not (seq (select users (fields :id)(where {:access_token token})))
     (update users (set-fields {:access_token token})(where {:id id}))
     )
   (id)
@@ -32,11 +32,12 @@

 (defpage "/signup/" []
-         (println "signups")
          (common/layout "Signup" :signup
            [:div.span4
             [:a {:href "/login/github"} "login with github"]]))

+(defpage "/login/" []
+         (common/layout "Login" :login))
 (defpage "/login/github" []
          (redirect (:uri ppl_auth/auth-req)))

@@ -46,11 +47,11 @@
            (let [guser (ppl_auth/github-user token)]
              ;new user? create and login
              ;
-            (def current-user (check-user (get guser "email")))
+            (let [current-user (check-user (get guser "email"))]
             (ppl_auth/login-user (if current-user
               (update-token current-user token)
               (insert users (values (create-user guser token)))
-            ))))
+            )))))
          (redirect "/home")

            ;login said user
@@ -61,4 +62,6 @@
 (defpage "/details" []
          (ppl_auth/github-user-email (session/get :github-token)))

-(defpage "/profile" [])
+(defpage "/profile" []
+  (when-not (ppl_auth/logged-in?)
+    (redirect "/login")))


clean up block sync test setup

clean up block sync test setup

--- test/block_chain/block_sync_test.clj
+++ test/block_chain/block_sync_test.clj
@@ -15,15 +15,14 @@
 (def our-db (atom nil))

 (defn setup [tests]
-  (reset! peer-db (db/make-db (str "/tmp/" (th/dashed-ns-name) "-peer")))
-  (reset! our-db (db/make-db (str "/tmp/" (th/dashed-ns-name) "-us")))
-  (q/add-block! peer-db db/genesis-block)
-  (q/add-block! our-db db/genesis-block)
-  (dotimes [_ 6] (miner/mine-and-commit-db! peer-db))
-  (try
-    (tests)
-    (finally
-      (th/close-conns! @peer-db @our-db))))
+  (with-open [our-conn (th/temp-db-conn)
+              peer-conn (th/temp-db-conn)]
+    (reset! peer-db (db/db-map peer-conn))
+    (reset! our-db (db/db-map our-conn))
+    (q/add-block! peer-db db/genesis-block)
+    (q/add-block! our-db db/genesis-block)
+    (dotimes [_ 6] (miner/mine-and-commit-db! peer-db))
+    (tests)))

 (use-fixtures :once setup)


update works

update works

--- test/celestial/integration/hooks.clj
+++ test/celestial/integration/hooks.clj
@@ -27,4 +27,5 @@
       (set-user {:username "admin"}
         (s/update-system 1 (merge-with merge (s/get-system 1) machine))
         (update-dns create) => "host added"
+        (update-dns reload) => "host updated"
         (remove-host delete) => "host removed"))))


Small addition to service_test.clj

Small addition to service_test.clj

--- test/clj/elephantdb/service_test.clj
+++ test/clj/elephantdb/service_test.clj
@@ -375,6 +375,11 @@
           (is (= (thrift/status-loading?
                   (.getDomainStatus handler "domain2"))))

+          (is (= (thrift/status-ready?
+                  (.getDomainStatus handler "domain1"))))
+          (is (= (thrift/status-ready?
+                  (.getDomainStatus handler "domain2"))))
+
           ;; wait a second
           (Thread/sleep 1000)


don't put! resmsg if out-ch is nil

don't put! resmsg if out-ch is nil

--- src/cljc/ow/starbuck/impl/core_async.cljc
+++ src/cljc/ow/starbuck/impl/core_async.cljc
@@ -69,7 +69,8 @@
 (defn component [name in-ch out-ch process-fn]
   (component* name in-ch process-fn
               (fn [this resmsg]
-                (a/put! out-ch resmsg))))
+                (when out-ch
+                  (a/put! out-ch resmsg)))))

 (defn echo-component [name in-ch out-ch]
   (component name in-ch out-ch


small fix

small fix

--- src/cljs/salava/badge/ui/endorsement.cljs
+++ src/cljs/salava/badge/ui/endorsement.cljs
@@ -241,7 +241,7 @@

 (defn endorsement-text [state]
   (let [user-endorsement (->> @(cursor state [:user-badge-endorsements])
-                              (filter #(= (:endorser-id @state) (:endorser_id %))))]
+                              (filter #(= (:endorser-id @state) (:issuer_id %))))]
     (if (seq user-endorsement)
       (case  (->> user-endorsement first :status)
         "accepted" [:span.label.label-success (t :badge/Youendorsebadge)]


Adding equator crossing longitude parameter converter to fix CI.

--- src/cmr/search/services/query_service.clj
+++ src/cmr/search/services/query_service.clj
@@ -21,6 +21,7 @@
             [cmr.search.services.parameter-converters.temporal]
             [cmr.search.services.parameter-converters.attribute]
             [cmr.search.services.parameter-converters.orbit-number]
+            [cmr.search.services.parameter-converters.equator-crossing-longitude]

             ;; Validation
             [cmr.search.validators.validation :as v]


fix namespaces

fix namespaces

--- test/infinitelives/utils/vec2_test.cljs
+++ test/infinitelives/utils/vec2_test.cljs
@@ -20,20 +20,20 @@
          (= (aget v3 1) 0)))))

 (deftest magnitude
-  (let [v (vec/vec2 on-root-2 on-root-2)]
-    (is (< 0.9999999 (vec/magnitude v) 1.0000001))
-    (is (< 0.9999999 (vec/magnitude v) 1.0000001)))
-  (let [v (vec/vec2 10 -10)]
-    (is (= (Math/sqrt 200) (vec/magnitude v)))
-    (is (= 200 (vec/magnitude-squared v)))))
+  (let [v (vec2/vec2 on-root-2 on-root-2)]
+    (is (< 0.9999999 (vec2/magnitude v) 1.0000001))
+    (is (< 0.9999999 (vec2/magnitude v) 1.0000001)))
+  (let [v (vec2/vec2 10 -10)]
+    (is (= (Math/sqrt 200) (vec2/magnitude v)))
+    (is (= 200 (vec2/magnitude-squared v)))))

 (deftest distance
-  (let [v0 (vec/vec2 20 10)
-        v1 (vec/vec2 -20 10)]
-    (is (= 40 (vec/distance v0 v1)))
-    (is (= 1600 (vec/distance-squared v0 v1)))))
+  (let [v0 (vec2/vec2 20 10)
+        v1 (vec2/vec2 -20 10)]
+    (is (= 40 (vec2/distance v0 v1)))
+    (is (= 1600 (vec2/distance-squared v0 v1)))))

 (deftest equals
-  (is (vec/equals
-       (vec/vec2 100 -200)
-       (vec/vec2 100 -200))))
+  (is (vec2/equals
+       (vec2/vec2 100 -200)
+       (vec2/vec2 100 -200))))


Organising tests

Organising tests

--- test/silly_image_store/handler_test.clj
+++ test/silly_image_store/handler_test.clj
@@ -7,51 +7,53 @@
 (def do-get #(app (mock/request :get %)))

 (deftest test-app
-  (testing "root route"
-    (let [response (do-get "/")
-          json-body (json/read-str (:body response))]
-        (is (= (:status response) 200))
-        (is (= json-body {"images" "http://localhost/images",
-                          "buckets" "http://localhost/buckets",
-                          "random" "http://localhost/random"}))))
+  (testing "root links"
+    (testing "from base"
+      (let [response (do-get "/")
+            json-body (json/read-str (:body response))]
+          (is (= (:status response) 200))
+          (is (= json-body {"images" "http://localhost/images",
+                            "buckets" "http://localhost/buckets",
+                            "random" "http://localhost/random"}))))

-  (testing "bucket root route"
-    (let [response (do-get "/buckets/some-bucket")
-          json-body (json/read-str (:body response))]
-        (is (= (:status response) 200))
-        (is (= json-body {"images" "http://localhost/buckets/some-bucket/images",
-                          "random" "http://localhost/buckets/some-bucket/random"}))))
+    (testing "from bucket"
+      (let [response (do-get "/buckets/some-bucket")
+            json-body (json/read-str (:body response))]
+          (is (= (:status response) 200))
+          (is (= json-body {"images" "http://localhost/buckets/some-bucket/images",
+                            "random" "http://localhost/buckets/some-bucket/random"})))))

   (testing "view image route"
-    (testing "serve image"
+    (testing "from base"
       (let [response (do-get "/images/tubes.jpg")
             body (:body response)]
         (is (= (:status response) 200))
         (is (= (class body) java.io.File))
         (is (= (.getPath body) "test/fixtures/tubes.jpg"))))

-    (testing "serve image from bucket"
+    (testing "from bucket"
       (let [response (do-get "/buckets/some-bucket/images/boxes.jpg")
             body (:body response)]
         (is (= (:status response) 200))
         (is (= (class body) java.io.File))
         (is (= (.getPath body) "test/fixtures/some-bucket/boxes.jpg")))))

-  (testing "serve random image"
-    (let [response (do-get "/random")
-          body (:body response)]
-      (is (= (:status response) 200))
-      (is (= (class body) java.io.File))))
+  (testing "random image"
+     (testing "from base"
+      (let [response (do-get "/random")
+            body (:body response)]
+        (is (= (:status response) 200))
+        (is (= (class body) java.io.File))))

-  (testing "serve random image from bucket"
-    (let [response (do-get "/buckets/some-bucket/random")
-          body (:body response)]
-      (is (= (:status response) 200))
-      (is (= (class body) java.io.File))))
+    (testing "from bucket"
+      (let [response (do-get "/buckets/some-bucket/random")
+            body (:body response)]
+        (is (= (:status response) 200))
+        (is (= (class body) java.io.File)))))

   (testing "listing images"
-    (testing "images from base dir as json"
+    (testing "from base as json"
       (let [response (do-get "/images")
             json-body (json/read-str (:body response))]
         (is (= (:status response) 200))
@@ -61,7 +63,7 @@
                 {"name" "tubes.jpg",
                  "url" "http://localhost/images/tubes.jpg"}]))))

-    (testing "images from bucket as json"
+    (testing "from bucket as json"
       (let [response (do-get "/buckets/some-bucket/images")
             json-body (json/read-str (:body response))]
         (is (= (:status response) 200))


Fix unit test sensitive to subtle timing

--- test/taoensso/carmine/tests/main.clj
+++ test/taoensso/carmine/tests/main.clj
@@ -74,8 +74,8 @@
   (expect ["Tom"] (wcar* (car/lrange k 0 -1))))

 (let [k (tkey "spanish")]
-  (expect "OK" (wcar* (car/set k "year->año")))
-  (expect "year->año" (wcar* (car/get k))))
+  (expect ["OK" "year->año"] (wcar* (car/set k "year->año")
+                                    (car/get k))))

 (let [k (tkey "str-field")]
   (expect Exception (do (wcar* (car/set k "str-value"))


remove old initialize call

remove old initialize call

--- src/vip/data_processor.clj
+++ src/vip/data_processor.clj
@@ -112,7 +112,6 @@
 (defn -main [& args]
   (let [id (java.util.UUID/randomUUID)]
     (log/info "VIP Data Processor starting up. ID:" id)
-    (q/initialize)
     (psql/initialize)
     (let [consumer-id (consume)]
       (.addShutdownHook (Runtime/getRuntime)


inject io functions

inject io functions

--- src/yorck_ratings/core.clj
+++ src/yorck_ratings/core.clj
@@ -74,12 +74,18 @@
        (yorck-titles yorck-page)
        (yorck-urls yorck-page)))

-(defn fetch-yorck-infos []
-  (async/go
-    (let [yorck-page (async/<! (get-async (str yorck-base-url "/filme?filter_today=true")))]
-      (->> yorck-page
-           (yorck-titles-urls)
-           (remove-sneak-preview)))))
+(defn- get-yorck-page-async []
+  (get-async (str yorck-base-url "/filme?filter_today=true")))
+
+(defn yorck-infos
+  ([result-chan] (yorck-infos result-chan get-yorck-page-async))
+  ([result-chan get-page-fn]
+   (async/go
+     (let [yorck-page (async/<! (get-page-fn))]
+       (async/>! result-chan (->> yorck-page
+             (yorck-titles-urls)
+             (remove-sneak-preview))))
+     (async/close! result-chan))))

 (defn imdb-title [search-page]
   (->> search-page
@@ -139,43 +145,52 @@
   {:rating       (imdb-rating detail-page)
    :rating-count (imdb-rating-count detail-page)})

-(defn- fetch-imdb-detail [rated-movie result-chan]
-  (async/go
-    (let [detail-page (async/<! (get-async (:imdb-url rated-movie)))
-          updated (merge rated-movie (imdb-detail-infos detail-page))]
-      (async/>! result-chan updated)
-      (async/close! result-chan))))
+(defn imdb-detail
+  ([rated-movie result-chan] (imdb-detail rated-movie result-chan get-async))
+  ([rated-movie result-chan get-page-fn]
+   (async/go
+     (let [detail-page (async/<! (get-page-fn (:imdb-url rated-movie)))
+           updated (merge rated-movie (imdb-detail-infos detail-page))]
+       (async/>! result-chan updated))
+     (async/close! result-chan))))

 (defn imdb-search-infos [search-page]
   {:imdb-title (imdb-title search-page)
    :imdb-url   (imdb-url search-page)})

-(defn fetch-imdb-search [rated-movie result-chan]
-  (async/go
-    (let [title (:yorck-title rated-movie)
-          enc-title (URLEncoder/encode title "UTF-8")
-          url (str imdb-base-url "/find?q=" enc-title)
-          search-page (async/<! (get-async url))
-          updated (merge rated-movie (imdb-search-infos search-page))]
-      (async/>! result-chan updated)
-      (async/close! result-chan))))
+(defn- get-search-page [title]
+  (let [enc-title (URLEncoder/encode title "UTF-8")
+        url (str imdb-base-url "/find?q=" enc-title)]
+    (async/go (async/<! (get-async url)))))
+
+(defn imdb-search
+  ([rated-movie result-chan] (imdb-search rated-movie result-chan get-search-page))
+  ([rated-movie result-chan get-search-page-fn]
+   (async/go
+     (let [search-page (async/<! (get-search-page-fn (:yorck-title rated-movie)))
+           updated (merge rated-movie (imdb-search-infos search-page))]
+       (async/>! result-chan updated))
+     (async/close! result-chan))))

 (defn- sort-by-rating [movies]
   (reverse (sort-by :rating movies)))

 (defn rated-movies [callback]
   (let [yorck-infos-chan (async/chan)
+        yorck-infos-split-chan (async/chan)
         imdb-search-chan (async/chan)
         imdb-detail-chan (async/chan)]

+    (yorck-infos yorck-infos-chan)
+
     (async/go
-      (let [yorck-infos (async/<! (fetch-yorck-infos))]
+      (let [yorck-infos (async/<! yorck-infos-chan)]
         (doseq [yorck-info yorck-infos]
-          (async/>! yorck-infos-chan yorck-info))
-        (async/close! yorck-infos-chan)))
+          (async/>! yorck-infos-split-chan yorck-info))
+        (async/close! yorck-infos-split-chan)))

-    (async/pipeline-async 1 imdb-search-chan fetch-imdb-search yorck-infos-chan)
-    (async/pipeline-async 1 imdb-detail-chan fetch-imdb-detail imdb-search-chan)
+    (async/pipeline-async 8 imdb-search-chan imdb-search yorck-infos-split-chan)
+    (async/pipeline-async 8 imdb-detail-chan imdb-detail imdb-search-chan)

     (async/go-loop [movies []]
       (if-let [movie (async/<! imdb-detail-chan)]


fix *print-fn* error

fix *print-fn* error

--- src-cljs/cljsbuild_ui/core.cljs
+++ src-cljs/cljsbuild_ui/core.cljs
@@ -5,6 +5,8 @@
     [cljsbuild-ui.pages.main]
     [cljsbuild-ui.util :refer [log js-log on-windows? uuid path-join]]
     [cljsbuild-ui.cljsbuild.config :refer [extract-options]]))
+
+(enable-console-print!)

 (def fs (js/require "fs"))
 (def ipc (js/require "ipc"))


Lint fixes

Lint fixes

--- test/toucan/test_models/category.clj
+++ test/toucan/test_models/category.clj
@@ -48,8 +48,8 @@
 (defn add-category-to-updated-queue! [{:keys [id]}]
   (swap! categories-recently-updated conj id))

-(models/defmodel Category :categories
-  models/IModel
+(extend-protocol models/IModel
+  (class Category)
   (types [_]
     {:name :lowercase-string})
   (pre-insert [this]


friendly keep-alive thread handling

friendly keep-alive thread handling

--- src/de/otto/tesla/stateful/keep_alive.clj
+++ src/de/otto/tesla/stateful/keep_alive.clj
@@ -1,13 +1,18 @@
 (ns de.otto.tesla.stateful.keep-alive
-  "This component is responsible for keeping the system alive."
+  "This component is responsible for keeping the system alive by creating a non-deamonized noop thread."
   (:require [clojure.tools.logging :as log]
             [com.stuartsierra.component :as component]))

-(defn do-nothing []
-  (while true (Thread/sleep 60000)))
+(defn do-nothing [running?]
+  (while @running?
+    (try
+      (Thread/sleep 60000)
+      (catch InterruptedException i
+        (log/debug "keepalive thread sleep interrupted!"))
+      (catch Exception e (throw e)))))

-(defn keep-alive []
-  (let [thread (Thread. do-nothing)]
+(defn keep-alive [running?]
+  (let [thread (Thread. (partial do-nothing running?) "keepalive")]
     (.start thread)
     thread))

@@ -15,11 +20,21 @@
   component/Lifecycle
   (start [self]
     (log/info "-> starting keepalive thread.")
-    (assoc self :thread (keep-alive)))
+    (let [running? (atom true)]
+      (assoc self
+        :running? running?
+        :thread (keep-alive running?))))

   (stop [self]
     (log/info "<- stopping keepalive thread.")
-    (.stop (:thread self))
+    (try
+      (when-let [running? (:running? self)]
+        (reset! running? false)
+        (.interrupt (:thread self)))                        ;; try the "not-so-unfriendly"-method first.
+      (Thread/sleep 1000)
+      (.stop (:thread self))                                ;; and finally kill it.
+      (catch Exception e
+        (log/debug e "Error stopping keepalive thread.")))
     self))

 (defn new-keep-alive [] (map->KeepAlive {}))


Don't try to determine new thread when creating message

We can just assert the thread-id and group regardless, using tempid in
either case; if the thread already exists, the tempid will resolve to
the :db/id of the extant thread.

--- src/braid/server/db/message.clj
+++ src/braid/server/db/message.clj
@@ -16,17 +16,11 @@

   ; upsert-thread
   (let [msg-id (d/tempid :entities)
-        new-thread? (nil? (d/entity (db/db) [:thread/id thread-id]))
-        thread (if new-thread?
-                    (d/tempid :entities)
-                    [:thread/id thread-id])]
+        thread (d/tempid :entities)]
     (concat
-      (if new-thread?
-        ; maybe create new thread
-        [{:db/id thread
-          :thread/id thread-id
-          :thread/group [:group/id group-id]}]
-        [])
+      [{:db/id thread
+        :thread/id thread-id
+        :thread/group [:group/id group-id]}]
       [; create message
        ^{:braid.server.db/return
          (fn [{:keys [db-after tempids]}]
@@ -61,9 +55,7 @@
            [:db/add [:user/id user-id] :user/open-thread thread]])
         mentioned-user-ids)
       ; open thread for users already subscribed to thread
-      (if new-thread?
-        []
-        (map
-          (fn [user-id]
-            [:db/add [:user/id user-id] :user/open-thread thread])
-          (thread/users-subscribed-to-thread thread-id))))))
+      (map
+        (fn [user-id]
+          [:db/add [:user/id user-id] :user/open-thread thread])
+        (thread/users-subscribed-to-thread thread-id)))))


Minor documentation tweak.

Minor documentation tweak.

--- src/clj/freefrog/governance.clj
+++ src/clj/freefrog/governance.clj
@@ -116,7 +116,7 @@
        (assoc-if :accountabilities accountabilities))))

 (defn create-circle
-  "Create a new circle."
+  "Create a new circle with no parent."
   [name]
   (validate-not (empty? name) "Name may not be empty")
   (convert-to-circle (make-role name)))


[REFACTOR] Use `def` for `Exhibit3_Initialized` and `Exhibit3_Loaded`

instead of using JavaScript global variables. This also saves up on some
redundant initialization code.

Signed-off-by: Pang Yan Han <22594c345857f664c61cd411f607c4d40a9d4af9@gmail.com>

--- src/cljs/cljs_nusmods/main.cljs
+++ src/cljs/cljs_nusmods/main.cljs
@@ -8,6 +8,15 @@
             [cljs-nusmods.select2               :as select2]
             [cljs-nusmods.time                  :as time-helper]
             [cljs-nusmods.timetable             :as timetable]))
+
+(def ^{:doc     "Whether the Exhibit3 library has been downloaded"
+       :private true}
+  EXHIBIT3-LOADED? false)
+
+(def ^{:doc     "Whether the Exhibit3 stuff on the Module Finder page has been
+                 initialized"
+       :private true}
+  EXHIBIT3-INITIALIZED? false)

 (defn- getScript
   "Wrapper for $.getScript"
@@ -231,7 +240,7 @@
   "Click event handler for the `Timetable Builder` tab"
   []
   ; Clear the interval when user switches to `Timetable Builder` page
-  (if (and (not (aget js/window "Exhibit3_Initialized"))
+  (if (and (not EXHIBIT3-INITIALIZED?)
            (not (nil? INITIALIZE-EXHIBIT3-INTERVAL-VAL)))
       (do
         (js/clearInterval INITIALIZE-EXHIBIT3-INTERVAL-VAL)
@@ -246,12 +255,12 @@

 (defn- initialize-exhibit3 [MODULES AUXMODULES]
   "Initialize Exhibit3 database and UI for Module Finder page"
-  (if (and (not (aget js/window "Exhibit3_Initialized"))
-           (aget js/window "Exhibit3_Loaded")
+  (if (and (not EXHIBIT3-INITIALIZED?)
+           EXHIBIT3-LOADED?
            MODULE-FINDER-SCRIPTS-DLED?
            (= (aget js/window "ActiveTab") MODULEFINDER-TAB-INDEX))
     (let [$timetable-builder-tab-link ($ :#timetable-builder-tab-link)]
-      (aset js/window "Exhibit3_Initialized" true)
+      (set! EXHIBIT3-INITIALIZED? true)
       ; Unbind the click event handler for `Timetable Builder` tab link so
       ; the user cannot switch tabs when we are initializing Exhibit3 here and
       ; screw things up
@@ -381,7 +390,7 @@
   (.log js/console "In `check-and-initialize-exhibit3`")
   (.log js/console (str "INITIALIZE-EXHIBIT3-INTERVAL-VAL = "
                         INITIALIZE-EXHIBIT3-INTERVAL-VAL))
-  (if (aget js/window "Exhibit3_Initialized")
+  (if EXHIBIT3-INITIALIZED?
       (do
         (.log js/console "Exhibit3 initialized, clearing interval")
         (js/clearInterval INITIALIZE-EXHIBIT3-INTERVAL-VAL)
@@ -405,8 +414,6 @@
         (.on js/Pace "done" (fn []
                               (fade-out ($ ".overlay"))))

-        (aset js/window "Exhibit3_Initialized" false)
-        (aset js/window "Exhibit3_Loaded" false)
         (aset js/window "ActiveTab" TIMETABLE-TAB-INDEX)
         (aset js/window "ModulesMap" (build-timetable-module-map MODULES))

@@ -437,8 +444,7 @@
                       (.toggleClass $timetable cssClass)))))

         (one $document "scriptsLoaded.exhibit"
-             (fn []
-               (aset js/window "Exhibit3_Loaded" true)))
+             #(set! EXHIBIT3-LOADED? true))

         ; Code for tabs
         (hide ($ :#module-finder))
@@ -454,7 +460,7 @@
                                                   ($ (resolve deferred nil)))))
                               (fn []
                                 (set! MODULE-FINDER-SCRIPTS-DLED? true)))))
-                  (if (and (not (aget js/window "Exhibit3_Initialized"))
+                  (if (and (not EXHIBIT3-INITIALIZED?)
                            (nil? INITIALIZE-EXHIBIT3-INTERVAL-VAL))
                     (set! INITIALIZE-EXHIBIT3-INTERVAL-VAL
                           (js/setInterval check-and-initialize-exhibit3 1000)))


Add an img-component for using Waypoints with React

--- src/cljs/comic_reader/main.cljs
+++ src/cljs/comic_reader/main.cljs
@@ -54,19 +54,37 @@
                                               :page 1}))))
                     comic-list)])))))

+(defn img-component [site
+                     {:keys [comic chapter page]}
+                     img-tag]
+  (let [waypoint (clojure.core/atom nil)]
+    (reagent/create-class
+     {:component-did-mount
+      (fn [this]
+        (let [wp (js/Waypoint.
+                  #js {:element (reagent/dom-node this)
+                       :offset "bottom-in-view"
+                       :handler #(r/go-to
+                                  (r/read-path
+                                   {:site site
+                                    :comic comic
+                                    :chapter chapter
+                                    :page page}))})]
+          (reset! waypoint wp)))
+      :reagent-render
+      (fn [img-tag]
+        img-tag)})))
+
 (defn reader []
   (let [site       (rf/subscribe [:site])
         location   (rf/subscribe [:location])
-        url-list   (rf/subscribe [:url-list])
         comic-imgs (rf/subscribe [:comic-imgs])]
     (fn []
       (let [site       @site
             location   @location
-            url-list   @url-list
             comic-imgs @comic-imgs]
         (when (and site
-                   location
-                   url-list)
+                   location)
           [:div
            [:h2 (str "Display chapter " (:chapter location)
                      " page " (:page location)
@@ -74,7 +92,9 @@
                      " from site " site)]
            [:br]
            (when comic-imgs
-             (into [:div] comic-imgs))])))))
+             (into [:div]
+                   (map (partial img-component site location)
+                        comic-imgs)))])))))

 (defn comic-reader []
   (let [page (rf/subscribe [:page])]


Use ":use" instead of ":require"

Use ":use" instead of ":require"

--- src/cljs/funnel_front/core.cljs
+++ src/cljs/funnel_front/core.cljs
@@ -1,12 +1,13 @@
 (ns funnel-front.core
   (:require [om.core :as om :include-macros true]
-            [om.dom :as dom :include-macros true]
-            [funnel-front.components.home.main :as home]
-            [funnel-front.stores.main-store :as store]))
+            [om.dom :as dom :include-macros true])
+
+  (:use [funnel-front.components.home.main :only [main-comp]]
+        [funnel-front.stores.main-store :only [app-state]]))

 (enable-console-print!)

 (om/root
-  home/main-comp
-  store/app-state
+  main-comp
+  app-state
   {:target (. js/document (getElementById "app"))})


Fix code style

Fix code style

--- src/cljs/lambdacd/pipeline.cljs
+++ src/cljs/lambdacd/pipeline.cljs
@@ -24,7 +24,7 @@
 (defn is-being-killed? [{result :result}]
   (and
     (:received-kill result)
-    (not (= "killed" (:status result)))))
+    (not= "killed" (:status result))))

 (defn has-dependencies [step]
   (:has-dependencies step))


Refactor the code to use data instead of code to define default event-handling protocols.

--- src/cljs/om_event_bus/core.cljs
+++ src/cljs/om_event_bus/core.cljs
@@ -37,6 +37,14 @@
   Use it in your component to override event bus options. Return an option hash to be merged into `default-config`."
   (init-event-bus [_]))

+(def default-protocols
+  {::all #(when (satisfies? IGotEvent %)
+           got-event)
+   ::bubbling #(when (satisfies? IGotBubblingEvent %)
+                got-bubbling-event)
+   ::trickling #(when (satisfies? IGotTricklingEvent %)
+                got-trickling-event)})
+
 ;; Here are the configuration options you can use along with their default values:
 ;;
 ;; * `:xform` - this optional xform will be applied to all passing through the component, e.g.
@@ -65,7 +73,8 @@
            options
            out-event-ch
            {::bubbling (impl/event-bus (impl/bubbling-router))
-            ::trickling (impl/event-bus (impl/trickling-router))})))
+            ::trickling (impl/event-bus (impl/trickling-router))}
+           default-protocols)))

 (defn root>
   "Use `root>` instead of om.core/root to add support for sending events from child components to parent components only.
@@ -80,7 +89,8 @@
            value
            options
            out-event-ch
-           {::bubbling (impl/event-bus (impl/bubbling-router))})))
+           {::bubbling (impl/event-bus (impl/bubbling-router))}
+           default-protocols)))

 (defn root<
   "Use `root>` instead of om.core/root to add support for sending events from parent components to child components only."
@@ -89,7 +99,8 @@
            value
            options
            nil
-           {::trickling (impl/event-bus (impl/trickling-router))})))
+           {::trickling (impl/event-bus (impl/trickling-router))}
+           default-protocols)))

 ; =============================================================================
 ;; ### Triggering events.
@@ -133,10 +144,10 @@
   and tear down the event bus for a component and to bind `*parent*` to be used in the `:instrument` function.

   3. It passes the custom descriptor to `om.core/build*`."
-  [f value options out-event-ch event-buses]
+  [f value options out-event-ch event-buses protocols]
   (let [descriptor (d/make-descriptor {:componentWillMount
                                        (fn [this super]
-                                         (init-event-bus! this)
+                                         (init-event-bus! this protocols)
                                          (super))
                                        :componentWillUnmount
                                        (fn [this super]
@@ -186,18 +197,18 @@

    This mult/tap magic happens only if the component reifies the `IGotEvent` protocol and, to some
    extend, for `IInitEventBus` protocol as well. For components that don't care about events, overhead is minimal."
-  [this]
+  [this protocols]
   (let [c (om/children this)
         {:keys [xform buf-or-n]} (merge default-config
                                         (when (satisfies? IInitEventBus c)
                                           (init-event-bus c)))
-        catch-all-handler (find-handler c ::all)]
+        catch-all-handler (find-handler c ::all protocols)]
     (impl/with-options {:buf-or-n buf-or-n}
                        (om/set-state! this
                                       ::event-buses
                                       (into {}
                                             (for [[k bus] (om/get-state this ::event-buses)]
-                                              (let [handler (compose-handlers catch-all-handler (find-handler c k))]
+                                              (let [handler (compose-handlers catch-all-handler (find-handler c k protocols))]
                                                 [k (if handler
                                                      (impl/add-fork bus handler xform)
                                                      (impl/add-leg bus xform))])))))))
@@ -210,17 +221,9 @@
         (f event)))))

 (defn- find-handler
-  [component bus-key]
-  ; Protocols are hard-coded because satisfies? in ClojureScript is a macro and requires a protocol name as an argument
-  ; and passing a var doesn't work.
-  (case bus-key
-    ::all  (when (satisfies? IGotEvent component)
-             (partial got-event component))
-    ::bubbling (when (satisfies? IGotBubblingEvent component)
-                 (partial got-bubbling-event component))
-    ::trickling (when (satisfies? IGotTricklingEvent component)
-                  (partial got-trickling-event component))
-    nil))
+  [component bus-key protocols]
+  (when-let [handler-fn ((bus-key protocols) component)]
+    (partial handler-fn component)))

 (defn- shutdown-event-bus!
   "This function mainly shuts down event bus for this component.


Support cljc files

Support cljc files

--- src/clojure/nightcode/utils.clj
+++ src/clojure/nightcode/utils.clj
@@ -71,7 +71,7 @@

 ; paths and encodings

-(def ^:const clojure-exts #{"clj" "cljs" "cljx" "edn"})
+(def ^:const clojure-exts #{"clj" "cljc" "cljs" "cljx" "edn"})
 (def ^:const wrap-exts #{"md" "txt"})
 (def styles {"as"         SyntaxConstants/SYNTAX_STYLE_ACTIONSCRIPT
              "asm"        SyntaxConstants/SYNTAX_STYLE_ASSEMBLER_X86
@@ -82,6 +82,7 @@
              "cpp"        SyntaxConstants/SYNTAX_STYLE_CPLUSPLUS
              "css"        SyntaxConstants/SYNTAX_STYLE_CSS
              "clj"        SyntaxConstants/SYNTAX_STYLE_CLOJURE
+             "cljc"       SyntaxConstants/SYNTAX_STYLE_CLOJURE
              "cljs"       SyntaxConstants/SYNTAX_STYLE_CLOJURE
              "cljx"       SyntaxConstants/SYNTAX_STYLE_CLOJURE
              "cs"         SyntaxConstants/SYNTAX_STYLE_CSHARP


remove redundant parenthesis

remove redundant parenthesis

--- src/clojure_web_app/handler.clj
+++ src/clojure_web_app/handler.clj
@@ -20,7 +20,7 @@
 ;; define the ring application
 (def app
   (-> (handler/api app-routes)
-      (wrap-json-body)
-      (wrap-json-params)
-      (wrap-json-response)))
+      wrap-json-body
+      wrap-json-params
+      wrap-json-response))


Remove openjdk dependencies for more flexibility

This came up when using the opscode-cookbooks/java cookbook. If you install the oracle flavor, which installs via tarballs, the riemann deb will install but will break apt-get for everything else. It won't let you install anything else because riemann doesn't have openjdk like it expects.

I vote that we remove java as a strict dependency to sidestep this problem.

--- tasks/leiningen/fatdeb.clj
+++ tasks/leiningen/fatdeb.clj
@@ -50,7 +50,7 @@
               :section "base"
               :priority "optional"
               :architecture "all"
-              :depends (join ", " ["bash" "default-jre-headless | java2-runtime-headless"])
+              :depends (join ", " ["bash"])
               :maintainer (:email (:maintainer project))
               :description (:description project)})))


add (default) for {:français :cat} = {:synsem :cat}


Convert window to ArrayValue before passing into chunkifier.

--- src/clj/forma/source/static.clj
+++ src/clj/forma/source/static.clj
@@ -3,6 +3,7 @@
         [forma.static :only (static-datasets)])
   (:require [cascalog.ops :as c]
             [forma.reproject :as r]
+            [forma.schema :as schema]
             [forma.hadoop.io :as io]
             [clojure.java.io :as java.io]
             [forma.hadoop.predicate :as p]))
@@ -117,10 +118,12 @@
     (<- [?datachunk]
         (src ?dataset ?s-res ?t-res !date ?mod-h ?mod-v  _ ?chunkid ?window)
         (p/flatten-window ?window :> ?chunk)
+        (schema/to-struct ?chunk :> ?struct)
+        (schema/mk-array-value ?struct :> ?arr)
         (count ?chunk :> ?count)
         (= ?count chunk-size)
         (chunkifier
-         ?dataset !date ?s-res ?t-res ?mod-h ?mod-v ?chunkid ?chunk :> ?datachunk)
+         ?dataset !date ?s-res ?t-res ?mod-h ?mod-v ?chunkid ?arr :> ?datachunk)
         (:distinct false))))

 (defn static-chunks


allow simple transactions

allow simple transactions

--- src/clj_money/serialization.clj
+++ src/clj_money/serialization.clj
@@ -163,12 +163,26 @@
                                     (map #(prepare-item context %)
                                          items))))

+(defn- expand-items
+  [transaction]
+  (if (:items transaction)
+    transaction
+    (-> transaction
+        (assoc :items [{:action :debit
+                        :amount (:amount transaction)
+                        :account-id (:debit-account transaction)}
+                       {:action :credit
+                        :amount (:amount transaction)
+                        :account-id (:credit-account transaction)}])
+        (dissoc :amount :debit-account :credit-account))))
+
 (defn- create-transactions
   [storage context transactions]
   []
   (mapv (fn [attributes]
           (transactions/create storage (-> attributes
                                            (resolve-entity context)
+                                           expand-items
                                            (prepare-items context))))
         transactions))


show pie charts of related dimensions

show pie charts of related dimensions

--- src/cljs/searchbot/parsets.cljs
+++ src/cljs/searchbot/parsets.cljs
@@ -5,7 +5,8 @@
             [sablono.core :as html :refer-macros [html]]
             [cljs.core.async :refer [put! <! >! chan timeout close!]]
             [searchbot.es :refer [es-agg filtered-agg]]
-            [searchbot.input.labels :as labels]))
+            [searchbot.input.labels :as labels]
+            [searchbot.charts :refer [es-chart]]))

 (defn- build-sub-aggs [sub-aggs]
   (if sub-aggs {:aggs sub-aggs} {}))
@@ -19,13 +20,21 @@
   [terms sub-aggs]
   (reduce (fn [agg-query a-term]
             {:aggs (merge
-                    {(keyword a-term) (merge
-                                       {:terms (merge
-                                                {:field a-term}
-                                                (sort-sub sub-aggs))}
-                                       agg-query)}
+                    {(keyword a-term)
+                     (merge {:terms
+                             (merge {:field a-term}
+                                    (sort-sub sub-aggs))}
+                            agg-query)}
                     sub-aggs)})
           (build-sub-aggs sub-aggs) terms))
+
+(defn- build-terms-agg [prefix terms sub-aggs]
+  (let [terms-aggs (for [term terms]
+                     {(str prefix (name term)) (merge {:terms (merge {:field (name term)}
+                                                                     (sort-sub sub-aggs))}
+                                                      (build-sub-aggs sub-aggs))})
+        terms-aggs (reduce merge terms-aggs)]
+    terms-aggs))

 (defn- walk-buckets [de-buck bucket prefix steps value-path]
   (map #(de-buck % de-buck prefix (first steps) (rest steps) value-path)
@@ -35,30 +44,38 @@
   (if (= 0 (count steps))
     (merge prefix {current-step (:key bucket) :value (get-in bucket value-path)})
     (let [prefix (merge prefix {current-step (:key bucket)})]
-      (walk-buckets <-buckets bucket prefix steps value-path))))
-
-(defn- agg->parsets [agg-result all-steps value-path]
-  (vec (flatten (walk-buckets <-buckets agg-result {} all-steps value-path))))
-
-(defn- new-svg [graph-id w h]
-  (-> js/d3 (.select graph-id) (.append "svg") (.attr "width" w) (.attr "height" h)))
+      (walk-buckets de-buck bucket prefix steps value-path))))
+
+(defn- agg->parsets [agg-result steps value-path]
+  (vec (flatten (walk-buckets <-buckets agg-result {} steps value-path))))

 (defn- ->query
-  [{:keys [agg-terms sub-aggs filters default-filter]}]
+  [{:keys [agg-terms sub-aggs agg-prefix-terms show-pies? filters default-filter]}]
   (let [agg-query (build-parsets-agg (reverse agg-terms) sub-aggs)
+        agg-query (if (show-pies?)
+                    {:aggs (merge (:aggs agg-query)
+                                  (build-terms-agg agg-prefix-terms agg-terms sub-aggs))}
+                    agg-query)
         agg-query (filtered-agg (merge {:body agg-query}
                                  (merge {:filter default-filter}
                                         (:combined-query filters))))]
     agg-query))

+(defn- update-terms-aggs [owner terms-aggs]
+  (om/update-state! owner :parsets-cursor #(assoc-in % [:terms-aggs :aggregations] terms-aggs)))
+
 (defn- do-parsets-agg
   [owner]
-  (let [{:keys [continue? comm url get-agg-terms make-agg-query value-path]} (om/get-state owner)
+  (let [{:keys [continue? comm url agg-prefix-terms get-agg-terms make-agg-query value-path]} (om/get-state owner)
         {es-settings :es-settings} (om/get-shared owner)]
     (when continue?
       (go (.log js/console "# running parsets aggregation:" (pr-str (get-agg-terms)))
           (let [{agg-result :aggregations} (<! (es-agg (or url (:url-agg (es-settings))) (make-agg-query)))]
-            (>! comm (agg->parsets agg-result (get-agg-terms) value-path)))))))
+            (let [term-keys (->> (get-agg-terms) (map #(->> % name (str agg-prefix-terms) keyword)))
+                  terms-aggs (-> agg-result (select-keys term-keys))]
+              (update-terms-aggs owner terms-aggs))
+            (>! comm (agg->parsets agg-result (get-agg-terms) value-path))
+            )))))

 (defn- update-agg-terms-with-label
   [owner label-string]
@@ -70,51 +87,84 @@
     (do-parsets-agg owner)
     ))

-(defn- make-parsets-chart [{:keys [height width get-parsets-agg]}]
+(defn- new-svg [{:keys [id height width-fn]}]
+  (-> js/d3 (.select id) (.append "svg") (.attr "width" (width-fn)) (.attr "height" height)))
+
+(defn- make-parsets-chart [{:keys [height width-fn get-parsets-agg]}]
   (-> js/d3
       .parsets
       (.tension 0.8)
-      (.width width)
+      (.width (width-fn))
       (.height height)
       (.dimensions (clj->js (map name (get-parsets-agg))))
       (.value (fn [d i] (. d -value)))))

 (defcomponent parsets [cursor owner {:keys [agg value-path url height] :or {height 600 value-path ["doc_count"]} :as opts}]
   (init-state [_]
-              (let [{:keys [es-settings ref-state]} (om/get-shared owner)]
+              (let [{:keys [es-settings ref-state]} (om/get-shared owner)
+                    prefix-terms "terms_"]
                 {:continue? true
                  :comm (chan)
                  :url url
-                 :parsets-agg (map keyword (:terms agg))
+                 :agg-prefix-terms prefix-terms
+                 :parsets-agg (->> agg :terms (map keyword))
                  :get-agg-terms #(:parsets-agg (om/get-state owner))
-                 :make-agg-query #(->query {:agg-terms ((:get-agg-terms (om/get-state owner)))
+                 :make-agg-query #(->query {:agg-prefix-terms prefix-terms
+                                            :agg-terms ((:get-agg-terms (om/get-state owner)))
                                             :sub-aggs (:sub agg)
+                                            :show-pies? (:show-pies? (om/get-state owner))
                                             :filters (ref-state :filters)
                                             :default-filter (get-in (es-settings) [:default :filter])})
                  :value-path (apply vector (map keyword value-path))
                  :combined-query nil
-                 :svg nil}))
+                 :svg nil
+                 :parsets-cursor (om/root-cursor (atom {:div {:width "90%" :height 200}}))
+                 :show-pies (:show-pies opts)
+                 :show-pies? #(:show-pies (om/get-state owner))}))
   (will-mount [_]
               (do-parsets-agg owner))
-  (render [_]
-          (html
-           [:.card {:ref "parsets-card"}
-            [:.card-content
-             [:div.right {:style {:max-width "50%"}}
-              (let [get-agg-terms #(:parsets-agg (om/get-state owner))
-                    label-string (->> (get-agg-terms)
-                                      (map name)
-                                      (clojure.string/join " "))]
-                (om/build labels/labels cursor
-                          {:opts {:labels (labels/labelize label-string)
-                                  :on-label-updated! (partial update-agg-terms-with-label owner)}}))]
-             [:span.card-title.black-text
-              "# PARSETS [ "
-              [:strong (->> (:parsets-agg (om/get-state owner))
-                            (map name)
-                            (clojure.string/join " > "))]
-              " ]"]
-             [:div#parsets {:ref "parsets-div"}]]]))
+  (render-state [_ {:keys [parsets-agg get-agg-terms agg-prefix-terms parsets-cursor show-pies ]}]
+                (html
+                 [:.card {:ref "parsets-card"}
+                  [:.card-content
+                   [:.row
+                    [:span.card-title.black-text "# PARSETS [ " [:strong (->> parsets-agg (map name) (clojure.string/join " > "))] " ]"]
+                    [:p
+                     [:input {:type "checkbox" :class "filled-in" :checked show-pies
+                              :id "toggle-show-pies" :ref "toggle-show-pies"
+                              :on-change (fn [_] (let [thisNode (om/get-node owner "toggle-show-pies")
+                                                       checked (.-checked thisNode)]
+                                                   (om/set-state! owner :show-pies checked)
+                                                   (do-parsets-agg owner)))}]
+                     [:label {:for "toggle-show-pies"} "Show Pie Charts"]]
+                    [:div.right {:style {:max-width "50%"}}
+                     (let [label-string (->> (get-agg-terms) (map name) (clojure.string/join " "))]
+                       (om/build labels/labels cursor
+                                 {:opts {:labels (labels/labelize label-string)
+                                         :on-label-updated! (partial update-agg-terms-with-label owner)}}))]
+                    ]
+                   [:.row
+                    [:.col {:class (if show-pies "s9" "s12") :id "parsets" :ref "parsets-div"}]
+                    [:.col {:class (if show-pies "s3" "hide")}
+                     (for [term (get-agg-terms)]
+                       (let [term-name (name term)]
+                         (om/build es-chart
+                                   parsets-cursor
+                                   {:opts {:type "es-chart"
+                                           :id (str term-name "_pie")
+                                           :agg-key "terms-aggs"
+                                           :agg-top (str agg-prefix-terms term-name)
+                                           :agg-view ["key" "sum_usage"]
+                                           :draw-fn "draw-ring"
+                                           :chart {:bounds {:x "5%" :y "15%" :width "80%" :height "80%"}
+                                                   :plot "pie"
+                                                   :p-axis "sum_usage"
+                                                   :c-axis "key"}}}
+                                   )
+                         ))
+                     ]
+                    ]]]
+                 ))
   (did-update [_ _ _]
               (if-let [filters ((:ref-state (om/get-shared owner)) :filters)]
                 (let [local-combined-query (-> (om/get-state owner) :combined-query)
@@ -127,10 +177,10 @@
   (did-mount [_]
              (let [{:keys [comm parsets-agg]} (om/get-state owner)
                    parsets-div (om/get-node owner "parsets-div")
-                   card-width (.-offsetWidth parsets-div)
-                   get-svg #(new-svg "#parsets" card-width height)
+                   card-width #(.-offsetWidth parsets-div)
+                   get-svg #(new-svg {:id "#parsets" :height height :width (card-width) :width-fn card-width})
                    chart #(make-parsets-chart
-                           {:height height :width card-width
+                           {:height height :width (card-width) :width-fn card-width
                             :get-parsets-agg (fn [_] (:parsets-agg (om/get-state owner)))})]
                (.attach js/Waves (om/get-node owner "parsets-div") "waves-yellow")
                (go (while (:continue? (om/get-state owner))


Remove maximum trace length from interp

Remove maximum trace length from interp

--- src/cljx/revue/interpreter.cljx
+++ src/cljx/revue/interpreter.cljx
@@ -298,10 +298,9 @@

 (defn interp
   ([& forms]
-     (let [result (take @*interp-steps*
-                        (take-while
-                         (fn [{:keys [form cont value]}] (or form cont value))
-                         (iterate step (apply initial-state forms))))]
+     (let [result (take-while
+                   (fn [{:keys [form cont value]}] (or form cont value))
+                   (iterate step (apply initial-state forms)))]
        result)))


Switched behaviour mgmt from macros to vanilla fns.

--- src/clojure/alfresco/behave.clj
+++ src/clojure/alfresco/behave.clj
@@ -14,32 +14,53 @@
 ; limitations under the License.

 (ns alfresco.behave
-  (:require [alfresco.core :as c]
+  (:require [alfresco.core  :as c]
             [alfresco.model :as m])
-  (:import [org.alfresco.repo.policy JavaBehaviour Behaviour$NotificationFrequency]
-           [org.alfresco.repo.node
-            NodeServicePolicies$OnAddAspectPolicy]))
+  (:import [org.alfresco.repo.policy JavaBehaviour
+                                     Behaviour$NotificationFrequency]
+           [org.alfresco.repo.node NodeServicePolicies$OnCreateNodePolicy
+                                   NodeServicePolicies$OnAddAspectPolicy]))

 ;; no static String to use here, unfortunately
 (defn policy-component
   []
   (c/get-bean "policyComponent"))

-(defmacro on-add-aspect!
-  "Registers a clojure behavior that will be called when an aspect with
-QName qname. The provided form f must accept two input parameters: a noderef and a qname"
+(defn- bind-class-behaviour!
+  [policy-qname binding-type-qname behaviour]
+  (.bindClassBehaviour (policy-component)
+                       policy-qname
+                       (m/qname binding-type-qname)
+                       behaviour)
+  nil)
+
+;####TODO: consider adding 3-arity version that receives a notification frequency (perhaps as a keyword?)
+(defn on-add-aspect!
+  "Registers the given function f as the handler for the onAddAspect policy of the given QName.
+   The function f must accept 2 parameters:
+   1. NodeRef
+   2. QName"
   [qname f]
-  `(let [p# (reify NodeServicePolicies$OnAddAspectPolicy
-                   (~'onAddAspect [~'this ~'node-in ~'qname-in]
-                     (~f ~'node-in (m/qname-str ~'qname-in))))
-         b# (JavaBehaviour. p#
-                            "onAddAspect"
-                            Behaviour$NotificationFrequency/TRANSACTION_COMMIT)]
-     (.bindClassBehaviour (policy-component)
-                         NodeServicePolicies$OnAddAspectPolicy/QNAME
-                         (m/qname ~qname)
-                         b#)))
+  (let [p (reify NodeServicePolicies$OnAddAspectPolicy
+            (onAddAspect [this node-in qname-in]
+              (f node-in (m/qname-str qname-in))))
+        b (JavaBehaviour. p
+                          "onAddAspect"
+                          Behaviour$NotificationFrequency/TRANSACTION_COMMIT)]
+    (bind-class-behaviour! NodeServicePolicies$OnAddAspectPolicy/QNAME qname b)))

-; ####TODO: add macros for other policy types and notification frequencies
+;####TODO: consider adding 3-arity version that receives a notification frequency (perhaps as a keyword?)
+(defn on-create-node!
+  "Registers the given function f as the handler for the onCreateNode policy of the given QName.
+   The function f must accept 1 parameter:
+   1. ChildAssociationRef"
+   [qname f]
+   (let [p (reify NodeServicePolicies$OnCreateNodePolicy
+             (onCreateNode [this child-assoc-ref]
+               (f child-assoc-ref)))
+         b (JavaBehaviour. p "onCreateNode" Behaviour$NotificationFrequency/TRANSACTION_COMMIT)]
+    (bind-class-behaviour! NodeServicePolicies$OnCreateNodePolicy/QNAME qname b)))
+
+; ####TODO: add fns for other policy types
 ; OR (better)
-; provide a generic macro that can handle all possible policy types and notification frequencies
+; generate the functions somewhat like https://github.com/xsc/jansi-clj/blob/master/src/jansi_clj/core.clj#L104


Add case to client/create-modification to support directly supplying bytes

For some operations, such as setting unicodePwd for an Active Directory entry,
the simplest way to provide the value of an attribute is as a byte array due to
encoding issues. As-is, when `values` is a byte array, it matches `:else` and
is processed with `str`, which is substantively incorrect.

The current behavior is particularly confusing because the underlying LDAP SDK
supports providing a byte array out of the box, and because the value that will
be written is not even an incorrectly-encoded version of `values`; it will be a
string of the form "[B@<reference>".

--- src/clojure/clj_ldap/client.clj
+++ src/clojure/clj_ldap/client.clj
@@ -215,6 +215,7 @@
   [modify-op attribute values]
   (cond
     (coll? values)    (Modification. modify-op attribute (into-array values))
+    (bytes? values)   (Modification. modify-op attribute values)
     (= :all values)   (Modification. modify-op attribute)
     :else             (Modification. modify-op attribute (str values))))


more debug for codeship

more debug for codeship

--- src/pathfinder/redis/expired_listener.clj
+++ src/pathfinder/redis/expired_listener.clj
@@ -31,6 +31,8 @@
     (car/psubscribe pattern)))

 (defstate expired-listener
-  :start (create-listener)
+  :start (do
+           (println "Startin expired-listener...")
+           (create-listener))
   :stop (when expired-listener
           (car/close-listener expired-listener)))


Improve section about Clojure's basic types.


still not working

still not working