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!
@enygard113 I tried to reproduce it but couldn't. See comment in issue: https://github.com/babashka/babashka-sql-pods/issues/70
Is this with bb or JVM?
bb
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
you can run the JVM version of the pod to insert debug stuff and see what's happening, if you're up for it
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)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
do you have the docker commands for me as well to spin up a postgres? and can you make a github issue from this?
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
Perhaps the issue is that bb quits before the transaction finishes or so?
Yeah that's what I was wondering
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
yeah this is because clojure waits for non-daemon threads to finish probably
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
Sounds good, working on writing up the issue now. Thanks for your help!
if you can produce a test which triggers the behavior in bb, that would also be very helpful.
but perhaps that's more difficult in a scenario where bb must quit to see the behavior
this is the code for with-transaction:
https://github.com/babashka/babashka-sql-pods/blob/c7c1f3989787d2375e543253c0bde77689fdf4c9/resources/with_transaction.clj
you can also inline that code in your own test to see if this behaves correctly
just put up the github issue. I'll see what I can do about writing the test