avoid using a second db connection for writes
This is a potentially breaking change in a very delicate area. However,
examining the code path for writes, I don't see any benefit to opening a
second db connection for them. If the write throws an exception,
commitDb will retry it with a new db connection.
A potential benefit to not opening a second db connection, beyond using
less resources, is it just might avoid problems in WSL with sqlite that
I have hypothesized are caused by multiple db connections.
Commit 5f9eff3f32
explains why it needs to
shut down the db connection to force the database to be updated on disk:
When closeDb does not get called, garbage collection of DbHandle may not
give the workterThread time to cleanly shut down before git-annex exits,
resulting in a recently written change not reaching disk.
This commit is contained in:
parent
f5b642318d
commit
d0ef8303cf
1 changed files with 6 additions and 12 deletions
|
@ -100,13 +100,13 @@ commitDb h wa = robustly Nothing 100 (commitDb' h wa)
|
||||||
commitDb' :: DbHandle -> SqlPersistM () -> IO (Either SomeException ())
|
commitDb' :: DbHandle -> SqlPersistM () -> IO (Either SomeException ())
|
||||||
commitDb' (DbHandle _ jobs) a = do
|
commitDb' (DbHandle _ jobs) a = do
|
||||||
res <- newEmptyMVar
|
res <- newEmptyMVar
|
||||||
putMVar jobs $ ChangeJob $ \runner ->
|
putMVar jobs $ ChangeJob $
|
||||||
liftIO $ putMVar res =<< tryNonAsync (runner a)
|
liftIO . putMVar res =<< tryNonAsync a
|
||||||
takeMVar res
|
takeMVar res
|
||||||
|
|
||||||
data Job
|
data Job
|
||||||
= QueryJob (SqlPersistM ())
|
= QueryJob (SqlPersistM ())
|
||||||
| ChangeJob ((SqlPersistM () -> IO ()) -> IO ())
|
| ChangeJob (SqlPersistM ())
|
||||||
| CloseJob
|
| CloseJob
|
||||||
|
|
||||||
workerThread :: T.Text -> TableName -> MVar Job -> IO ()
|
workerThread :: T.Text -> TableName -> MVar Job -> IO ()
|
||||||
|
@ -128,16 +128,10 @@ workerThread db tablename jobs = newconn
|
||||||
Left BlockedIndefinitelyOnMVar -> return (return ())
|
Left BlockedIndefinitelyOnMVar -> return (return ())
|
||||||
Right CloseJob -> return (return ())
|
Right CloseJob -> return (return ())
|
||||||
Right (QueryJob a) -> a >> loop
|
Right (QueryJob a) -> a >> loop
|
||||||
-- Change is run in a separate database connection
|
|
||||||
-- since sqlite only supports a single writer at a
|
|
||||||
-- time, and it may crash the database connection
|
|
||||||
-- that the write is made to.
|
|
||||||
Right (ChangeJob a) -> do
|
Right (ChangeJob a) -> do
|
||||||
liftIO (a (runSqliteRobustly tablename db))
|
a
|
||||||
-- Exit this sqlite connection so the
|
-- Exit the sqlite connection so the
|
||||||
-- change that was just written, using
|
-- database gets updated on disk.
|
||||||
-- a different db handle, is immediately
|
|
||||||
-- visible to queries.
|
|
||||||
return newconn
|
return newconn
|
||||||
|
|
||||||
getjob :: IO (Either BlockedIndefinitelyOnMVar Job)
|
getjob :: IO (Either BlockedIndefinitelyOnMVar Job)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue