babashka

https://github.com/babashka/babashka. Also see #sci, #nbb and #babashka-circleci-builds .
borkdude 2021-06-07T10:21:43.416600Z

Mindbending demo of building an AWS Lambda front-end with babashka and scittle that interacts with other AWS features like Polly: https://twitter.com/FieryCodDev/status/1401843357555511301

🤯 3
Endre Bakken Stovner 2021-06-07T15:57:17.417400Z

In my REPL I get:

user> (require '[babashka.process :as p :refer [process]])
;; => nil
user> (process ["ls"])
Error printing return value (IllegalArgumentException) at clojure.lang.MultiFn/findAndCacheBestMethod (MultiFn.java:179).
Multiple methods in multimethod 'simple-dispatch' match dispatch value: class babashka.process.Process -> interface clojure.lang.IDeref and interface clojure.lang.IPersistentMap, and neither is preferred
How do I fix this?

Endre Bakken Stovner 2021-06-07T15:59:12.417900Z

I guess you aren't meant to be able to print processes like that...

borkdude 2021-06-07T16:00:59.418100Z

Is this a bb repl?

Endre Bakken Stovner 2021-06-07T16:01:19.418300Z

No, CIDER 🙂

borkdude 2021-06-07T16:02:01.418700Z

It seems cider is using pprint in the REPL then: https://github.com/babashka/process#clojurepprint

Endre Bakken Stovner 2021-06-07T16:19:31.420500Z

Do you also know why CIDER might be eating my stderr? The below gives stderr output in a regular REPL, but not in CIDER:

(require '[babashka.process :as p :refer [process]]
         '[<http://clojure.java.io|clojure.java.io> :as io])
(def bwa-mem (process ["bash" "-c" "bwa mem -R '@RG\\tID:A\\tSM:A'  /Users/endrebakkenstovner/everclear/snakemake-flow/data/genome.fa /Users/endrebakkenstovner/everclear/snakemake-flow/data/samples/A.fastq | samtools view -Sb - &gt; /Users/endrebakkenstovner/everclear/snakemake-flow/bwa-map/genome/hg19/sample/A/bwa-map.bam"] {:err :inherit
                           :shutdown p/destroy}))
(with-open [rdr (io/reader (:out bwa-mem))]
  (binding [*in* rdr]
    (loop []
      (let [line (read-line)]
        (println :line line)
      (when (not (nil? line))
        (recur))))))

Endre Bakken Stovner 2021-06-07T16:19:44.420900Z

Just curious. Otherwise I'll ask in CIDER.

Endre Bakken Stovner 2021-06-07T16:20:07.421400Z

The above command would only show stderr output.

borkdude 2021-06-07T16:20:30.421800Z

the stderr of a process is written to System/err, if you use :inherit, not to *err*

borkdude 2021-06-07T16:20:46.422100Z

Unless you configure it with {:err *err*}

borkdude 2021-06-07T16:21:24.422600Z

that is probably the issue

Endre Bakken Stovner 2021-06-07T16:21:43.423Z

Yes, it was! I had been playing around with it for so long XD, thanks!

Endre Bakken Stovner 2021-06-07T16:23:46.425100Z

Anyways, can I use :shutdown to issue a callback after process has finished? Or is some other way recommended? I'd love to do (process bwa-map {:shutdown #(do (notify-others %) (p/shutdown %))

borkdude 2021-06-07T16:25:49.425600Z

currently there is no callback that you can add when the process exits, but it is possible to add this

Endre Bakken Stovner 2021-06-07T16:26:15.426100Z

But can't I cheat in the way I showed above?

borkdude 2021-06-07T16:26:37.426500Z

I think you can. But the :shutdown hook is only executed when the JVM or babashka shuts down, not directly when the process itself ends

borkdude 2021-06-07T16:28:51.427700Z

but in Java 11 there is an onExit hook

borkdude 2021-06-07T16:29:01.428Z

which babashka.process could also support

borkdude 2021-06-07T16:29:21.428600Z

it depends on your use case, so far I didn't need it

Endre Bakken Stovner 2021-06-07T16:30:45.430200Z

That would be neat. My program dispatches plenty of jobs (think make) and I would love to be notified when they finish (ideally with all the info found in (process ...)) so that I could process the results easily.

Endre Bakken Stovner 2021-06-07T16:30:50.430400Z

I'll look into it!

borkdude 2021-06-07T16:31:21.430700Z

you could use this as of today, but using Java interop

borkdude 2021-06-07T16:31:28.430900Z

the process is available under :proc

Endre Bakken Stovner 2021-06-07T16:31:54.431400Z

Mind if I ask you questions if I can't get it working? XD I'll start looking into it now 🙂

borkdude 2021-06-07T16:34:41.431900Z

sure. is your target with this usage the JVM or bb?

Endre Bakken Stovner 2021-06-07T16:34:54.432600Z

It is the JVM 🙂

borkdude 2021-06-07T16:34:55.432700Z

I don't think bb allows interop with CompleteableFuture yet

borkdude 2021-06-07T16:34:57.432900Z

ok

mathpunk 2021-06-07T16:35:57.433600Z

I expected this to work from a bb script, since I saw a usage of http://java.net classes in an example in the book:

(import [<http://java.net|java.net> DatagramSocket
         DatagramPacket
         InetSocketAddress])
yet, Unable to resolve classname: java.net.InetSocketAddress :thinking_face:

mathpunk 2021-06-07T16:36:27.433700Z

i've done no setup other than the shebang so if I have to get into pods or a bb.edn, I haven't tried that

mathpunk 2021-06-07T16:37:42.433900Z

A selection of Java classes are available, see babashka/impl/classes.clj in babashka's git repo.

mathpunk 2021-06-07T16:38:26.434100Z

The example I saw was at the end of this section: https://book.babashka.org/#_nrepl

borkdude 2021-06-07T16:38:32.434400Z

user=&gt; (def proc (:proc (babashka.process/process ["ls"])))
#'user/proc
user=&gt; (def cf (.thenApply (.onExit proc) (reify java.util.function.Function (apply [this p] (.exitValue p)))))
#'user/cf
user=&gt; (.get cf)
0
@endrebak85

🙏 1
mathpunk 2021-06-07T16:38:48.434600Z

do I need to do something classpath-y in order to invoke an import like that?

mathpunk 2021-06-07T16:41:38.435200Z

gotcha, didn't consider that a subset of http://java.net might be present

borkdude 2021-06-07T16:42:55.435500Z

we could consider adding it if there is a good use case for it and if the added binary size is still reasonable. could you explain why you need it?

mathpunk 2021-06-07T16:43:40.435700Z

I am communicating with datadog via UDP datagram

mathpunk 2021-06-07T16:44:04.435900Z

I might should just use curl instead

borkdude 2021-06-07T16:44:30.436100Z

Are you the same person I recently gave the statsd example to? I think that is all you need

mathpunk 2021-06-07T16:44:48.436600Z

I am not, I bet I could reuse it

mathpunk 2021-06-07T16:46:02.436900Z

great, I'm sending events rather than incrementing a thing but, I think I can see enough to find my way toward that

mathpunk 2021-06-07T16:46:07.437100Z

thank you!

borkdude 2021-06-07T16:46:56.437300Z

:thumbsup:

Endre Bakken Stovner 2021-06-07T17:01:32.437500Z

This worked beautifully, thanks.

borkdude 2021-06-07T18:26:34.437700Z

I added InetSocketAddress for the next release so the next person won't run into this issue again

mathpunk 2021-06-07T22:57:27.440300Z

It's been a pretty successful day getting babashka to help me do a task. One thing though: I created a second .clj file, and went to require the other one, and it's not found. I figured: 1. I'll probably have to learn more about classpaths to do that; but also, 2. Maybe if I split up namespaces that's a sign I'm using babashka for too large a problem?

borkdude 2021-06-08T07:48:25.442600Z

@mathpunk 1. This works pretty similar to how normal Clojure projects work. Add a bb.edn instead of a deps.edn and add your source directories to :paths. An alternative to using the classpath is using load-file.

borkdude 2021-06-08T07:48:46.442900Z

2. No, this is totally fine

mathpunk 2021-06-07T23:00:15.442500Z

I'm adding functionality to existing shell scripts, which will call my program, so I thought it was the right thing to grab. I could be wrong and it's a good time in this project to figure out if I am 🙂