babashka

https://github.com/babashka/babashka. Also see #sci, #nbb and #babashka-circleci-builds .
borkdude 2020-10-16T11:55:48.438600Z

If I would do one more talk this year about bb, would you like me to go into: 1) babashka / sci internals 2) dedicated talk on babashka pods 3) other (respond in thread) Vote here: https://twitter.com/borkdude/status/1317072035542171650

Mitch 2020-10-16T14:13:03.441Z

I notice that *file* isn't bound when I am using the nrepl server (which makes sense). Is the best way to work around this to just manually bind it during my repl sessions?

nate 2020-10-16T14:48:21.441100Z

I would recommend something like this, where most of the code that deals with the filename takes it as an argument:

(defn process
 [filename]
 (println filename))

(when *file*
  (process *file*))

borkdude 2020-10-16T15:21:15.442900Z

I've made a couple of updates to babashka process: https://github.com/babashka/process. Breaking changes: - use slurp to realize output into strings, :out and :err are always streams - :exit is always a delay, forcing the delay will wait for the process to end - :throw is removed, use (wait (process ...) {:throw true}) to explicitly throw

borkdude 2020-10-16T15:24:26.443400Z

@mitchell_clojure Are you running into an unexpected error because of this?

Mitch 2020-10-16T15:28:56.443600Z

Thanks, @nate, I think that is the way I am going (or setting a default value for *file* if not bound). @borkdude no breaking errors because of this, just trying to make my REPL flow ergonomic. I noticed that evaluating the buffer from cider did not produce the same result as running the script. It was simple to track down the cause and work around. I am not sure if the bb nrepl server can see which files forms come from, but that is the only place where I think this could be fixed

Mitch 2020-10-16T15:29:29.443800Z

it is small potatoes regardless and maybe not worth rebinding the var root every time the nrepl server gets a message

borkdude 2020-10-16T16:03:19.444Z

@mitchell_clojure Can you give an example of how to reproduce this difference? I do have emacs + CIDER

borkdude 2020-10-16T16:27:52.444200Z

I see, can reproduce it

borkdude 2020-10-16T16:27:54.444400Z

will fix

Mitch 2020-10-16T16:28:08.444600Z

ah cool, was just about to send the repro

Mitch 2020-10-16T16:28:28.444800Z

thank you!!

borkdude 2020-10-16T16:41:27.445Z

Fix pushed to master https://github.com/babashka/babashka.nrepl/issues/31

😲 1
borkdude 2020-10-16T16:50:57.446700Z

I think I solved most of the problems I had doubts about in this lib. Might be ready for inclusion in bb. One issue I could not solve: https://github.com/babashka/process#piping-infinite-input It seems that io/copy of an infinite input stream never flushes to the output stream or something?

borkdude 2020-10-16T17:13:31.447600Z

One thing of doubt: should (wait (process ...)) throw by default when the exit code is non-zero? Now it only does so when (wait (process ....) {:throw true})

borkdude 2020-10-16T17:14:34.448800Z

I think it might make sense to throw by default...

(-> (process ["ls" "foo"]) (wait) (process ["cat"]))
would then succesfully crash because there is no foo

nate 2020-10-16T18:38:50.449300Z

I think throw by default makes sense

nate 2020-10-16T18:39:19.450Z

can you do a {:throw false} if you don't want it to throw?

borkdude 2020-10-16T18:40:01.450900Z

The above can now also be written as:

(-> @(process ["ls" "foo"]) @(process ["cat"]))
because of an IDeref implementation :-) Yes, throw false is an option.

nate 2020-10-16T18:41:26.451600Z

hm, a couple of thoughts to consider: 1. default in bash is not to throw an exception (as in it doesn't exit the script) 2. defaults in bash might not be a sensible thing to follow

borkdude 2020-10-16T18:41:48.451900Z

thanks :)

nate 2020-10-16T18:42:08.452400Z

does clojure.java.shell throw if the command errors?

nate 2020-10-16T18:42:27.452700Z

