Fork me on GitHub
#clojure
<
2023-01-30
>
Lycheese12:01:58

We are deploying an Uberjar to a Docker container and after about 19 days the docker reports a graceful shutdown:

app  | 1702694476 INFO  app.core - Shutting down system.                                                                                                                                                                                 
app exited with code 143
app exited with code 0
We are using this as our -main:
(defn -main [& _]
  (let [system (prod-system)
        shutdown-promise (promise)]
    (.addShutdownHook (Runtime/getRuntime) (Thread. (fn []
                                                      (log/info "Shutting down system.")
                                                      (component/stop-system system)
                                                      (deliver shutdown-promise true))))
    (component/start system)
    @shutdown-promise))
The strange thing is the container is still running and the app is still responsive. Any suggestions on how to debug this greatly appreciated.

delaguardo12:01:32

exit code 143 means there was SIGTERM signal sent to your application. https://docs.docker.com/engine/reference/commandline/events/ you could monitor docker events to see if this happens due to some error, low memory for example

valerauko13:01:45

how are you running the container?

Lycheese13:01:09

Through a docker-compose with restart: unless-stopped and a Dockerfile (`eclipse-temurin:17-jre`) with CMD ["java", "-Dhttp.proxyHost=...", "-Dhttp.proxyPort=80", "-Dhttps.proxyHost=...", "-Dhttps.proxyPort=80", "-Dconf=/app/conf.edn", "-jar", "/app/app.jar"].

Lycheese13:01:37

Looking through the docker events log right now. Doesn't seem to be OOM.

Lycheese13:01:07

Oh. The last time it occured was further back than 1000 log entries. I guess I will have to wait until it occurs again.

delaguardo13:01:37

btw, there are --since and --until options for docker events so you can fetch events around exact time of exit

Lycheese13:01:01

Yeah, I tried that, but it does not go back far enough.

Lycheese13:01:20

The last event occured on Jan 9th and it only goes back to the 25th

Lycheese13:01:52

At the time I didn't realize anything happened since the application kept on working

Lycheese13:01:45

Ah it probably kept working since I have restart: unless-stopped

Lycheese13:01:01

Guess I will get rid of that for now

Lycheese08:01:21

Figured out what it was when it happened again today. We enabled automatic upgrades with dnf-automatic and it had an update for containerd which caused docker to restart.

Ian Fernandez14:01:31

Is there a way to open a repl server in another thread, send some stuff to it and see if it continues to work and then turn it down?

2
Ian Fernandez14:01:52

My idea is to have a test to prohibit people to break repl driven with certain commands

Phillip Mates14:01:48

👋 I was looking to add a reader macro extension for a symbolic value, along the lines of the existing ##Inf and ##NaN, and https://github.com/clojure/tools.reader/blob/v1.3.6/src/main/clojure/clojure/tools/reader.clj#L412-L419 I'm curious if there is a specific reason for that? For context, I work with a weird database that represents the absence of a date using the smallest date value: (java.sql.Date. -1899 0 1). I got to thinking it would be nice to be able to write queries like [:= :some-field ##null-db-date] instead of using a tagged literal like [:= :some-field #sql-date "0001-01-01"]

delaguardo15:01:21

main idea behind it is not extendable is that clojure code must remains "readable" to the standard Clojure. and that is not achievable if it would be possible to introduce something like you describe in original question.

Phillip Mates15:01:50

I'm not sure I follow that reasoning. Like wouldn't that apply to ability to define your own tagged value readers?

delaguardo15:01:33

to some degree - yes. official, defined through api, scope for tagged literals is clojure.edn/read which accept mapping from tag to function and clojure.core/read which can use redefined mapping. That way it is possible to at least read tagged literal as is even if you don't have the implementation for actual reading function.

Alex Miller (Clojure team)15:01:38

symbolic values are a tool for us, not for you :)

delaguardo15:01:42

at least this is my understanding

Alex Miller (Clojure team)15:01:58

tagged literals are a tool for you

pithyless15:01:04

