Skip to content

Commit

Permalink
add with-conn and get-conn
Browse files Browse the repository at this point in the history
  • Loading branch information
huahaiy committed Sep 25, 2020
1 parent 2b2e22e commit 4563d38
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 2 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ All notable changes to this project will be documented in this file. This change
### Changed
- Remove unnecessary locks in read transaction
- Improved error message and documentation for managing LMDB connection
### Added
- `core/get-conn` and `core/with-conn`

## 0.3.8
### Fixed
Expand Down
59 changes: 57 additions & 2 deletions src/datalevin/core.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -370,13 +370,14 @@
:cljs (satisfies? cljs.core/IDeref conn))
(db/db? @conn)))

(defprotocol ConnClosable
(close [this]))

(defn conn-from-db
"Creates a mutable reference to a given database. See [[create-conn]]."
[db]
(atom db :meta { :listeners (atom {}) }))


(defn conn-from-datoms
"Creates an empty DB and a mutable reference to it. See [[create-conn]]."
([datoms] (conn-from-db (init-db datoms)))
Expand All @@ -389,7 +390,7 @@
Please note that the connection should be managed like a stateful resource. Application should hold on to the same connection rather than opening multiple connections to the same database in the same process.
Connections are lightweight in-memory structures (~atoms). See also [[transact!]], [[db]], [[close]], and [[lmdb/open-lmdb]].
Connections are lightweight in-memory structures (~atoms). See also [[transact!]], [[db]], [[close]], [[get-conn]], and [[lmdb/open-lmdb]].
To access underlying DB, deref: `@conn`.
Expand Down Expand Up @@ -637,6 +638,60 @@
:rschema (db/rschema s))))
(schema conn)))

(defonce ^:private connections (atom {}))

(defn- add-conn [dir conn] (swap! connections assoc dir conn))

(defn- new-conn
[dir]
(let [conn (create-conn dir)]
(add-conn dir conn)
conn))

(defn get-conn
"Obtain an open connection to a database. Create the database if it does not
exist. Reuse the same connection if a connection to the same database already
exists. Open the database if it is closed. Return the connection.
See also [[create-conn]] and [[with-conn]]"
([dir]
(get-conn dir nil))
([dir schema]
(let [conn (if-let [c (get @connections dir)]
(if (closed? c) (new-conn dir) c)
(new-conn dir))]
(when schema (update-schema conn schema))
conn)))

(defmacro with-conn
"Evaluate body in the context of an connection to the database.
If the database does not exist, this will create it. If it is closed,
this will open it. However, the connection will be closed in the end of
this call. If a database needs to be kept open, use `create-conn` and
hold onto the returned connection. See also [[create-conn]] and [[get-conn]]
`spec` is a vector of an identifier of the database connection, a data path
string, and optionally a schema map.
Example:
(with-conn [conn \"my-data-path\"]
...conn...)
(with-conn [conn \"my-data-path\" {:likes {:db/cardinality :db.cardinality/many}}]
...conn...)
"
[spec & body]
`(let [dir# ~(second spec)
schema# ~(second (rest spec))
conn# (get-conn dir#)]
(when schema# (update-schema conn# schema#))
(try
(let [~(first spec) conn#] ~@body)
(finally
(close conn#)))))

(defn transact
"Same as [[transact!]], but returns an immediately realized future.
Expand Down
7 changes: 7 additions & 0 deletions test/datalevin/test/conn.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -72,3 +72,10 @@
:name "Another name"
:dt/updated-at (Date.)}])
(is (= 4 (count (d/datoms @conn2 :eavt)))))))

(deftest test-with-conn
(d/with-conn [conn (u/tmp-dir (str "with-conn-test-" (UUID/randomUUID)))]
(d/transact! conn [{:db/id -1
:name "something"
:updated-at (Date.)}])
(is (= 2 (count (d/datoms @conn :eav))))))

0 comments on commit 4563d38

Please sign in to comment.