agent: add reopenStore function for postgres; run notification tests with postgres (#1435)

This commit is contained in:
spaced4ndy
2025-01-17 16:27:37 +04:00
committed by GitHub
parent 9404a3ab63
commit fdde9863cd
9 changed files with 58 additions and 32 deletions
+1 -1
View File
@@ -414,6 +414,7 @@ test-suite simplexmq-test
AgentTests.EqInstances
AgentTests.FunctionalAPITests
AgentTests.MigrationTests
AgentTests.NotificationTests
AgentTests.ServerChoice
CLITests
CoreTests.BatchingTests
@@ -446,7 +447,6 @@ test-suite simplexmq-test
Paths_simplexmq
if !flag(client_postgres)
other-modules:
AgentTests.NotificationTests
AgentTests.SchemaDump
AgentTests.SQLiteTests
hs-source-dirs:
+3
View File
@@ -73,6 +73,9 @@ createStore dbFilePath dbKey keepKey = Store.createDBStore dbFilePath dbKey keep
closeStore :: DBStore -> IO ()
closeStore = Store.closeDBStore
reopenStore :: DBStore -> IO ()
reopenStore = Store.reopenDBStore
execSQL :: DB.Connection -> Text -> IO [Text]
execSQL = Store.execSQL
+24 -6
View File
@@ -1,3 +1,4 @@
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes #-}
@@ -6,7 +7,8 @@
module Simplex.Messaging.Agent.Store.Postgres
( createDBStore,
closeDBStore,
execSQL
reopenDBStore,
execSQL,
)
where
@@ -15,7 +17,7 @@ import Control.Monad (unless, void)
import Data.Functor (($>))
import Data.String (fromString)
import Data.Text (Text)
import Database.PostgreSQL.Simple (ConnectInfo (..), Only (..), defaultConnectInfo)
import Database.PostgreSQL.Simple (ConnectInfo (..), Only (..))
import qualified Database.PostgreSQL.Simple as PSQL
import Database.PostgreSQL.Simple.SqlQQ (sql)
import Simplex.Messaging.Agent.Store.Migrations (migrateSchema)
@@ -24,7 +26,7 @@ import qualified Simplex.Messaging.Agent.Store.Postgres.DB as DB
import Simplex.Messaging.Agent.Store.Postgres.Util (createDBAndUserIfNotExists)
import Simplex.Messaging.Agent.Store.Shared (Migration (..), MigrationConfirmation (..), MigrationError (..))
import Simplex.Messaging.Util (ifM)
import UnliftIO.Exception (onException)
import UnliftIO.Exception (bracketOnError, onException)
import UnliftIO.MVar
import UnliftIO.STM
@@ -44,11 +46,11 @@ createDBStore connectInfo schema migrations confirmMigrations = do
Left e -> closeDBStore st $> Left e
connectPostgresStore :: ConnectInfo -> String -> IO DBStore
connectPostgresStore dbConnectInfo schema = do
(dbConn, dbNew) <- connectDB dbConnectInfo schema -- TODO [postgres] analogue for dbBusyLoop?
connectPostgresStore dbConnectInfo dbSchema = do
(dbConn, dbNew) <- connectDB dbConnectInfo dbSchema -- TODO [postgres] analogue for dbBusyLoop?
dbConnection <- newMVar dbConn
dbClosed <- newTVarIO False
pure DBStore {dbConnectInfo, dbConnection, dbNew, dbClosed}
pure DBStore {dbConnectInfo, dbSchema, dbConnection, dbNew, dbClosed}
connectDB :: ConnectInfo -> String -> IO (DB.Connection, Bool)
connectDB dbConnectInfo schema = do
@@ -81,6 +83,22 @@ closeDBStore st@DBStore {dbClosed} =
DB.close conn
atomically $ writeTVar dbClosed True
openPostgresStore_ :: DBStore -> IO ()
openPostgresStore_ DBStore {dbConnectInfo, dbSchema, dbConnection, dbClosed} =
bracketOnError
(takeMVar dbConnection)
(tryPutMVar dbConnection)
$ \_dbConn -> do
(dbConn, _dbNew) <- connectDB dbConnectInfo dbSchema
atomically $ writeTVar dbClosed False
putMVar dbConnection dbConn
reopenDBStore :: DBStore -> IO ()
reopenDBStore st@DBStore {dbClosed} =
ifM (readTVarIO dbClosed) open (putStrLn "reopenDBStore: already opened")
where
open = openPostgresStore_ st
-- TODO [postgres] not necessary for postgres (used for ExecAgentStoreSQL, ExecChatStoreSQL)
execSQL :: PSQL.Connection -> Text -> IO [Text]
execSQL _db _query = throwIO (userError "not implemented")
@@ -17,6 +17,7 @@ import UnliftIO.STM
-- TODO [postgres] use log_min_duration_statement instead of custom slow queries (SQLite's Connection type)
data DBStore = DBStore
{ dbConnectInfo :: PSQL.ConnectInfo,
dbSchema :: String,
dbConnection :: MVar PSQL.Connection,
dbClosed :: TVar Bool,
dbNew :: Bool
@@ -208,7 +208,7 @@ CREATE TABLE ntf_tokens(
tkn_action BYTEA,
created_at TIMESTAMPTZ NOT NULL DEFAULT (now()),
updated_at TIMESTAMPTZ NOT NULL DEFAULT (now()),
ntf_mode TEXT NULL,
ntf_mode BYTEA NULL,
PRIMARY KEY(provider, device_token, ntf_host, ntf_port),
FOREIGN KEY(ntf_host, ntf_port) REFERENCES ntf_servers
ON DELETE RESTRICT ON UPDATE CASCADE
@@ -222,8 +222,8 @@ CREATE TABLE ntf_subscriptions(
ntf_port TEXT NOT NULL,
ntf_sub_id BYTEA,
ntf_sub_status TEXT NOT NULL,
ntf_sub_action TEXT,
ntf_sub_smp_action TEXT,
ntf_sub_action BYTEA,
ntf_sub_smp_action BYTEA,
ntf_sub_action_ts TIMESTAMPTZ,
updated_by_supervisor SMALLINT NOT NULL DEFAULT 0,
created_at TIMESTAMPTZ NOT NULL DEFAULT (now()),
+5 -6
View File
@@ -27,13 +27,12 @@
module Simplex.Messaging.Agent.Store.SQLite
( createDBStore,
closeDBStore,
reopenDBStore,
execSQL,
-- used in Simplex.Chat.Archive
sqlString,
keyString,
storeKey,
-- used in Simplex.Chat.Mobile and tests
reopenSQLiteStore,
-- used in tests
connectSQLiteStore,
openSQLiteStore,
@@ -127,14 +126,14 @@ openSQLiteStore_ DBStore {dbConnection, dbFilePath, dbKey, dbClosed} key keepKey
writeTVar dbKey $! storeKey key keepKey
putMVar dbConnection DB.Connection {conn, slow}
reopenSQLiteStore :: DBStore -> IO ()
reopenSQLiteStore st@DBStore {dbKey, dbClosed} =
ifM (readTVarIO dbClosed) open (putStrLn "reopenSQLiteStore: already opened")
reopenDBStore :: DBStore -> IO ()
reopenDBStore st@DBStore {dbKey, dbClosed} =
ifM (readTVarIO dbClosed) open (putStrLn "reopenDBStore: already opened")
where
open =
readTVarIO dbKey >>= \case
Just key -> openSQLiteStore_ st key True
Nothing -> fail "reopenSQLiteStore: no key"
Nothing -> fail "reopenDBStore: no key"
keyString :: ScrubbedBytes -> Text
keyString = sqlString . safeDecodeUtf8 . BA.convert
+6 -6
View File
@@ -12,6 +12,7 @@ import AgentTests.ConnectionRequestTests
import AgentTests.DoubleRatchetTests (doubleRatchetTests)
import AgentTests.FunctionalAPITests (functionalAPITests)
import AgentTests.MigrationTests (migrationTests)
import AgentTests.NotificationTests (notificationTests)
import AgentTests.ServerChoice (serverChoiceTests)
import Simplex.Messaging.Transport (ATransport (..))
import Test.Hspec
@@ -19,7 +20,6 @@ import Test.Hspec
import Fixtures
import Simplex.Messaging.Agent.Store.Postgres.Util (dropAllSchemasExceptSystem)
#else
import AgentTests.NotificationTests (notificationTests)
import AgentTests.SQLiteTests (storeTests)
#endif
@@ -30,12 +30,12 @@ agentTests (ATransport t) = do
describe "Double ratchet tests" doubleRatchetTests
#if defined(dbPostgres)
after_ (dropAllSchemasExceptSystem testDBConnectInfo) $ do
#else
do
#endif
describe "Functional API" $ functionalAPITests (ATransport t)
describe "Chosen servers" serverChoiceTests
#else
describe "Functional API" $ functionalAPITests (ATransport t)
describe "Chosen servers" serverChoiceTests
-- notifications aren't tested with postgres, as we don't plan to use iOS client with it
describe "Notification tests" $ notificationTests (ATransport t)
describe "Notification tests" $ notificationTests (ATransport t)
#if !defined(dbPostgres)
describe "SQLite store" storeTests
#endif
+11 -6
View File
@@ -1,3 +1,4 @@
{-# LANGUAGE CPP #-}
{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE GADTs #-}
@@ -53,7 +54,6 @@ import qualified Data.ByteString.Char8 as B
import Data.List.NonEmpty (NonEmpty (..))
import qualified Data.List.NonEmpty as L
import Data.Text.Encoding (encodeUtf8)
import Database.SQLite.Simple.QQ (sql)
import NtfClient
import SMPAgentClient (agentCfg, initAgentServers, initAgentServers2, testDB, testDB2, testNtfServer, testNtfServer2)
import SMPClient (cfg, cfgVPrev, testPort, testPort2, testStoreLogFile2, testStoreMsgsDir2, withSmpServer, withSmpServerConfigOn, withSmpServerStoreLogOn, withSmpServerStoreMsgLogOn)
@@ -62,9 +62,9 @@ import Simplex.Messaging.Agent.Client (ProtocolTestFailure (..), ProtocolTestSte
import Simplex.Messaging.Agent.Env.SQLite (AgentConfig, Env (..), InitialAgentServers)
import Simplex.Messaging.Agent.Protocol hiding (CON, CONF, INFO, SENT)
import Simplex.Messaging.Agent.Store.AgentStore (getSavedNtfToken)
import Simplex.Messaging.Agent.Store.SQLite (closeDBStore, reopenSQLiteStore)
import Simplex.Messaging.Agent.Store.SQLite.Common (withTransaction)
import qualified Simplex.Messaging.Agent.Store.SQLite.DB as DB
import Simplex.Messaging.Agent.Store (closeStore, reopenStore)
import Simplex.Messaging.Agent.Store.Common (withTransaction)
import qualified Simplex.Messaging.Agent.Store.DB as DB
import qualified Simplex.Messaging.Crypto as C
import Simplex.Messaging.Encoding.String
import Simplex.Messaging.Notifications.Protocol
@@ -78,6 +78,11 @@ import Simplex.Messaging.Server.Env.STM (ServerConfig (..))
import Simplex.Messaging.Transport (ATransport)
import Test.Hspec
import UnliftIO
#if defined(dbPostgres)
import Database.PostgreSQL.Simple.SqlQQ (sql)
#else
import Database.SQLite.Simple.QQ (sql)
#endif
notificationTests :: ATransport -> Spec
notificationTests t = do
@@ -496,7 +501,7 @@ testNotificationSubscriptionExistingConnection apns baseId alice@AgentClient {ag
threadDelay 500000
suspendAgent alice 0
closeDBStore store
closeStore store
threadDelay 1000000
putStrLn "before opening the database from another agent"
@@ -507,7 +512,7 @@ testNotificationSubscriptionExistingConnection apns baseId alice@AgentClient {ag
threadDelay 1000000
putStrLn "after closing the database in another agent"
reopenSQLiteStore store
reopenStore store
foregroundAgent alice
threadDelay 500000
+4 -4
View File
@@ -604,7 +604,7 @@ testCloseReopenStore = do
hasMigrations st
closeDBStore st
errorGettingMigrations st
reopenSQLiteStore st
reopenDBStore st
hasMigrations st
testCloseReopenEncryptedStore :: IO ()
@@ -615,13 +615,13 @@ testCloseReopenEncryptedStore = do
closeDBStore st
closeDBStore st
errorGettingMigrations st
reopenSQLiteStore st `shouldThrow` \(e :: SomeException) -> "reopenSQLiteStore: no key" `isInfixOf` show e
reopenDBStore st `shouldThrow` \(e :: SomeException) -> "reopenDBStore: no key" `isInfixOf` show e
openSQLiteStore st key True
openSQLiteStore st key True
hasMigrations st
closeDBStore st
errorGettingMigrations st
reopenSQLiteStore st
reopenDBStore st
hasMigrations st
testReopenEncryptedStoreKeepKey :: IO ()
@@ -631,7 +631,7 @@ testReopenEncryptedStoreKeepKey = do
hasMigrations st
closeDBStore st
errorGettingMigrations st
reopenSQLiteStore st
reopenDBStore st
hasMigrations st
getMigrations :: DBStore -> IO Bool