minor corrections to tutorial

minor corrections to tutorial

--- welcome.clj
+++ welcome.clj
@@ -21,7 +21,12 @@
 ;;;
 ;;; Executable code is written in Clojure. (@@GrapeVine@@ code is a domain specific language extension of Clojure).
 ;;;
-;;; _Shift + enter evaluates a code segment._
+;;; Executable segments are not automatically invoked when a worksheet is loaded.
+;;;
+;;;
+;;; _Shift + enter evaluates a single code segment._
+;;;
+;;; _Ctrl + Shift + enter evaluates all code segments in a worksheet._
 ;;;
 ;; **

@@ -45,7 +50,7 @@
 ;; **
 ;;; ## 1.4 Using @@GrapeVine@@ - Resources and namespaces
 ;;;
-;;; To make @@GrapeVine@@ available, *its library must be imported*. Under the hood, @@GrapeVine@@ connects to the graph database NEO4J so the import. The simplest way to do the import is by using a  `(use 'grape.core')` form, but it's best practice to define a separate namespace for each worksheet. Below creates a worksheet of name `worksheet1`.
+;;; To make @@GrapeVine@@ available, *its library must be imported*. Under the hood, @@GrapeVine@@ connects to the graph database NEO4J. The simplest way to do the import is by using a  `(use 'grape.core')` form, but it's best practice to define a separate namespace for each worksheet. Below creates a worksheet of name `tutorial`.
 ;;;
 ;;; (**Remember: The statement below must be executed before any @@GrapeVine@@-related commands.**
 ;;; (Shift-enter) Establishing the session may take a few seconds. Wait until the green light is gone.)
@@ -162,7 +167,7 @@
  )
 ;; @@
 ;; =>
