agent: support closing and re-opening store (#855)

* agent: support closing and re-opening store

* add closed flag, tests
This commit is contained in:
Evgeny Poberezkin
2023-09-27 12:50:24 +01:00
committed by GitHub
parent 8d47f69083
commit fda1284ae4
4 changed files with 80 additions and 12 deletions
+28 -7
View File
@@ -31,6 +31,7 @@ module Simplex.Messaging.Agent.Store.SQLite
createSQLiteStore,
connectSQLiteStore,
closeSQLiteStore,
openSQLiteStore,
sqlString,
execSQL,
upMigration, -- used in tests
@@ -269,13 +270,13 @@ import Simplex.Messaging.Parsers (blobFieldParser, dropPrefix, fromTextField_, s
import Simplex.Messaging.Protocol
import qualified Simplex.Messaging.Protocol as SMP
import Simplex.Messaging.Transport.Client (TransportHost)
import Simplex.Messaging.Util (bshow, eitherToMaybe, groupOn, ($>>=), (<$$>))
import Simplex.Messaging.Util (bshow, eitherToMaybe, groupOn, ifM, ($>>=), (<$$>))
import Simplex.Messaging.Version
import System.Directory (copyFile, createDirectoryIfMissing, doesFileExist)
import System.Exit (exitFailure)
import System.FilePath (takeDirectory)
import System.IO (hFlush, stdout)
import UnliftIO.Exception (onException)
import UnliftIO.Exception (onException, bracketOnError)
import qualified UnliftIO.Exception as E
import UnliftIO.STM
@@ -379,10 +380,12 @@ confirmOrExit s = do
connectSQLiteStore :: FilePath -> String -> IO SQLiteStore
connectSQLiteStore dbFilePath dbKey = do
dbNew <- not <$> doesFileExist dbFilePath
dbConn <- dbBusyLoop $ connectDB dbFilePath dbKey
dbConnVar <- newTMVarIO dbConn
dbEncrypted <- newTVarIO . not $ null dbKey
pure SQLiteStore {dbFilePath, dbEncrypted, dbConnection = dbConnVar, dbNew}
dbConn <- dbBusyLoop (connectDB dbFilePath dbKey)
atomically $ do
dbConnection <- newTMVar dbConn
dbEncrypted <- newTVar . not $ null dbKey
dbClosed <- newTVar False
pure SQLiteStore {dbFilePath, dbEncrypted, dbConnection, dbNew, dbClosed}
connectDB :: FilePath -> String -> IO DB.Connection
connectDB path key = do
@@ -404,7 +407,25 @@ connectDB path key = do
|]
closeSQLiteStore :: SQLiteStore -> IO ()
closeSQLiteStore st = atomically (takeTMVar $ dbConnection st) >>= DB.close
closeSQLiteStore st@SQLiteStore {dbClosed} =
ifM (readTVarIO dbClosed) (putStrLn "closeSQLiteStore: already closed") $
withConnection st $ \conn -> do
DB.close conn
atomically $ writeTVar dbClosed True
openSQLiteStore :: SQLiteStore -> String -> IO ()
openSQLiteStore SQLiteStore {dbConnection, dbFilePath, dbClosed} key =
ifM (readTVarIO dbClosed) open (putStrLn "closeSQLiteStore: already opened")
where
open =
bracketOnError
(atomically $ takeTMVar dbConnection)
(atomically . tryPutTMVar dbConnection)
$ \DB.Connection {slow} -> do
DB.Connection {conn} <- connectDB dbFilePath key
atomically $ do
putTMVar dbConnection DB.Connection {conn, slow}
writeTVar dbClosed False
sqlString :: String -> Text
sqlString s = quote <> T.replace quote "''" (T.pack s) <> quote
@@ -27,6 +27,7 @@ data SQLiteStore = SQLiteStore
{ dbFilePath :: FilePath,
dbEncrypted :: TVar Bool,
dbConnection :: TMVar DB.Connection,
dbClosed :: TVar Bool,
dbNew :: Bool
}
-3
View File
@@ -3,13 +3,11 @@
module Simplex.Messaging.Util where
import Control.Concurrent (threadDelay)
import qualified Control.Exception as E
import Control.Monad
import Control.Monad.Except
import Control.Monad.IO.Unlift
import Data.Bifunctor (first)
import qualified Data.ByteString as BW
import Data.ByteString.Char8 (ByteString)
import qualified Data.ByteString.Char8 as B
import Data.Int (Int64)
@@ -21,7 +19,6 @@ import qualified Data.Text as T
import Data.Text.Encoding (decodeUtf8With)
import Data.Time (NominalDiffTime)
import GHC.Conc
import Numeric (showHex)
import UnliftIO.Async
import qualified UnliftIO.Exception as UE