More robust handling of ErrorBusy when writing to sqlite databases

While ErrorBusy and other exceptions were caught and the write retried for
up to 10 seconds, it was still possible for git-annex to eventually
give up and error out without writing to the database. Now it will retry
as long as necessary.

This does mean that, if one git-annex process is suspended just as sqlite
has locked the database for writing, another git-annex that tries to write
it it might get stuck retrying forever. But, that could already happen when
opening the sqlite database, which retries forever on ErrorBusy. This is an
area where git-annex is known to not behave well, there's a todo about the
general case of it.

Sponsored-by: Dartmouth College's Datalad project
This commit is contained in:
Joey Hess 2022-10-17 15:56:19 -04:00
parent 0d762acf7e
commit 3149a1e2fe
No known key found for this signature in database
GPG key ID: DB12DB0FF05F8F38
4 changed files with 120 additions and 22 deletions

View file

@ -82,22 +82,20 @@ queryDb (DbHandle _ jobs) a = do
{- Writes a change to the database.
-
- Writes can fail if another write is happening concurrently.
- So write failures are caught and retried repeatedly for up to 10
- seconds, which should avoid all but the most exceptional problems.
- Writes can fail when another write is happening concurrently.
- So write failures are caught and retried repeatedly.
-}
commitDb :: DbHandle -> SqlPersistM () -> IO ()
commitDb h wa = robustly Nothing 100 (commitDb' h wa)
commitDb h wa = robustly (commitDb' h wa)
where
robustly :: Maybe SomeException -> Int -> IO (Either SomeException ()) -> IO ()
robustly e 0 _ = error $ "failed to commit changes to sqlite database: " ++ show e
robustly _ n a = do
robustly :: IO (Either SomeException ()) -> IO ()
robustly a = do
r <- a
case r of
Right _ -> return ()
Left e -> do
Left _ -> do
threadDelay 100000 -- 1/10th second
robustly (Just e) (n-1) a
robustly a
commitDb' :: DbHandle -> SqlPersistM () -> IO (Either SomeException ())
commitDb' (DbHandle _ jobs) a = do