This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-06-08
Channels
- # asami (15)
- # babashka (123)
- # beginners (174)
- # calva (4)
- # cider (6)
- # cljdoc (4)
- # cljs-dev (4)
- # cljsrn (18)
- # clojure (268)
- # clojure-australia (1)
- # clojure-europe (107)
- # clojure-ireland (5)
- # clojure-nl (2)
- # clojure-uk (18)
- # clojured (1)
- # clojurescript (21)
- # conjure (4)
- # cursive (38)
- # data-science (1)
- # datahike (6)
- # datomic (4)
- # events (1)
- # fulcro (9)
- # graalvm (16)
- # helix (6)
- # honeysql (4)
- # instaparse (3)
- # jobs (1)
- # observability (15)
- # pathom (7)
- # pedestal (15)
- # polylith (9)
- # practicalli (1)
- # re-frame (6)
- # remote-jobs (2)
- # specter (7)
- # sql (16)
- # tools-deps (1)
- # vim (5)
- # xtdb (1)
Hello, i'm trying to use babashka.process for a little thing. I would like to be able to launch a process that do not terminate and do something whenever some new output occurs from it. Is there a builtin way to do this? I've try this example from the documentation:
(future
(loop []
(spit "log.txt" (str (rand-int 10) "\n") :append true)
(Thread/sleep 10)
(recur)))
(pipeline (pb '[tail -f "log.txt"])
(pb '[cat])
(pb '[grep "5"] {:out :inherit}))
but I do no see anything printing out, is it intended ?Yes, so this works:
(require '[babashka.process :refer [pipeline pb]])
(future
(loop []
(spit "log.txt" (str (rand-int 10) "\n") :append true)
(Thread/sleep 10)
(recur)))
(-> (pipeline (pb '[tail -f "log.txt"])
(pb '[cat])
(pb '[grep "5"] {:out :inherit}))
last
deref)
thank you @borkdude, I've just tried this snippet in my editor (intellij cursive) on Java 15 and clojure 1.10.0. Am I supposed to see something printed in the repl ?
you can remove the deref
to make it not hang. I just added that to make the bb script not terminate
Can you please try this in a standalone bb script and then execute it from the terminal?
ok, thank you for your time @borkdude! I will investigate on my own and let you know if I find something
Can I connect to the bb repl in VSC Calva without manually entering it every time? it does not pick it up from .nrepl-port file
@dennisa Babashka does not write an .nrepl-port
file since that can conflict with a Clojure process.
I can write it myself, just need Calva to pick it up from somewhere, otherwise getting this promt with no port. I have to restart the bb repl rather often as it slows down and it's a chore to type every time 1667 : )
@dennisa There is a snippet about writing this port file here: https://book.babashka.org/#_nrepl
(I think this script can be simplified/refactored now since there is babashka.process)
I haven’t tried this myself, but you can probably configure a connect sequence, nReplPortFile
with the name of whatever nrepl-port file you write. See: https://calva.io/connect-sequences/
Now tried it. This setting works:
"calva.replConnectSequences": [
{
"name": "bb",
"projectType": "generic",
"nReplPortFile": [".bb-nrepl-port"],
"cljsType": "none"
}
]
Then start babashka like so:
echo 1667 > .bb-nrepl-port && bb --nrepl-server
It won’t work for me. I can see ‘bb’ in the ‘connect to repl’ prompt but the port is still empty after localhost: The .bb-nrepl-port is created fine with 1667 port in it. @pez
I now tried this on my Windows machine, and it just works there as well… Please file an issue about this using the Help menu in vscode. Attach the setting and the command line you are using.
It's on the mac. Do you want me to file issue to Microsoft about calva )? What's the chance to resolve it? )
There is an option there to file the issue on the extension, so it will land in Calva’s GiHub repo. The point with doing it this way is that some system info will be attached to the issue.
Continuing from #clojure in a thread: I'd like to add babashka support to https://github.com/IGJoshua/farolero The key thing that would prevent it from working as-is is the requirement to be able to throw an object that isn't caught by ex-info catch clauses.
If there's a way to throw an arbitrary object or extend a throwable marker protocol or something that'd be ideal, but since babashka is likely to be used in smaller projects with fewer dependencies, I may if need be just use ex-info, but I'd prefer to not as there's a requirement to re-throw exceptions from catch blocks based on a condition, and a normal catch block for ex-infos won't re-throw based on that condition.
I solve this by making the farolero-signal
artifact on maven that contains a single class that extends java.lang.Error
(which extends from Throwable
but not Exception
), https://github.com/IGJoshua/farolero/blob/master/signal/src/farolero/signal/Signal.java
Then in the actual farolero lib I just extend-protocol
to this class to add the functionality for storing the objects that need to get passed around.
And the reason that it's in a different artifact altogether is to allow git dependencies on farolero.
@U5NCUG8NR So your library, does it catch only this specific exception and handle that one? Or does it install some global exception handler?
It only catches this one specific exception, and it never throws the exception except if it knows for a fact that it's currently in a dynamic context where it will be caught.
For the CLJS support it catches all objects thrown and re-throws them if they don't implement the protocol.
In particular there is exactly one construct that throws or catches this exception, and it is block
, and everything else is implemented on top of that.
(block the-block
(some code)
(return-from the-block :returned)
:unreachable)
return-from
throws the exception, and block
catches itYeah, it's a feature of JS.
A workaround I can come up with for bb is: Make one singleton Exception instance, e.g.:
(defonce FaroleroEx (Exception. "my-special"))
and then in the catch clause check (identical? FaroleroEx ex)
That's a good thought, I might do that. The key reason that I would want to throw arbitrary objects or something would just be to prevent catch blocks from interfering with this mechanism, but if I can't do that in bb, that's fine.
The features already won't be 100% parity anyway because I doubt bb implements locking
and so the debugger won't be the same.
btw another thought. I see you mix specs with your code. If they are non-essential to your lib, e.g. only for development, I recommend putting them aside in a farolero.specs
namespace so they can be optionally loaded. This saves startup time
but there is https://github.com/borkdude/spartan.spec as a drop-in replacement
Oh, cool, maybe it can be on part with the debugger then. The main part I was concerned about is this highlighted portion: https://github.com/IGJoshua/farolero/blob/master/src/cljc/farolero/core.cljc#L1192-L1269 I guess it's worthwhile to see if it'll run unmodified on bb though. Thanks! As for the exception mechanism, I think I can just do what you suggested with an extra field on an ex-info
Oh, yeah, the specs. Good to know. The reason the specs are there is just to help with macroexpansion, they aren't used at runtime at all. Moving them to a separate namespace is far from out of the question.
Hmm, dosync
and ref
etc are not in babashka. Nobody ever asked for this. Those features were cool in the beginning of Clojure but nowadays pretty much everyone uses atoms
Yeah, this was the first time I'd ever found a use for refs.
I might be able to refactor it to use atoms, but it could be a challenge, this is all pretty sensitive code and prone to race conditions on changes.
It's a unique cons of the condition and arguments.
line 1283
I don't think .wait
and .notify
currently work, but I think they could be made to work, with some work ;)
Fair enough. I'd like to take a peek in the source of babashka/sci to see how hard adding notify and wait are. dosync etc I might be able to avoid by refactoring to use an atom, although we'll see if that ends up worth it.
Oh nice!
Are numbers interned objects in bb?
hm, this didn't work:
user=> (def c (cons 1 2))
user=> (locking c (.wait c))
java.lang.IllegalArgumentException: No matching method wait found taking 0 args for class clojure.lang.PersistentList [at <repl>:1:8]
The interop in bb is implemented using reflection and reflection inside a native image needs some special attention sometimesAh, I see.
Yeah, I was able to get just a bare object to work as expected with wait and notify
Fair enough. Anyway, it looks like wait and notify don't work on clojure's collections, yeah, so that'd probably be where the work on wait and notify would have to be put.
I'm going afk now, as it's getting late. Let's revisit some other time and make issues for the things that could be examined / improved
Also I'm looking at this and while the ref code could be re-expressed in terms of atoms, it'd be clunky at best.
Sounds good!
btw, I think I know what the issue is. bb supports reflection on a selection of classes. e.g. this works:
user=> (def c (java.io.File. "foo"))
#'user/c
user=> (locking c (.wait c))
Fair enough. I'll make an issue for this now.
As well as a discussion issue about ref/dosync
As an aside, farolero kind of completed my personal trek through the multithreading facilities that clojure provides, since before this I'd used atoms of course, core.async channels, reducers, and agents for per-endpoint ratelimits on a discord client. Finally with farolero I've also used refs. Now I guess it's time for me to learn manifold, lol.
Honestly the one thing that I felt was really missing from core.async though was a promise channel that you could deref. So I've had to write one. 😛 https://github.com/IGJoshua/discljord/blob/master/src/discljord/util.clj#L93-L151
@U5NCUG8NR I've got dosync
etc working. I'm also looking into .wait
and .notify
: this does work if you use an ^Object
type hint, so you could try that as a workaround meanwhile.
I also made this GraalVM issue: https://github.com/oracle/graal/discussions/3456
Awesome, I'll give it a try today.
I'm using nixos
ok, then the static linux binary probably works for you: https://19891-201467090-gh.circle-artifacts.com/0/release/babashka-0.4.5-SNAPSHOT-linux-amd64-static.tar.gz
@borkdude the commute
and alter
functions would be great to have too. I know farolero uses at least alter
. I'll get to actually testing it once my workday is done.
Thanks
@U5NCUG8NR Now the .notify
/ .wait
stuff also works :)
$ time bb -e '(def x (cons 1 nil)) (locking x (.wait x 2000))'
bb -e '(def x (cons 1 nil)) (locking x (.wait x 2000))' 0.01s user 0.01s system 1% cpu 2.033 total
Thanks! Sorry I didn't get to try it out last night, life just kinda got in the way. Got a kitten recently and she requires a lot of attention.
Sounds good