babashka-sci-dev

borkdude 2025-10-02T17:15:48.856559Z

@davclark @rahul080327 some Golang help here is welcome too: https://github.com/babashka/pod-babashka-go-sqlite3/issues/38

davclark 2025-10-06T13:55:07.922079Z

Pushed a minimal test that ensures an attempt to query following a close-connection results in an exception. As I say in a comment, it's a bit ugly and I'm not sure if this is the best final form, but I think it does the job.

borkdude 2025-10-06T14:24:43.702519Z

Does the pod still work after catching the exception on new queries?

davclark 2025-10-06T15:19:30.401809Z

It does keep working in the repl after getting an exception... should I also check in the test script?

borkdude 2025-10-06T15:21:25.267559Z

yeah maybe good to test. since you mentioned EOF I thought the pod had died :)

davclark 2025-10-06T15:25:38.239939Z

Hmm... the old test doesn't generate an EOF on my mac. The EOF was seen on my linux machine. Lemme go test a change there real quick...

davclark 2025-10-06T15:39:03.407669Z

Weird. I looked at my terminal history on my linux machine and that EOF definitely happened, but only once. I can't recreate with the current or previous version of the test. I never experienced an actual problem with functionality - so it might have just been some race condition on process vs. sub-process shutdown? I don't know enough about the pod architecture to properly theorize

borkdude 2025-10-06T15:39:55.629479Z

no problem, just add a test to verify that stuff still works after closed connection use and be done with it :)

davclark 2025-10-06T15:40:10.216049Z

It's there already!

borkdude 2025-10-06T15:42:01.376659Z

merged, thanks!

πŸŽ‰ 1
davclark 2025-10-06T15:42:36.477489Z

Thanks for the warm welcome as a contributor! I feel ready to pick up some work on the duckdb pod now

πŸ™ 1
πŸ™πŸΎ 1
borkdude 2025-10-02T17:16:48.088399Z

And this could also be applied to the duckdb pod I think, so code written can be relatively well carried over there too

πŸ‘€ 1
borkdude 2025-10-02T17:17:01.492669Z

cc @richiardiandrea

borkdude 2025-10-02T17:40:47.889779Z

I feel since this benefits two very similar projects and it has direct benefit to a user, maybe we can do this one first? I can guide you in the implementation as well @davclark (at least I know what should happen, and maybe you know how to do that in golang)

lispyclouds 2025-10-02T17:53:17.788759Z

Please go ahead, I’ll help review the go side too.

lispyclouds 2025-10-02T17:53:30.066319Z

Bit bogged down at work

borkdude 2025-10-02T17:54:14.628269Z

thanks

lispyclouds 2025-10-02T17:55:30.020749Z

@davclark I think the simplest would be to have a global sync.Map where the connections can be stored with id

lispyclouds 2025-10-02T17:56:20.415909Z

Might necessitate a go version bump but should be okay

borkdude 2025-10-02T17:57:46.163369Z

@rahul080327 I tried to build go-sqlite locally but couldn't anymore after I messed with transit locally. Maybe you can upgrade it to our local transit-go lib? :)

borkdude 2025-10-02T17:58:16.602809Z

is sync.Map thread-safe?

lispyclouds 2025-10-02T17:58:35.748539Z

Yes hence sync map not usual map

borkdude 2025-10-02T17:59:05.184879Z

nice

lispyclouds 2025-10-02T17:59:24.557079Z

It should be using the forked transit. If you blow away the go module cache and try again, should pull the right thing

lispyclouds 2025-10-02T18:00:02.712969Z

Ah no it’s in the duck one. Can refer its go.mod?

lispyclouds 2025-10-02T18:00:11.661789Z

I’m on phone, bit hard now

borkdude 2025-10-02T18:00:15.461069Z

no problem

borkdude 2025-10-02T18:00:28.944419Z

maybe @davclark can do this as his first task to get a success experience with little effort ;)

πŸ‘πŸΎ 1
davclark 2025-10-02T18:01:30.987269Z

I'm on my work computer, and haven't actually determined the policy for open source contributions on work-owned devices... so I need a bit to get that set up, or otherwise can maybe pick this up my nighttime (like 9pm-ish EST)

lispyclouds 2025-10-02T18:02:13.620889Z

I can take a shot in an hour or so

lispyclouds 2025-10-02T18:02:38.250699Z

Happy to wait for dav if not urgent

lispyclouds 2025-10-02T18:03:04.554809Z

Getting more gophers in bb world is nice

borkdude 2025-10-02T18:04:20.392269Z

is this a valid go.mod? I removed some indirect deps, not sure why they are needed.

module 

go 1.15

require (
	 v0.0.0-20250914122507-fb54c87ade49
	 v1.0.0
	 v1.14.22
	 v1.2.1 // indirect
)