-;;; {"type":"list-like","open":"(","close":")","separator":" ","items":[{"type":"html","content":"<img src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJcAAACFCAYAAABWgWrpAAAH0klEQVR42u2deahMbRzHrz2EyL5k+8N6/6LckhLxh5DlkhApRKTssi+RcLNGUXZyX2SJ7Gu6QiRKkhJC9n1ffq/vU2eaGTP3nrl3xswdn8/01Huec2bOc8753Of5ned4zy/DABLDfxmcA0AuQC4A5ALkAuQCQC5ALkAuAOQC5ALkAkAuQC5ArnBycnIsOzubkqYlLy8veXKpAfXr1+dCpGHJyMiw3Nzc5MqlAukHcgFyAXIhFyAXIBcg19+T68KFC7Zt27ZA2b59u+3evduOHTtmjx49KlQbvn//bnv27LHOnTvbihUr4nqCHz58aLNnz7YGDRrY58+f49a+eLf54MGDNmjQoEDZuXOnXblyJaROc5JpLdevX7/s6NGjVqJECatevbqtWrXKli9fbm3atLGSJUva+PHj7dOnTzG14d69e+53dDKWLl0aV7nOnj1rnTp1cr8da7vya1+827x48WKrXbu2vXjxwpWPHz/a169fA8s9evSwnj17/hvDYrVq1axFixYhdQMHDnQHNG/evJh/TycwEXKJuXPnFkmuaO2LZ5slV926daOu79u3778jl/7KwuU6deqUO6Dwej+8efMmYXItXLiwyHJFal8824xcBcilGEEH1K1bt0Ddrl27XPyguMxD/626ffv2Berevn0b8UKpfv369W64Xb16tb1//z6w7sOHD66XvH37ti+5FHPdunXL5syZY5s2bbJv37753lek9kVr85cvX1wMOn36dFuzZo3dvXsXuYoi18+fP613797ugIKleffunbVv394qV64cqHv8+LFlZma638jvQt25c8fFGrpQ169ft9atW1vTpk3t9evXbv3x48fdd6ZMmeJLLrVryJAhrmhZ9X735VcuCdyxY0f3R6XvStJKlSrZ3r17kSsWuerVq2ebN2+2BQsWWMuWLa1du3YhPZTH2LFjQ+QSw4cPL1CuLl26hIh65MgRt82sWbPc8o8fP+zAgQP28uVLX3IFX2BdqEaNGvnel1+5FHcOGzbsj3Ncvnx5d+eKXD7l0sXR1ESfPn3cgRw+fDjituPGjftDrpEjR+Yrl3o3LU+ePNmmTZvmiiRt27atTZw4sVAxV/BUhIa+ihUr+t6XH7l0h1emTBl3FxkpFp0/fz5yxTosqvtv2LCh1ahRw548eRIXuc6dO+eWnz9/HreAPlguDaVly5b1vS8/cp04ccItr127NuS7Dx48cPWDBw9GrsLEXOrBSpUqZV27dnVzYUWV6+LFi25ZMVA4iuPiKZefffmRS/N/kSTSXSo9VxHvFnXnpgNasmRJSP3MmTOtXLlyIXUjRoxwPV20C/Xq1Ssna1ZWlptM9Hj27JmtW7curnL52ZcfuZ4+feqOs3HjxiH7v3//vtvuzJkzyFUQevRRunRpF9AHowC7Q4cO7kIdOnQoUL9hwwZ3oLq7U6+mO6lWrVq5i6u5In1Pj460jSY8PcaMGePqdNF37Njhpg8UeOs7QkNwv379XK+ZHzNmzHC/Exz4K5bSUwZPpoL2Fal9keomTZrk6k6fPh2oW7lypWtneI+OXGGcP3/eHagarjJq1Ci7fPlySHxRtWpVJ1+vXr1cHKJAV7f22r5WrVq2ZcsWNyxqO12Mmzdv2ujRo9163XXu378/ECB70wYqGlqD7+hOnjzp6jVvFQ09s2vevLnbTgJpzklyN2nSJDCN4T1uibYvBfzh7YtU503JTJgwwfXKU6dOtaFDh1r//v0LfK6JXEVAf7U3btxwF9GbV/I7Y65A++rVqxG31+/ogsaL/PYVC/r+tWvXfD8sRy5IGMgFCZWrTp06rhdW8eIzb1lzicgFhUJPNrp37x4oGzdudP/PoZ7TeiXWf22CXJAwkAuQC5ALuQC5ALkAuZALkAuQC5ALuQC5ALkAuZALkAuQC7mQC7kAuQC5EiZXNp+YP3mWh1y+Dur3J+v3B2X8fXS+ci0XufzKlYiTlbbDF3IhF3IhF3IhFyAXciEXciEXcgFyIRdyIRdyIRcgF3IhF3IhF3IBciEXciEXciFX4uUKT4es4r2yXOli9C754HVKwVfQm5X/Rrph5ComPZfeia8TqKwVer13MMpuoRR3Wq8sYt4ryvPjb6QbRq5iNCwql2F4OhQPyaATrJ7LL4lON4xcxUiumjVrRk17rCytOsGRckBGI9HphpErBU9WtJTDhZErmemGkSsF5YqWcjhWuZKdbhi5UlCuaCmHJVeVKlVcAqfworTI4XIlO90wchWzmKtZs2ZuaAsvOTk5IXKlQrph5ErTgD4V0g0jV5rKlQrphpErTeVKhXTDyJWCckVKOay0cRUqVAhJxB7MokWL3AnWtINHstMNI1cKyhWecliPfgYMGBBIG6w5q0uXLrl1mhpYtmyZy8GtdZmZmS7PtqYPkp1uGLlSdFiMZ8rhZKUbRq5iFHOlA8iFXMhVnOTSvJD+nVRBZevWrciFXLGdLN1V6eFvQUWPfpALuRgWkQu5kAu5kAu5kAu5kAu5kAu5kAu5kAu5kAu5kAu5kAu5kAu5kAu5kAu5kCs15CIlHinxSOZJMs/iJRekyHCLXIBcgFzIBcgFyAXIhVyAXIBcgFzxkUuvE1IjKOlVUkIu73VClPQrSZULALkAuQC5AJALkAuQCwC5ALkAuQCQC5ALkAsAuQC54N+T639Zg1RGzPm1FAAAAABJRU5ErkJggg==\" width=\"151\" height=\"133\" alt=\"\" />","value":"#object[java.awt.image.BufferedImage 0x553a373b \"BufferedImage@553a373b: type = 6 ColorModel: #pixelBits = 32 numComponents = 4 color space = java.awt.color.ICC_ColorSpace@73c0f0d4 transparency = 3 has alpha = true isAlphaPre = false ByteInterleavedRaster: width = 151 height = 133 #numDataElements 4 dataOff[0] = 3\"]"},{"type":"html","content":"<img src=\"data:image/png;base64,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\" width=\"157\" height=\"251\" alt=\"\" />","value":"#object[java.awt.image.BufferedImage 0x735cff45 \"BufferedImage@735cff45: type = 6 ColorModel: #pixelBits = 32 numComponents = 4 color space = java.awt.color.ICC_ColorSpace@73c0f0d4 transparency = 3 has alpha = true isAlphaPre = false ByteInterleavedRaster: width = 157 height = 251 #numDataElements 4 dataOff[0] = 3\"]"},{"type":"html","content":"<img src=\"data:image/png;base64,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\" width=\"243\" height=\"251\" alt=\"\" />","value":"#object[java.awt.image.BufferedImage 0x1ab9bfbd \"BufferedImage@1ab9bfbd: type = 6 ColorModel: #pixelBits = 32 numComponents = 4 color space = java.awt.color.ICC_ColorSpace@73c0f0d4 transparency = 3 has alpha = true isAlphaPre = false ByteInterleavedRaster: width = 243 height = 251 #numDataElements 4 dataOff[0] = 3\"]"}],"value":"(#gorilla_repl.image.ImageView{:image #object[java.awt.image.BufferedImage 0x553a373b \"BufferedImage@553a373b: type = 6 ColorModel: #pixelBits = 32 numComponents = 4 color space = java.awt.color.ICC_ColorSpace@73c0f0d4 transparency = 3 has alpha = true isAlphaPre = false ByteInterleavedRaster: width = 151 height = 133 #numDataElements 4 dataOff[0] = 3\"], :alt \"\", :type \"png\", :width 151, :height 133} #gorilla_repl.image.ImageView{:image #object[java.awt.image.BufferedImage 0x735cff45 \"BufferedImage@735cff45: type = 6 ColorModel: #pixelBits = 32 numComponents = 4 color space = java.awt.color.ICC_ColorSpace@73c0f0d4 transparency = 3 has alpha = true isAlphaPre = false ByteInterleavedRaster: width = 157 height = 251 #numDataElements 4 dataOff[0] = 3\"], :alt \"\", :type \"png\", :width 157, :height 251} #gorilla_repl.image.ImageView{:image #object[java.awt.image.BufferedImage 0x1ab9bfbd \"BufferedImage@1ab9bfbd: type = 6 ColorModel: #pixelBits = 32 numComponents = 4 color space = java.awt.color.ICC_ColorSpace@73c0f0d4 transparency = 3 has alpha = true isAlphaPre = false ByteInterleavedRaster: width = 243 height = 251 #numDataElements 4 dataOff[0] = 3\"], :alt \"\", :type \"png\", :width 243, :height 251})"}
+;;; {"type":"list-like","open":"(","close":")","separator":" ","items":[{"type":"html","content":"<img src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJcAAACFCAYAAABWgWrpAAAH0klEQVR42u2deahMbRzHrz2EyL5k+8N6/6LckhLxh5DlkhApRKTssi+RcLNGUXZyX2SJ7Gu6QiRKkhJC9n1ffq/vU2eaGTP3nrl3xswdn8/01Huec2bOc8753Of5ned4zy/DABLDfxmcA0AuQC4A5ALkAuQCQC5ALkAuAOQC5ALkAkAuQC5ArnBycnIsOzubkqYlLy8veXKpAfXr1+dCpGHJyMiw3Nzc5MqlAukHcgFyAXIhFyAXIBcg19+T68KFC7Zt27ZA2b59u+3evduOHTtmjx49KlQbvn//bnv27LHOnTvbihUr4nqCHz58aLNnz7YGDRrY58+f49a+eLf54MGDNmjQoEDZuXOnXblyJaROc5JpLdevX7/s6NGjVqJECatevbqtWrXKli9fbm3atLGSJUva+PHj7dOnTzG14d69e+53dDKWLl0aV7nOnj1rnTp1cr8da7vya1+827x48WKrXbu2vXjxwpWPHz/a169fA8s9evSwnj17/hvDYrVq1axFixYhdQMHDnQHNG/evJh/TycwEXKJuXPnFkmuaO2LZ5slV926daOu79u3778jl/7KwuU6deqUO6Dwej+8efMmYXItXLiwyHJFal8824xcBcilGEEH1K1bt0Ddrl27XPyguMxD/626ffv2Berevn0b8UKpfv369W64Xb16tb1//z6w7sOHD66XvH37ti+5FHPdunXL5syZY5s2bbJv37753lek9kVr85cvX1wMOn36dFuzZo3dvXsXuYoi18+fP613797ugIKleffunbVv394qV64cqHv8+LFlZma638jvQt25c8fFGrpQ169ft9atW1vTpk3t9evXbv3x48fdd6ZMmeJLLrVryJAhrmhZ9X735VcuCdyxY0f3R6XvStJKlSrZ3r17kSsWuerVq2ebN2+2BQsWWMuWLa1du3YhPZTH2LFjQ+QSw4cPL1CuLl26hIh65MgRt82sWbPc8o8fP+zAgQP28uVLX3IFX2BdqEaNGvnel1+5FHcOGzbsj3Ncvnx5d+eKXD7l0sXR1ESfPn3cgRw+fDjituPGjftDrpEjR+Yrl3o3LU+ePNmmTZvmiiRt27atTZw4sVAxV/BUhIa+ihUr+t6XH7l0h1emTBl3FxkpFp0/fz5yxTosqvtv2LCh1ahRw548eRIXuc6dO+eWnz9/HreAPlguDaVly5b1vS8/cp04ccItr127NuS7Dx48cPWDBw9GrsLEXOrBSpUqZV27dnVzYUWV6+LFi25ZMVA4iuPiKZefffmRS/N/kSTSXSo9VxHvFnXnpgNasmRJSP3MmTOtXLlyIXUjRoxwPV20C/Xq1Ssna1ZWlptM9Hj27JmtW7curnL52ZcfuZ4+feqOs3HjxiH7v3//vtvuzJkzyFUQevRRunRpF9AHowC7Q4cO7kIdOnQoUL9hwwZ3oLq7U6+mO6lWrVq5i6u5In1Pj460jSY8PcaMGePqdNF37Njhpg8UeOs7QkNwv379XK+ZHzNmzHC/Exz4K5bSUwZPpoL2Fal9keomTZrk6k6fPh2oW7lypWtneI+OXGGcP3/eHagarjJq1Ci7fPlySHxRtWpVJ1+vXr1cHKJAV7f22r5WrVq2ZcsWNyxqO12Mmzdv2ujRo9163XXu378/ECB70wYqGlqD7+hOnjzp6jVvFQ09s2vevLnbTgJpzklyN2nSJDCN4T1uibYvBfzh7YtU503JTJgwwfXKU6dOtaFDh1r//v0LfK6JXEVAf7U3btxwF9GbV/I7Y65A++rVqxG31+/ogsaL/PYVC/r+tWvXfD8sRy5IGMgFCZWrTp06rhdW8eIzb1lzicgFhUJPNrp37x4oGzdudP/PoZ7TeiXWf22CXJAwkAuQC5ALuQC5ALkAuZALkAuQC5ALuQC5ALkAuZALkAuQC7mQC7kAuQC5EiZXNp+YP3mWh1y+Dur3J+v3B2X8fXS+ci0XufzKlYiTlbbDF3IhF3IhF3IhFyAXciEXciEXcgFyIRdyIRdyIRcgF3IhF3IhF3IBciEXciEXciFX4uUKT4es4r2yXOli9C754HVKwVfQm5X/Rrph5ComPZfeia8TqKwVer13MMpuoRR3Wq8sYt4ryvPjb6QbRq5iNCwql2F4OhQPyaATrJ7LL4lON4xcxUiumjVrRk17rCytOsGRckBGI9HphpErBU9WtJTDhZErmemGkSsF5YqWcjhWuZKdbhi5UlCuaCmHJVeVKlVcAqfworTI4XIlO90wchWzmKtZs2ZuaAsvOTk5IXKlQrph5ErTgD4V0g0jV5rKlQrphpErTeVKhXTDyJWCckVKOay0cRUqVAhJxB7MokWL3AnWtINHstMNI1cKyhWecliPfgYMGBBIG6w5q0uXLrl1mhpYtmyZy8GtdZmZmS7PtqYPkp1uGLlSdFiMZ8rhZKUbRq5iFHOlA8iFXMhVnOTSvJD+nVRBZevWrciFXLGdLN1V6eFvQUWPfpALuRgWkQu5kAu5kAu5kAu5kAu5kAu5kAu5kAu5kAu5kAu5kAu5kAu5kAu5kAu5kCs15CIlHinxSOZJMs/iJRekyHCLXIBcgFzIBcgFyAXIhVyAXIBcgFzxkUuvE1IjKOlVUkIu73VClPQrSZULALkAuQC5AJALkAuQCwC5ALkAuQCQC5ALkAsAuQC54N+T639Zg1RGzPm1FAAAAABJRU5ErkJggg==\" width=\"151\" height=\"133\" alt=\"\" />","value":"#object[java.awt.image.BufferedImage 0x2b3576c2 \"BufferedImage@2b3576c2: type = 6 ColorModel: #pixelBits = 32 numComponents = 4 color space = java.awt.color.ICC_ColorSpace@3f3385ea transparency = 3 has alpha = true isAlphaPre = false ByteInterleavedRaster: width = 151 height = 133 #numDataElements 4 dataOff[0] = 3\"]"},{"type":"html","content":"<img src=\"data:image/png;base64,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\" width=\"157\" height=\"251\" alt=\"\" />","value":"#object[java.awt.image.BufferedImage 0xd85e5fe \"BufferedImage@d85e5fe: type = 6 ColorModel: #pixelBits = 32 numComponents = 4 color space = java.awt.color.ICC_ColorSpace@3f3385ea transparency = 3 has alpha = true isAlphaPre = false ByteInterleavedRaster: width = 157 height = 251 #numDataElements 4 dataOff[0] = 3\"]"},{"type":"html","content":"<img src=\"data:image/png;base64,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\" width=\"243\" height=\"251\" alt=\"\" />","value":"#object[java.awt.image.BufferedImage 0x2ef6d6c9 \"BufferedImage@2ef6d6c9: type = 6 ColorModel: #pixelBits = 32 numComponents = 4 color space = java.awt.color.ICC_ColorSpace@3f3385ea transparency = 3 has alpha = true isAlphaPre = false ByteInterleavedRaster: width = 243 height = 251 #numDataElements 4 dataOff[0] = 3\"]"}],"value":"(#gorilla_repl.image.ImageView{:image #object[java.awt.image.BufferedImage 0x2b3576c2 \"BufferedImage@2b3576c2: type = 6 ColorModel: #pixelBits = 32 numComponents = 4 color space = java.awt.color.ICC_ColorSpace@3f3385ea transparency = 3 has alpha = true isAlphaPre = false ByteInterleavedRaster: width = 151 height = 133 #numDataElements 4 dataOff[0] = 3\"], :alt \"\", :type \"png\", :width 151, :height 133} #gorilla_repl.image.ImageView{:image #object[java.awt.image.BufferedImage 0xd85e5fe \"BufferedImage@d85e5fe: type = 6 ColorModel: #pixelBits = 32 numComponents = 4 color space = java.awt.color.ICC_ColorSpace@3f3385ea transparency = 3 has alpha = true isAlphaPre = false ByteInterleavedRaster: width = 157 height = 251 #numDataElements 4 dataOff[0] = 3\"], :alt \"\", :type \"png\", :width 157, :height 251} #gorilla_repl.image.ImageView{:image #object[java.awt.image.BufferedImage 0x2ef6d6c9 \"BufferedImage@2ef6d6c9: type = 6 ColorModel: #pixelBits = 32 numComponents = 4 color space = java.awt.color.ICC_ColorSpace@3f3385ea transparency = 3 has alpha = true isAlphaPre = false ByteInterleavedRaster: width = 243 height = 251 #numDataElements 4 dataOff[0] = 3\"], :alt \"\", :type \"png\", :width 243, :height 251})"}
 ;; <=

 ;; **
