Back
read (clj)
(source)function
(read)
(read stream)
(read opts stream)
Reads the next object from stream, which must be an instance of
java.io.PushbackReader or some derivee. stream defaults to the
current value of *in*.
Reads data in the edn format (subset of Clojure data):
http://edn-format.org
opts is a map that can include the following keys:
:eof - value to return on end-of-file. When not supplied, eof throws an exception.
:readers - a map of tag symbols to data-reader functions to be considered before default-data-readers.
When not supplied, only the default-data-readers will be used.
:default - A function of two args, that will, if present and no reader is found for a tag,
be called with the tag and the value.
Examples
clojure
(ns clojure.test-clojure.reader
(:use clojure.test)
(:use [clojure.instant :only [read-instant-date
read-instant-calendar
read-instant-timestamp]])
(:require clojure.walk
[clojure.edn :as edn]
[clojure.test.generative :refer (defspec)]
[clojure.test-clojure.generators :as cgen]
[clojure.edn :as edn])
(:import [clojure.lang BigInt Ratio]
java.io.File
java.util.TimeZone))
(defn read-from
[source file form]
(if (= :string source)
(read-string form)
(do
(spit file form)
(load-file (str file)))))
(deftest Strings
(is (= "abcde" (str \a \b \c \d \e)))
(is (= "abc
def" (str \a \b \c \newline \space \space \d \e \f)))
(let [f (temp-file "clojure.core-reader" "test")]
(doseq [source [:string :file]]
(testing (str "Valid string literals read from " (name source))
(are [x form] (= x (code-units
(read-from source f (str "\"" form "\""))))
[] ""
[34] "\\\""
[10] "\\n"
[0] "\\u0000"
[0xd7ff] "\\ud7ff"
[0xd800] "\\ud800"
[0xdfff] "\\udfff"
[0xe000] "\\ue000"
[0xffff] "\\uffff"
[4 49] "\\u00041"))
(testing (str "Errors reading string literals from " (name source))
(are [err msg form] (thrown-with-cause-msg? err msg
(read-from source f (str "\"" form "\"")))
Exception #"EOF while reading string" "\\"
Exception #"Unsupported escape character: \\o" "\\o"
(deftest t-Characters
(let [f (temp-file "clojure.core-reader" "test")]
(doseq [source [:string :file]]
(testing (str "Valid char literals read from " (name source))
(are [x form] (= x (read-from source f form))
(first "o") "\\o"
(char 0) "\\o0"
(char 0) "\\o000"
(char 047) "\\o47"
(char 0377) "\\o377"
(first "u") "\\u"
(first "A") "\\u0041"
(char 0) "\\u0000"
(char 0xd7ff) "\\ud7ff"
(char 0xe000) "\\ue000"
(char 0xffff) "\\uffff"))
(testing (str "Errors reading char literals from " (name source))
(are [err msg form] (thrown-with-cause-msg? err msg (read-from source f form))
Exception #"EOF while reading character" "\\"
Exception #"Unsupported character: \\00" "\\00"
Exception #"Unsupported character: \\0009" "\\0009"
(deftest reading-keywords
(are [x y] (= x (binding [*ns* (the-ns 'user)] (read-string y)))
:foo ":foo"
:foo/bar ":foo/bar"
:user/foo "::foo")
(are [err msg form] (thrown-with-msg? err msg (read-string form))
Exception #"Invalid token: foo:" "foo:"
Exception #"Invalid token: :bar/" ":bar/"
Exception #"Invalid token: ::does.not/exist" "::does.not/exist"))
;; Lists
(deftest t-line-column-numbers
(let [code "(ns reader-metadata-test
(:require [clojure.java.io
:refer (resource reader)]))
(let [a 5]
^:added-metadata
(defn add-5
[x]
(reduce + x (range a))))"
stream (clojure.lang.LineNumberingPushbackReader.
(java.io.StringReader. code))
top-levels (take-while identity (repeatedly #(read stream false nil)))
expected-metadata '{ns {:line 1, :column 1}
:require {:line 2, :column 3}
resource {:line 3, :column 21}
let {:line 5, :column 1}
defn {:line 6, :column 3 :added-metadata true}
reduce {:line 9, :column 5}
range {:line 9, :column 17}}
verified-forms (atom 0)]
(doseq [form top-levels]
(clojure.walk/postwalk
#(when (list? %)
(is (= (expected-metadata (first %))
(meta %)))
(is (->> (meta %)
vals
(filter number?)
(every? (partial instance? Integer))))
(swap! verified-forms inc))
form))
;; sanity check against e.g. reading returning ()
(is (= (count expected-metadata) @verified-forms))))
;; (read)
;; (read stream)
;; (read stream eof-is-error)
;; (read stream eof-is-error eof-value)
;; (read stream eof-is-error eof-value is-recursive)
(deftest t-read)
(deftest Instants
(testing "Instants are read as java.util.Date by default"
(is (= java.util.Date (class #inst "2010-11-12T13:14:15.666"))))
(let [s "#inst \"2010-11-12T13:14:15.666-06:00\""]
(binding [*data-readers* {'inst read-instant-date}]
(testing "read-instant-date produces java.util.Date"
(is (= java.util.Date (class (read-string s)))))
(testing "java.util.Date instants round-trips"
(is (= (-> s read-string)
(-> s read-string pr-str read-string))))
(testing "java.util.Date instants round-trip throughout the year"
(doseq [month (range 1 13) day (range 1 29) hour (range 1 23)]
(let [s (format "#inst \"2010-%02d-%02dT%02d:14:15.666-06:00\"" month day hour)]
(is (= (-> s read-string)
(-> s read-string pr-str read-string))))))
(testing "java.util.Date handling DST in time zones"
(let [dtz (TimeZone/getDefault)]
(try
;; A timezone with DST in effect during 2010-11-12
(TimeZone/setDefault (TimeZone/getTimeZone "Australia/Sydney"))
(is (= (-> s read-string)
(-> s read-string pr-str read-string)))
(finally (TimeZone/setDefault dtz)))))
(testing "java.util.Date should always print in UTC"
(let [d (read-string s)
pstr (print-str d)
len (.length pstr)]
(is (= (subs pstr (- len 7)) "-00:00\"")))))
(binding [*data-readers* {'inst read-instant-calendar}]
(testing "read-instant-calendar produces java.util.Calendar"
(is (instance? java.util.Calendar (read-string s))))
(testing "java.util.Calendar round-trips"
(is (= (-> s read-string)
(-> s read-string pr-str read-string))))
(testing "java.util.Calendar remembers timezone in literal"
(is (= "#inst \"2010-11-12T13:14:15.666-06:00\""
(-> s read-string pr-str)))
(is (= (-> s read-string)
(-> s read-string pr-str read-string))))
(testing "java.util.Calendar preserves milliseconds"
(is (= 666 (-> s read-string
(.get java.util.Calendar/MILLISECOND)))))))
(let [s "#inst \"2010-11-12T13:14:15.123456789\""
s2 "#inst \"2010-11-12T13:14:15.123\""
s3 "#inst \"2010-11-12T13:14:15.123456789123\""]
(binding [*data-readers* {'inst read-instant-timestamp}]
(testing "read-instant-timestamp produces java.sql.Timestamp"
(is (= java.sql.Timestamp (class (read-string s)))))
(testing "java.sql.Timestamp preserves nanoseconds"
(is (= 123456789 (-> s read-string .getNanos)))
(is (= 123456789 (-> s read-string pr-str read-string .getNanos)))
;; truncate at nanos for s3
(is (= 123456789 (-> s3 read-string pr-str read-string .getNanos))))
(testing "java.sql.Timestamp should compare nanos"
(is (= (read-string s) (read-string s3)))
(is (not= (read-string s) (read-string s2)))))
(binding [*data-readers* {'inst read-instant-date}]
(testing "read-instant-date should truncate at milliseconds"
(is (= (read-string s) (read-string s2) (read-string s3))))))
(let [s "#inst \"2010-11-12T03:14:15.123+05:00\""
s2 "#inst \"2010-11-11T22:14:15.123Z\""]
(binding [*data-readers* {'inst read-instant-date}]
(testing "read-instant-date should convert to UTC"
(is (= (read-string s) (read-string s2)))))
(binding [*data-readers* {'inst read-instant-timestamp}]
(testing "read-instant-timestamp should convert to UTC"
(is (= (read-string s) (read-string s2)))))
(binding [*data-readers* {'inst read-instant-calendar}]
(testing "read-instant-calendar should preserve timezone"
(is (not= (read-string s) (read-string s2)))))))
(deftest unknown-tag
(let [my-unknown (fn [tag val] {:unknown-tag tag :value val})
throw-on-unknown (fn [tag val] (throw (RuntimeException. (str "No data reader function for tag " tag))))
my-uuid (partial my-unknown 'uuid)
u "#uuid \"550e8400-e29b-41d4-a716-446655440000\""
s "#never.heard.of/some-tag [1 2]" ]
(binding [*data-readers* {'uuid my-uuid}
*default-data-reader-fn* my-unknown]
(testing "Unknown tag"
(is (= (read-string s)
{:unknown-tag 'never.heard.of/some-tag
:value [1 2]})))
(testing "Override uuid tag"
(is (= (read-string u)
{:unknown-tag 'uuid
:value "550e8400-e29b-41d4-a716-446655440000"}))))
(binding [*default-data-reader-fn* throw-on-unknown]
(testing "Unknown tag with custom throw-on-unknown"
(are [err msg form] (thrown-with-msg? err msg (read-string form))
Exception #"No data reader function for tag foo" "#foo [1 2]"
Exception #"No data reader function for tag bar/foo" "#bar/foo [1 2]"
Exception #"No data reader function for tag bar.baz/foo" "#bar.baz/foo [1 2]")))
(testing "Unknown tag out-of-the-box behavior (like Clojure 1.4)"
(are [err msg form] (thrown-with-msg? err msg (read-string form))
Exception #"No reader function for tag foo" "#foo [1 2]"
Exception #"No reader function for tag bar/foo" "#bar/foo [1 2]"
Exception #"No reader function for tag bar.baz/foo" "#bar.baz/foo [1 2]"))))
(defn roundtrip
"Print an object and read it back. Returns rather than throws
any exceptions."
[o]
(binding [*print-length* nil
*print-dup* nil
*print-level* nil]
(try
(-> o pr-str read-string)
(catch Throwable t t))))
(defn roundtrip-dup
"Print an object with print-dup and read it back.
Returns rather than throws any exceptions."
[o]
(binding [*print-length* nil
*print-dup* true
*print-level* nil]
(try
(-> o pr-str read-string)
(catch Throwable t t))))
(defspec types-that-should-roundtrip
roundtrip
[^{:tag cgen/ednable} o]
(when-not (= o %)
(throw (ex-info "Value cannot roundtrip, see ex-data" {:printed o :read %}))))
(defspec types-that-need-dup-to-roundtrip
roundtrip-dup
[^{:tag cgen/dup-readable} o]
(when-not (= o %)
(throw (ex-info "Value cannot roundtrip, see ex-data" {:printed o :read %}))))
(deftest preserve-read-cond-test
(let [x (read-string {:read-cond :preserve} "#?(:clj foo :cljs bar)" )]
(is (reader-conditional? x))
(is (not (:splicing? x)))
(is (= :foo (get x :no-such-key :foo)))
(is (= (:form x) '(:clj foo :cljs bar)))
(is (= x (reader-conditional '(:clj foo :cljs bar) false))))
(let [x (read-string {:read-cond :preserve} "#?@(:clj [foo])" )]
(is (reader-conditional? x))
(is (:splicing? x))
(is (= :foo (get x :no-such-key :foo)))
(is (= (:form x) '(:clj [foo])))
(is (= x (reader-conditional '(:clj [foo]) true))))
(is (thrown-with-msg? RuntimeException #"No reader function for tag"
(read-string {:read-cond :preserve} "#js {:x 1 :y 2}" )))
(let [x (read-string {:read-cond :preserve} "#?(:cljs #js {:x 1 :y 2})")
[platform tl] (:form x)]
(is (reader-conditional? x))
(is (tagged-literal? tl))
(is (= 'js (:tag tl)))
(is (= {:x 1 :y 2} (:form tl)))
(is (= :foo (get tl :no-such-key :foo)))
(is (= tl (tagged-literal 'js {:x 1 :y 2}))))
(testing "print form roundtrips"
(doseq [s ["#?(:clj foo :cljs bar)"
"#?(:cljs #js {:x 1, :y 2})"
"#?(:clj #clojure.test_clojure.reader.TestRecord [42 85])"]]
(is (= s (pr-str (read-string {:read-cond :preserve} s)))))))
(deftest reader-conditionals
(testing "basic read-cond"
(is (= '[foo-form]
(read-string {:read-cond :allow :features #{:foo}} "[#?(:foo foo-form :bar bar-form)]")))
(is (= '[bar-form]
(read-string {:read-cond :allow :features #{:bar}} "[#?(:foo foo-form :bar bar-form)]")))
(is (= '[foo-form]
(read-string {:read-cond :allow :features #{:foo :bar}} "[#?(:foo foo-form :bar bar-form)]")))
(is (= '[]
(read-string {:read-cond :allow :features #{:baz}} "[#?( :foo foo-form :bar bar-form)]"))))
(testing "environmental features"
(is (= "clojure" #?(:clj "clojure" :cljs "clojurescript" :default "default"))))
(testing "default features"
(is (= "default" #?(:clj-clr "clr" :cljs "cljs" :default "default"))))
(testing "splicing"
(is (= [] [#?@(:clj [])]))
(is (= [:a] [#?@(:clj [:a])]))
(is (= [:a :b] [#?@(:clj [:a :b])]))
(is (= [:a :b :c] [#?@(:clj [:a :b :c])]))
(is (= [:a :b :c] [#?@(:clj [:a :b :c])])))
(testing "nested splicing"
(is (= [:a :b :c :d :e]
[#?@(:clj [:a #?@(:clj [:b #?@(:clj [:c]) :d]):e])]))
(is (= '(+ 1 (+ 2 3))
'(+ #?@(:clj [1 (+ #?@(:clj [2 3]))]))))
(is (= '(+ (+ 2 3) 1)
'(+ #?@(:clj [(+ #?@(:clj [2 3])) 1]))))
(is (= [:a [:b [:c] :d] :e]
[#?@(:clj [:a [#?@(:clj [:b #?@(:clj [[:c]]) :d])] :e])])))
(testing "bypass unknown tagged literals"
(is (= [1 2 3] #?(:cljs #js [1 2 3] :clj [1 2 3])))
(is (= :clojure #?(:foo #some.nonexistent.Record {:x 1} :clj :clojure))))
(testing "error cases"
(is (thrown-with-msg? RuntimeException #"Feature should be a keyword" (read-string {:read-cond :allow} "#?((+ 1 2) :a)")))
(is (thrown-with-msg? RuntimeException #"even number of forms" (read-string {:read-cond :allow} "#?(:cljs :a :clj)")))
(is (thrown-with-msg? RuntimeException #"read-cond-splicing must implement" (read-string {:read-cond :allow} "#?@(:clj :a)")))
(is (thrown-with-msg? RuntimeException #"is reserved" (read-string {:read-cond :allow} "#?@(:foo :a :else :b)")))
(is (thrown-with-msg? RuntimeException #"must be a list" (read-string {:read-cond :allow} "#?[:foo :a :else :b]")))
(is (thrown-with-msg? RuntimeException #"Conditional read not allowed" (read-string {:read-cond :BOGUS} "#?[:clj :a :default nil]")))
(is (thrown-with-msg? RuntimeException #"Conditional read not allowed" (read-string "#?[:clj :a :default nil]")))
(is (thrown-with-msg? RuntimeException #"Reader conditional splicing not allowed at the top level" (read-string {:read-cond :allow} "#?@(:clj [1 2])")))
(is (thrown-with-msg? RuntimeException #"Reader conditional splicing not allowed at the top level" (read-string {:read-cond :allow} "#?@(:clj [1])")))
(is (thrown-with-msg? RuntimeException #"Reader conditional splicing not allowed at the top level" (read-string {:read-cond :allow} "#?@(:clj []) 1"))))
(testing "clj-1698-regression"
(let [opts {:features #{:clj} :read-cond :allow}]
(is (= 1 (read-string opts "#?(:cljs {'a 1 'b 2} :clj 1)")))
(is (= 1 (read-string opts "#?(:cljs (let [{{b :b} :a {d :d} :c} {}]) :clj 1)")))
(is (= '(def m {}) (read-string opts "(def m #?(:cljs ^{:a :b} {} :clj ^{:a :b} {}))")))
(is (= '(def m {}) (read-string opts "(def m #?(:cljs ^{:a :b} {} :clj ^{:a :b} {}))")))
(is (= 1 (read-string opts "#?(:cljs {:a #_:b :c} :clj 1)")))))
(testing "nil expressions"
(is (nil? #?(:default nil)))
(is (nil? #?(:foo :bar :clj nil)))
(is (nil? #?(:clj nil :foo :bar)))
(is (nil? #?(:foo :bar :default nil)))))
(deftest eof-option
(is (= 23 (read-string {:eof 23} "")))
(is (= 23 (read {:eof 23} (clojure.lang.LineNumberingPushbackReader.
(java.io.StringReader. ""))))))
(require '[clojure.string :as s])
(deftest namespaced-maps
(is (= #:a{1 nil, :b nil, :b/c nil, :_/d nil}
#:a {1 nil, :b nil, :b/c nil, :_/d nil}
{1 nil, :a/b nil, :b/c nil, :d nil}))
(is (= #::{1 nil, :a nil, :a/b nil, :_/d nil}
#:: {1 nil, :a nil, :a/b nil, :_/d nil}
{1 nil, :clojure.test-clojure.reader/a nil, :a/b nil, :d nil} ))
(is (= #::s{1 nil, :a nil, :a/b nil, :_/d nil}
#::s {1 nil, :a nil, :a/b nil, :_/d nil}
{1 nil, :clojure.string/a nil, :a/b nil, :d nil}))
(is (= (read-string "#:a{b 1 b/c 2}") {'a/b 1, 'b/c 2}))
(is (= (binding [*ns* (the-ns 'clojure.test-clojure.reader)] (read-string "#::{b 1, b/c 2, _/d 3}")) {'clojure.test-clojure.reader/b 1, 'b/c 2, 'd 3}))
(is (= (binding [*ns* (the-ns 'clojure.test-clojure.reader)] (read-string "#::s{b 1, b/c 2, _/d 3}")) {'clojure.string/b 1, 'b/c 2, 'd 3})))
(deftest namespaced-map-errors
(are [err msg form] (thrown-with-msg? err msg (read-string form))
Exception #"Invalid token" "#:::"
Exception #"Namespaced map literal must contain an even number of forms" "#:s{1}"
Exception #"Namespaced map must specify a valid namespace" "#:s/t{1 2}"
Exception #"Unknown auto-resolved namespace alias" "#::BOGUS{1 2}"
Exception #"Namespaced map must specify a namespace" "#: s{:a 1}"
Exception #"Duplicate key: :user/a" "#::{:a 1 :a 2}"
Exception #"Duplicate key: user/a" "#::{a 1 a 2}"))
(deftest namespaced-map-edn
(is (= {1 1, :a/b 2, :b/c 3, :d 4}
(edn/read-string "#:a{1 1, :b 2, :b/c 3, :_/d 4}")
(edn/read-string "#:a {1 1, :b 2, :b/c 3, :_/d 4}"))))
(deftest invalid-symbol-value
(is (thrown-with-msg? Exception #"Invalid token" (read-string "##5")))
(is (thrown-with-msg? Exception #"Invalid token" (edn/read-string "##5")))
(is (thrown-with-msg? Exception #"Unknown symbolic value" (read-string "##Foo")))
(is (thrown-with-msg? Exception #"Unknown symbolic value" (edn/read-string "##Foo"))))
(deftest test-read+string
(let [[r s] (read+string (str->lnpr "[:foo 100]"))]
(is (= [:foo 100] r))
(is (= "[:foo 100]" s)))
(let [[r s] (read+string {:read-cond :allow :features #{:y}} (str->lnpr "#?(:x :foo :y :bar)"))]
(is (= :bar r))
(is (= "#?(:x :foo :y :bar)" s))))
(deftest t-Explicit-line-column-numbers
(is (= {:line 42 :column 99}
(-> "^{:line 42 :column 99} (1 2)" read-string meta (select-keys [:line :column]))))
(are [l c s] (= {:line l :column c} (-> s str->lnpr read meta (select-keys [:line :column])))
42 99 "^{:line 42 :column 99} (1 2)"
1 99 "^{:column 99} (1 2)")
(eval (-> "^{:line 42 :column 99} (defn explicit-line-numbering [])" str->lnpr read))
(is (= {:line 42 :column 99}
(-> 'explicit-line-numbering resolve meta (select-keys [:line :column])))))
clojure
(ns clojure.test-clojure.edn
(:require [clojure.test.generative :refer (defspec)]
[clojure.test-clojure.generators :as cgen]
[clojure.edn :as edn]))
(defn roundtrip
"Print an object and read it back as edn. Returns rather than throws
any exceptions."
[o]
(binding [*print-length* nil
*print-dup* nil
*print-level* nil]
(try
(-> o pr-str edn/read-string)
(catch Throwable t t))))
(defspec types-that-should-roundtrip
roundtrip
[^{:tag cgen/ednable} o]
(when-not (= o %)
(throw (ex-info "Value cannot roundtrip, see ex-data" {:printed o :read %}))))
(defspec types-that-should-not-roundtrip
roundtrip
[^{:tag cgen/non-ednable} o]
(when-not (instance? Throwable %)
(throw (ex-info "edn/read should have thrown, see ex-data" {:printed o :read %}))))
hyperfiddle/electric
(ns contrib.datomic-cloud-contrib
(:require clojure.edn
[hyperfiddle.rcf :refer [tests]])
(:import [goog.math Long]))
; transit-js works around this by reading too-large numbers as goog.math.Long:
; https://github.com/cognitect/transit-js/blob/9c28b4d9afaddae3cf15073296fcd736f68600a9/src/com/cognitect/transit/types.js#L82-L99
; EDN serializers must encode the value as strings, because by the time the cljs reader sees a
; value, it has already been ready by javascript and damaged.
(tests
(cljs.reader/read-string "#goog.math/Long \"9007199254740996\"")
:throws js/Error ; No reader function for tag long.
(def x (cljs.reader/read-string {:readers {'goog.math/Long goog.math.Long/fromString}} "#goog.math/Long \"9007199254740996\""))
x := (goog.math.Long/fromString "9007199254740996")
"you can inject something like this over a region (to avoid global state)"
; yes we know bindings are pretty busted in clojure, but it beats mutable global state
(def ^:dynamic *read-str* nil)
(binding [*read-str* (partial cljs.reader/read-string {:readers {'goog.math/Long goog.math.Long/fromString}})]
(*read-str* "#goog.math/Long \"9007199254740996\"")) := x)
(tests
"edn reader"
(cljs.reader/read-string "#goog.math/Long \"9007199254740996\"")
:throws js/Error ; No reader function for tag long.
(clojure.edn/read-string {:readers {'goog.math/Long goog.math.Long/fromString}} "#goog.math/Long \"9007199254740996\"")
:= x
(def ^:dynamic *read-str* nil)
(binding [*read-str* (partial clojure.edn/read-string {:readers {'goog.math/Long goog.math.Long/fromString}})]
(*read-str* "#goog.math/Long \"9007199254740996\"")) := x)
; For the Clojure reader case, I think we don't need to support large compile-time literal longs,
; this is a runtime concern only and thus we only implement the EDN readers in clojurescript.
commsor/titanoboa
(ns titanoboa.database.postgres
(:require [honeysql.core :as sql]
[honeysql.helpers :as h]
[clojure.java.jdbc :as jdbc]
[taoensso.nippy :as nippy]
[titanoboa.database :as db]
[clojure.edn :as edn]))
(defmethod db/list-jobs "org.postgresql.Driver"
[ds limit offset order {:keys [tenant-id jobdef] :as filters}]
(let [query (cond->
{:select [:jobid :jobdef :revision :tenantid :state :start :ended :stepid :steptype :stepstate :isparent :parentjobid :threadstack (sql/raw "count(*) OVER() AS totalcount")],
:from [:jobs]}
limit (h/limit limit)
offset (h/offset offset)
order (h/order-by order))
query (if (or (not (clojure.string/blank? tenant-id)) (not (clojure.string/blank? jobdef)))
(let [filters-query (->>
[(when tenant-id [:= :tenantid tenant-id])
(when (string? jobdef) [:= :jobdef jobdef])
(when (and (vector? jobdef) (not-empty jobdef)) [:in :jobdef jobdef])]
(keep identity)
vec)]
(apply h/where query filters-query))
query)]
(reduce (fn [val item]
(-> (if (:totalcount val) val (assoc val :totalcount (:totalcount item)))
(update-in [:values] conj {:jobid (str (:jobid item))
:parent-jobid (when (:parentjobid item) (str (:parentjobid item)))
:jobdef {:name (:jobdef item)
:revision (:revision item)}
:tenant-id (:tenantid item)
:isparent? (:isparent item)
:state (keyword (:state item))
:start (:start item)
:end (:ended item)
:step-state (keyword (:stepstate item))
:step {:id (:stepid item)
:type (keyword (:steptype item))}
:thread-stack (edn/read-string (:threadstack item))})))
{:offset offset :limit limit :order order :values []}
(jdbc/query ds (sql/format query)))))
BrunoBonacci/mulog
(ns perf
(:require [com.brunobonacci.mulog :as u]
[com.brunobonacci.mulog.utils :as ut]
[com.brunobonacci.mulog.flakes :as f]
[amalloy.ring-buffer :refer [ring-buffer]]
[criterium.core :refer [bench quick-bench]]
[clj-async-profiler.core :as prof]
[jmh.core :as jmh]
[clojure.edn :as edn]
[clojure.string :as str])
(:import com.brunobonacci.mulog.core.Flake))
;; --------------------------------------
;; dynamic bindings are relatively slow
;; thread-local variables are much faster
;; --------------------------------------
(def ^:dynamic *b* nil)
(bench
(binding [*b* 1]
(+ 1 *b*)))
;; Execution time mean : 386.223452 ns
;; Execution time std-deviation : 13.368965 ns
;; Execution time lower quantile : 378.564691 ns ( 2.5%)
;; Execution time upper quantile : 406.533186 ns (97.5%)
;; Overhead used : 6.656971 ns
(def tl (ut/thread-local nil))
(bench
(ut/thread-local-binding [tl 1]
(+ 1 @tl)))
;; Execution time mean : 26.640304 ns
;; Execution time std-deviation : 0.383869 ns
;; Execution time lower quantile : 26.293054 ns ( 2.5%)
;; Execution time upper quantile : 27.107705 ns (97.5%)
;; Overhead used : 2.096266 ns
;; --------------------------------------
(def tl (java.util.concurrent.ThreadLocalRandom/current))
(bench (.nextLong ^java.util.Random tl)) ;; 6.528802 ns +/- 0.3
(->> (jmh/run
(merge
(clojure.edn/read-string (slurp "./perf/benchmarks.edn"))
{:selectors {:one (comp #(str/includes? % "context") name :fn)}})
{:type :quick
:status true
:pprint true
:select :one
})
(prn-str)
(spit (format "./temp/mulog-perf-run-%d.edn" (System/currentTimeMillis))))
fluree/db
(ns fluree.sdk.version
#?(:clj (:require [clojure.java.shell :refer [sh]]
[clojure.edn :as edn])
:cljs (:require-macros [fluree.sdk.version :refer [version]])))
(defmacro version
"Compiles in the current version in CLJS code. Returns a map like:
{:version \"1.2.3\"}"
[]
(-> (sh "clojure" "-T:build" "print-version")
:out
edn/read-string))
zhuangxm/clj-rpc
;; Different wire formats support.
(ns clj-rpc.wire-format
(:require [cheshire.core :as json]
[clojure.edn :as edn]))
(defmethod serialization ::clj [_]
[pr-str edn/read-string])