lispyclouds 2025-10-02T18:05:33.555209Z

Yes it’s referring to a commit. Need a go mod tidy after that too

borkdude 2025-10-02T18:07:22.942639Z

sorry, I pushed it ;)

πŸ‘πŸ» 1
lispyclouds 2025-10-02T18:32:40.523849Z

okay taking a look now

lispyclouds 2025-10-02T18:35:12.285269Z

so we are looking at 2 things? β€’ get-connection: returns a map {:connection "conn-id"} β€’ close-connection: takes this map and cleans up? since these are new ones, shouldnt break anything?

lispyclouds 2025-10-02T18:36:24.885699Z

but the queries would now need this extra conn param, do we have a different arity for that?

lispyclouds 2025-10-02T19:06:37.429839Z

or (sqlite/execute! (string to db | connection-map) ...)

borkdude 2025-10-02T19:21:09.786599Z

To get you going @davclark I've made a branch here with the idea: https://github.com/babashka/pod-babashka-go-sqlite3/tree/get-connection

πŸ‘πŸΎ 1
borkdude 2025-10-02T19:21:36.917379Z

get-connection works, but it contains a bug. The connection is supposed to be stored under a uuid in the syncMap but somehow never gets it

borkdude 2025-10-02T19:21:50.212999Z

I'll leave that up to you to fix it and also implement close-connection

borkdude 2025-10-02T19:22:19.986739Z

The way I test this is by running go build -tags "json1 fts5" -o pod-babashka-go-sqlite3 main.go && bb test/script.clj

βž• 1
davclark 2025-10-02T19:23:01.342619Z

Awesome - thank you for the easy-mode start!

borkdude 2025-10-02T19:23:37.938819Z

I also wanted to make connection a keyword -> uuid, but it's now a string -> uuid, but that's a minor thing

lispyclouds 2025-10-02T19:39:14.077819Z

https://github.com/babashka/pod-babashka-go-sqlite3/blob/get-connection/main.go#L276 should be syncMap.Store(id.String(), conn)

borkdude 2025-10-02T20:23:28.108169Z

thanks. still doesn't work though

borkdude 2025-10-02T20:23:36.512679Z

I mean, that was a good improvement nonetheless

lispyclouds 2025-10-02T20:23:47.652109Z

yeah im pushing in the big changes now

borkdude 2025-10-02T20:24:15.353939Z

ok I pushed something too, small change though

borkdude 2025-10-02T20:24:17.740419Z

thank you

borkdude 2025-10-02T20:24:38.016269Z

I just made id into a string, no uuid object to mess around with

borkdude 2025-10-02T20:24:47.715209Z

id := uuid.New().String()
			

lispyclouds 2025-10-02T20:24:57.906469Z

i have exactly that

borkdude 2025-10-02T20:26:02.045919Z

when parsing the query / exec args I think it might be better to return a connection string (id) instead of part of the db value, so we can distuingish

borkdude 2025-10-02T20:26:16.387279Z

I now mashed them together which is a bit messy

lispyclouds 2025-10-02T20:26:27.029979Z

pushed mine

lispyclouds 2025-10-02T20:26:32.725519Z

all tests pass

lispyclouds 2025-10-02T20:26:40.821099Z

but leaks the ephemeral connections

borkdude 2025-10-02T20:27:05.380379Z

nice :)

borkdude 2025-10-02T20:27:22.212079Z

what do you mean, leak ephemeral?

lispyclouds 2025-10-02T20:27:55.462499Z

the non cached ones. the parsequery returns a conn, either a new one or from cache depending on what it sees

lispyclouds 2025-10-02T20:28:13.084419Z

there is no good way to close the new one

borkdude 2025-10-02T20:28:24.566549Z

you read the cache in the parseQuery, that seems a bit intertwined, but I must admit I had this idea too ;)

borkdude 2025-10-02T20:28:53.103189Z

there is no good way to just close the new one? why not?

lispyclouds 2025-10-02T20:28:54.345229Z

yeah bit complected

borkdude 2025-10-02T20:29:14.426079Z

my idea after contempating this was to return an extra string in the tupel

borkdude 2025-10-02T20:29:21.218699Z

that signals that we should only read from cache

borkdude 2025-10-02T20:29:33.878799Z

and only when we read this connection, we don't defer close the connection

lispyclouds 2025-10-02T20:30:14.222809Z

why not?so the new one is made in a different function and if er defer close there it would close too soon and the place where its called it cant differntiate cached or not

borkdude 2025-10-02T20:30:34.174169Z

this is exactly why it shouldn't happen in parseQueryArg

borkdude 2025-10-02T20:31:36.210889Z

