This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-05-21
Channels
- # announcements (3)
- # babashka (26)
- # beginners (45)
- # calva (10)
- # chlorine-clover (9)
- # cider (4)
- # clj-kondo (7)
- # cljs-dev (10)
- # clojure (95)
- # clojure-europe (33)
- # clojure-france (5)
- # clojure-nl (3)
- # clojure-spec (2)
- # clojure-sweden (3)
- # clojure-uk (33)
- # clojurescript (54)
- # conjure (101)
- # core-async (14)
- # cursive (1)
- # data-science (91)
- # datascript (3)
- # datomic (16)
- # figwheel (3)
- # figwheel-main (15)
- # fulcro (35)
- # ghostwheel (5)
- # graalvm (13)
- # helix (29)
- # java (5)
- # jobs (6)
- # kaocha (6)
- # leiningen (1)
- # meander (12)
- # off-topic (54)
- # pathom (13)
- # re-frame (16)
- # reagent (8)
- # reitit (4)
- # rum (3)
- # shadow-cljs (49)
- # spacemacs (2)
- # sql (5)
- # tools-deps (10)
- # xtdb (8)
- # yada (3)
@ramonp.rios If you want to do that you either need to wrap what you are calling into a function at runtime or make that a macro which will take in your code at compile time
(wrap-exception
(fn []
(-> (persist/update-subcategory datasource body id)
(handle-result id :update))
"Subcategory was not updated.")
Hey, thanks for the tip ! I'm still getting the macro stuff.
(defmacro- wrap-exception
[f info]
`(try
(do ~f)
(catch Exception e
(log/error "Exception was handled: " (.getClass e) ": " (.getMessage e))
(throw (ex-info ~info {:status 500
:message (.getMessage e)})))))
you don't need do
inside try
btw
(try
(do
(-> (persist/update-subcategory datasource body id)
(handle-result id :update)))
(catch Exception e
(log/error ...)
(throw (ex-info "Subcategory was not updated." ...))))```hey, has anyone dealt with log4j(2) here before? basically when i send exception back to the client over http i also see passed map's contents with ExceptionInfo, but i can't see that in logger output
11:31:50 [manifold-pool-3-12] E zentria.emperor.core - Failed to start server
clojure.lang.ExceptionInfo: HTTP Error: 500
and that's itseems like when i stringify the error, i'll always see the map; while log4j does its own thing. how can i special case that?
user=> (str (ex-info "test" {:a true :b false}))
"clojure.lang.ExceptionInfo: test {:a true, :b false}"
iirc you can't. i ended up doing json structured logs and i put such stuff in the "message" (the part of the json that i could control)
when i tried i was told using mdc was the "only way" so i just went with all-json instead. sorry if that wasn't what you were asking about
technically could abuse this...
i figure it's missing because normally libs just log the message and the stacktrace of the exception object -- i'd just catch and log the exception myself in the format i like, though i don't know how feasible that is in your case
honestly could tap into clojure.tools.logging
i'm not using log4j directly, but that library instead
@U011YV400HX If you are using a pattern layout, it should work if you explicitly use %exception
specifier in the pattern string, e.g.:
%date %level %logger %message%n%exception
Without a specifier to handle exceptions, log4j defaults to %xException
, which doesn't print the data map (same for %rException
).I've added this to the readme: https://github.com/clojure/tools.logging#log4j2
thank you very much. it did the trick. i was using %xEx
Is it advisable to call macroexpand
type functions within a macro? For example if I want to expand the inner forms before modifying them with my macro?
I think the short answer is no
The long answer might also be no but would depend on what you're actually doing
the macroexpand function is not the same as what actually happens in the compiler
I see, it did seem like macroexpand
was more for development than production code, but wasn't sure about where the line was drawn. Thanks!
there are libraries that approximate it more closely but I can't say I've never needed to do so in 10+ yrs of Clojure
I have an object which I can write to an output-stream, but I need to return an output stream. Do I need to start a thread to call write
or something? I am concerned about my output consuming large amounts of memory (i.e. I don't want to use a bytearrayoutputstream)
Looks like I'm mixed up, I need to produce an input stream, which is easier, because that means I just need a pipedinputstream
right - someone can read an inputstream, and will get what you wrote to the other end of the pipe
Looks like I'm mixed up, I need to produce an input stream, which is easier, because that means I just need a pipedinputstream
i've been trying my hands at using netty to make a http server. i got to the point that i can receive and respond to requests. i'm not doing any java->ring transformations yet because i first wanted to make sure the stuff is solid. however load testing with wrk shows very high (3-4x avg) standard deviation in response time. i'm lost what could cause this. i have an order of magnitude difference between 75%ile and 90%ile. i figure it might be something about concurrency but i can't guess how to pinpoint the problem. any and all hints would be appreciated.
running pohjavirta with the same handler from the same repl it has much lower std dev, so it's not something hardware. i don't see extreme gc either.
under supposedly the same conditions aleph:
❯ wrk/wrk -t2 -c16 -d10s --latency
Running 10s test @
2 threads and 16 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 296.44us 1.34ms 48.40ms 98.07%
Req/Sec 45.32k 5.62k 50.56k 91.50%
Latency Distribution
50% 127.00us
75% 203.00us
90% 350.00us
99% 3.40ms
902286 requests in 10.01s, 142.84MB read
Requests/sec: 90148.68
Transfer/sec: 14.27MB
pohjavirta:
❯ wrk/wrk -t2 -c16 -d10s --latency
Running 10s test @
2 threads and 16 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 168.65us 618.22us 15.25ms 96.13%
Req/Sec 109.93k 14.03k 123.63k 91.00%
Latency Distribution
50% 54.00us
75% 92.00us
90% 108.00us
99% 2.98ms
2186950 requests in 10.01s, 294.07MB read
Requests/sec: 218570.44
Transfer/sec: 29.39MB
my stuff:
❯ wrk/wrk -t2 -c16 -d10s --latency
Running 10s test @
2 threads and 16 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 458.61us 1.21ms 29.13ms 91.36%
Req/Sec 76.04k 14.39k 106.41k 66.00%
Latency Distribution
50% 63.00us
75% 161.00us
90% 1.37ms
99% 6.15ms
1517000 requests in 10.04s, 83.91MB read
Requests/sec: 151141.26
Transfer/sec: 8.36MB
Have you tried Aleph? It provides a web server and is built on top of netty: https://github.com/ztellman/aleph
i'm familiar with aleph. i started this to learn how netty works so i can maintain a fork of aleph or build my own if the former is too complex and i can get something feasible working
just at a surface level: those numbers smell like a throughput / latency tradeoff
when you have more requests going through, and less throughput speed, then I'd expect higher variation / more bursty behavior due to context switching overhead
if you optimize throughput instead you'll have more predictable behavior, but higher worst case wait / block times for consumers
what affects that the most? i'd prefer the flatter (predictable) behavior. i think it's easier to tune stuff if it behaves consistently
I'm approaching this from a systems background, not really knowing what tuning parameters netty offers
but fundamentally you have dials whose behavior includes larger variation in results -it's a complex system and you often can't get the best performance while also maximizing predictability
this post from aphyr looks apropos https://aphyr.com/posts/269-reaching-200k-events-sec
yeah, reading now, and it's describing precisely the kinds of parameters you'd want to tune
aphyr has some great stuff on distributed systems - and/but I'd be careful not to go to his twitter if coworkers or children might see your screen
yeah - it reads like a precise response to @UAEH11THP’s question - he is on twitter currently, but is more active on mastadon now on an explicitly gay themed server
(not judging his choice of social media practice, just saying even having his posts on your screen could get you in hr trouble at work)
> Many “architecture patterns” are scar tissue around the absence of higher-level language features. brilliant
i saw that on wikipedia https://en.wikipedia.org/wiki/Design_Patterns#Criticism
i was like, "meh no way i'd need executors and all that for such a simple thing" but then i guess at some point it stopped being simple huh... this rabbit hole is going to be deep
yeah, there's nothing simple about distsys - you start out thinking "wow this is weird and difficult" and then after years of study you realize it is weirder and more difficult than you even imagined
What is the state of the art these days for running Jupyter/Gorrilla Repl style notebooks in Clojure these days? Is there a library that is well maintained with good community prevailing?
Depending on how much structure (or lack thereof) you're looking for, https://github.com/metasoarous/oz could be a good fit.
My intention is to build a Sanity Check platform — When supporting legacy apps, when we get unexpected outputs, it would be good to have repeatable troubleshooting steps to look over the input data in question and determine what the source of insanity is.. So I would like to be able to enable a user to run a set of moderately arbitrary queries, Explain their reasoning, then save their work for the next time a similar issue arises.
When using lein deps :tree, suggestion will sometimes be made to "Consider using these exclusions:...". Is there ever a downside to taking this advice?
there are libraries (eg. jackson) that will have breaking changes, and which version you exclude will decide which things break for which consumer of the lib
luckily, usually, you can find a version that doesn't break the functionality your app needs
So would you say it's a bad practice to automatically make the suggested exclusions, and wait until you suspect there are dependency issues in play before you start fiddling with these things?
when there's a conflict it will usually have at least two suggested exclusions
and a third option is to explicitly ask for a version before anything with a dependency is asked for (by putting it higher in the deps list)
I've often opted to explicitly ask for a version once rather than putting exclusions in 5 different things
OK, thanks!
It is worth noting that lein seems to suggest excluding on the version with the highest requirement in its “consider using …” statement. So I tend to not follow its advice blindly
Hey folks! Quick clarification question- How different is using java on the frontend for desktop or mobile applications the same, or different, as using it for the backend for web applications?
the language itself will be the same regardless, but support from tooling, libraries, and frameworks will be different. clojure on the jvm is most commonly used for backend servers so you’ll probably have an easier time getting started on backend applications. using clojure for desktop and mobile applications is possible, but is far less common. for web applications, clojurescript is really great option and has tons of tooling, libraries, tutorials, and frameworks. clojurescript can also be used to target mobile applications, but it’s less common. It’s hard to give a more detailed response without a little bit more info about your use case.
I have an immutable data structure that represents the state of my app and ~10 operations (implemented as functions of this immutable data) to change the state in all ways that are needed.
I can put this in an atom and swap!
those functions on it and that works good except for that fact that some of the operations, when used in the real "app" call for additional side effects beyond just the state mutation.
I'm somewhat stuck on how to do this cleanly/minimally. I'm thinking about having a protocol of all the operations, and then implementing that on an immutable record, and then also on a mutable record which depends on the immutable one in an atom.
Any general tips for how to deal with these situations?
I'll second agents. You lose concurrent updates to state in return for sequential side effects, but its probably okay
if "fire and forget" with a queue of changes work for your app, you can use an agent and send instead of atom and swap, that won't retry so you can do a side effect as well as altering the data
alternatively, you could set a watcher on the atom for the actions, that only gets fired once per change, regardless of the number of retries
another model is to not use an atom at all, and use iterate
, where the function you use is some "driver" that encapsulates all the actions you'd take on the state, plus the dispatch that picks one
this likely also needs a queue for events from the outside world
the iterate version needs a queue, as unlike agent / send or atom /swap it doesn't have an implicit / invisible queue built in
sounds fine? like you have an atom and some functions and no problem. the pure functions are swap! on the atom, and the impure functions have to manage the swapping themself
I've done things like
(declare ^:dynamic q)
(defn f [x] (update-in x [:x] (fnil inc 0)))
(defn g [x]
(.put q #(println "Hello World"))
(update-in g [:g] (fnil inc 0)))
(defn my-swap! [a f & args]
(binding [q (java.util.concurrent.LinkedBlockingDeque.)]
(loop []
(let [ov @a
nv (apply f ov args)]
(if (compare-and-set! a ov nv)
(do
(loop []
(when-let [f (.poll q)]
(f)
(recur)))
ov)
(do
(.clear q)
(recur)))))))
which is analogous to the way the stm queues up agent sendsdoes q
need to be a java.util.concurrent.LinkedBlockingDeque
or could it be any mutable Deque like data type? it seems like you’re guaranteed that all operations on q
will be from the same thread.
so your functions update the value, but can also queue up side effects to run on a successful swap

A watch runs on all changes, you have to split your functions into the pure part, and the part that runs in a watch, and then you would have to look at the old and new value in the watch to determine which f just ran to figure out which side effect to run
Ah okay I see. I guess I can't think of a use case right now where it couldn't be remodeled as such, but I'm sure there are some
but like, you have a namespace of functions that do stuff when passed data or an atom, you are done
Thanks @hiredman & @noisesmith, I think I felt further off from the goal than I actually am after a long day of working on it