I can't remember

borkdude 2020-10-16T18:42:43.453100Z

no, it doesn't. which is something I probably always wrap myself, or not, if I'm too lazy

borkdude 2020-10-16T18:48:39.453500Z

I'm trying to completely mimic clojure.java.shell either though. if you want to use that, use that

borkdude 2020-10-16T18:52:23.453800Z

From the docs: The function wait takes a process, waits for it to finish and returns it. When the exit code is non-zero, it will throw, which can be turned off with `{:throw false}`.

clojure
user=> (-> (process ["ls" "foo"]) wait :exit deref)
Execution error (ExceptionInfo) at babashka.process/wait (process.clj:74).
ls: foo: No such file or directory
clojure
user=> (-> (process ["ls" "foo"]) (wait {:throw false}) :exit deref)
1
The return value of process implements clojure.lang.IDeref. When dereferenced, it will execute wait with default option :throw true:
clojure
user=> @(process ["ls" "foo"])
Execution error (ExceptionInfo) at babashka.process/wait (process.clj:74).
ls: foo: No such file or directory

nate 2020-10-16T18:56:21.454100Z

Looks very good

borkdude 2020-10-16T20:37:04.455Z

I found the issue with piping infinite streams. If I put a flush in io/do-copy for stream -> stream:

(defn copy [in out opts]
  (let [buffer (make-array Byte/TYPE (buffer-size opts))]
    (loop []
      (prn :copy)
      (let [size (.read in buffer)]
        (when (pos? size)
          (.write out buffer 0 size)
          (.flush out)
          (recur))))))
then it works. I wonder if this is a good idea or not... Probably not, but now I know the issue: buffering

isak 2020-10-16T21:21:57.455300Z

Pod for SQL Server support: https://github.com/xledger/pod_sql_server

💯 1
🦜 2
borkdude 2020-10-16T21:26:56.455800Z

Amazing, thanks!

🙂 1
borkdude 2020-10-16T21:29:10.456100Z

Any reason why not to use keywords as keys instead of strings btw?

1
isak 2020-10-16T21:30:10.456300Z

Oh no, I guess it probably works either way, let me verify and update the readme

borkdude 2020-10-16T21:42:04.456600Z

