babashka

Evan Nygard 2025-07-18T19:22:13.064179Z

Hello everyone! I’ve got an interesting bug when attempting to run transactions using the postgresql pod. I’m running a select and insert statement - when running them inside with-transaction, the inserted data apparently fails to get committed. Postgres logs say “unexpected EOF on client connection with an open transaction”. Running the two queries outside a transaction works normally, as one would expect. I also tried building the transaction manually instead of using with-transaction, which works somewhat more reliably, but is still flaky. (In this case, when data is not inserted, there’s no log explaining why). In the course of puzzling through the issue, I became suspicious that there might be some sort of race condition going on, or some kind of trouble with the transaction not being cleaned up before the script terminated. Notably, inserting either (Thread/sleep 1000) or (shutdown-agents) after the call to with-transaction caused the transaction to succeed reliably. Happy to send sample code to reproduce the error if anyone wants. I’m very curious as to whether I just wasn’t terminating the script properly, or whether there might be some kind of deeper issue. Thank you all so much in advance for your thoughts!

borkdude 2025-08-08T09:17:01.925679Z

@enygard113 I tried to reproduce it but couldn't. See comment in issue: https://github.com/babashka/babashka-sql-pods/issues/70

borkdude 2025-07-18T19:25:46.701549Z

Is this with bb or JVM?

Evan Nygard 2025-07-18T19:35:31.839379Z

bb

borkdude 2025-07-18T19:36:44.810009Z

repro welcome. also to welcome to debug the sql pod yourself of course.. it doesn't ring a bell immediately. the transaction stuff is implemented around here: https://github.com/babashka/babashka-sql-pods/blob/c7c1f3989787d2375e543253c0bde77689fdf4c9/src/pod/babashka/sql.clj#L106-L107

borkdude 2025-07-18T19:37:15.016319Z

you can run the JVM version of the pod to insert debug stuff and see what's happening, if you're up for it

Evan Nygard 2025-07-18T19:43:33.057209Z

gotcha thanks. Here's a minimal repro:

#!/usr/bin/env bb
(ns test
  (:require
   [babashka.deps :as deps]
   [babashka.pods :as pods]))

(pods/load-pod 'org.babashka/postgresql "0.1.1")
(deps/add-deps
  '{:deps {com.github.seancorfield/honeysql {:mvn/version "2.7.1310"}}})

(require '[clojure.pprint :as pp]
  '[honey.sql :as sql]
  '[pod.babashka.postgresql :as pg]
  '[pod.babashka.postgresql.transaction :as pg.transaction])

(def datasource
  {:dbtype "postgresql"
   :hostname "localhost"
   :dbname "bb_test"
   :user "user"
   :password "password"
   :port 5432})

(def select-query
  (sql/format {:select :*
               :from :test}))

(def insert-query
  (sql/format {:insert-into :test
               :columns [:first_name :last_name]
               :values [["John" "Doe"]]}))

;; This always works
(defn basic-query
  []
  (pp/pprint (pg/execute! datasource select-query))
  (pp/pprint (pg/execute! datasource insert-query)))

;; This one fails almost every time
;; Postgres logs say "unexpected EOF on client connection with an open transaction"
(defn query-with-transaction
  []
  (pg/with-transaction [conn datasource]
    (pp/pprint (pg/execute! conn select-query))
    (pp/pprint (pg/execute! conn insert-query))))

;; This one is flaky, often succeeds but occasionally fails. When it fails, there's no log
(defn query-with-manual-transaction
  []
  (let [conn (pg/get-connection datasource)]
    (try
      (pg.transaction/begin conn)
      (pp/pprint (pg/execute! conn select-query))
      (pp/pprint (pg/execute! conn insert-query))
      (pg.transaction/commit conn)
      (pg/close-connection conn)
      (catch Exception e
        (pg.transaction/rollback conn)
        (pg/close-connection conn)
        (throw e)))))

;; (basic-query)
(query-with-transaction)
;; (query-with-manual-transaction)

;; Calling either of these causes the transaction to succeed
;;(Thread/sleep 1000)
;;(shutdown-agents)

Evan Nygard 2025-07-18T19:44:48.762919Z

Using a docker container for postgres Also, something that was notable too was I'm using mac, a colleague who uses linux was able to execute more reliably

borkdude 2025-07-18T20:08:04.200289Z

do you have the docker commands for me as well to spin up a postgres? and can you make a github issue from this?

Evan Nygard 2025-07-18T20:10:03.651019Z

docker run --name bb-test-db -e POSTGRES_PASSWORD=password -e POSTGRES_USER=user -e POSTGRES_DB=bb_test -p 5432:5432 -v postgres-data:/Users/evannygard/scripts/bb-test/postgres-data -d postgres

borkdude 2025-07-18T20:10:21.223809Z

Perhaps the issue is that bb quits before the transaction finishes or so?

Evan Nygard 2025-07-18T20:10:55.390959Z

Yeah that's what I was wondering

Evan Nygard 2025-07-18T20:11:47.335569Z

Also notably, running the script in the JVM with clojure -M test.clj seems to succeed reliably, although I have to kill the process manually, it doesn't exit itself

borkdude 2025-07-18T20:12:26.289849Z

yeah this is because clojure waits for non-daemon threads to finish probably

borkdude 2025-07-18T20:13:10.059659Z

thanks for the repro. if you can collect this in a github issue that will be helpful. probably won't have time until next week to look into it

Evan Nygard 2025-07-18T20:13:40.496789Z

Sounds good, working on writing up the issue now. Thanks for your help!

borkdude 2025-07-18T20:19:38.895499Z

if you can produce a test which triggers the behavior in bb, that would also be very helpful.

borkdude 2025-07-18T20:19:55.963559Z

but perhaps that's more difficult in a scenario where bb must quit to see the behavior

borkdude 2025-07-18T20:21:27.257179Z

you can also inline that code in your own test to see if this behaves correctly

Evan Nygard 2025-07-18T20:42:34.174189Z

just put up the github issue. I'll see what I can do about writing the test