This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-07-04
Channels
- # announcements (10)
- # asami (6)
- # babashka (22)
- # beginners (44)
- # biff (1)
- # calva (8)
- # clj-kondo (13)
- # clojure (62)
- # clojure-art (1)
- # clojure-europe (27)
- # clojure-nl (1)
- # clojure-norway (19)
- # clojure-spec (19)
- # clojure-uk (2)
- # component (29)
- # datascript (1)
- # fulcro (9)
- # gratitude (2)
- # kaocha (6)
- # klipse (1)
- # luminus (16)
- # malli (9)
- # nbb (5)
- # off-topic (4)
- # reagent (5)
- # shadow-cljs (85)
- # spacemacs (1)
- # tools-deps (10)
- # vim (9)
- # xtdb (2)
Does anyone know how to generate a LazySeq of date time's using the new Java time API? Below is how I did it with clj-time:
(defn time-range
"Returns a lazy sequence of DateTimes in the half-open interval [start, end), incremented by 'step' units of time."
[start end step]
(let [inf-range (time-period/periodic-seq start step)
before-end? (fn [t] (time/within? (time/interval start end)
This seems to do the trick
(map #(-> (java.time.LocalDate/parse "2015-02-13") (.plusDays %) str) (range 10 15 1))
What does "wdyt" mean?Nice and concise solution. Maybe just bind the parsed date in a let outside the sequence
How do I write a jpg
image blob from a mysql database to a file?
The image is a byte array that looks like #object[[B 0x5f79a914 [B@5f79a914]
and I converted it to an input stream with java.io.ByteArrayInputStream
so now it looks like #object[java.io.ByteArrayInputStream 0x575af21a
.
I'm trying to follow https://stackoverflow.com/a/50427686, which looks like what I need, but I'm struggling to translate to clojure. Is this the write approach to use javax.imageio.ImageIO
to write the image to a file?
(-> (ImageIO/read your-ByteArrayInputStream-here)
(ImageIO/write "jpg" (File. "output.jpg")))
Hmm, why would (ImageIO/read image-input-stream)
return nil
?
I was able to get it to work with this:
(defn base64-to-file [base64-string]
(with-open [out (output-stream "kitten.jpg")]
(.write out (.decode (java.util.Base64/getDecoder) base64-string)))))
In general, how would you synchronize authorization attempts so there is no two concurrent requests are being made? I'm writing a simple rest client which has a session lifetime, and would appreciate some guidelines in that area.
Each client is given a session token in response to auth request. I want to avoid creating two sessions//sending two auth requests, so there is a need to sync login attempts somehow. 1. Two threads are attempting to make a request. 2. Both found out that session token is missing or expired 3. Both trying to login by sending an auth request I'm missing an insight on how to make second thread wait with it's login attempt and use session token acquired by the first thread instead. In Java I would synchronize and check on a status variable which indicates that session is ok and second thread can skip the login stage.
What do you want to happen to the second request? Do you want to reject it? do you want to return to it the same result?
You can try doing something optimistic using https://clojuredocs.org/clojure.core/compare-and-set!
have some key value mapping, both requests take it, check if they already have a token for their key. If so, done, if not, generate a token, assoc to the map, and try to set it relative to the old value. This will succeed only for one request
There could be some errors here, but this is the gist of it:
(defn acquire-token
[request tokens]
(let [k (request-key request)]
(if-let [v (get @tokens k)]
v
(let [token (create-token request)]
(loop [old @tokens]
(if-let [v (get old k)]
v
(let [newv (assoc old k token)]
(if (compare-and-set! tokens old newv)
v
(recur @tokens)))))))))
Another solution is to have a single writer - both requests come in, "enqueue" their requests for a token and get back a promise. The writer gets the first request, keeps an association for it, the result is returned to the promise. Second request comes in, belongs to same association, so it gets the same result
(loop [state {}]
(let [req (<! in)
k (request-key req)]
(if-let [v (get state k)]
(do (>! (:promise req) v)
(recur state))
(let [token (create-token req)]
(>! (:promise req) token)
(recur (assoc state k token))))))
@UK0810AQ2 i've done a prototype using simple lock, could you review it?
(def state (atom {:login :bad
:token nil}))
(defn authorized? []
(let [{:keys [login token]} @state]
(and (= login :good) (when token true))))
(defn reset-login []
(reset! state {:login :bad
:token nil}))
(def login
(let [lck (Object.)]
(fn []
(locking lck
(if (authorized?)
[:reusing-token (@state :token)]
(do (let [token (rand-int 1000)]
(Thread/sleep (rand-int 2000))
(reset! state (-> @state
(assoc :login :good)
(assoc :token token))))
[:new-token (@state :token)]))))))
(comment
(authorized?)
(login)
(reset-login))
(defn test-1 []
(-> (group-by #(first @%) (doall (take 1000 (repeatedly #(future (login))))))
(update :new-token count)
(update :reusing-token count)))
(comment
(reset-login)
(test-1))
Extracted test to a function.
And just to make it clear, authorized?
and login
both are called from an async requests in my client.
When I pull in
ch.qos.logback/logback-classic {:mvn/version "1.2.8"}
I get SLF4J: Class path contains multiple SLF4J bindings.
I think I can exclude slf4j-nop
how do I do that ?:exclusions [whatever/slf4j-nop]
With whatever being the correct groupId (don't remember what that is)
That goes in the coord map
SLF4J: Found binding in [jar:file:/home/benj/.m2/repository/org/slf4j/slf4j-nop/1.7.36/slf4j-nop-1.7.36.jar!/org/slf4j/impl/StaticLoggerBinder.class]
deps:
ch.qos.logback/logback-classic
{:mvn/version "1.2.8"
:exclusions [org.slf4j/slf4j-api]}
when I do clj -X:deps tree | grep slf4j
there is nothing left
Tried excluding org.slf4j/slf4j-nop
Well you can't exclude the api, presumably that's what's being used for logging
What do you see with the grep before the change
[benj@benj-pc my-oauth-example] 0 $ clj -X:deps tree | grep slf --before-context=3
. com.fasterxml.jackson.core/jackson-core 2.13.2
ch.qos.logback/logback-classic 1.2.8
. ch.qos.logback/logback-core 1.2.8
. org.slf4j/slf4j-api 1.7.32
That looks like there is no impl
I guess then some library must be pulling it in dynamically or something? Full deps:
{:paths ["src"]
:deps {org.clojure/clojure {:mvn/version "1.11.1"}
metosin/reitit {:mvn/version "0.5.18"}
metosin/muuntaja {:mvn/version "0.6.8"}
metosin/ring-http-response {:mvn/version "0.9.3"}
ring/ring-core {:mvn/version "1.9.5"}
ring/ring-defaults {:mvn/version "0.3.3"}
luminus/ring-undertow-adapter {:mvn/version "1.2.6"}
org.clojure/data.json {:mvn/version "2.4.0"}
ring-oauth2/ring-oauth2 {:mvn/version "0.2.0"}
radicalzephyr/ring.middleware.logger {:mvn/version "0.6.0"}
ch.qos.logback/logback-classic
{:mvn/version "1.2.8"}}}
The other possibility is that something is (wrongly) including slf4j inside it's own jar
But even then I'd assume that wouldn't happen multiple times. I'm not really sure what to suggest. I guess you could pull in these top level deps one by one until you see the issue
Or the opposite - remove them one by one