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:
Joey Hess 2021-10-20 12:32:46 -04:00
parent f5b642318d
commit d0ef8303cf
No known key found for this signature in database
GPG key ID: DB12DB0FF05F8F38

View file

@ -100,13 +100,13 @@ commitDb h wa = robustly Nothing 100 (commitDb' h wa)
commitDb' :: DbHandle -> SqlPersistM () -> IO (Either SomeException ())
commitDb' (DbHandle _ jobs) a = do
res <- newEmptyMVar
putMVar jobs $ ChangeJob $ \runner ->
liftIO $ putMVar res =<< tryNonAsync (runner a)
putMVar jobs $ ChangeJob $
liftIO . putMVar res =<< tryNonAsync a
takeMVar res
data Job
= QueryJob (SqlPersistM ())
| ChangeJob ((SqlPersistM () -> IO ()) -> IO ())
| ChangeJob (SqlPersistM ())
| CloseJob
workerThread :: T.Text -> TableName -> MVar Job -> IO ()
@ -128,16 +128,10 @@ workerThread db tablename jobs = newconn
Left BlockedIndefinitelyOnMVar -> return (return ())
Right CloseJob -> return (return ())
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
liftIO (a (runSqliteRobustly tablename db))
-- Exit this sqlite connection so the
-- change that was just written, using
-- a different db handle, is immediately
-- visible to queries.
a
-- Exit the sqlite connection so the
-- database gets updated on disk.
return newconn
getjob :: IO (Either BlockedIndefinitelyOnMVar Job)