This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-03-10
Channels
- # announcements (3)
- # asami (4)
- # babashka (21)
- # beginners (97)
- # calva (32)
- # cider (4)
- # clj-kondo (7)
- # cljdoc (1)
- # clojure (70)
- # clojure-europe (27)
- # clojure-nl (10)
- # clojure-norway (18)
- # clojure-uk (8)
- # clojure-ukraine (1)
- # clojurescript (5)
- # datalevin (7)
- # docker (1)
- # emacs (3)
- # fulcro (4)
- # girouette (4)
- # graalvm (2)
- # graphql (9)
- # gratitude (3)
- # honeysql (4)
- # hoplon (3)
- # hyperfiddle (7)
- # jobs (3)
- # kaocha (31)
- # lsp (23)
- # malli (7)
- # missionary (6)
- # nextjournal (9)
- # off-topic (6)
- # pathom (13)
- # polylith (13)
- # practicalli (3)
- # remote-jobs (3)
- # reveal (7)
- # schema (1)
- # sci (23)
- # shadow-cljs (31)
- # tools-deps (62)
- # xtdb (8)
$ lein do clean, classpath
/home/anonimito/work/audience-republic/server-4/.cpcache/21FA38690A160741FD2BB36A1C13039C.jar
Aha [lein-classpath-jar "0.1.0"]
- removing this "fixes" it
When generating a CSV as a web handler response, is using
and writing CSV to a writer the most recommended approach?
depends, the easiest thing, data size permitting, just write it out as a blob in memory and return that
I should have known I was over-complicating things lol.
how do folks deal with AssertionError
s thrown by :pre
and :post
conditions? We’ve analyzed the libraries we depend on and see that it’s not uncommon to use :pre
and :post
conditions for argument checking (something that should really throw IllegalArguementException
and not AssertionError
.
1. turn off assertions in production
2. catch Throwable
or Exception
+ AssertionError
3. let our whole webapp terminate & restart whenever one request fails a :pre
or :post
condition
All of the above seem not ideal. Also wondering if there’s been a prior discussion of the decision to let pre & post conditions throw AssertionError
s.
assertions are designed to be turned off in production
and should be invariants that indicate a serious error - basically these should only fail if the program is wrong, not if a user provides invalid input
@alexmiller I’m aware of the latter, and I know that folks do turn them off but that also doesn’t seem ideal?
if the program is right, they are redundant. testing is for checking that the program is right
The trouble is that you can rarely reproduce everything that happens in production in a testing environment. I found assertions (used sparingly) very useful and definitely valuable in production.
we’re using tools.build
to build the uberjar. Would this also be the place to turn them off?
the place it matters is during compilation, so yes (but I'm not actually sure how easy that is to do!)
might be a needed feature in tools.build
Clojure doesn't use Java assertions so that won't do anything - it's a dynamic variable that needs to be set assert
filed https://clojure.atlassian.net/browse/TBUILD-29 (which is really a special case of https://clojure.atlassian.net/browse/TBUILD-28)
also wondering how much this simple right / wrong categorization applies to a multi-user application like a web service
on further thought, are those two statements really compatible: 1. assertions are designed to be turned off in production 2. and should be invariants that indicate a serious error if there’s a serious error in production, I think I’d like to know about it early, rather than continue.
assertions are designed so that they can be turned off in production to remove the cost of the assertion. they are designed to catch logically impossible situations that can only occur if the program is wrong. they should not be used to detect invalid input (like a bad web request, bad user input, etc). you can use them in production, but the AssertionErrors are, by definition, not designed to be caught
but not catching them and not turning them off in production means that either one needs to make sure that every library one uses follows that exact meaning (which I’ve found to be not true for our deps) or live with the fact that our app will terminate on a bad request
your complaint that people are not use pre/post conditions correctly is a valid one, but those seem like concerns to levy on the libraries in question
It's a matter of communication, catching an error in the running program then continuing (as opposed to halting) turns the error into a control flow mechanism like an If or when branching statement. Using it that way, means there is a input case to your system it knows it needs to handle, if that's true, is it really an "error" that needs to halt the program, which is the the natural progression of a throw? Thats how i see it at least. Not something that i have had to deal a lot with thankfully.
@ghadi I think was mixing up two things, it’s just the thread that will terminate, not the whole app, correct?
your complaint that people are not use pre/post conditions correctly is a valid one, but those seem like concerns to levy on the libraries in question
I was also thinking of the case where you have a single thread that does a unit of work that you want to make sure keeps running, is catching AssertionError
valid in this case?
what I'm saying is: it's not a guarantee that your app will terminate, unless something is trapping the AE and terminating
right. like Alex said, lean on the naughty libraries that are using pre/post conditions for invalid user input
one situation I’m thinking of is a core.async/go-loop
like the one https://github.com/ptaoussanis/sente/blob/master/src/taoensso/sente.cljc#L1743 that takes care of message handling. I think I’d catch AssertionError
in that case because I don’t want a combination of a bad message with a naughty library to bring down that part of my system.
pre/post is simultaneously under- and over-used. It's under-used for true program invariants and over-used for input validation.
not sure I know better what we should actually do I our app now 😹 Think we’re going with, catch AssertionError
s, in some specific circumstances for now and re-evaluate once we have more data. Thanks for the input!
You could wrap the naughty libraries and catch AssertionError in the wrapper, re-throwing it as an ExceptionInfo with a cause. At least until you can convince the library authors to fix their :pre’s and :post’s.
> naughty libraries I am wondering what the actual use case is. Are you passing user input directly to libraries that are not designed for user input? Using assertions for argument checks actually makes sense, since it is a programmer mistake to pass invalid arguments to functions.
Today I noticed a bug in a 7 year old Clojure project. I bumped Clojure from 1.5.1 to 1.10.3 and started the process. Everything ran smoothly, with no breakage. 😍 Fixed the bug and moved on.
I also realized it's been 7 years since I made https://www.parens-of-the-dead.com - a clj/cljs screencast which isn't too outdated either. Such a blessing jumping off that churn train, and using a stable programming language and environment.
Hey Magnars! What amazing work you did! Kudos 🥳
Hello everyone. What’s the best way to use malli
for generative testing?
Didn’t realize there was a malli, channel, thanks
me either! there’s so many golden gems to be found 🙂
interesting difference a coworker just noticed:
❯ java -version
openjdk version "1.8.0_322"
OpenJDK Runtime Environment (Temurin)(build 1.8.0_322-b06)
OpenJDK 64-Bit Server VM (Temurin)(build 25.322-b06, mixed mode)
~
❯ clj -M -e "(println (.getPackage (class (proxy [Object] []))))"
nil
# vs java 17:
❯ java --version
openjdk 17.0.1 2021-10-19 LTS
OpenJDK Runtime Environment Zulu17.30+15-CA (build 17.0.1+12-LTS)
OpenJDK 64-Bit Server VM Zulu17.30+15-CA (build 17.0.1+12-LTS, mixed mode, sharing)
❯ clj -M -e "(.getPackage (class (proxy [Object] [])))"
#object[java.lang.Package 0x4aa3d36 "package user.proxy$java.lang"]
This difference seems to be causing some pain due to liquibase logging and we are confused why this would be differentgetting an NPE because liquibase assumes that clazz.getPackage.getName
seems to always be defined:
and https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Class.html#getPackage()
Hmmm
> Gets the package of this class.
>
> If this class represents an array type, a primitive type or void
, this method returns null
.
A little ambiguous but you could definitely interpret this as meaning that for normal classes it does not return null
Nice find. There is a ticket created to fix the issue in Liquibase now: https://github.com/liquibase/liquibase/issues/2633
This might be a silly question but are uberjars deployable, for lack of a better term? Which is to say, I create an uberjar locally and then rsync it to a server and it runs correctly
yup. the only issue might be that there is a different version of Java on the server you’re rsyncing to
Excellent, thank you
oh, also, the uberjar might be using resources like config files, which you would also have to rsync over
That's a great point
Right now I'm ssh-ing in and then git pull, lein uberjar, and that's a real pain in the butt lol
anything you get via io/resource will be packaged in the uberjar
any files besides that you read manually will not be in the uberjar and will also have to be rsynced manually