Caches as atoms

Caches as atoms

--- src/cyanite_cache/cache.clj
+++ src/cyanite_cache/cache.clj
@@ -4,7 +4,7 @@
             [clojure.core.cache :as cache]))

 (defprotocol StoreCache
-  (push! [this tenant period rollup time path data ttl])
+  (put! [this tenant period rollup time path data ttl])
   (flush! [this]))

 (def ^:const metric-wait-time 60)
@@ -102,12 +102,14 @@
                      caches
                      (let [cache-ttl (to-ms (calc-delay rollup
                                                         cache-add-ttl))]
-                       (assoc caches rollup (cache/ttl-cache-factory
-                                             {} :ttl cache-ttl))))))
+                       (assoc caches rollup
+                              (atom (cache/ttl-cache-factory
+                                     {} :ttl cache-ttl)))))))
           (get @caches rollup))
         create-fn-get
         (fn [cache]
-          (fn [key]))
+          (fn [key]
+            (get cache key)))
         get-get-fn!
         (fn [rollup]
           (let [rollup (int rollup)]
@@ -116,12 +118,14 @@
                      (if (contains? get-fns rollup)
                        get-fns
                        (assoc get-fns rollup
-                              (create-fn-get (get-cache! rollup)))))))
+                              (create-fn-get @(get-cache! rollup)))))))
           (get @get-fns rollup))]
     (reify
       StoreCache
-      (push! [this tenant period rollup time path data ttl]
+      (put! [this tenant period rollup time path data ttl]
         (set-keys! mkeys tenant period rollup time path ttl (get-get-fn! rollup)
                    fn-agg fn-store)
-        )
-      )))
+        (swap! (get-cache! rollup)
+               (fn [cache]
+                 (assoc cache key (conj (get cache key) data)))))
+      (flush! [this]))))


Add default applet title, and applet/defapplet docstrings.