Just built the project on macOS as well: ` $ dotnet build Microsoft (R) Build Engine version 16.7.0+7fb82e5b2 for .NET Copyright (C) Microsoft Corporation. All rights reserved. Determining projects to restore... Restored /private/tmp/pod_sql_server/pod_sql_server.csproj (in 3.27 sec). pod_sql_server -> /private/tmp/pod_sql_server/bin/Debug/netcoreapp3.1/pod.xledger.sql_server.dll Build succeeded. 0 Warning(s) 0 Error(s) Time Elapsed 00:00:05.23

borkdude 2020-10-16T21:42:18.456800Z

This works:

(require '[babashka.pods :as pods])

(pods/load-pod ["dotnet" "bin/Debug/netcoreapp3.1/pod.xledger.sql_server.dll"])

(require '[pod.xledger.sql-server :as sql])

borkdude 2020-10-16T21:43:34.457Z

But I don't have a sql server db. So I just tried the first example to see if it would produce an error, but it seems to hang

isak 2020-10-16T21:46:24.457200Z

Ah interesting. Do you think that form is better? I was going to try and eventually merge it all to one .exe (it isn't yet), because I think they plan to release stuff that lets you bake in the dotnet dependency, so even people without it can run the code

isak 2020-10-16T21:46:54.457400Z

Oh strange, I'll try to fix to repro + fix that

borkdude 2020-10-16T21:47:23.457600Z

which form?

isak 2020-10-16T21:47:34.457800Z

dotnet my.dll

borkdude 2020-10-16T21:47:47.458Z

no, on macOS it just baked a .dll, I can't run .exe here

isak 2020-10-16T21:47:57.458200Z

ohh gotcha

isak 2020-10-16T21:48:52.458400Z

I wonder if the IntegratedAuthentication would work on Mac, I'd guess not because I think it relies only on active directory

borkdude 2020-10-16T21:53:13.458600Z

not sure. but anyway, I put some logging in the catch of the try/catch of HandleVar_Execute_Internal and it doesn't seem to reach there, it's waiting for something

borkdude 2020-10-16T21:54:12.458800Z

Not sure if that's the same for you since I'm on macOS, which is a but unusual for this pod maybe

isak 2020-10-16T21:54:22.459Z

Strange, I get the exception. Does it help if you add await _writer.FlushAsync(); at the end of SendException?

borkdude 2020-10-16T21:54:50.459200Z

} catch (Exception ex) {
                Console.Error.WriteLine("in try");
            
                await SendException(id, ex.Message);
            }
It doesn't print "in try"

isak 2020-10-16T21:55:13.459400Z

ah

borkdude 2020-10-16T21:55:21.459600Z

but it does print earlier logs

isak 2020-10-16T21:55:45.459800Z

oh. I wonder if it is a different and bizzarely high connection timeout

borkdude 2020-10-16T21:57:40.460Z

could be, I can let it sit there for a few minutes

borkdude 2020-10-16T21:59:19.460500Z

Ah, after a while it seems to get stuck in a loop

isak 2020-10-16T21:59:37.460700Z

Oh, for what code?

borkdude 2020-10-16T21:59:59.460900Z

async Task SendException(string id, string exMessage, object exData = null) {
            Console.Error.WriteLine("dude");
        
It prints dude repeatedly

isak 2020-10-16T22:00:52.461100Z

Hm I guess it must be that outer exception handler catching a new exception when sending the exception message

borkdude 2020-10-16T22:01:21.461300Z

ah if I remove that line, then I get this:

7: (sql/execute! {:connection-string "Data Source=my.db.host;Application Name=my.script;Initial Catalog=my_db_name;Integrated Security=True"
   ^--- A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: TCP Provider, error: 35 - An internal exception was caught)
8:                :command-text "select top 1 * from sys.objects"
9:                :multi-rs true  ;; Return multiple result sets, or just the first?
10:                })
which seems to be correct

borkdude 2020-10-16T22:01:56.461500Z

but I do need to kill dotnet since it seems to stay running

isak 2020-10-16T22:02:00.461700Z

Ok yea that is what I get too

borkdude 2020-10-16T22:02:01.461900Z

and activates my CPU :)

isak 2020-10-16T22:03:22.462100Z

strange, is that related to the pod load/unload thing?

isak 2020-10-16T22:04:20.462300Z

This is what you removed, right? https://github.com/xledger/pod_sql_server/blob/master/PodHandler.cs#L37-L39

borkdude 2020-10-16T22:05:44.462600Z

no, I only removed my own Console.Error.WriteLine("dude");

borkdude 2020-10-16T22:06:06.462800Z

yeah, could be related to the unload error

borkdude 2020-10-16T22:06:16.463Z

let me me try with a fresh bb

isak 2020-10-16T22:06:22.463200Z

ok

borkdude 2020-10-16T22:07:56.463400Z

yep, that's probably it :)

1
borkdude 2020-10-16T22:08:01.463600Z

sorry for the hassle

isak 2020-10-16T22:08:34.463900Z

np, thanks for testing it

borkdude 2020-10-16T22:09:01.464100Z

I wonder if it would work with a real SQL Server DB... is there like a free Azure thing I could connect to? I'd be really cool to have non-Windows users use this too

isak 2020-10-16T22:11:35.464300Z

There might be a trial or something, and that would probably work with this

isak 2020-10-16T22:11:56.464500Z

Otherwise it looks like you can install SQL Server on mac if you have docker: https://database.guide/how-to-install-sql-server-on-a-mac/

borkdude 2020-10-16T22:12:22.464800Z

hmm yeah, docker!

borkdude 2020-10-16T22:12:28.465Z

going to test this tomorrow, thanks man

1