Review comment: ensure <transact! after <close is rejected.
This commit is contained in:
parent
b20c70fc2a
commit
f02d508370
2 changed files with 39 additions and 9 deletions
|
@ -35,7 +35,9 @@
|
||||||
(defprotocol IConnection
|
(defprotocol IConnection
|
||||||
(close
|
(close
|
||||||
[conn]
|
[conn]
|
||||||
"Close this connection. Returns a pair channel of [nil error].")
|
"Close this connection. Returns a pair channel of [nil error].
|
||||||
|
|
||||||
|
Closing a closed connection is a no-op.")
|
||||||
|
|
||||||
(db
|
(db
|
||||||
[conn]
|
[conn]
|
||||||
|
@ -45,11 +47,15 @@
|
||||||
[conn]
|
[conn]
|
||||||
"Get the full transaction history DB associated with this connection."))
|
"Get the full transaction history DB associated with this connection."))
|
||||||
|
|
||||||
(defrecord Connection [current-db transact-chan]
|
(defrecord Connection [closed? current-db transact-chan]
|
||||||
IConnection
|
IConnection
|
||||||
(close [conn]
|
(close [conn]
|
||||||
|
(if (compare-and-set! (:closed? conn) false true)
|
||||||
|
(do
|
||||||
|
;; This immediately stops <transact! enqueueing new work.
|
||||||
(a/close! (:transact-chan conn))
|
(a/close! (:transact-chan conn))
|
||||||
(db/close-db @(:current-db conn)))
|
(db/close-db @(:current-db conn)))
|
||||||
|
(go [nil nil])))
|
||||||
|
|
||||||
(db [conn] @(:current-db conn))
|
(db [conn] @(:current-db conn))
|
||||||
|
|
||||||
|
@ -112,7 +118,8 @@
|
||||||
(a/mult listener-source) ;; Just for tapping.
|
(a/mult listener-source) ;; Just for tapping.
|
||||||
|
|
||||||
connection
|
connection
|
||||||
(map->Connection {:current-db (atom db)
|
(map->Connection {:closed? (atom false)
|
||||||
|
:current-db (atom db)
|
||||||
:listener-source listener-source
|
:listener-source listener-source
|
||||||
:listener-mult listener-mult
|
:listener-mult listener-mult
|
||||||
:transact-chan (a/chan (util/unlimited-buffer))
|
:transact-chan (a/chan (util/unlimited-buffer))
|
||||||
|
@ -576,10 +583,12 @@
|
||||||
{:pre [(conn? conn)]}
|
{:pre [(conn? conn)]}
|
||||||
;; Any race to put! is a real race between callers of <transact!. We can't just park on put!,
|
;; Any race to put! is a real race between callers of <transact!. We can't just park on put!,
|
||||||
;; because the parked putter that is woken is non-deterministic.
|
;; because the parked putter that is woken is non-deterministic.
|
||||||
(a/put! (:transact-chan conn) [tx-data result close?])
|
(let [closed? (not (a/put! (:transact-chan conn) [tx-data result close?]))]
|
||||||
(go-pair
|
(go-pair
|
||||||
;; We want to return a pair-chan, no matter what kind of channel result is.
|
;; We want to return a pair-chan, no matter what kind of channel result is.
|
||||||
(<? result))))
|
(if closed?
|
||||||
|
(raise "Connection is closed" {:error :transact/connection-closed})
|
||||||
|
(<? result))))))
|
||||||
|
|
||||||
(defn- start-transactor [conn]
|
(defn- start-transactor [conn]
|
||||||
(let [token-chan (a/chan 1)]
|
(let [token-chan (a/chan 1)]
|
||||||
|
|
|
@ -221,4 +221,25 @@
|
||||||
(is (= (<? (<datoms-after (d/db conn) tx0))
|
(is (= (<? (<datoms-after (d/db conn) tx0))
|
||||||
#{[101 :name "Petr"]})))))
|
#{[101 :name "Petr"]})))))
|
||||||
|
|
||||||
|
;; We don't use deftest-db in order to be able to close the connection ourselves.
|
||||||
|
(deftest-async test-transact-after-close
|
||||||
|
(with-tempfile [t (tempfile)]
|
||||||
|
(let [conn (<? (d/<connect t))
|
||||||
|
{tx0 :tx} (<? (d/<transact! conn test-schema))]
|
||||||
|
(try
|
||||||
|
(testing "transaction before close is applied"
|
||||||
|
(<? (d/<transact! conn [{:db/id 101 :name "Petr"}]))
|
||||||
|
(is (= (<? (<datoms-after (d/db conn) tx0))
|
||||||
|
#{[101 :name "Petr"]})))
|
||||||
|
(finally
|
||||||
|
(<? (d/<close conn))))
|
||||||
|
|
||||||
|
(testing "transact after close throws"
|
||||||
|
(is (thrown-with-msg?
|
||||||
|
ExceptionInfo #"Connection is closed"
|
||||||
|
(<? (d/<transact! conn [{:db/id (d/id-literal :db.part/user -1) :name "Petr"}])))))
|
||||||
|
|
||||||
|
;; Closing a closed connection is a no-op.
|
||||||
|
(<? (d/<close conn)))))
|
||||||
|
|
||||||
#_ (time (t/run-tests))
|
#_ (time (t/run-tests))
|
||||||
|
|
Loading…
Reference in a new issue