This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-05-27
Channels
- # aws (7)
- # babashka (145)
- # beginners (83)
- # calva (18)
- # cider (11)
- # clara (9)
- # clj-kondo (59)
- # cljdoc (4)
- # cljs-dev (4)
- # cljsrn (11)
- # clojure (168)
- # clojure-australia (21)
- # clojure-dev (5)
- # clojure-europe (46)
- # clojure-italy (3)
- # clojure-nl (10)
- # clojure-taiwan (1)
- # clojure-uk (55)
- # clojurescript (85)
- # clojureverse-ops (1)
- # code-reviews (3)
- # conjure (22)
- # cursive (3)
- # datahike (3)
- # datomic (4)
- # emacs (5)
- # helix (20)
- # jackdaw (1)
- # jobs (2)
- # jobs-discuss (7)
- # lsp (1)
- # malli (5)
- # off-topic (85)
- # other-languages (4)
- # practicalli (4)
- # reitit (2)
- # releases (2)
- # sci (62)
- # shadow-cljs (181)
- # testing (5)
- # tools-deps (15)
- # xtdb (31)
Hello all. I created a #show-and-tell channel today. #announcements channel is lovely for libs but I want to be inspired by the systems and products people are building. What are you building with clojure today? Show a screenshot and tell us about it. Few fun screenshots at #show-and-tell already.
how can i use the threaded form but avoid particular parts of the thread based on the current threaded value, I'm aware of cond-> but that doesn't test on current value, eg:
(-> data
(fn1)
(fn2)
(thread-if #(= (:needs-doing %)) (needs-doing))
(fn5)
You could make a function for this pretty easily.
(defn when-pred
[val pred then]
(if (pred val)
(then val)
val))
(defmacro if->
[val sym test clause]
`(when-pred ~val (fn [~sym] ~test) (fn [~sym] ~clause)))
(-> data
fn1
fn2
(when-pred :needs-doing needs-doing)
fn4)
(-> data
fn1
fn2
(if-> val (= (:some-key val) :some-thing) (update val :some-key some-update))
fn4)
Or lift the if into a fn above
hi
please advice is there a smart trick to know if it is a last iteration inside the run!
(the consumed sequence is lazy and it is important to keep it lazy)
there is no way to know if you're at the last element without looking ahead one element
is there a run! which accepts two elements? 🙂
makes sense!
thanks
almost. the nil?
check would not be enough if the seq also can contain nils, so I would use:
(loop [xs (seq xs0)]
(let [next-xs (next xs)
last? (not next-xs)]
(recur next-xs)
You could also do it with a transducer/eduction
(run! identity (eduction (fn [rf] (fn ([] (rf)) ([r] (prn 'done r) (rf r)) ([r i] (rf r i)))) (range 5)))
but I guess it kinda depends on why you need to know it's the last elementit is interesting idea with a transducer thanks!
seems like custom loop as simplier solution
thanks for the input
you could also pair each element with the next one and look for where the paired elements run out:
(let [data (range 5)]
(run! (fn [[a b]] (if (= a ::last) (do (prn b) b) b)) (map vector (concat (drop 1 data) [::last]) data)))
maybe?thanks
I just got this. Who do I need to poke (if anyone)?: > WARNING: Illegal reflective access by clojure.lang.InjectedInvoker/0x0000000800232040 (file:/C:/Users/x/.m2/repository/org/clojure/clojure/1.10.1/clojure-1.10.1.jar) to method sun.security.x509.X509CertImpl.getSubjectDN() > WARNING: Please consider reporting this to the maintainers of clojure.lang.InjectedInvoker/0x0000000800232040 > WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations > WARNING: All illegal access operations will be denied in a future release
--illegal-access=debug
@U5QB8D59A add ^ to your JVM to get some better stacktrace
The actual code creating the issue is this: (->> cert (.getSubjectDN) (.getName) (drop 3) (apply str))] cert is an X509CertImpl pulled from an sslContext Solution is to use a different method but it asked to warn someone..so here I am.
unfortunately, because this is in code generated by the compiler on your code's behalf, it will always get reported as if it is Clojure ;)
the issue is not actually one of deprecation, but rather calling into a function that you cannot access due to module visibility.
And it's true that switching from getSubjectDN to getSubjectX500Principal still gives an error
this being one of the internal sun jdk methods, you're not supposed to use this class directly
yeah, would be curious to see the code
probably should be using java.security.cert.X509Certificate ?
ok here is what I got for you: > WARNING: Illegal reflective access by clojure.lang.InjectedInvoker/0x0000000800232040 (file:/C:/Users/sweb/.m2/repository/org/clojure/clojure/1.10.1/clojure-1.10.1.jar) to method sun.security.x509.X509CertImpl.getSubjectX500Principal() > at clojure.lang.Reflector.canAccess(Reflector.java:49) > at clojure.lang.Reflector.invokeMatchingMethod(Reflector.java:156) > at clojure.lang.Reflector.invokeNoArgInstanceMember(Reflector.java:438) > at url_check.core$wildcard_QMARK_.invokeStatic(core.clj:70) > at url_check.core$wildcard_QMARK_.invoke(core.clj:67) > at url_check.core$eval8394.invokeStatic(form-init16933106916591026780.clj:205) > at url_check.core$eval8394.invoke(form-init16933106916591026780.clj:205) > at clojure.lang.Compiler.eval(Compiler.java:7177) > at clojure.lang.Compiler.eval(Compiler.java:7132) > at clojure.core$eval.invokeStatic(core.clj:3214) > at clojure.core$eval.invoke(core.clj:3210) > at clojure.main$repl$read_eval_print__9086$fn__9089.invoke(main.clj:437) > at clojure.main$repl$read_eval_print__9086.invoke(main.clj:437) > at clojure.main$repl$fn__9095.invoke(main.clj:458) > at clojure.main$repl.invokeStatic(main.clj:458) > at clojure.main$repl.doInvoke(main.clj:368) > at clojure.lang.RestFn.invoke(RestFn.java:1523) > at nrepl.middleware.interruptible_eval$evaluate.invokeStatic(interruptible_eval.clj:79) > at nrepl.middleware.interruptible_eval$evaluate.invoke(interruptible_eval.clj:55) > at nrepl.middleware.interruptible_eval$interruptible_eval$fn__3452$fn__3456.invoke(interruptible_eval.clj:142) > at clojure.lang.AFn.run(AFn.java:22) > at nrepl.middleware.session$session_exec$main_loop__3553$fn__3557.invoke(session.clj:171) > at nrepl.middleware.session$session_exec$main_loop__3553.invoke(session.clj:170) > at clojure.lang.AFn.run(AFn.java:22) > at java.base/java.lang.Thread.run(Thread.java:834) > WARNING: Illegal reflective access by clojure.lang.Reflector (file:/C:/Users/sweb/.m2/repository/org/clojure/clojure/1.10.1/clojure-1.10.1.jar) to method sun.security.x509.X509CertImpl.getSubjectX500Principal() > at clojure.lang.Reflector.invokeMatchingMethod(Reflector.java:167) > at clojure.lang.Reflector.invokeNoArgInstanceMember(Reflector.java:438) > at url_check.core$wildcard_QMARK_.invokeStatic(core.clj:70) > at url_check.core$wildcard_QMARK_.invoke(core.clj:67) > at url_check.core$eval8394.invokeStatic(form-init16933106916591026780.clj:205) > at url_check.core$eval8394.invoke(form-init16933106916591026780.clj:205) > at clojure.lang.Compiler.eval(Compiler.java:7177) > at clojure.lang.Compiler.eval(Compiler.java:7132) > at clojure.core$eval.invokeStatic(core.clj:3214) > at clojure.core$eval.invoke(core.clj:3210) > at clojure.main$repl$read_eval_print__9086$fn__9089.invoke(main.clj:437) > at clojure.main$repl$read_eval_print__9086.invoke(main.clj:437) > at clojure.main$repl$fn__9095.invoke(main.clj:458) > at clojure.main$repl.invokeStatic(main.clj:458) > at clojure.main$repl.doInvoke(main.clj:368) > at clojure.lang.RestFn.invoke(RestFn.java:1523) > at nrepl.middleware.interruptible_eval$evaluate.invokeStatic(interruptible_eval.clj:79) > at nrepl.middleware.interruptible_eval$evaluate.invoke(interruptible_eval.clj:55) > at nrepl.middleware.interruptible_eval$interruptible_eval$fn__3452$fn__3456.invoke(interruptible_eval.clj:142) > at clojure.lang.AFn.run(AFn.java:22) > at nrepl.middleware.session$session_exec$main_loop__3553$fn__3557.invoke(session.clj:171) > at nrepl.middleware.session$session_exec$main_loop__3553.invoke(session.clj:170) > at clojure.lang.AFn.run(AFn.java:22) > at java.base/java.lang.Thread.run(Thread.java:834)
seems like https://github.com/davidkeen/url-check-clojure/blob/master/src/url_check/core.clj
line #s don't seem right there though
or maybe that's your code? I'm just guessing from the ns
ok, well what's your code at line 70?
he seems to be checking for a well formed response from a server. I am checking cookie compliance, form usage, cert validity (where I am running into the interop issues) etc
as per your faq, changing it to: > (let [n (->> ^java.security.cert.X509Certificate cert > (.getSubjectX500Principal) > (.getName) > (drop 3) > (apply str))] worked without error.
What would be the best way to run command-line tools from Clojure? I do not just want to dispatch jobs, but also be notified when they are finished and learn the exit-code, std(out/err), and so on.
https://clojuredocs.org/clojure.java.shell/sh perhaps does what you need?
I like babashka/process https://github.com/babashka/process as the name implies, it's included in babashka
Thanks. I'll look at both of them!
For now clojure.ava.shell.sh
is enough. It is synchronous though. But I am sure I can just use Thread
to make it non-synchronous.
I am building a (Snake)make-like workflow management system where users provide the rules in text files to be parsed by my program to create a DAG for execution (phew!). The rules look like this (there would obviously be many more rules in a file):
(defrule samtools-sort
"Sort the bams."
{:wildcards [:sample :genome]
:input "bwa-map.bam"
:output ["bam/sorted.bam"]
:shell "samtools sort -T {{wildcards.sample}} -O bam {{input.0}} > {{output.0}}"})
It would be cool if I could include a :clojure
-directive as an alternative to the :shell
directive in case users wanted to do their data processing in Clojure rather than in shell, like:
:clojure (-> infile slurp process-data write-result-to-file)
This in itself would not be hard. But it would be cool if it were possible to let users include/require external libraries in the code too. I do not see any easy way to do this as the workflow files are fed to a precompiled program.
Any suggestions/ideas?how are you starting the java process? if you want to download code from the internet and add it to your classpath, you may want to look at something like the add-lib branch of the clj tool (which is currently work in progress)
My Clojure program will be a jar 🙂
Cool! Will keep my eyes open for updates on the tool 😎
for what it's worth: nREPL 0.7 got sideloader:
#97: Added a sideloader, a network classloader that allows dependencies to be added even when the source/class files are not available on the server JVM's classpath (e.g. supplied by the client).
https://github.com/nrepl/nrepl/releases
(I haven't tried this feature myself)
Cool to know about 🙂
I guess. This would require me to learn lots more about tooling. Up to this day I've just cargo-culted and used luminus-recipes XD
Thanks, btw.
It seems like this will be really easy with the clj
command-line tool :thumbsup:
I had only worked with lein and that would be a bit more involved. Plus it would add another rather large dependency.
any hints on how to debug a memory leak / performance leak in a clojure app on production ? The normal way to look on gc generation does not really help because clojure does not have classes.
Perhaps with VisualVM: https://docs.oracle.com/javase/8/docs/technotes/guides/visualvm/heapdump.html
bash-5.0# jcmd 1 GC.class_histogram -all > GC.class_histogram.csv bash-5.0# head GC.class_histogram.csv 1: num #instances #bytes class name (module) ------------------------------------------------------- 1: 96854702 3099350464 clojure.lang.LazySeq 2: 64655045 2068961440 clojure.lang.Cons 3: 5122755 394906984 [Ljava.lang.Object; ([email protected]) 4: 3382334 157481032 [B ([email protected]) 5: 3323357 79760568 java.lang.String ([email protected]) 6: 1509001 60360040 clojure.lang.PersistentVector 7: 2059526 49428624 clojure.lang.PersistentVector$Node
@U011NGC5FFY did you try to force a GC before taking this data?
if you take a thread dump can you see something in the list of things that the process is doing that's a common code path that looks like it might be holding onto the head of something large?
it's a bit difficult since it's hard to reproduce the performance issue that triggers the issue and the app runs remotely inside docker
what kind of things is it connected to? if it's selecting large amounts of data from a db, and trying to serve that up over http it might be calling doall
on something before trying to convert it to an http response?
Can you dump the heap on out of memory exception and have it written to a mounted docker volume to be inspected later? https://www.baeldung.com/java-heap-dump-capture#automatically
thanks - the app does not throw memory exception - it starts lots of threads and it slows down to a halt
are you catching and logging/printing uncaught thread exceptions?
have you tried the old strategy of doubling the heap size and seeing what happens over longer periods of time?
@U011NGC5FFY > it starts lots of threads can you see what the app is doing in those threads?
@U0P0TMEFJ default with java 11 - G1
@U04V15CAJ: I am working on that
@UGJE0MM0W: not sure how to reply
I think @UGJE0MM0W meant are you doing this: https://stuartsierra.com/2015/05/27/clojure-uncaught-exceptions ?
thanks @U0P0TMEFJ, will check
if you've got multiple docker processes to play with, you could always have one start up with the serial collector, which is a bit easier to follow what's getting cleaned up, because it just stops the world rather than trying to let all the threads progress ... (just as an idea of trying to work out what's going on 😉 )
Yes that's what I was suggesting
the performance issue is difficult to trigger, the app uses ~ 12 - 23 GB of ram and needs a cache, db and queue - these make things difficult to debug
you could take a memory dump and examine any instance of the LazySeq, check its .s
field
thank you, I found a very good presentation on the subject: https://www.youtube.com/watch?v=_gineh_HcoQ (shorter version available online someplace)
thanks, I am putting some load on the system now (trying, I can't seem to be able 😄 ) .
https://github.com/clojure-goes-fast/clj-async-profiler. I found the flame graph quite useful in analysing both space and time issues.
@U011NGC5FFY if you can download the heapdump, you can offline analyze it with https://visualvm.github.io/download.html
thanks. Will try it out. I don't lknow how useful it will be for me now since I can't seem to reproduce the issue
seems I can't create a heap dump - size is 0. tried with both jcmd and jmap - files have size 0
Because the system is stalled or wrong pid? I did it like this some time ago:
$ docker exec my-service ps
PID USER TIME COMMAND
1 java 0:00 /dev/init -- java -Xmx8g -Dcom.sun.management.jmxremote.rmi.port=19090 -Dcom.sun.management.jmxremote=true -Dcom.sun.management.jmxremote.port=19090 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.local.only=true -Djava.rmi.server.hostname=localhost -jar /my-jar.jar
8 java 0:26 java -Xmx8g -Dcom.sun.management.jmxremote.rmi.port=19090 -Dcom.sun.management.jmxremote=true -Dcom.sun.management.jmxremote.port=19090 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.local.only=true -Djava.rmi.server.hostname=localhost -jar /my-jar.jar
256 java 0:00 ps
# Make a heap dump for PID 8
$ docker exec my-service jcmd 8 GC.heap_dump /tmp/docker.hprof
and then:
docker cp my-service:/tmp/docker.hprof .
I am following the https://clojure.org/guides/deps_and_cli#_using_a_main but I cannot find out how to run the example program from a different folder:
clj -X hello/run
Like, my code resides at ~/code/hello/
, but I want to run it from ~/whatevz/some/bogus/folder
. Is there a way?
I know I could just use pushd ~/code/hello; clj -X hello/run; popd
, but I was hoping there existed a way that did not involve jumping between paths.I see there is a -Jopt
. Will read up on the possible flags I can send there.
that just lets you use any jvm option
But I thought one of them might be relative-to
or something 🙂
Any advice on propagating errors when you have multiple long-running threads in a clojure service on the jvm?
i.e.
my-process
returns [input-ch done-ch]
and starts some background some work somehow -`ExecutorService`, async/thread
, future
, etc. The problem is all these wrappers to background work end up with uncaught exceptions not being handled (i.e. by top-level Thread$UncaughtExceptionHandler
unless a specific uncaught exception handler is added to the thread, and this then needs to exit the process.
It seems possible to return a future and deref futures from all these processes, but this doesn’t seem to be the way, as the deref order on the main thread then matters or you end up with the same problem :thinking_face:
I’ve read this from a few years ago, but I’m not sure what the best approach is https://stuartsierra.com/2015/05/27/clojure-uncaught-exceptions
Most (all?) of the ExecutorService
implementations allow you to provide a ThreadFactory which would allow you to set an uncaught exception handler
The error handling strategy will depend on the use case. Generally, it's hard to recover from unexpected errors from arbitrary processes.
As far as using something like core.async
, I would generally turn all "outputs" (including exceptions) into data. That can mean wrapping work in a try/catch
+1 on this, the ideal here is to start all your processes with core.async and then use alt to wait for the first one to fail and then exit on that.
regarding using deref to test future failure, you can use the second and third args to deref to time out and provide a placeholder value if the future isn't ready, then move to the next future
contrived example:
(cmd)user=> (def futs (map future-call (repeat 10 #(doto (rand-int 20000) (Thread/sleep)))))
#'user/futs
(cmd)user=> (do (doall (take-while #{:waiting} (map #(deref % 1000 :waiting) (cycle futs)))) (map #(deref % 1000 :waiting) futs))
(6165 :waiting 7143 1631 :waiting 1091 :waiting :waiting :waiting :waiting)
There are some types in the transit spec like "point in time" that are listed as "extension" types
most of the examples make it seem like the one letter, string prepending tagged values are an internal thing
@emccue these types should be handled by registering transit handlers for those with a tag
transit has been extended to many languages
https://github.com/cognitect/transit-format/wiki/Community-Implementations
yeah one of the challenges is that all the community implementations seem to take the same "pass a map of handlers" approach so I don't have much prior art to look at
but in elm, we don't have much of a choice but to use an api similar to elm/json where you put explicit expectations at each point
Does anyone know if there's an existing macro/library/idiom for using something like let
with channels for fan-in? For example:
(let* [thing1 (<!! (do-thing1-returning-channel))
thing2 (<!! (do-thing2-returning-channel))]
[thing1 thing2])
The naive way to write this does thing1 and thing2 sequentially. It seems so natural to want to do them in parallel and allow the let
to gather results that I wonder if someone has written the macro already...Yeah, I can think of several good ways to get it done, just don't want to recreate someone's prior art needlessly
import Array
import Transit.Decode as TD
type alias Point =
{ x : Int
, y : Int
}
decoder : TD.Decoder (List Point)
decoder =
TD.vector
(TD.map2 Point
(TD.tagged "point" (TD.index 0 ))
(TD.tagged "point" (TD.index 1 )))
|> TD.map Array.toList
Hello all. I created a #show-and-tell channel today. (Resend for us time zones) #announcements channel is lovely for libs but I want to be inspired by the systems and products people are building. What are you building with clojure today? Show a screenshot and tell us about it. Few fun screenshots at #show-and-tell already.
If I’m applying a filter on a set, what is the time complexity, where the size of the set n?
for a sorted-set
you can get better time complexity for a split based on the ordering if you use subseq