here I defer-ed the close only when it is a new connection, not from cache https://github.com/babashka/pod-babashka-go-sqlite3/blob/b6eda30744da48d7e1d91c002bcfb785d22a5241/main.go#L220

borkdude 2025-10-02T20:31:58.612079Z

I think we want to restore that behavior

lispyclouds 2025-10-02T20:32:35.730799Z

yes im thinking more, something with types

borkdude 2025-10-02T20:33:18.421259Z

instead of this:

(*sql.DB, string, []interface{}, error)
queryArgs should return: (dbspec, connid, string, []interface{}, error)

borkdude 2025-10-02T20:33:23.315369Z

and then it's solved

lispyclouds 2025-10-02T20:33:27.039799Z

yep

borkdude 2025-10-02T20:33:33.972079Z

at least, we if we can read from this stupid map, which didn't work in my case

lispyclouds 2025-10-02T20:33:46.392119Z

we're more or less thinking the same

borkdude 2025-10-02T20:34:17.943279Z

spend 1 hour with go, love clojure even more

lispyclouds 2025-10-02T20:34:56.442109Z

well, spend x hrs with y, y not being clojure, same effect

lispyclouds 2025-10-02T20:38:22.376979Z

i have another idea (probably weird) go 1.24 has runtime.AddCleanup which lets you add a fn which is called when the thing is about to be GC'ed. can attach that to the non cached ones https://medium.com/@ajitem/improved-finalization-in-go-1-24-introducing-runtime-addcleanup-e2f7a43831c2

lispyclouds 2025-10-02T20:48:47.418219Z

returning the connid idea

lispyclouds 2025-10-02T20:50:08.500549Z

maybe @davclark can take over the close-connection

borkdude 2025-10-02T20:56:18.411879Z

now that we have the connId separate, I think it's still better to get the cached connection or make a new one + defer

borkdude 2025-10-02T20:56:56.017579Z

oh I see, you didn't go with the weird option

borkdude 2025-10-02T20:57:21.474729Z

returning a connection from a parse function doesn't feel right though

lispyclouds 2025-10-02T20:59:23.641269Z

yeah the gc one is non deterministic and no idea what impact it may have

lispyclouds 2025-10-02T21:07:07.111389Z

so how about this β€’ parseQuery returns a DBConn interface, which is implemented by CachedConn or Conn β€’ has a Connect method, which we would call returning the appropriate connection β€’ has a Close method which is a no op for the cached ones, defer call can be made for both β€’ for close-connection, we directly close it from the sync.Map

lispyclouds 2025-10-02T21:07:48.548829Z

complex, but trying to think how to decomplect the parse

lispyclouds 2025-10-02T21:11:21.411029Z

that way parse doesnt have side effects

borkdude 2025-10-02T21:14:04.230319Z

pushed the change

borkdude 2025-10-02T21:14:08.238469Z

decomplected

borkdude 2025-10-02T21:14:59.590819Z

@rahul080327

lispyclouds 2025-10-02T21:19:06.719279Z

yeah was trying to avoid that repeated code

borkdude 2025-10-02T21:19:51.340589Z

the code repetition can be avoided by collapsing query and exec into one thing that has a flag whether it's query or exec

borkdude 2025-10-02T21:20:05.583279Z

but it's no big deal to me. it's golang, it's meant to be straightforward stupid code

lispyclouds 2025-10-02T21:20:36.276739Z

heh

borkdude 2025-10-02T21:21:19.504549Z

or maybe I can factor this out in a function, which returns a sql.DB + a bool that says if it should be deferred

borkdude 2025-10-02T21:21:45.826189Z

going to try that and then sign off

lispyclouds 2025-10-02T21:22:06.918419Z

yep something like that is good enough

lispyclouds 2025-10-02T21:22:38.241259Z

that bool idea came to me too, but gopher in my head says do polymorphic interfaces

lispyclouds 2025-10-02T21:32:45.589379Z

pretty good i would say

borkdude 2025-10-02T21:33:11.047199Z

perhaps it's better to make connId nil though

borkdude 2025-10-02T21:33:17.571059Z

but minor thing

borkdude 2025-10-02T21:33:26.115149Z

instead of the empty string I mean

borkdude 2025-10-02T21:33:29.728129Z

seems a bit sloppy

lispyclouds 2025-10-02T21:34:09.979269Z

yeah then making it into a pointer not too worth it i think

borkdude 2025-10-02T21:34:24.062629Z

can't strings be nil?

lispyclouds 2025-10-02T21:34:38.729999Z

nope

borkdude 2025-10-02T21:34:43.445359Z

ok then we'll leave it

lispyclouds 2025-10-02T21:34:49.077679Z

*string is needed

borkdude 2025-10-02T21:34:58.357549Z