just out of curiosity, why the need for a data literal? Wouldn't a (def null-db-date (Date. -1899 0 1)) suffice?

Phillip Mates15:01:32

> just out of curiosity, why the need for a data literal? Wouldn't a (def null-db-date (Date. -1899 0 1)) suffice? also possible, but it would require the namespace that contains null-db-date to be required. And also doesn't work when writing out to edn files

pithyless15:01:22

yeah, it wouldn't work for edn files. I guess you could always define a custom reader, e.g. #null-db-date "" or maybe #my/sql-date (i.e. support both #my/sql-date "2020-01-02" and #my/sql-date "none")

Phillip Mates15:01:03

> symbolic values are a tool for us, not for you 🙂 I can understand not wanting to expand the surface area of this for a feature that would rarely make sense to use by clojure programmers (especially with the point @U04V4KLKCmade about a default reader). Yet in this case I don't know how much I understand or buy this "us/you" distinction. I see the capability to define and use one's own special constants a useful tool to both Clojure maintainers and maintainers of systems written in Clojure

Alex Miller (Clojure team)15:01:30

that's what tagged literals are for

Alex Miller (Clojure team)15:01:39

and edn does support https://github.com/edn-format/edn#tagged-elements, not sure I understand that complaint above

Alex Miller (Clojure team)15:01:07

and notably, edn does NOT support symbolic values

👍 2
borkdude21:01:41

Why not [:= :some-field the-null-db-date] where the-null-db-date is normal var

Phillip Mates09:01:22

I think it is the same as @U05476190 suggested. Totally works, differing only in that it requires requiring the namespace everywhere it is used, but perhaps that is a good thing.

Phillip Mates09:01:57

Anyways, wanted to thank everyone for exploring this question. I really love Clojure because it almost never prevents me from implementing the ideas I have in my head. The times that I do run up against the limits of the language, I often realize that it is me that was misguided in my framing of the problem/solution. This feels very mind-expanding and so very contrary to so many other languages out there.

zalky15:01:23

Hey folks. Just about to open-source a number of libraries in case people might find them useful. Any suggestions for how to do that? Just post them here on Clojurians? Or...

zalky15:01:31

To clarify, I'm just referring to the "getting it out there" bit so it reaches whomever might find it useful. Not deploying or whatnot.

p-himik15:01:02

If you want to reach as many eyes as possible, I'd post in every place mentioned at https://clojure.org/community/resources#_clojure_discussion

👍 2
zalky15:01:06

That's really helpful, thanks!

practicalli-johnny15:01:03

Remember to include the purpose of each library so people know why they should look at them. 😁 I see a lot of things posted in #C06MAR553 that I don't look at because I don't know what they are (and my learning Todo list is already quite long)

👍 2
zalky15:01:04

A nice, I didn't even know about that channel. Thanks!

escherize16:01:07

What’s a good way to impliment a union find aka https://en.wikipedia.org/wiki/Disjoint-set_data_structure in clojure?

emilaasa16:01:29

Are there some good blog articles or other resources on investigating memory leaks in Clojure code?

delaguardo16:01:22

https://www.yourkit.com/java/profiler/ yourkit has very good memory profiler

emilaasa17:01:08

Thanks @U04V4KLKC! I love the look of that program

emilaasa17:01:43

I think I would see the problem immediately if I saw the names of my oldest objects

emilaasa17:01:56

Something sticks around 🙂

emilaasa17:01:30

That was super effective @U04V4KLKC - thanks for the prod. I've heard about YourKit before and even tried it a bunch of years ago. It's pretty discoverable.

emilaasa18:01:29

And fixed! It was almost worth writing the buggy code for the fun experience of finding what was wrong. I hope my subconscious isn't listening and getting any ideas. Thanks again.

jjttjj22:01:37

There's also this https://www.eclipse.org/mat/ which I only used one time when yourkit /visualVM were failing me for discovering a memory leak, and I forgot the details but just remember it seemed magic in the way it just told me directly what was causing my memory leak