This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2023-09-22
Channels
- # babashka (106)
- # beginners (29)
- # biff (29)
- # calva (9)
- # cider (6)
- # clj-kondo (24)
- # clojure (40)
- # clojure-europe (94)
- # clojure-japan (1)
- # clojure-nl (1)
- # clojure-norway (45)
- # clojure-uk (13)
- # clojuredesign-podcast (5)
- # clojurescript (12)
- # clr (4)
- # community-development (2)
- # conjure (13)
- # cryogen (4)
- # cursive (4)
- # deps-new (1)
- # fulcro (18)
- # hugsql (2)
- # hyperfiddle (67)
- # jobs (1)
- # malli (47)
- # meander (2)
- # missionary (34)
- # off-topic (1)
- # podcasts-discuss (1)
- # polylith (24)
- # reagent (19)
- # reitit (9)
- # sci (7)
- # shadow-cljs (3)
- # testing (28)
- # tools-deps (1)
- # xtdb (9)
hiya community! I got a question for BB experts: I wanna be able to run an external command in the background… and: 1. check if it’s doing OK 2. exit my BB program, but keep that one running in the background how would you approach this?
like… you start here dear program… please don’t print to stdout, save stuff to this temp file… I am exiting now, but you carry on doing your stuff!
Not sure, but you can always use unix* commands to do this https://www.howtogeek.com/440848/how-to-run-and-control-background-processes-on-linux/ and write to a file. Then you'd just be launching the babashka script as the main starting point.
Got a feeling that you're asking for a unix style fork, but don't think JVM supports this https://stackoverflow.com/questions/287633/java-c-like-fork . Then again I don't do enough of this stuff to know.
Ok… this actually keeps the process running after program has exited
(let [{:keys [proc]} (process "python" "daemon.py")]
(println (format "PID %s" (.pid proc))))
Yea I think that is usually the easy case, doing the opposite is what requires a little work usually
also… weirdly enough, if I do a
(future
(while true
(Thread/sleep 1000)
(println "YAY!")))
That does not keep the BB thing running @U5B8QSSC9 Indeed, threads are killed on exit. If you want to keep bb running in the background, start it with $ bb ... &
on the command line, I'd say?
you can also use "exec" in babashka process, to do a unix exec call (let another process take over exection of the process), not sure if that is relevant here though
How does babashka get Clojure proper if it doesn't already exist on the system/in the expected path?
@U6SUWNB9N the readme suggests that Babashka ships its own tiny graal jvm and supports a reduced subset of the full Clojure language: https://github.com/babashka/babashka#setting-expectations If you have a hard requirement to connect your scripts to a full Clojure install I imagine babashka wouldn’t be the best fit.
Scratch that, I’ve just read the next thread and it looks like you got what you needed.
CLJ_CONFIG=bb-test/.clojure DEPS_CLJ_TOOLS_DIR=bb-test/.deps.clj bb --config bb-test/bb.edn uberjar deps.jar
Clojure tools not yet in expected location: bb-test/.deps.clj/clojure-tools-1.11.1.1403.jar
Downloading to bb-test/.deps.clj/clojure-tools.zip
Unzipping bb-test/.deps.clj/clojure-tools.zip ...
Successfully installed clojure tools!
Error: Could not find or load main class clojure.main
Caused by: java.lang.ClassNotFoundException: clojure.main
Exception in thread "main" clojure.lang.ExceptionInfo: babashka.process.Process@e72f7c71
Sorry.
I don't have access to ~/.clojure
, so I need to point it somewhere else which I thought CLJ_CONFIG
should do, but then I don't know what I need to populate into that dir and what bb
should auto-fetch
So I assume I'm getting the "Could not find clojure.main" error because I'm missing some step in populating that CLJ_CONFIG
directory. If I have a look after the command fails it contains a deps.edn
and tools/tools.edn
, but no .cpcache
, which I guess is what it's looking for
Try -Sforce and also upgrade bb to latest. At a conf right now so I have to be short
Already @ latest, so that's good 🙂 Same with -Sforce
and deleting the existing cache in my homedir
I'm trying to make a deftype or defrecord that is over IAtom and a couple other related protocols Babashka compatible. I'm running into issues with the interfaces IObj and IRef. I'm using these two to implement the add-watch method and the with-meta method. The error is about defrecord/type only supporting protocol implementations. I believe that Babashka supports atom watchers. But I don't know. Can anyone point me in the right direction? Cheers!
I'm assuming you're talking about https://github.com/babashka/sci/tree/3eee320309edbd94fed457d696eede6ae8f35e61/https://github.com/babashka/sci/tree/3eee320309edbd94fed457d696eede6ae8f35e61/src/https://github.com/babashka/sci/tree/3eee320309edbd94fed457d696eede6ae8f35e61/src/sci/https://github.com/babashka/sci/tree/3eee320309edbd94fed457d696eede6ae8f35e61/src/sci/impl /core_protocols.cljc That code is a doozy! You're a good man for navigating those waters.
Thanks for checking in. As it sits atm I've just got the bb version of the code without methods for IRef, IObj, IMeta, IReference, and Closeable.
Looking at how you implemented protocols with multi-methods was a very cool idea.
If you have the time to answer a few bb development related question a little nudge would help me help myself.
I'd like to run a server bb so I can get fast starts on edge, When I've got a library like kixi.stats that isn't bb compatible, how do I go about finding out which namespaces contain that non-portable code so I can assess if I'm actually using anything that's a problem and formulate a plan?
I usually just try to run the library's unit tests. See test-resources/lib-tests, bb tests a plethora of libs on CI
As for the IRef and IReference stuff I'm a bit lost on what I would do, we talked long ago about porting durable atom to bb, I've got everything working quite well, outside of the watch stuff, but feel a bit lost on exactly what to do when I get into a spot where I want to use a protocol that isn't ready out of the box
The issue is usually with deftypes which implement Java interfaces:
$ bb -cp src:test -e "(require '[kixi.stats.core])"
----- Error --------------------------------------------------------------------
Type: clojure.lang.ExceptionInfo
Message: defrecord/deftype currently only support protocol implementations, found: clojure.lang.Seqable
So, does that mean that I've touched a hard line or is there some finesse I can employ?
The issue with bb is that graalvm needs to know all types beforehand. So if you create a deftype in userland with a number of protocols, it needs to exactly match with a type that already exists in bb. I've done this with reify for a number of often used combinations, but this doesn't work in general
I've tried the approach to create a type which just implements all possible interfaces, but this will not work with instance?
checks obviously
Shucks bork, I seem to have great ideas and a complete lack of if my ideas touch reality/my abilities
I do know if I could put watches in a protocol implementation it would open up a lot of my functionality on the JVM/CLJS front, and I wouldn't miss not calling instance?
you could try to rewrite kixi so that it doesn't use seq
but the specific function sampleable->seq
instead and then avoid the overloaded interface clojure.lang.Seq
for bb
So does that mean I can make a generic type explicit with those methods and then implement watches on them?
So instead of implementing IReference, I just do the same thing on a protocol MYIReference?
I commented out all clojure.lang.Seqable overloads in kixi.stats.distribution. The next thing I hit was com.tdunning.math.stats.TDigest
is not included in bb, so it relies on a Java lib it seems
What bb could also do is allow all types on the "type that implements all user types" and patch bb's instance?
to check if a type dynamically implements an interface. The only thing is when passing such a type to an external library, you could get false positives
but maybe the chance of that isn't so large and those external libraries could be patched in bb (since there is a fixed number of them anyway), but it's a bit risky maybe
In that type of situation I typically put metadata on a var or I call (-> % class str) and predicate the string.
But I don't know if that's viable. I'm really just guessing seemingly all the time:smiley:
I'll def with a metadata key like, atom-watch? true and check if somethings and atom-watch by passing a ref. I hope that isn't too ugly and hacky to admit.
I should have said var reference
IRef
(setValidator [_ validator]
(.setValidator ^IRef atom-ref validator))
(getValidator [_]
(.getValidator ^IRef atom-ref))
(addWatch [this watch-key watch-fn]
(.addWatch ^IRef atom-ref watch-key watch-fn)
this)
(removeWatch [this watch-key]
(.removeWatch ^IRef atom-ref watch-key)
this)
(getWatches [_]
(.getWatches ^IRef atom-ref))
See if I got this right? I'm worried it's too simple for me to be right. So I'd need to define my own protocol MyIWatchable
, with a addWatch
method, then dig into core and see what .removeWatch is doing, and basically do a less JVM dependent version of that.Yes, but the trouble is that add-watch
(in Clojure) calls the JVM interface, not your protocol, so you can't re-use add-watch for your custom atom then, but maybe that's not so bad
I can manage that part.
One more thing that's confusing me. If I can't implement the methods in IRef in bb, how come I can require clojure.lang IRef in bb? What exactly is the point where I cross the JVM/BB line and break?
The clojure.lang.IRef
interface exists in bb as a regular JVM interface and is there when people e.g. write (instance? clojure.lang.IRef ..)
- this happens in some libraries
I think I get enough of what's going on... Just as a guage, is the http-kit integration you've built into bb being used to good effect in production? Or was that more intended for dev tooling?
it works fine in production I think but I don't have numbers on how many people use it in production
Currently I'm doing the lazy thing where I call bb task-name
in a dockfile. But the binary approach is proper modern and sexy.
or fork babashka and add some libraries you're missing and build your own version for the edge with your libs
Now we're talking!
Surely, you've got some docs on forking and adding libs I've missed.
"https://github.com/babashka/babashka/blob/master/doc/dev.md#adding-classes
Add necessary classes to babashka/impl/classes.clj
. For every addition, write a unit test, so it's clear why it is added and removing it will break the tests. Try to reduce the size of the binary by only adding the necessary parts of a class in :instance-check
, :constructors
, :methods
, :fields
or :custom
.
The reflection.json
file that is needed for GraalVM compilation is generated as part of script/uberjar
."
There are a number of feature flags for specific libs: https://github.com/babashka/babashka/blob/master/doc/build.md That should give you an idea where to add stuff
Cursory scan tells me that's within my current capabilities, a stretch but I'm capable.
yeah, you just need to set GRAALVM_HOME to a download of graalvm and then run script/uberjar && script/compile
- should just work ™️
sometimes it's just a matter of (sci/copy-ns kixi.stats.core (sci/create-ns 'kixi.stats.core))
if you're lucky
I'm familiar with the sci context. I'm not sure how much I'm following, but I know my mental picture is fuller.
I need to spend more time with the code instead of treating it like another shell utility.
I won't take up any more of your time. Thanks Borkent! As usual, you've been helpful and didn't make me feel stupid. What a treat for me. lololol CHEERS!
There's a blazingly fast bun, hono, and nbb in an edge in Dallas. So I'm already close to a BB in Amsterdam.
Having a senior moment. I know how to load pods and use them in a bb script but how do i use it in a bb task? Script i’m trying to convert to a bb task below
#!/usr/bin/env bb
(require
'[babashka.pods :as pods]
'[clojure.pprint :refer [print-table] :rename {print-table pt}])
(pods/load-pod 'org.babashka/mssql "0.1.2")
(require '[pod.babashka.mssql :as ms])
(def db {:dbtype "mssql",
:dbname "***",
:host "localhost",
:port "1434",
:user "sa",
:password "***",
:trustServerCertificate "true"})
(defn q [s] (ms/execute! db [s]))
(pt
(q "update dbo.users set email = '***'"))
Adding something like this to bb.edn and running bb run <task-name> should work.
{:paths ["."]
:tasks
{task-name {:doc "Task doc"
:requires ([abc :as abc])
:task (abc/update-user-email)}
}}
@U64FXM56W i want to keep it all in a single bb.edn
It should still work the same way only the namespace will change. The namespace should match with where the file is located w.r.t bb.edn.
Did it fix the issue @U06GMV0B0? I am more curious now.:thinking_face: Scripts with pods work fine for me without using :pods in bb.edn. Also if loading the pod failed earlier the error from babashka would have been at the line (pod/load-pod ..) itself.