Closes #660 Store management #260
Labels
No labels
A-build
A-cli
A-core
A-design
A-edn
A-ffi
A-query
A-sdk
A-sdk-android
A-sdk-ios
A-sync
A-transact
A-views
A-vocab
P-Android
P-desktop
P-iOS
bug
correctness
dependencies
dev-ergonomics
discussion
documentation
duplicate
enhancement
enquiry
good first bug
good first issue
help wanted
hygiene
in progress
invalid
question
ready
size
speed
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: greg/mentat#260
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Add Store manager to ensure that we only have one open handle to each database.
This implementation has gone through several iterations. The considerations that formed the current design are as follows:
rusqlite::Connection
isSend
but notSync
and therefore cannot be stored in a static var. This is why we only store theConn
insideStores
.Conn
is stored as aWeak
reference because otherwise every time we return aStore
we increase the reference count from one to two, forcing every mutable operation performed on theConn
to clone rather than return a mutable reference, dramatically increasing the number of Conn references proliferating the system. By storingConn
as aWeak
, for as long as there is only one Store we can perform mutable operations without increasing the reference count onConn
.Conn
as aWeak
reference, if we cease to hold any strong references to theConn
, by not having any activeStore
's, theWeak
will no longer be upgradable, but the entry will remain in the map of openConns
. We therefore must recreate theConn
if a request for a previously opened store is received. We do this in the background without consumers being aware.thread_local
store of openRc<rusqlite::Connection>
's mapped by the same key asConn
's. However, due torusqlite::Connection
not beingClone
, this meant thatRc::make_mut
could not be used, which resulted in the code being unable to get a mutable reference to therusqlite::Connection
if there was more than one reference. As the map retained a strong reference, that ensured that every returned Store had a reference count of at least 2 on it'srusqlite::Connection
which resulted in all mutable operations on theStore
failing. I therefore made the decision to create a newrusqlite::Connection
for every Store returned. This contravenes the original spec, but given the constraints something had to give and I decided on this one.Store
lead to a problem where the sameConn
was shared between tests and the assertions around reference counts on storedConn
's were unreliable. In order to get around this I introduced the concept of thenamed_in_memory_store
which assigns a name to an in memory store ensuring that the sameConn
was not shared between tests. This is the requirement that lead to the decision to store keys asString
's rather thanPathBuf
.The thing I don't like about this is the number of
rusqlite::Connection
s that we create. After chatting with @rnewman I will look into providing athread_local
connection pool and getStores
to take a reference to a connection that it will use to createStores
s.