Fork me on GitHub
#clojure
<
2022-07-05
>
Ivan Koz06:07:48

I'm writing a simple async rest client, and there is an auth session token that should be shared, updated between all requests. I came up with a lock based solution, is there better options to do so? <https://gist.github.com/nxtk/b1936633ccb5b456e51198d2f958fc56>

hiredman06:07:14

I usually have a core.async go block that runs a loop keeping credentials fresh and handing credentials to anyone that needs them. I don't think keeping state for a rest client in a global singleton (a def) is a good idea.

Ivan Koz06:07:47

do you have any public code at hand that i could peek into?

hiredman06:07:26

Not of mine, no. https://github.com/cognitect-labs/aws-api/blob/master/src/cognitect/aws/credentials.clj is vaguely similar, but much more complex, largely due to different potential ways to get away credentials. I've mostly used the core.async loop think for exchanging credentials for a bearer token and keeping that token up to date.

hiredman06:07:15

aws-api creates a single scheduled executor for doing refreshes, but the credential state itself is in passed around atoms (not singletons)

Ivan Koz06:07:53

thanks, i'll dig into it

hiredman06:07:42

If it truly is a kind of stateful session token, forcing serial interaction, I would be tempted to use a threadpool of size 1 to enforce that instead of a lock, basically instead of blocking on a lock, when you need to access the serial resource you throw a thunk on the threadpool for that resource. But that may be more complex, just the idea that serial usage can be well represented by the execution of a single thread, instead serializing multiple threads via a lock

Setzer2207:07:39

When calling core.async's thread function, will that use the thread pool? Or is it equivalent to spawning a new Java thread?

mpenet07:07:02

it's backed by a cachedthreadpool

Setzer2207:07:37

I see, thanks! 🙂

henrik07:07:06

This took me by surprise:

(sorted-map "hello" "world")               ;; => {"hello" "world"}
(sorted-map :hello :world)                 ;; => {:hello :world}
(sorted-map "hello" "world" :hello :world) ;; => Execution error: class java.lang.String cannot be cast to class clojure.lang.Keyword
Is this expected?

vlaaad08:07:35

Sorted map needs comparable keys. This makes it unsafe for checking if a key is there or not, unless you provide a comparator that can sort any key

kirill.salykin12:07:29

hi please help how i can do arity overload in defprotocol?

(defprotocol Logger
  (error
    ([_ params])
    ([_ ex params]))
  )
(defprotocol Logger
  (error [_ params])
  (error [_ ex params])))
are not working --- UPD: found
(defprotocol Logger
  (error
    [_ params]
    [_ ex params]))

vemv12:07:31

The empty? docstring famously recommends using seq instead of (not (empty? . However doesn't that create transient garbage? Which might happen in a tight loop, you never know Maybe I can use not-empty (or just (not (empty? )? What is being traded off other than concision?

p-himik12:07:51

(empty? x) is already (not (seq x)).

👍 1
vemv12:07:45

what about not-empty then?

p-himik12:07:15

Clojure 1.11.1
user=> (source not-empty)
(defn not-empty
  "If coll is empty, returns nil, else coll"
  {:added "1.0"
   :static true}
  [coll] (when (seq coll) coll))
nil

vemv12:07:24

I should have checked :) I thought not-empty was directly backed by some java code

p-himik12:07:12

Nah, seq is at the very bottom.

vemv12:07:14

It sounds a bit off that for any emptiness check you have to coerce to seq first. I would wager that any given coll just knows whether it's empty - it could be a fast boolean check?

rolt12:07:50

i think it's changing in clojure 1.12

rolt12:07:51

it will be based on count if the operation is O(1)

vemv12:07:24

awesome! Good timing

p-himik13:07:54

> any given coll just knows whether it's empty Lazy seqs don't know that though. And constructing ephemeral classes that will be thrown away almost immediately should be a cheap op at the end of the day, at least as far as I'm aware, given all the optimizations JVM is doing. Of course, probably not as cheap as a check of a field or whatever, but still much cheaper than one might guess.

roklenarcic16:07:24

Ephemeral objects rather than ephemeral classes

👍 1