ok, then this is fine

borkdude 2025-10-02T21:35:04.707599Z

good, that leaves us with close-connection...

lispyclouds 2025-10-02T21:35:40.200119Z

maybe dav has fun with it, will take a look tomorrow too

borkdude 2025-10-02T21:36:16.082299Z

yep, feel free to make close-connection dav, shouldn't be that much work. I think we'll just merge this to main for now, right?

lispyclouds 2025-10-02T21:36:36.284879Z

its in a good state

borkdude 2025-10-02T21:39:20.004419Z

I should actually be working on my presentation (I give the first version next week at a meetup) and I take any chance to distract me from that, even golang ;)

πŸ˜† 1
lispyclouds 2025-10-02T21:42:26.368899Z

deadline driven dev is real

borkdude 2025-10-02T21:44:27.012739Z

oh dang, I squashed the commit and forgot to make you co-author, sorry

lispyclouds 2025-10-02T21:45:10.559169Z

eh no worries, have bashed on it quite a bit already πŸ˜›

πŸ˜… 1
borkdude 2025-10-02T21:53:39.938919Z

behold this beautiful code that now works:

#!/usr/bin/env bb

(ns go-sqlite3
  (:require
   [babashka.fs :as fs]
   [babashka.pods :as pods]))

(pods/load-pod 'org.babashka/go-sqlite3 "0.3.12")
(require '[pod.babashka.go-sqlite3 :as sqlite])

(when-not (fs/exists? "/tmp/foo.db")
  (sqlite/execute! "/tmp/foo.db" ["create table foo (bar)"]))
(let [conn (sqlite/get-connection "/tmp/foo.db")]
  (sqlite/execute! conn ["insert into foo (bar) values (?)" "baz"])
  (prn (sqlite/query conn ["select * from foo"])))

πŸš€ 1
lispyclouds 2025-10-03T08:05:10.637429Z

borkdude 2025-10-03T09:16:36.656079Z

I'm going to use this meme for my talk, thanks

lispyclouds 2025-10-03T11:01:00.605789Z

This meme is under GPLv3

borkdude 2025-10-03T11:01:53.228819Z

ok I wont' then

lispyclouds 2025-10-03T11:02:10.854259Z

Heh, as long as you give your talk source code

borkdude 2025-10-03T11:04:00.422889Z

still working on that :-s

davclark 2025-10-03T19:26:08.526509Z

While the topic of this thread has meandered... I pushed a not-yet-working version of a close-connection function here: https://github.com/babashka/pod-babashka-go-sqlite3/compare/main...davclark:pod-babashka-go-sqlite3:close-connection?expand=1 It compiles, but then the test hangs. No action needed for now and hopefully I'll get some time to finish this tonight BUT I'm going camping for the weekend, so wanted to share ahead of time in case you wanted to have a look. I also still need to remove the id from the syncMap, and maybe the error handling / messaging could be a bit more thoughtful. But I figure it's better to get something mediocre working before trying to polish it up.

davclark 2025-10-03T19:27:43.928859Z

I also wonder what you'd think about DRY'ing up the argument parsing?

borkdude 2025-10-03T19:28:24.150839Z

That's awesome @davclark. Maybe you can make a separate PR for close-connecting and a separate one for DRY-ing up some stuff

davclark 2025-10-03T19:28:37.315989Z

Wisdom!

borkdude 2025-10-03T19:29:28.439419Z

I think the test hangs because you're not sending a reply to babashka on success

davclark 2025-10-03T19:29:49.208439Z

I knew you'd figure it out right quick πŸ˜›

borkdude 2025-10-03T19:31:18.514589Z

golang forces you to think about error conditions, but ignore success ;)

davclark 2025-10-03T19:32:54.919239Z

Pushed what appears to be a working version now

davclark 2025-10-03T19:33:03.465109Z

Includes deleting the entry in the map

davclark 2025-10-03T19:33:49.468909Z

I think it's at a point where it makes sense to pull the trigger on a PR. It's not ready, but that gives some space for async feedback

davclark 2025-10-03T19:33:55.679769Z

Sound good?

borkdude 2025-10-03T19:34:17.088979Z

sure!

borkdude 2025-10-03T19:37:55.409389Z

left some feedback

davclark 2025-10-03T19:39:53.901399Z

You're so fast! I was thinking the same about test cases. I'll see if I can get that done tonight, but might be Monday

borkdude 2025-10-03T19:41:00.524239Z

no hurry, thanks for the contrib!

borkdude 2025-10-04T14:26:27.254279Z

lispyclouds 2025-10-05T07:56:44.517509Z

This is perfect! I could also imagine something similar for the Java backing the JVM Clojure too?

borkdude 2025-10-05T08:03:42.768339Z

indeed