--- src/processing/core/applet.clj
+++ src/processing/core/applet.clj
@@ -58,7 +58,7 @@
                       JFrame/EXIT_ON_CLOSE
                       JFrame/DISPOSE_ON_CLOSE)]
        (reset! (:frame m)
-               (doto (JFrame. (or (:title m) (:name m)))
+               (doto (JFrame. (or (:title m) "Processing-core"))
                  (.addWindowListener  (reify WindowListener
                                         (windowActivated [this e])
                                         (windowClosing [this e]
@@ -88,9 +88,55 @@
        (.size *applet* (int width) (int height) renderer))))

 (defn applet
+  "Create and start a new visualisation applet.
+
+  :size           - a vector of width, height and optional renderer
+                    (one of :p2d, :java2d, :opengl, :pdf or :dxf). i.e.
+                    [500 300] or [400 600 :opengl].
+                    Defaults to [500 300].
+
+  :title          - a string which will be displayed at the top of
+                    the applet window.
+
+  :setup          - a fn to be called once when setting the applet up.
+
+  :draw           - a fn to be repeatedly called at most n times per
+                    second where n is the target frame-rate set for
+                    the visualisation.
+
+  :focus-gained   - Called when the applet gains focus.
+
+  :focus-lost     - Called when the applet loses focus.
+
+  :mouse-entered  - Called when the mouse enters the applet window.
+
+  :mouse-exited   - Called when the mouse leaves the applet window
+
+  :mouse-pressed  - Called every time a mouse button is pressed.
+
+  :mouse-released - Called every time a mouse button is released.
+
+  :mouse-clicked  - called once after a mouse button has been pressed
+                    and then released.
+
+  :mouse-moved    - Called every time the mouse moves and a button is
+                    not pressed.
+
+  :mouse-dragged  - Called every time the mouse moves and a button is
+                    pressed.
+
+  :key-pressed    - Called every time any key is pressed.
+
+  :key-released   - Called every time any key is released.
+
+  :key-typed      - Called once every time non-modifier keys are
+                    pressed."
+
+
+
   [& opts]
   (let [options           (merge {:size [500 300]} (apply hash-map opts))
-        fns               (dissoc options :name :title :size :key-pressed
+        fns               (dissoc options :title :size :key-pressed
                                   :key-released :key-typed :mouse-pressed
                                   :mouse-released :mouse-moved :mouse-dragged
                                   :focus-gained :focus-lost :mouse-entered
@@ -105,7 +151,7 @@
         mouse-dragged-fn  (or (:mouse-dragged options) (fn [] nil))
         mouse-entered-fn  (or (:mouse-entered options) (fn [] nil))
         mouse-exited-fn   (or (:mouse-exited options) (fn [] nil))
-        mouse-clicked-fn  (or (:mouse-exited options) (fn [] nil))
+        mouse-clicked-fn  (or (:mouse-clicked options) (fn [] nil))
         focus-gained-fn   (or (:focus-gained options) (fn [] nil))
         focus-lost-fn     (or (:focus-lost options) (fn [] nil))
         setup-fn          (fn []
@@ -225,7 +271,11 @@
     prx))

 (defmacro defapplet
-  "Define an applet. Takes an app-name and a map of options."
+  "Define and start an applet and bind it to a var with the symbol
+  app-name. If any of the options to the various callbacks are
+  symbols, it wraps them in a call to var to ensure they aren't
+  inlined and that redefinitions to the original fns are reflected in
+  the visualisation. See applet for the available options."
   [app-name & opts]
   (let [opts  (mapcat (fn [[k v]] [k (if (symbol? v) `(var ~v) v)]) (partition 2 opts))]
     `(def ~app-name (applet ~@opts))))


Use InProcessPipelineRunner in the examples

--- src/datasplash/examples.clj
+++ src/datasplash/examples.clj
@@ -218,7 +218,7 @@
   (let [p (ds/make-pipeline
            'StandardSQLOptions
            str-args
-           {:runner "DataflowPipelineRunner"})  ;; the DirectPipelineRunner doesn't support standardSql yet
+           {:runner "InProcessPipelineRunner"})
         {:keys [input output usingStandardSql]} (ds/get-pipeline-configuration p)
         query "SELECT * from `bigquery-public-data.samples.shakespeare` LIMIT 100"
         results (->> p


Fix wrap-incise to load config first.

Fix wrap-incise to load config first.

--- src/ring/middleware/incise.clj
+++ src/ring/middleware/incise.clj
@@ -51,5 +51,7 @@

 (defn wrap-incise
   [handler]
-  (-> (apply wrap-incise-parse handler)
+  (conf/load)
+  (-> handler
+      (wrap-incise-parse)
       (wrap-reset-modified-files-with-source-change)))


Stops leaking connections in CassandraDatabase functions

--- joplin.cassandra/src/joplin/cassandra/database.clj
+++ joplin.cassandra/src/joplin/cassandra/database.clj
@@ -19,8 +19,13 @@
     (catch AlreadyExistsException e)))

 (defn get-connection [hosts keyspace]
+  (cc/connect hosts keyspace))
+
+(defn with-connection [hosts keyspace f]
   (when-let [conn (cc/connect hosts keyspace)]
-    conn))
+    (try
+      (f conn)
+      (finally (cc/disconnect! conn)))))

 ;; ============================================================================
 ;; Ragtime interface
@@ -28,22 +33,28 @@
 (defrecord CassandraDatabase [hosts keyspace]
   Migratable
   (add-migration-id [db id]
-    (ensure-migration-schema (get-connection hosts keyspace))
-    (cql/insert (get-connection hosts keyspace)
-                "migrations"
-                {:id id, :created_at (java.util.Date.)}))
+    (with-connection hosts keyspace
+      (fn [conn]
+        (ensure-migration-schema conn)
+        (cql/insert conn
+                    "migrations"
+                    {:id id, :created_at (java.util.Date.)}))))
   (remove-migration-id [db id]
-    (ensure-migration-schema (get-connection hosts keyspace))
-    (cql/delete (get-connection hosts keyspace)
-                "migrations"
-                (cq/where {:id id})))
+    (with-connection hosts keyspace
+      (fn [conn]
+        (ensure-migration-schema conn)
+        (cql/delete conn
+                    "migrations"
+                    (cq/where {:id id})))))

   (applied-migration-ids [db]
-    (ensure-migration-schema (get-connection hosts keyspace))
-    (->> (cql/select (get-connection hosts keyspace)
-                     "migrations")
-         (sort-by :created_at)
-         (map :id))))
+    (with-connection hosts keyspace
+      (fn [conn]
+        (ensure-migration-schema conn)
+        (->> (cql/select conn
+                         "migrations")
+             (sort-by :created_at)
+             (map :id))))))

 (defn- ->CassDatabase [target]
   (map->CassandraDatabase (select-keys (:db target) [:hosts :keyspace])))


BUGFIX: Startpage sorting had broken after switching to second precision

https://app.asana.com/0/50978096561390/65490379643757

--- src/content/relevance/startpage.cljs
+++ src/content/relevance/startpage.cljs
@@ -51,8 +51,8 @@
           nodes
           (map #(aget % "rootItem"))
           (map-indexed #(do
-                         ;; We assign it (- 100 %1) so that the first nodes get a higher value
-                         (aset %2 "sort-order" (or (aget %2 "total-time") (- 100 %1)))
+                         ;; We assign it (- %1) so that the first nodes get a higher value
+                         (aset %2 "sort-order" (or (aget %2 "total-time") (- %1)))
                          %2))
           (sort-by #(* -1 (aget % "sort-order")))
           (map #(.appendChild base %))))


Resolve username to ENS right after 1-1 chat opened after username search from 'Start new chat' by ENS

Signed-off-by: Brian Sztamfater <760e7dab2836853c63805033e514668301fa9c47@status.im>

--- src/status_im/ui/screens/add_new/new_chat/views.cljs
+++ src/status_im/ui/screens/add_new/new_chat/views.cljs
@@ -191,7 +191,9 @@
                :subtitle (if ens-name (gfycat/generate-gfy public-key) (utils/get-shortened-address public-key))
                :icon     [chat-icon/contact-icon-contacts-tab
                           (identicon/identicon public-key)]
-               :on-press #(re-frame/dispatch [:chat.ui/start-chat public-key])}
+               :on-press #(do
+                            (debounce/dispatch-and-chill [:contact.ui/contact-code-submitted false] 3000)
+                            (re-frame/dispatch [:search/home-filter-changed nil]))}
               (when ens-name {:subtitle-secondary public-key}))]
             [quo/text {:style {:margin-horizontal 16}
                        :size  :base


Revert back tp PAMIA

Revert back tp PAMIA

The convention for most dbg-println calls is that first string arg is a label (usually an acronym) that identifies where we are in the call stack and/or what follows in the debug output.

--- src/pamela/htn.clj
+++ src/pamela/htn.clj
@@ -2622,7 +2622,7 @@
   (tpn/reinitialize-tpn-plan-map)
   (reinitialize-pclass-instances)
   (let [[pclass pargs method mi args pca] (identify-root-task ir root-task)
-        _ (dbg-println :info "PAMELA" pclass pargs "METHOD" method mi
+        _ (dbg-println :info "PAMIA" pclass pargs "METHOD" method mi
             "\n  ARGS" (with-out-str (pprint args))
             "\n  PCA" pca)
         _ (dbg-println :trace "PCLASS-INSTANCES===\n"


Refactor and docstring exclude? to clarify its logic

--- src/docker_clojure/core.clj
+++ src/docker_clojure/core.clj
@@ -60,12 +60,21 @@
     (= distro "alpine")
     (:wes maintainers)))

-(defn exclude? [exclusions variant]
-  (some (fn [exclusion]
-          (every? (fn [[k v]]
-                    (= v (get variant k)))
-                  exclusion))
-        exclusions))
+(defn contains-every-key-value?
+  "Returns true if the map `haystack` contains every key-value pair in the map
+  `needles`. `haystack` may contain additional keys that are not in `needles`.
+  Returns false if any of the keys in `needles` are missing from `haystack` or
+  have different values."
+  [haystack needles]
+  (every? (fn [[k v]]
+            (= v (get haystack k)))
+          needles))
+
+(defn exclude?
+  "Returns true if `variant` matches one of `exclusions` elements (meaning
+  `(contains-every-key-value? variant exclusion)` returns true)."
+  [exclusions variant]
+  (some (partial contains-every-key-value? variant) exclusions))

 (defn base-image->tag-component [base-image]
   (str/replace base-image ":" "-"))


:bug: Fixed performance problem

:bug: Fixed performance problem

--- frontend/src/app/main/ui/workspace/snap_distances.cljs
+++ frontend/src/app/main/ui/workspace/snap_distances.cljs
@@ -104,8 +104,18 @@
                :x2 x2 :y2 y2
                :style {:stroke line-color :stroke-width (str (/ 1 zoom))}}])]))

-(mf/defc shape-distance [{:keys [frame selrect page-id zoom coord selected]}]
-  (let [subject (mf/use-memo #(rx/subject))
+(mf/defc shape-distance
+  {::mf/wrap-props false}
+  [props]
+  (let [frame (unchecked-get props "frame")
+        selrect (unchecked-get props "selrect")
+        page-id (unchecked-get props "page-id")
+        zoom (unchecked-get props "zoom")
+        coord (unchecked-get props "coord")
+        selected (unchecked-get props "selected")
+        ;{:keys [frame selrect page-id zoom coord selected]}
+
+        subject (mf/use-memo #(rx/subject))
         to-measure (mf/use-state [])

         pair->distance+pair
@@ -204,7 +214,9 @@
          ;; On unmount dispose
          #(rx/dispose! sub))))

-    (mf/use-effect (mf/deps selrect selected) #(rx/push! subject [selrect selected frame]))
+    (mf/use-effect
+     (mf/deps selrect)
+     #(rx/push! subject [selrect selected frame]))

     (for [[sr1 sr2] segments-to-display]
       [:& shape-distance-segment {:key (str/join "-" [(:x sr1) (:y sr1) (:x sr2) (:y sr2)])
@@ -215,23 +227,29 @@

 (mf/defc snap-distances
   [{:keys [layout page-id zoom selected transform]}]
-  (when (and (contains? layout :dynamic-alignment)
-             (= transform :move)
-             (not (empty? selected)))
-    (let [shapes (->> (refs/objects-by-id selected)
-                      (mf/deref)
-                      (map gsh/transform-shape))
-          selrect  (gsh/selection-rect shapes)
-          frame-id (-> shapes first :frame-id)
-          frame    (mf/deref (refs/object-by-id frame-id))
-          key      (->> selected (map str) (str/join "-"))]
-      [:g.distance
-       (for [coord [:x :y]]
+  (let [selected-shapes (mf/deref (refs/objects-by-id selected))
+        frame-id (-> selected-shapes first :frame-id)
+        frame  (mf/deref (refs/object-by-id frame-id))]
+
+    (when (and (contains? layout :dynamic-alignment)
+               (= transform :move)
+               (not (empty? selected)))
+      (let [shapes (->> selected-shapes (map gsh/transform-shape))
+            selrect  (gsh/selection-rect shapes)
+            key      (->> selected (map str) (str/join "-"))]
+        [:g.distance
          [:& shape-distance
-          {:key (str key (name coord))
-           :selrect selrect
+            {:selrect selrect
+             :page-id page-id
+             :frame frame
+             :zoom zoom
+             :coord :x
+             :selected selected}]
+
+         [:& shape-distance
+          {:selrect selrect
            :page-id page-id
            :frame frame
            :zoom zoom
-           :coord coord
-           :selected selected}])])))
+           :coord :y
+           :selected selected}]]))))


First step towards being able to partially scan game

- Renamed scan-all-votes -> scan-all-votes-after
- scan-all-votes-after now takes first index, current cycle number and
cycle type as argument

--- src/mafia_votecount/views/create_game.clj
+++ src/mafia_votecount/views/create_game.clj
@@ -18,7 +18,7 @@
 (defn- scan-all-votes [id]
   (let [hosts (models/get-hosts id)
         url (models/get-game-url id)
-        votes (scraper/scan-all-votes url hosts)]
+        votes (scraper/scan-all-votes-after url hosts 1 0 :none)]
     (-> (map #(assoc % :game id) votes)
         (models/add-votes))))


debugger: reorder menu, update style

debugger: reorder menu, update style

--- examples/_common/middleware/devtools.cljs
+++ examples/_common/middleware/devtools.cljs
@@ -255,10 +255,10 @@
            ; for bare app actions (e.g. when originating signal was cleared) create an "unknown signal" event
            :else
            (let [[signal-id _ :as unknown-signal-event] (-signal-event (-> model ::debugger :next-signal-id) ::unknown-signal)]
-                (-> model
-                    (update-in [::debugger :signal-events] concat [unknown-signal-event])
-                    (update-in [::debugger :next-signal-id] inc)
-                    (reconcile [::app-action signal-id action]))))))
+             (-> model
+                 (update-in [::debugger :signal-events] concat [unknown-signal-event])
+                 (update-in [::debugger :next-signal-id] inc)
+                 (reconcile [::app-action signal-id action]))))))

 ;;;;;;;;;;;;;;;;;;;;;;;; View model
 (defn -view-model
@@ -267,11 +267,16 @@
                    [:initial-model :persist? :visible? :toggle-visibility-shortcut :signal-events :action-events]))

 ;;;;;;;;;;;;;;;;;;;;;;;; View
-(def -menu-button-style {:font-weight   "bold"
+(def -menu-button-style {:font-size     "inherit"
+                         :font-family   "inherit"
+                         :font-weight   "bold"
+                         :color         "white"
                          :cursor        "pointer"
                          :padding       "4px"
                          :margin        "5px 3px"
-                         :border-radius "3px"})
+                         :border-radius "3px"
+                         :border        0
+                         :background    "none"})

 (defn -menu-button
   [caption on-click title]
@@ -304,17 +309,21 @@
                  :border-bottom-width 1
                  :border-bottom-style "solid"
                  :border-color        "#4F5A65"}}
-   [:input#persist-toggle.toggle {:title     "Persist debug session into local storage?"
-                                  :type      "checkbox"
-                                  :checked   persist?
-                                  :on-change #(dispatch ::on-toggle-persist)}]
-   [:label {:for "persist-toggle"} "Persist"]
+   [-menu-button "Clear" #(dispatch ::on-clear) "Clears debugger history"]
    [-menu-button "Vacuum" #(dispatch ::on-vacuum) "Removes disabled actions and signals with no actions from history"]
-   [-menu-button "Clear" #(dispatch ::on-clear) "Clears debugger history"]
    [-menu-button "Reset" #(dispatch ::on-reset) "Removes all actions and signals resetting the model to initial state"]
+   [-menu-button "Save" #(dispatch ::on-save) "Saves current debugger session into file"]
+   [-menu-file-selector "Load" #(dispatch [::on-load %]) "Loads debugger session from file"]
    [-menu-button "Hide" #(dispatch ::on-toggle-visibility) (str "Hides debugger view (" toggle-visibility-shortcut ")")]
-   [-menu-button "Save" #(dispatch ::on-save) "Saves current debugger session into file"]
-   [-menu-file-selector "Load" #(dispatch [::on-load %]) "Loads debugger session from file"]])
+
+   [:label {:style {:font-weight "bold"
+                    :padding "4px"
+                    :margin  "5px 3px"}}
+    "Persist"
+    [:input {:title     "Persist debug session into local storage?"
+             :type      "checkbox"
+             :checked   persist?
+             :on-change #(dispatch ::on-toggle-persist)}]]])

 (defn -signals-view
   [signal-events action-events dispatch]
@@ -392,10 +401,16 @@
                             :width          "30%"
                             :height         "100%"
                             :pointer-events "all"}}
-    [:div {:style {:height           "100%"
-                   :overflow         "auto"
-                   :background-color "#2A2F3A"
-                   :color            "white"}}
+    [:div {:style {:height                 "100%"
+                   :overflow               "auto"
+                   :background-color       "#2A2F3A"
+                   :color                  "white"
+                   :font-size              14
+                   :font-family            "sans-serif"
+                   :line-height            "1.4em"
+                   :font-smoothing         "antialiased"
+                   :-moz-font-smoothing    "antialiased"
+                   :-webkit-font-smoothing "antialiased"}}
      [-menu @persist? @toggle-visibility-shortcut dispatch]
      [-signals-view @signal-events @action-events dispatch]
      [-initial-model-view @initial-model]]]])


Remove unnecessary-in-1.3 catches

Remove unnecessary-in-1.3 catches

--- src/reply/main.clj
+++ src/reply/main.clj
@@ -82,13 +82,7 @@
       (do
         (Thread/interrupted) ; just to clear the status
         (actual-read input-stream request-prompt request-exit)))
-    (catch InterruptedException e
-      (clear-jline-buffer)
-      request-prompt)
-    (catch IOException e
-      (clear-jline-buffer)
-      request-prompt)
-    ; NOTE: this weirdness is for wrapped exceptions in 1.3
+    ; NOTE: this indirection is for wrapped exceptions in 1.3
     (catch Throwable e
       (if (#{IOException InterruptedException} (type (repl-exception e)))
         (do


hide react native long timeout warning [ref #2408]

Signed-off-by: andytudhope <c672c4c1a527a9fd06f4d78cd6b98935596c1575@gmail.com>

--- src/status_im/core.cljs
+++ src/status_im/core.cljs
@@ -9,7 +9,7 @@
             [goog.object :as object]))

 (when js/goog.DEBUG
-  (object/set js/console "ignoredYellowBox" #js ["re-frame: overwriting"]))
+  (object/set js/console "ignoredYellowBox" #js ["re-frame: overwriting" "Setting a timer"]))

 (defn init [app-root]
   (log/set-level! config/log-level)


Task-options! shouldn't merge updated options, it should replace them (fixes #65)

--- boot/core/src/boot/core.clj
+++ boot/core/src/boot/core.clj
@@ -682,25 +682,26 @@

   Example:

-  (disable-task! repl jar)"
+      (disable-task! repl jar)"
   [& tasks]
   `(do ~@(for [task tasks]
            `(replace-task! [t# ~task] (fn [& _#] identity)))))

 (defmacro task-options!
   "Given a number of task/map-of-curried-arguments pairs, replaces the root
-  bindings of the tasks with their curried values.
-
-  Example:
-
-  (task-options!
-    repl {:port     12345}
-    jar  {:manifest {:howdy \"world\"}})
+  bindings of the tasks with their curried values. For example:
+
+      (task-options!
+        repl {:port     12345}
+        jar  {:manifest {:howdy \"world\"}})

-  You can update options, too:
-
-  (task-options!
-    jar {:manifest #(assoc % :i-like \"turtles\")})"
+  You can update options, too, by providing a function instead of an option
+  map. This function will be passed the current option map and its result will
+  be used as the new one. For example:
+
+      (task-options!
+        repl #(update-in % [:port] (fnil inc 1234))
+        jar  #(assoc-in % [:manifest \"ILike\"] \"Turtles\"))"
   [& task-option-pairs]
   `(do ~@(for [[task opts] (partition 2 task-option-pairs)]
            `(let [opt# ~opts
@@ -709,7 +710,7 @@
                   new# (if (map? opt#) opt# (opt# old#))
                   arg# (mapcat identity new#)]
               (replace-task! [t# ~task] (fn [& xs#] (apply t# (concat arg# xs#))))
-              (alter-meta! var# (fn [x#] (update-in x# [:task-options] merge new#)))))
+              (alter-meta! var# (fn [x#] (assoc x# :task-options new#)))))
        nil))

 ;; Task Utility Functions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


Fix issue where TempDir objects returned instead of File objects

--- boot/core/src/boot/core.clj
+++ boot/core/src/boot/core.clj
@@ -59,10 +59,11 @@
   [key & masks+]
   (let [k (or key (keyword "boot.core" (str (gensym))))
         m (->> masks+ (map masks) (apply merge))]
-    (util/with-let [t (map->TempDir (assoc m :dir (temp-dir* k)))]
-      (swap! tempdirs conj t)
-      (when (:input t)
-        (set-env! :directories #(conj % (.getPath (:dir t))))))))
+    (util/with-let [d (temp-dir* k)]
+      (let [t (map->TempDir (assoc m :dir d))]
+        (swap! tempdirs conj t)
+        (when (:input t)
+          (set-env! :directories #(conj % (.getPath (:dir t)))))))))

 (defn- temp-dirs-by
   [& masks+]


Fix camelize-keys alias in ClojureScript

--- src/main/workflo/macros/jscomponents.cljs
+++ src/main/workflo/macros/jscomponents.cljs
@@ -1 +1,6 @@
-(ns workflo.macros.jscomponents)
+(ns workflo.macros.jscomponents
+  (:require-macros [workflo.macros.jscomponents
+                    :refer [defjscomponents]])
+  (:require [workflo.macros.util.string]))
+
+(def camelize-keys workflo.macros.util.string/camelize-keys)


core: cycle

core: cycle

--- data/core.clj
+++ data/core.clj
@@ -1450,3 +1450,10 @@
                    (recur pred (rest s))
                    s)))]
     (lazy-seq (step pred coll))))
+
+(defn cycle
+  "Returns a lazy (infinite!) sequence of repetitions of the items in coll."
+  {:added "1.0"}
+  [coll] (lazy-seq
+          (when-let [s (seq coll)]
+            (concat s (cycle s)))))


Housekeeping

Housekeeping

--- src/taoensso/carmine/utils.clj
+++ src/taoensso/carmine/utils.clj
@@ -34,7 +34,7 @@
 (defmacro bench
   "Repeatedly executes form and returns time taken to complete execution."
   [num-laps form & {:keys [warmup-laps num-threads as-ms?]
-                :or   {as-ms? true}}]
+                    :or   {as-ms? true}}]
   `(try (when ~warmup-laps (dotimes [_# ~warmup-laps] ~form))
         (let [nanosecs#
               (if-not ~num-threads
@@ -78,7 +78,6 @@
          (time (dotimes [_ 10000] (name :foo)))
          (time (dotimes [_ 10000] (keyname :foo))))

-;; Clojure 1.5
 (defn keywordize-map [m] (reduce (fn [m [k v]] (assoc m (keyword k) v)) {} m))

 ;; TODO Waiting for Clojure 1.5 support


Disable storing queryable state until production ready.

--- src/onyx/peer/queryable_state_manager.clj
+++ src/onyx/peer/queryable_state_manager.clj
@@ -14,7 +14,7 @@
    (:onyx.core/slot-id event)])

 (defn add-store [state peer-config [_ replica-version event exported]]
-  (let [serializers (onyx.state.serializers.utils/event->state-serializers event)]
+  #_(let [serializers (onyx.state.serializers.utils/event->state-serializers event)]
     (swap! state
            assoc
            (state-key replica-version event)
@@ -22,7 +22,7 @@
             :db (db/open-db-reader peer-config exported serializers)})))

 (defn drop-store [state peer-config [_ replica-version event]]
-  (let [serializers (onyx.state.serializers.utils/event->state-serializers event)
+  #_(let [serializers (onyx.state.serializers.utils/event->state-serializers event)
         k (state-key replica-version event)
         store (get @state k)]
     (db/close! store)


Remove unnecessary inner transactions

Remove unnecessary inner transactions

--- src/time_tracker/timers/db.clj
+++ src/time_tracker/timers/db.clj
@@ -44,24 +44,22 @@

 (defn create!
   "Creates and returns a timer if authorized."
-  [conn project-id google-id]
-  (jdbc/with-db-transaction [connection conn]
-    (create-timer-query<! {:google_id  google-id
-                           :project_id project-id}
-                          {:connection connection})))
+  [connection project-id google-id]
+  (create-timer-query<! {:google_id  google-id
+                         :project_id project-id}
+                        {:connection connection}))

 (defn update-duration!
   "Set the elapsed duration of the timer."
-  [conn timer-id duration current-time]
-  (jdbc/with-db-transaction [connection conn]
-    (when (statement-success? (update-timer-duration-query! {:duration     duration
-                                                             :timer_id     timer-id
-                                                             :current_time current-time}
-                                                            {:connection connection}))
-      (-> (retrieve-timer-query {:timer_id timer-id}
-                                {:connection connection})
-          (first)
-          (select-keys [:started_time :duration])))))
+  [connection timer-id duration current-time]
+  (when (statement-success? (update-timer-duration-query! {:duration     duration
+                                                           :timer_id     timer-id
+                                                           :current_time current-time}
+                                                          {:connection connection}))
+    (-> (retrieve-timer-query {:timer_id timer-id}
+                              {:connection connection})
+        (first)
+        (select-keys [:started_time :duration]))))

 (defn delete!
   "Deletes a timer. Returns false if the timer doesn't exist."
@@ -80,26 +78,24 @@
 (defn start!
   "Starts a timer if the timer is not already started.
   Returns {:keys [start_time duration]} or nil."
-  [conn timer-id current-time]
-  (jdbc/with-db-transaction [connection conn]
-    (when (statement-success? (start-timer-query! {:timer_id     timer-id
-                                                   :current_time current-time}
-                                                  {:connection connection}))
-      (-> (retrieve-timer-query {:timer_id  timer-id}
-                                {:connection connection})
-          (first)
-          (select-keys [:started_time :duration])))))
+  [connection timer-id current-time]
+  (when (statement-success? (start-timer-query! {:timer_id     timer-id
+                                                 :current_time current-time}
+                                                {:connection connection}))
+    (-> (retrieve-timer-query {:timer_id  timer-id}
+                              {:connection connection})
+        (first)
+        (select-keys [:started_time :duration]))))

 (defn stop!
   "Stops a timer if the timer is not already stopped.
   Returns {:keys [duration]} or nil."
-  [conn timer-id current-time]
-  (jdbc/with-db-transaction [connection conn]
-    (when (statement-success? (stop-timer-query! {:timer_id     timer-id
-                                                  :current_time current-time}
-                                                 {:connection connection}))
-      (-> (retrieve-timer-query {:timer_id  timer-id}
-                                {:connection connection})
-          (first)
-          (select-keys [:duration])))))
+  [connection timer-id current-time]
+  (when (statement-success? (stop-timer-query! {:timer_id     timer-id
+                                                :current_time current-time}
+                                               {:connection connection}))
+    (-> (retrieve-timer-query {:timer_id  timer-id}
+                              {:connection connection})
+        (first)
+        (select-keys [:duration]))))


Store tweets in single transactions.

Store tweets in single transactions.

--- src/twitter_collector/core.clj
+++ src/twitter_collector/core.clj
@@ -28,7 +28,7 @@
   (go-try
    (let [st (.getTime (java.util.Date.))
          tweets (vec (first (swap! pending (fn [[prev cur]] [cur '()]))))
-         tweet-txs [['add-tweets tweets]]]
+         tweet-txs (mapv (fn [t] ['add-tweet t]) tweets)]
      (when-not (empty? tweets)
        (<? (cs/transact! stage [user cdvcs-id] tweet-txs))
        (when (< (rand) 0.05)


Add better docstring for page change watcher on pages ns.

--- src/uxbox/main/data/pages.cljs
+++ src/uxbox/main/data/pages.cljs
@@ -174,13 +174,19 @@
   (UpdatePage. id))

 (defn watch-page-changes
+  "A function that starts watching for `IPageUpdate`
+  events emited to the global event stream and just
+  reacts emiting an other event in order to perform
+  the page persistence.
+
+  The main behavior debounces the posible emmited
+  events with 1sec of delay allowing batch updates
+  on fastly performed events."
   [id]
-  (letfn [(on-value []
-            (rs/emit! (update-page id)))]
-    (as-> rs/stream $
-      (rx/filter #(satisfies? IPageUpdate %) $)
-      (rx/debounce 2000 $)
-      (rx/on-next $ on-value))))
+  (as-> rs/stream $
+    (rx/filter #(satisfies? IPageUpdate %) $)
+    (rx/debounce 1000 $)
+    (rx/on-next $ #(rs/emit! (update-page id)))))

 ;; --- Update Page Metadata


[#11507] Fix e2e tests

[#11507] Fix e2e tests

--- src/status_im/ethereum/subscriptions.cljs
+++ src/status_im/ethereum/subscriptions.cljs
@@ -20,26 +20,32 @@
   [{:keys [db]} id handler]
   {:db (assoc-in db [:ethereum/subscriptions id] handler)})

+(fx/defn max-known-block
+  [{:keys [db]} block-number]
+  {:db (assoc db :wallet/max-known-block block-number)})
+
 (fx/defn new-block
   [{:keys [db] :as cofx} historical? block-number accounts transactions-per-account]
   (log/debug "[wallet-subs] new-block"
              "accounts" accounts
              "block" block-number
-             "transactions-per-account" transactions-per-account)
-  (fx/merge cofx
-            (cond-> {}
-              (not historical?)
-              (assoc :db (assoc db :ethereum/current-block block-number))
+             "transactions-per-account" transactions-per-account
+             "max-known-block" (:wallet/max-known-block db))
+  (when (>= block-number (:wallet/max-known-block db))
+    (fx/merge cofx
+              (cond-> {}
+                (not historical?)
+                (assoc :db (assoc db :ethereum/current-block block-number))

-              ;;NOTE only get transfers if the new block contains some
-              ;;     from/to one of the multiaccount accounts
-              (not-empty accounts)
-              (assoc :transactions/get-transfers
-                     {:chain-tokens (:wallet/all-tokens db)
-                      :addresses    accounts
-                      :before-block block-number
-                      :historical?  historical?}))
-            (transactions/check-watched-transactions)))
+                ;;NOTE only get transfers if the new block contains some
+                ;;     from/to one of the multiaccount accounts
+                (not-empty accounts)
+                (assoc :transactions/get-transfers
+                       {:chain-tokens (:wallet/all-tokens db)
+                        :addresses    accounts
+                        :before-block block-number
+                        :historical?  historical?}))
+              (transactions/check-watched-transactions))))

 (fx/defn reorg
   [{:keys [db] :as cofx} {:keys [blockNumber accounts]}]
@@ -91,6 +97,7 @@
   (case type
     "newblock" (new-block cofx false blockNumber accounts newTransactions)
     "history" (new-block cofx true blockNumber accounts nil)
+    "maxKnownBlock" (max-known-block cofx blockNumber)
     "reorg" (reorg cofx event)
     "recent-history-fetching" (recent-history-fetching-started cofx accounts)
     "recent-history-ready" (recent-history-fetching-ended cofx event)