@@ -189,7 +194,7 @@
 ;; <=

 ;; **
-;;; > _Note: The graph ids of the two applications or rule `hello` are differnt. Indeed we actually get a new graph each time a rule is applied. _
+;;; > _Note: The graph ids of the two applications of rule `hello` are differnt. Indeed we actually get a new graph each time a rule is applied. _
 ;;;
 ;;; For convenience, @@GrapeVine@@ also provides a shortcut symbol **`_`** (underscore), to refer to the "last created graph" (resp. "last created @@grape@@"). So the following also works:
 ;; **
@@ -470,7 +475,7 @@
 ;;; > 1. Step 3: World* (two concurrent derivations)
 ;;; > 1. Step 4: vine (two concurrent derivations)
 ;;;
-;;; Each of these steps can be represented by a @@grape@@. We can use the form `steps` to attain this sequence of a Grapes that characterize a history graph:
+;;; Each of these steps can be represented by a @@grape@@. We can use the form `steps` to attain this sequence of @@grapes@@ that characterize a history graph:
 ;; **

 ;; @@
@@ -844,7 +849,7 @@
 ;; <=

 ;; **
-;;; There is only one graph in the Grape that is fed to the query `self-related?`, so the result is a set that contains only a single relation. Moreover, that relation only contains a single tuple. Extracting information of interest simply uses Clojure to navigate this set of relations. For example, the following extracts the ID of the first `h` node in the first graph:
+;;; There is only one graph in the Grape that is fed to the query `hello-to?`, so the result is a set that contains only a single relation. Moreover, that relation only contains a single tuple. Extracting information of interest simply uses Clojure to navigate this set of relations. For example, the following extracts the ID of the first `h` node in the first graph:
 ;; **

 ;; @@


Minor note about Dana

Minor note about Dana

--- scrape-n-mail/src/scrape_n_mail/core.cljs
+++ scrape-n-mail/src/scrape_n_mail/core.cljs
@@ -196,6 +196,8 @@

                [:p "https://docs.google.com/forms/d/e/1FAIpQLSc_FFrH7a_ClDmpAq36vA7gdUd1njmoEK0wfhRNaYcjfLox0w/viewform"]

+               [:p "Please recall that it is traditional to offer Dana along with the submission of names."]
+
                [:p "If we do not hear from you, we will remove these names from the altar. Jai mitra!"]

                ; Note that the \ is an escape character!


Check peer timeoutts on coordinator heartbeat duty cycle.

--- src/onyx/peer/coordinator.clj
+++ src/onyx/peer/coordinator.clj
@@ -258,12 +258,13 @@
    barrier-period-ns
    heartbeat-ns]
   (let [_ (run! pub/poll-heartbeats! (m/publishers messenger))
-        state (check-peer-timeout! state)
         status (merged-statuses messenger)
         {:keys [sealing? completed?]} job]
     (cond (> (System/nanoTime) (+ last-heartbeat-time heartbeat-ns))
           ;; Immediately offer heartbeats
-          (offer-heartbeats state)
+          (-> state
+              (offer-heartbeats)
+              (check-peer-timeout!))

           (:offering? barrier)
           ;; Continue offering barriers until success


Fix aeron health check for aeron 1.2.5.

Fix aeron health check for aeron 1.2.5.

--- src/onyx/peer_query/aeron.clj
+++ src/onyx/peer_query/aeron.clj
@@ -3,17 +3,18 @@
            [java.util.function Consumer]))

 (defn media-driver-health []
-  (let [common-context (CommonContext.)
+  (let [common-context (.conclude (CommonContext.))
         log-output (atom [])]
     (try
-     (let [driver-timout-ms (.driverTimeoutMs common-context)
+     (let [driver-timeout-ms (.driverTimeoutMs common-context)
            active? (.isDriverActive common-context
-                                    driver-timout-ms
+                                    driver-timeout-ms
                                     (reify Consumer
                                       (accept [this log]
                                         (swap! log-output conj log))))]
        {:active active?
-        :driver-timeout-ms driver-timout-ms
+        :aeron-dir (.aeronDirectoryName common-context)
+        :driver-timeout-ms driver-timeout-ms
         :log (clojure.string/join "\n" @log-output)})
      (finally
       (.close common-context)))))


remove debug comment

remove debug comment

--- src/pc/datomic/migrations.clj
+++ src/pc/datomic/migrations.clj
@@ -98,7 +98,7 @@
   "Converts attributes that store ids to refs, e.g. layers go from :document/id to :layer/document"
   [conn]
   (let [db (d/db conn)]
-    ;(document-ids->document-refs db conn)
+    (document-ids->document-refs db conn)
     (access-entities-ids->refs db conn)))

 (def migrations


CMR-1199: Updated test

CMR-1199: Updated test

--- system-int-test/test/cmr/system_int_test/ingest/granule_ingest_test.clj
+++ system-int-test/test/cmr/system_int_test/ingest/granule_ingest_test.clj
@@ -112,12 +112,11 @@

 ;; Verify that the accept header works with returned errors
 (deftest granule-ingest-with-errors-accept-header-test
-  (let [collection (d/ingest "PROV1" (dc/collection {:entry-title "Coll1"}))]
+  (let [collection (dc/collection {:entry-title "Coll1"})]
     (testing "json response"
       (let [umm-granule (dg/granule collection {:concept-id "G1-PROV1"
                                                 :granule-ur "Gran1"})
             granule (d/item->concept umm-granule)
-            _ (ingest/delete-concept (d/item->concept collection :echo10))
             response (ingest/ingest-concept granule {:accept-format :json :raw? true})
             status (:status response)
             {:keys [errors]} (ingest/parse-ingest-response :json response)]
@@ -127,7 +126,6 @@
       (let [umm-granule (dg/granule collection {:concept-id "G1-PROV1"
                                                 :granule-ur "Gran1"})
             granule (d/item->concept umm-granule)
-            _ (ingest/delete-concept (d/item->concept collection :echo10))
             response (ingest/ingest-concept granule {:accept-format :xml :raw? true})
             status (:status response)
             {:keys [errors]} (ingest/parse-ingest-response :xml response)]


Adding more fields to CLJS client

Adding more fields to CLJS client

Added input and button

--- src/webapp/framework/client/macros.cljs
+++ src/webapp/framework/client/macros.cljs
@@ -2,6 +2,15 @@

   ;(:require [webapp.framework.client.fns :refer [abcd-fn] ])
 )
+
+
+
+(defmacro input [attributes & more]
+  `(om.dom/input  (webapp.framework.client.coreclient/attrs ~attributes) ~@more))
+
+
+(defmacro button [attributes & more]
+  `(om.dom/button  (webapp.framework.client.coreclient/attrs ~attributes) ~@more))

 (defmacro div [attributes & more]
@@ -9,6 +18,8 @@

+
 (defmacro zoo [attr]
   attr)

+


[#7776] Blank screen after username submit when creating new account on Desktop

Signed-off-by: Andrey Shovkoplyas <b713972e59b8e606e23253c4a13e948139fea4d1@gmail.com>

--- src/status_im/accounts/create/core.cljs
+++ src/status_im/accounts/create/core.cljs
@@ -20,7 +20,8 @@
             [taoensso.timbre :as log]
             [status-im.utils.fx :as fx]
             [status-im.node.core :as node]
-            [status-im.ui.screens.mobile-network-settings.events :as mobile-network]))
+            [status-im.ui.screens.mobile-network-settings.events :as mobile-network]
+            [status-im.utils.platform :as platform]))

 (defn get-signing-phrase [cofx]
   (assoc cofx :signing-phrase (signing-phrase/generate)))
@@ -110,7 +111,8 @@
             {:db                                              db
              :notifications/request-notifications-permissions nil
              :dispatch-n                                      [[:navigate-to :home]
-                                                               [:navigate-to :welcome]]}
+                                                               (when-not platform/desktop?
+                                                                 [:navigate-to :welcome])]}
             ;; We set last updated as we are actually changing a field,
             ;; unlike on recovery where the name is not set
             (accounts.update/account-update {:last-updated now


Remove link around email main copy

Remove link around email main copy

--- src/oc/email/content.clj
+++ src/oc/email/content.clj
@@ -518,8 +518,7 @@
                                                           :logo-height :org-logo-height
                                                           :logo-width :org-logo-width})))
       (when logo? (spacer 32))
-      [:a {:href entry-url}
-        (h1 intro)]
+      (h1 intro)
       (spacer 24)
       (spacer 8 "note-paragraph top-note-paragraph" "note-paragraph top-note-paragraph")
       (note-author notification-author-name notification-author-url)


move logging setup into start fn

move logging setup into start fn

--- src/open_company/app.clj
+++ src/open_company/app.clj
@@ -4,6 +4,7 @@
   (:require
     [liberator.dev :refer (wrap-trace)]
     [raven-clj.ring :refer (wrap-sentry)]
+    [taoensso.timbre :as timbre]
     [ring.middleware.params :refer (wrap-params)]
     [ring.middleware.reload :refer (wrap-reload)]
     [ring.middleware.cors :refer (wrap-cors)]
@@ -46,6 +47,7 @@
     hot-reload-routes))

 (defn start [port]
+  (timbre/set-config! config/log-config)
   (run-server app {:port port :join? false})
   (println (str "\n" (slurp (clojure.java.io/resource "open_company/assets/ascii_art.txt")) "\n"
     "OpenCompany API Server\n"


buffers: when adding buffers using add-buffers, merge new buffers into category instead of overwriting previously added buffers

--- src/overtime/buffers.clj
+++ src/overtime/buffers.clj
@@ -33,7 +33,7 @@

 (defn add-buffers
   [category new-buffers]
-  (swap! buffers assoc category new-buffers))
+  (swap! buffers update category merge new-buffers))

 (defn view-buffer
   "View buffer as X/Y plot using Incanter view"


Order results by descending similarity score.

--- src/kosha/app/search.clj
+++ src/kosha/app/search.clj
@@ -8,9 +8,10 @@
 (defn get-results
   "Retrieves 2n best matches for given ragam or kriti name."
   [query n]
-  (let [ragams (future (db-search/ragams query n))
-        kritis (future (db-search/kritis query n))]
-    (util/json-response (into [] (concat @ragams @kritis)))))
+  (let [ragams  (future (db-search/ragams query n))
+        kritis  (future (db-search/kritis query n))
+        results (sort-by :similarity > (concat @ragams @kritis))]
+    (util/json-response (into [] results))))

 (defn handler [{:keys [params]}]
   (let [query (:query params)]


Fix: `with-replies*` now unstashes correctly after exceptions

--- src/taoensso/carmine.clj
+++ src/taoensso/carmine.clj
@@ -133,10 +133,12 @@
   queued with Redis server: i.e. should be compatible with pipelining."
   [as-vector? & body]
   `(let [stashed-replies# (protocol/get-replies! true)]
-     ~@body
-     (let [replies# (protocol/get-replies! ~as-vector?)]
-       (doseq [reply# stashed-replies#] (return reply#))
-       replies#)))
+     (try ~@body
+          (protocol/get-replies! ~as-vector?)
+          (finally
+           ;; Broken in for Clojure <1.5, Ref. http://goo.gl/5DvRt
+           ;; (doseq [reply# stashed-replies#] (return reply#))
+           (dorun (map return stashed-replies#))))))

 (defmacro with-replies     [& body] `(with-replies* false ~@body))
 (defmacro with-replies-vec [& body] `(with-replies* true  ~@body))


Add `with-reply` and `with-replies`

Add `with-reply` and `with-replies`

--- src/taoensso/carmine.clj
+++ src/taoensso/carmine.clj
@@ -64,6 +64,15 @@
   `(with-parser
      (fn [multi-bulk-reply#] (vec (map ~parser-fn multi-bulk-reply#)))
      ~@body))
+
+(defmacro with-reply
+  "Executes body then BLOCKS to receive a single reply from Redis server."
+  [& body] `(do ~@body (protocol/get-one-reply!)))
+
+(defmacro with-replies
+  "Executes body then BLOCKS to receive one or more (pipelined) replies from
+  Redis server."
+  [& body] `(do ~@body (protocol/get-replies!)))

 (defmacro skip-replies
   [& body] `(with-parser (constantly :taoensso.carmine.protocol/skip-reply)


`wcar`, `atomic*` now catch `Throwable`s instead of `Exception`s

AssertionErrors (like :pre/:post cond failures) could previously result in
Redis connections going unreleased.

--- src/taoensso/carmine.clj
+++ src/taoensso/carmine.clj
@@ -50,8 +50,8 @@
          (conns/release-conn pool# conn#)
          response#)

-       (catch Exception e#
-         (conns/release-conn pool# conn# e#) (throw e#))
+       (catch Throwable t# ; nb Throwable to catch assertions, etc.
+         (conns/release-conn pool# conn# t#) (throw t#))

        ;; Restore any stashed replies to preexisting context:
        (finally
@@ -309,10 +309,10 @@
            (loop [idx# 1]
              (try (reset! prelude-result#
                     (protocol/with-replies* :as-pipeline (do ~on-success)))
-                  (catch Exception e#
+                  (catch Throwable t# ; nb Throwable to catch assertions, etc.
                     ;; Always return conn to normal state:
                     (protocol/with-replies* (discard))
-                    (throw e#)))
+                    (throw t#)))
              (let [r# (protocol/with-replies* (exec))]
                (if-not (nil? r#) ; => empty `multi` or watched key changed
                  ;; Was [] with < Carmine v3


Warn on DDB num precision overflows

Warn on DDB num precision overflows

--- src/taoensso/faraday.clj
+++ src/taoensso/faraday.clj
@@ -139,6 +139,19 @@
                         (encore/bytes? x)))
 (defn- stringy? [x] (or (string? x) (keyword? x)))

+(defn- assert-precision [x]
+  (let [^BigDecimal dec (if (string? x) (BigDecimal. ^String x) (bigdec x))]
+    (assert (<= (.precision dec) 38)
+      (str "DynamoDB numbers have <= 38 digits of precision. See `freeze` for "
+           "arbitrary-precision binary serialization."))
+    true))
+
+(comment
+  (assert-precision "0.00000000000000000000000000000000000001")
+  (assert-precision "0.12345678901234567890123456789012345678")
+  (assert-precision "12345678901234567890123456789012345678")
+  (assert-precision 10))
+
 (defn- ddb-native-num? [x]
   "Is `x` a number type natively storable by DynamoDB? Note that DDB stores _all_
   numbers as exact-value strings with <= 38 digits of precision. For greater
@@ -148,10 +161,10 @@
       (instance? Double  x)
       (instance? Integer x)
       (instance? Float   x)
-      ;;
-      (instance? BigInt     x)
-      (instance? BigDecimal x)
-      (instance? BigInteger x)))
+      ;;; High-precision types:
+      (and (instance? BigInt     x) (assert-precision x))
+      (and (instance? BigDecimal x) (assert-precision x))
+      (and (instance? BigInteger x) (assert-precision x))))

 (defn- num->ddb-native-num
   "Coerce any special Clojure types that'd trip up the DDB Java client."


managed-button for extend-trial-clicked

managed-button for extend-trial-clicked

It was already using release-button

--- frontend/components/org_settings.cljs
+++ frontend/components/org_settings.cljs
@@ -222,7 +222,7 @@
                (> 3 (plan-model/days-left-in-trial plan)))
       [:p
        "Need more time to decide? "
-       (forms/stateful-button
+       (forms/managed-button
         [:button.btn.btn-mini.btn-success
          {:data-success-text "Extended!",
           :data-loading-text "Extending...",


comments on the data flow macro

comments on the data flow macro

--- src/clj/algorithms_clj/macro_initiation.clj
+++ src/clj/algorithms_clj/macro_initiation.clj
@@ -548,19 +548,15 @@

 ;; --------------------------------------------------------
 ;; Example 7: Generating some code based on data structure
-;; Something based on description of data model
-;; - Generate the code to save it
-;; - Generate the classes
-;; - Find something else...
 ;;
-;; Show that macros can be used at the business level as well
+;; Macros can be used at the business level as well:
+;; - Expression your business
+;; - Get powerful code for it
 ;;
-;; Other ideas:
-;; - Financial product: create a defrecord with the right
-;; protocols given data describing the product
-;; - Product a data flow for a financial product based
-;; on its dependencies => reactive!
-;; - Produce a data flow for a simple computation
+;; Here we define a computation in terms of variables
+;; - We produce a record for this computation (type)
+;; - We produce an implementation of an evaluator
+;; - Everything is done at compile time (and can be tested)
 ;; --------------------------------------------------------

 (def computation-tree [+ :a [* :b :c]])


Disable debug output

Disable debug output

--- src/clojure/clojurewerkz/cassaforte/cql.clj
+++ src/clojure/clojurewerkz/cassaforte/cql.clj
@@ -23,7 +23,7 @@
     (alter-var-root (var *client*) (constantly c))
     c))

-(def ^:dynamic *debug-output* true)
+(def ^:dynamic *debug-output* false)

 ;; Execute could be a protocol, taht takes either string or map, converts map to string (renders query when
 ;; needed?


4clojure:: impl the palindrome in clojure

--- src/clojure_learning/4clojure-exercises.clj
+++ src/clojure_learning/4clojure-exercises.clj
@@ -68,3 +68,45 @@
       some-num
       (+ (fib (- some-num 1)) (fib (- some-num 2)))))
 (range 1 (inc %))) 8)
+
+(doc letfn)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Write a function which returns true if the given sequence is a palindrome.
+;; preparing:
+(clojure.core/reverse "RACE c ar")
+(= "racecar" (apply str (map str/lower-case (remove #(re-seq #"\s" %) (map str (clojure.core/reverse "RACE c ar")))))); true
+(= "113311" (apply str (map str/lower-case (remove #(re-seq #"\s" %) (map str (clojure.core/reverse [1 1 3 3 1 1])))))); true
+(= ":foo:bar:foo" (apply str (map str/lower-case (remove #(re-seq #"\s" %) (map str (clojure.core/reverse [:foo :bar :foo])))))); true
+
+(remove #(re-seq #"\s" %) (map str (clojure.core/reverse [:foo :bar :foo])))
+
+;; my palindrome function(ignoring upper/lower-case & *whitespaces) follows :)
+(defn palindrome? [subject]
+  (let [post-subj (-> subject
+                      ((partial apply str))
+                      (clojure.string/replace #"\s+" "")
+                      (clojure.string/lower-case))
+        processed (->> subject
+                       clojure.core/reverse
+                       (map str)
+                       (remove #(re-seq #"\s" %))
+                       (map clojure.string/lower-case)
+                       ((partial apply str))
+                       )]
+
+    (= post-subj processed)
+    ))
+
+;; testing::
+(palindrome? "racecar")
+(palindrome? "RACE c ar")
+(palindrome? '(1 2 3 4))
+(palindrome? '(1 1 3 3 1 1))
+(palindrome? [:foo :bar :foo])
+(palindrome? '(:a :b :c))
+
+;; others responded with:
+(true? (#(= (seq %) (clojure.core/reverse (seq %))) "racecar")) ;true
+(true? (#(= (seq %) (clojure.core/reverse (seq %))) "RACE c ar"))
+; But here: false, as opposed to my palindrome function which ignores: upper/lowercase & *whitespaces


Fixed merge issues.

Fixed merge issues.

--- src/cmr/search/services/query_execution.clj
+++ src/cmr/search/services/query_execution.clj
@@ -127,11 +127,11 @@

 (defmethod execute-query :specific-elastic-items
   [context query]
-  (let [elastic-results (->> query
+  (let [processed-query (->> query
                              (pre-process-query-result-features context)
-                             c2s/reduce-query
-                             (r/resolve-collection-queries context)
-                             (idx/execute-query context))
+                             (r/resolve-collection-queries context))
+        processed-query (c2s/reduce-query processed-query context)
+        elastic-results (idx/execute-query context)
         query-results (rc/elastic-results->query-results context query elastic-results)
         query-results (if (:skip-acls? query)
                         query-results
@@ -143,9 +143,9 @@
   [context query]
   (let [processed-query (pre-process-query-result-features context query)

-
-        [collection-ids processed-query] (r/resolve-collection-queries context processed-query)
-        context (assoc context :orbit-collection-ids collection-ids)
+        processed-query (r/resolve-collection-queries context processed-query)
+        ;[collection-ids processed-query] (r/resolve-collection-queries context processed-query)
+        ;context (assoc context :orbit-collection-ids collection-ids)
         processed-query (c2s/reduce-query processed-query context)
         processed-query (if (:skip-acls? processed-query)
                           processed-query


Require hugsql.adapter.clojure-java-jdbc to avoid hugsql.core/get-adapter crashing on first usage

--- src/territory_bro/db.clj
+++ src/territory_bro/db.clj
@@ -10,6 +10,7 @@
             [clojure.tools.logging :as log]
             [conman.core :as conman]
             [hikari-cp.core :as hikari-cp]
+            [hugsql.adapter.clojure-java-jdbc] ; for hugsql.core/get-adapter to not crash on first usage
             [hugsql.core :as hugsql]
             [mount.core :as mount]
             [territory-bro.config :as config]


updates core.cache and core.memoize versions to 0.7.1 (#464)

--- waiter/project.clj
+++ waiter/project.clj
@@ -70,8 +70,8 @@
                  [org.clojure/clojure "1.8.0"]
                  [org.clojure/core.async "0.3.442"
                   :exclusions [org.clojure/clojure org.clojure/tools.reader]]
-                 [org.clojure/core.cache "0.6.5"]
-                 [org.clojure/core.memoize "0.5.9"
+                 [org.clojure/core.cache "0.7.1"]
+                 [org.clojure/core.memoize "0.7.1"
                   :exclusions [org.clojure/clojure]]
                  [org.clojure/data.codec "0.1.0"]
                  [org.clojure/data.json "0.2.6"]


CMR-2291: Fixed typo

CMR-2291: Fixed typo

--- common-app-lib/src/cmr/common_app/api/routes.clj
+++ common-app-lib/src/cmr/common_app/api/routes.clj
@@ -145,7 +145,7 @@
         ((ring-json/wrap-json-response f) request)))))

 (defn add-request-id-response-handler
-  "Adds a request id header to every response to facillitate clientside debugging."
+  "Adds a request id header to every response to facilitate clientside debugging."
   [f]
   (fn [{context :request-context :as request}]
     (if-let [request-id (cxt/context->request-id context)]


permission checks on all org membership modification endpoints.

--- src/metabase/api/org.clj
+++ src/metabase/api/org.clj
@@ -20,15 +20,18 @@
   {:status 200
    :body {}})

+
 (defendpoint GET "/:id" [id]
   (let-404 [{:keys [can_read] :as org} (sel :one Org :id id)]
     (check-403 @can_read)
     org))

+
 (defendpoint GET "/slug/:slug" [slug]
   (let-404 [{:keys [can_read] :as org} (sel :one Org :slug slug)]
     (check-403 @can_read)
     org))
+

 (defendpoint PUT "/:id" [id :as {body :body}]
   (let-404 [{:keys [can_write] :as org} (sel :one Org :id id)]
@@ -77,28 +80,30 @@

 (defendpoint POST "/:id/members/:user-id" [id user-id :as {body :body}]
-  ;; TODO - permissions check
-  (let-404 [org (sel :one Org :id id)]
+  ; user must have admin perms on org to proceed
+  (let-404 [{:keys [can_write] :as org} (sel :one Org :id id)]
+    (check-403 @can_write)
     (let-404 [user (sel :one User :id user-id)]
       (grant-org-perm id user-id (or (:admin body) false))
       {:success true})))

 (defendpoint PUT "/:id/members/:user-id" [id user-id :as {body :body}]
-  ;; TODO - permissions check
-  ;; HMMM, same body as endpoint above in this case.  how can we unify the impl of 2 endpoints?
-  (let-404 [org (sel :one Org :id id)]
+  ; user must have admin perms on org to proceed
+  (let-404 [{:keys [can_write] :as org} (sel :one Org :id id)]
+    (check-403 @can_write)
     (let-404 [user (sel :one User :id user-id)]
       (grant-org-perm id user-id (or (:admin body) false))
       {:success true})))

 (defendpoint DELETE "/:id/members/:user-id" [id user-id :as {body :body}]
-  ;; TODO - permissions check
-  ;; HMMM, same body as endpoint above in this case.  how can we unify the impl of 2 endpoints?
-  (let-404 [org (sel :one Org :id id)]
+  ; user must have admin perms on org to proceed
+  (let-404 [{:keys [can_write] :as org} (sel :one Org :id id)]
+    (check-403 @can_write)
     (let-404 [user (sel :one User :id user-id)]
-      (del OrgPerm :user_id user-id :organization_id id))))
+      (del OrgPerm :user_id user-id :organization_id id)
+      {:success true})))

 (define-routes)


(SERVER-1097) Use timed waits for lockable-pool-test promises

This commit modifies logic in the `lockable-pool-test` tests to use a
timed wait with assertions for all promises other than just ones related
to thread start synchronization.  Hopefully, this would help better
pinpoint any test failures when they occur, as opposed to just having a
test potentially hang and be aborted by a test runner without any better
information to help diagnose the problem.

--- test/unit/puppetlabs/puppetserver/lockable_pool_test.clj
+++ test/unit/puppetlabs/puppetserver/lockable_pool_test.clj
@@ -2,6 +2,10 @@
   (:require [clojure.test :refer :all])
   (:import (com.puppetlabs.puppetserver.pool JRubyPool)
            (java.util.concurrent TimeUnit ExecutionException)))
+
+(defn timed-deref
+  [ref]
+  (deref ref 10000 :timed-out))

 (defn create-empty-pool
   [size]
@@ -60,7 +64,8 @@
                               (.lock pool)
                               (deliver lock-acquired? true)
                               @unlock?
-                              (.unlock pool))]
+                              (.unlock pool)
+                              true)]
       @future-started?
       (testing "pool.lock() blocks until all instances are returned to the pool"
         (is (not (realized? lock-acquired?)))
@@ -73,11 +78,13 @@
           (is (not (realized? lock-acquired?)))
           (.releaseItem pool (nth instances 2)))

-        @lock-acquired?
+        (is (true? (timed-deref lock-acquired?))
+            "timed out waiting for the lock to be acquired")
         (is (not (realized? lock-thread)))
         (is (.isLocked pool))
         (deliver unlock? true)
-        @lock-thread
+        (is (true? (timed-deref lock-thread))
+            "timed out waiting for the lock thread to finish")
         (is (not (.isLocked pool))))

       (testing "borrows may be resumed after unlock()"
@@ -99,7 +106,8 @@
                               (.lock pool)
                               (deliver lock-acquired? true)
                               @unlock?
-                              (.unlock pool))]
+                              (.unlock pool)
+                              true)]
       @future-started?
       (testing "pool.lock() blocks until borrowed instances are unregistered"
         (is (not (realized? lock-thread)))
@@ -110,17 +118,20 @@
           (is (not (realized? lock-thread)))
           (.unregister pool (second instances)))

-        @lock-acquired?
+        (is (true? (timed-deref lock-acquired?))
+            "timed out waiting for the lock thread to be acquired"))
         (is (not (realized? lock-thread)))
         (is (.isLocked pool))
         (deliver unlock? true)
-        @lock-thread
-        (is (not (.isLocked pool)))))
+        (is (true? (timed-deref lock-thread))
+            "timed out waiting for the lock thread to finish"))
+        (is (not (.isLocked pool)))

     (let [future-started? (promise)
           last-instance (.borrowItem pool)
           lock-thread (future (deliver future-started? true)
-                              (.lock pool))]
+                              (.lock pool)
+                              true)]
       @future-started?
       (testing "pool.lock() blocks until last borrowed instance is unregistered"
         (is (not (realized? lock-thread)))
@@ -129,7 +140,8 @@
                       "is being executed")
           (.unregister pool last-instance))

-        @lock-thread
+        (is (true? (timed-deref lock-thread))
+            "timed out waiting for the lock thread to finish")
         (is (.isLocked pool))))))

 (deftest pool-lock-blocks-borrows-test
@@ -145,7 +157,8 @@
                                 (.lock pool)
                                 (deliver lock-acquired? true)
                                 @unlock?
-                                (.unlock pool))]
+                                (.unlock pool)
+                                true)]
         @lock-thread-started?
         (is (not (realized? lock-acquired?)))
         (let [borrow-after-lock-requested-thread-started? (promise)
@@ -154,12 +167,14 @@
               (future (deliver borrow-after-lock-requested-thread-started? true)
                       (let [instance (.borrowItem pool)]
                         (deliver borrow-after-lock-requested-instance-acquired? true)
-                        (.releaseItem pool instance)))]
+                        (.releaseItem pool instance))
+                      true)]
           @borrow-after-lock-requested-thread-started?
           (is (not (realized? borrow-after-lock-requested-instance-acquired?)))

           (return-instances pool instances)
-          @lock-acquired?
+          (is (true? (timed-deref lock-acquired?))
+              "timed out waiting for the lock acquired thread to start")
           (is (.isLocked pool))
           (is (not (realized? borrow-after-lock-requested-instance-acquired?)))
           (is (not (realized? lock-thread)))
@@ -167,20 +182,35 @@
           (let [borrow-after-lock-acquired-thread-started? (promise)
                 borrow-after-lock-acquired-instance-acquired? (promise)
                 borrow-after-lock-acquired-thread
-                (future (deliver borrow-after-lock-acquired-thread-started? (promise))
+                (future (deliver borrow-after-lock-acquired-thread-started?
+                                 true)
                         (let [instance (.borrowItem pool)]
                           (deliver borrow-after-lock-acquired-instance-acquired? true)
-                          (.releaseItem pool instance)))]
+                          (.releaseItem pool instance))
+                        true)]
             @borrow-after-lock-acquired-thread-started?
             (is (not (realized? borrow-after-lock-acquired-instance-acquired?)))

             (deliver unlock? true)
-            @lock-thread
-            @borrow-after-lock-requested-instance-acquired?
-            @borrow-after-lock-requested-thread
-            @borrow-after-lock-acquired-instance-acquired?
-            @borrow-after-lock-acquired-thread
-            (is (not (.isLocked pool)))))))))
+
+            (is (true? (timed-deref lock-thread))
+                "timed out waiting for the lock thread to finish")
+            (is (true? (timed-deref
+                        borrow-after-lock-requested-instance-acquired?))
+                (str "timed out waiting for the borrow after lock requested "
+                     "to be completed"))
+            (is (true? (timed-deref
+                        borrow-after-lock-requested-thread))
+                (str "timed out waiting for the borrow after lock requested "
+                     "thread to finish"))
+            (is (true? (timed-deref
+                        borrow-after-lock-acquired-instance-acquired?))
+                "timed out waiting for the borrow after lock acquired")
+            (is (true? (timed-deref
+                        borrow-after-lock-acquired-thread))
+                (str "timed out waiting for the borrow after lock acquired "
+                     "thread to finish")))))
+            (is (not (.isLocked pool))))))

 (deftest pool-lock-supersedes-existing-borrows-test
   (testing "if there are pending borrows when pool.lock() is called, they aren't fulfilled until after unlock()"
@@ -191,7 +221,8 @@
           blocked-borrow-thread (future (deliver blocked-borrow-thread-started? true)
                                         (let [instance (.borrowItem pool)]
                                           (deliver blocked-borrow-thread-borrowed? true)
-                                          (.releaseItem pool instance)))
+                                          (.releaseItem pool instance))
+                                        true)
           lock-thread-started? (promise)
           lock-acquired? (promise)
           unlock? (promise)
@@ -199,7 +230,8 @@
                               (.lock pool)
                               (deliver lock-acquired? true)
                               @unlock?
-                              (.unlock pool))]
+                              (.unlock pool)
+                              true)]
       @blocked-borrow-thread-started?
       @lock-thread-started?
       (is (not (realized? blocked-borrow-thread-borrowed?)))
@@ -208,14 +240,17 @@
       (return-instances pool instances)
       (is (not (realized? blocked-borrow-thread-borrowed?)))
       (is (not (realized? lock-thread)))
-      @lock-acquired?
+      (is (true? (timed-deref lock-acquired?))
+          "timed out waiting for the lock to be acquired")
       (is (.isLocked pool))

       (deliver unlock? true)
-      @lock-thread
-      @blocked-borrow-thread-borrowed?
-      @blocked-borrow-thread
-
+      (is (true? (timed-deref lock-thread))
+          "timed out waiting for the lock thread to finish")
+      (is (true? (timed-deref blocked-borrow-thread-borrowed?))
+          "timed out waiting for the borrow to complete")
+      (is (true? (timed-deref blocked-borrow-thread))
+          "timed out waiting for the borrow thread to complete")
       (is (not (.isLocked pool))))))

 (deftest pool-lock-reentrant-for-borrow-from-locking-thread
@@ -244,11 +279,13 @@
             borrow-thread-1 (future (deliver borrow-thread-started-1? true)
                                     (let [instance (.borrowItem pool)]
                                       (deliver borrow-thread-borrowed-1? true)
-                                      (.releaseItem pool instance)))
+                                      (.releaseItem pool instance))
+                                    true)
             borrow-thread-2 (future (deliver borrow-thread-started-2? true)
                                     (let [instance (.borrowItem pool)]
                                       (deliver borrow-thread-borrowed-2? true)
-                                      (.releaseItem pool instance)))]
+                                      (.releaseItem pool instance))
+                                    true)]
         @borrow-thread-started-1?
         @borrow-thread-started-2?
         (is (not (realized? borrow-thread-borrowed-1?)))
@@ -260,9 +297,11 @@

         (is (true? true))
         (.unlock pool)
-        @borrow-thread-1
-        @borrow-thread-2
-        (is (not (.isLocked pool)))))))
+        (is (true? (timed-deref borrow-thread-1))
+            "timed out waiting for first borrow thread to finish")
+        (is (true? (timed-deref borrow-thread-2))
+            "timed out waiting for second borrow thread to finish"))
+        (is (not (.isLocked pool))))))

 (deftest pool-lock-reentrant-for-many-locks-test
   (testing "multiple threads cannot lock the pool while it is already locked"
@@ -277,21 +316,23 @@
             lock-thread-1 (future (deliver lock-thread-started-1? true)
                                   (.lock pool)
                                   (deliver lock-thread-locked-1? true)
-                                  (.unlock pool))
+                                  (.unlock pool)
+                                  true)
             lock-thread-2 (future (deliver lock-thread-started-2? true)
                                   (.lock pool)
                                   (deliver lock-thread-locked-2? true)
-                                  (.unlock pool))]
+                                  (.unlock pool)
+                                  true)]
         @lock-thread-started-1?
         @lock-thread-started-2?
         (is (not (realized? lock-thread-locked-1?)))
         (is (not (realized? lock-thread-locked-2?)))
         (.unlock pool)
-        (is (true? true))
-        @lock-thread-1
-        (is (true? true))
-        @lock-thread-2
-        (is (not (.isLocked pool)))))))
+        (is (true? (timed-deref lock-thread-1))
+            "timed out waiting for first lock thread to finish")
+        (is (true? (timed-deref lock-thread-2))
+            "timed out waiting for second lock thread to finish"))
+        (is (not (.isLocked pool))))))

 (deftest pool-lock-not-held-after-thread-interrupt
   (let [pool (create-populated-pool 1)
@@ -304,9 +345,10 @@
     (testing (str "write locker's thread can be interrupted while waiting for "
                   "instances to be returned")
       (.interrupt @lock-thread-obj)
-      (is (thrown? ExecutionException @lock-thread))
-      (is (not (realized? lock-thread-locked?)))
-      (is (not (.isLocked pool))))
+      (is (thrown? ExecutionException (timed-deref lock-thread)))
+      (is (not (realized? lock-thread-locked?))))
+      (is (not (.isLocked pool)))
+
     (.releaseItem pool item)
     (testing "new write lock can be taken after prior write lock interrupted"
       (.lock pool)
@@ -323,12 +365,14 @@
           lock-thread (future (.lock pool)
                               (deliver lock-started? true)
                               @unlock?
-                              (.unlock pool))]
+                              (.unlock pool)
+                              true)]
       @lock-started?
       (is (.isLocked pool))
       (is (thrown? IllegalStateException (.unlock pool)))
       (deliver unlock? true)
-      @lock-thread
+      (is (true? (timed-deref lock-thread))
+          "timed out waiting for lock thread to finish")
       (is (not (.isLocked pool))))))

 (deftest pool-release-item-test
@@ -343,14 +387,19 @@
       (is (not (.isLocked pool)))
       (.lock pool)
       (is (.isLocked pool))
-      (is (nil? @(future (.borrowItemWithTimeout pool
-                                                 1
-                                                 TimeUnit/MICROSECONDS))))
+      (is (nil? (timed-deref
+                  (future (.borrowItemWithTimeout pool
+                                                   1
+                                                   TimeUnit/MICROSECONDS))))
+          "timed out waiting for borrow with timeout in lock to finish")
       (.unlock pool)
-      (is (not (nil? @(future (.borrowItemWithTimeout pool
+      (is (not (nil? (timed-deref
+                      (future (.borrowItemWithTimeout pool
                                                       1
                                                       TimeUnit/MICROSECONDS)))))
+          "timed out waiting for borrow with timeout after unlock to finish")
       (is (not (.isLocked pool)))))
+
   (testing (str "releaseItem call with value 'true' returns item to "
                 "pool and allows pool to still be lockable")
     (let [pool (create-populated-pool 2)
@@ -361,13 +410,17 @@
       (is (not (.isLocked pool)))
       (.lock pool)
       (is (.isLocked pool))
-      (is (nil? @(future (.borrowItemWithTimeout pool
+      (is (nil? (timed-deref
+                 (future (.borrowItemWithTimeout pool
                                                  1
                                                  TimeUnit/MICROSECONDS))))
+          "timed out waiting for borrow with timeout in lock to finish")
       (.unlock pool)
-      (is (not (nil? @(future (.borrowItemWithTimeout pool
+      (is (not (nil? (timed-deref
+                      (future (.borrowItemWithTimeout pool
                                                       1
                                                       TimeUnit/MICROSECONDS)))))
+          "timed out waiting for borrow with timeout after unlock to finish")
       (is (not (.isLocked pool))))))

 (deftest pool-borrow-blocks-borrow-when-pool-empty
@@ -379,24 +432,30 @@
           borrow-thread (future (deliver borrow-thread-started? true)
                                 (let [instance (.borrowItem pool)]
                                   (deliver borrow-thread-borrowed? true)
-                                  (.releaseItem pool instance)))]
+                                  (.releaseItem pool instance))
+                                true)]
       @borrow-thread-started?
       (is (not (realized? borrow-thread-borrowed?)))
       (.releaseItem pool item)
-      @borrow-thread
-      (is (true? true)))))
+      (is (true? (timed-deref borrow-thread))
+          "timed out waiting for borrow thread to finish"))))

 (deftest pool-timed-borrows-test
   (testing "pool borrows with timeout"
     (let [pool (create-populated-pool 1)
           item (.borrowItem pool)]
       (testing "borrow times out and returns nil when pool is empty"
-        (is (nil? (.borrowItemWithTimeout pool 1 TimeUnit/MICROSECONDS))))
+        (is (nil? (timed-deref
+                   (future (.borrowItemWithTimeout pool
+                                                   1
+                                                   TimeUnit/MICROSECONDS))))))
       (.releaseItem pool item)
       (testing "borrow succeeds when pool is non-empty"
-        (is (identical? item (.borrowItemWithTimeout pool
-                                                     1
-                                                     TimeUnit/MICROSECONDS)))))))
+        (is (identical? item (timed-deref
+                              (future (.borrowItemWithTimeout
+                                       pool
+                                       1
+                                       TimeUnit/MICROSECONDS)))))))))

 (deftest pool-can-do-blocking-borrow-after-borrow-timed-out
   (testing "can do blocking borrow from pool after previous borrow timed out"
@@ -408,12 +467,13 @@
             borrow-thread (future (deliver borrow-thread-started? true)
                                   (let [instance (.borrowItem pool)]
                                     (deliver borrow-thread-borrowed? true)
-                                    (.releaseItem pool instance)))]
+                                    (.releaseItem pool instance))
+                                  true)]
         @borrow-thread-started?
         (is (not (realized? borrow-thread-borrowed?)))
         (.releaseItem pool item)
-        @borrow-thread
-        (is (true? true))))))
+        (is (true? (timed-deref borrow-thread))
+            "timed out waiting for borrow thread to finish")))))

 (deftest pool-can-do-blocking-borrow-after-borrow-timed-out-during-lock
   (testing (str "can do a blocking borrow from pool after previous borrow "
@@ -421,19 +481,24 @@
     (let [pool (create-populated-pool 1)]
       (.lock pool)
       (is (.isLocked pool))
-      (is (nil? @(future (.borrowItemWithTimeout pool
+      (is (nil? (timed-deref
+                 (future (.borrowItemWithTimeout pool
                                                  1
                                                  TimeUnit/MICROSECONDS))))
+          "timed out waiting for borrow with timeout to finish")
+
       (let [borrow-thread-started? (promise)
             borrow-thread-borrowed? (promise)
             borrow-thread (future (deliver borrow-thread-started? true)
                                   (let [instance (.borrowItem pool)]
                                     (deliver borrow-thread-borrowed? true)
-                                    (.releaseItem pool instance)))]
+                                    (.releaseItem pool instance))
+                                  true)]
         @borrow-thread-started?
         (is (not (realized? borrow-thread-borrowed?)))
         (.unlock pool)
-        @borrow-thread
+        (is (true? (timed-deref borrow-thread))
+            "timed out waiting for borrow thread to finish")
         (is (not (.isLocked pool)))))))

 (deftest pool-can-borrow-after-borrow-interrupted-during-lock
@@ -460,25 +525,28 @@
                        (.lock pool)
                        (deliver lock-thread-locked? true)
                        @unlock?
-                       (.unlock pool))]
+                       (.unlock pool)
+                       true)]
       @lock-thread-started?
       (.releaseItem pool borrow-1)
-      @lock-thread-locked?
-      (is (.isLocked pool))
+      (is (true? (timed-deref lock-thread-locked?))
+          "timed out waiting for the lock to be acquired")
+      (is (true? (.isLocked pool)))
       ;; Interrupt the second borrow thread so that it will stop waiting for the
       ;; pool to be not empty and not locked.
       (.interrupt borrow-thread-obj-2)
-      (is (thrown? ExecutionException @borrow-thread-2)
+      (is (thrown? ExecutionException (timed-deref borrow-thread-2))
           "second borrow could not be interrupted")
       (is (not (realized? borrow-thread-3)))
       (deliver unlock? true)
-      @lock-thread
+      (is (true? (timed-deref lock-thread))
+          "timed out waiting for the lock thread to finish")
       (is (not (.isLocked pool)))
       ;; If the third borrow doesn't block indefinitely, we've confirmed that
       ;; the interruption of the second borrow while the write lock was
       ;; held did not adversely affect the ability of the third borrow call
       ;; to return.
-      (is (identical? borrow-1 @borrow-thread-3)
+      (is (identical? borrow-1 (timed-deref borrow-thread-3))
           (str "did not get back the same instance from the third borrow"
                "attempt as was returned from the first borrow attempt")))))

@@ -510,17 +578,20 @@
                        (.lock pool)
                        (deliver lock-thread-locked? true)
                        @unlock?
-                       (.unlock pool))]
+                       (.unlock pool)
+                       true)]
       @lock-thread-started?
       (.releaseItem pool borrow-1)
-      @lock-thread-locked?
-      (is (.isLocked pool))
-      (is (nil? @borrow-thread-2)
+      (is (true? (timed-deref lock-thread-locked?))
+          "timed out waiting for the lock to be acquired")
+      (is (.isLocked pool))
+      (is (nil? (timed-deref borrow-thread-2))
           "second borrow attempt did not time out")
       (deliver unlock? true)
-      @lock-thread
-      (is (not (.isLocked pool)))
-      (is (identical? borrow-1 @borrow-thread-3)
+      (is (true? (timed-deref lock-thread))
+          "timed out waiting for the lock thread to finish")
+      (is (not (.isLocked pool)))
+      (is (identical? borrow-1 (timed-deref borrow-thread-3))
           (str "did not get back the same instance from the third borrow"
                "attempt as was returned from the first borrow attempt")))))


Sortable sensors table.

Sortable sensors table.

--- src-cljs/kixi/hecuba/tabs/programmes.cljs
+++ src-cljs/kixi/hecuba/tabs/programmes.cljs
@@ -504,11 +504,19 @@
     [:span {:class "label label-success"} status]
     [:span {:class "label label-danger"} status]))

+(defn sorting-th [owner label sort-key sorted-by]
+  [:th {:onClick (fn [_ _] (om/set-state! owner :sort-by sort-key))}
+   (str label " ") (if (= sort-key sorted-by) [:i.fa.fa-sort-asc] " ")])
+
 (defn sensors-table [data owner {:keys [histkey path]}]
   (reify
-    om/IRender
-    (render [_]
-      (let [sensors              (:sensors data)
+    om/IInitState
+    (init-state [_]
+      {:sort-by :type})
+    om/IRenderState
+    (render-state [_ state]
+      (let [sorted-by            (:sort-by state)
+            sensors              (:sensors data)
             selected-property-id (-> data :active-components :properties)
             flattened-sensors    (get-sensors selected-property-id data)
             chart                (:chart data)
@@ -517,9 +525,14 @@
         (html
          [:table {:className "table table-hover"}
           [:thead
-           [:tr [:th "Type"] [:th "Unit"] [:th "Period"] [:th "Device"] [:th "Status"]]]
+           [:tr
+            (sorting-th owner "Type" :type sorted-by)
+            (sorting-th owner "Unit" :unit sorted-by)
+            (sorting-th owner "Period" :period sorted-by)
+            (sorting-th owner "Device" :device_id sorted-by)
+            (sorting-th owner "Status" :status sorted-by)]]
           [:tbody
-           (for [row (sort-by :type flattened-sensors)]
+           (for [row (sort-by sorted-by flattened-sensors)]
              (let [{:keys [device_id type unit period status]} row
                    id (str type "-" device_id)]
                [:tr {:onClick (fn [_ _]


Fix typo

Fix typo

--- src/cljs/koeeoadi/components/history.cljs
+++ src/cljs/koeeoadi/components/history.cljs
@@ -13,7 +13,7 @@
    'theme/select           "change theme"
    'theme/rename           "rename theme"
    'theme/new              "new theme"
-   'theme/load             "loa theme"
+   'theme/load             "load theme"
    'user-face/add          "add face"
    'user-face/change-name  "change face name"
    'user-face/remove       "remove face"


Use the right transaction key

Use the right transaction key

--- src/cljs/mdr2/productions/production.cljs
+++ src/cljs/mdr2/productions/production.cljs
@@ -41,7 +41,7 @@
       [:tbody
        [:tr [:th {:width 200} (tr [:title])] [:td title]]
        [:tr [:th (tr [:creator])] [:td creator]]
-       [:tr [:th (tr [:source-publisher])] [:td source_publisher]]
+       [:tr [:th (tr [:source_publisher])] [:td source_publisher]]
        [:tr [:th (tr [:state])] [:td state]]]]])

 (defn details [production]