@@ -66,7 +66,7 @@ import Data.ByteString.Char8 (ByteString)
6666import qualified Data.ByteString.Char8 as B
6767import Data.Either (isRight )
6868import Data.Int (Int64 )
69- import Data.List (find , isSuffixOf , nub )
69+ import Data.List (find , isPrefixOf , isSuffixOf , nub )
7070import Data.List.NonEmpty (NonEmpty )
7171import qualified Data.Map as M
7272import Data.Maybe (isJust , isNothing )
@@ -113,7 +113,7 @@ import Simplex.Messaging.Util (bshow, diffToMicroseconds)
113113import Simplex.Messaging.Version (VersionRange (.. ))
114114import qualified Simplex.Messaging.Version as V
115115import Simplex.Messaging.Version.Internal (Version (.. ))
116- import System.Directory (copyFile , renameFile )
116+ import System.Directory (copyFile , removeFile , renameFile )
117117import Test.Hspec hiding (fit , it )
118118import UnliftIO
119119import Util
@@ -124,10 +124,13 @@ import Fixtures
124124#endif
125125#if defined(dbServerPostgres)
126126import qualified Database.PostgreSQL.Simple as PSQL
127+ import qualified Simplex.Messaging.Agent.Store.Postgres as Postgres
128+ import qualified Simplex.Messaging.Agent.Store.Postgres.Common as Postgres
127129import Simplex.Messaging.Server.MsgStore.Journal (JournalQueue )
128130import Simplex.Messaging.Server.MsgStore.Postgres (PostgresQueue )
129131import Simplex.Messaging.Server.MsgStore.Types (QSType (.. ))
130132import Simplex.Messaging.Server.QueueStore.Postgres
133+ import Simplex.Messaging.Server.QueueStore.Postgres.Migrations
131134import Simplex.Messaging.Server.QueueStore.Types (QueueStoreClass (.. ))
132135#endif
133136
@@ -476,6 +479,7 @@ functionalAPITests ps = do
476479 withSmpServer ps testTwoUsers
477480 describe " Client service certificates" $ do
478481 it " should connect, subscribe and reconnect as a service" $ testClientServiceConnection ps
482+ it " should re-subscribe when service ID changed" $ testClientServiceIDChange ps
479483 describe " Connection switch" $ do
480484 describe " should switch delivery to the new queue" $
481485 testServerMatrix2 ps testSwitchConnection
@@ -3715,6 +3719,47 @@ testClientServiceConnection ps = do
37153719 exchangeGreetingsMsgId 4 user sId' service uId'
37163720 exchangeGreetingsMsgId 10 service uId user sId
37173721
3722+ testClientServiceIDChange :: HasCallStack => (ASrvTransport , AStoreType ) -> IO ()
3723+ testClientServiceIDChange ps@ (_, ASType qs _) = do
3724+ (sId, uId) <- withAgentClientsServers2 (agentCfg, initAgentServersClientService) (agentCfg, initAgentServers) $ \ service user -> do
3725+ withSmpServerStoreLogOn ps testPort $ \ _ -> runRight $ do
3726+ conns@ (sId, uId) <- makeConnection service user
3727+ exchangeGreetings service uId user sId
3728+ pure conns
3729+ _ :: () <- case qs of
3730+ SQSPostgres -> do
3731+ #if defined(dbServerPostgres)
3732+ st <- either (error . show ) pure =<< Postgres. createDBStore testStoreDBOpts serverMigrations (MigrationConfig MCError Nothing )
3733+ void $ Postgres. withTransaction st (`PSQL.execute_` " DELETE FROM services" )
3734+ #else
3735+ pure ()
3736+ #endif
3737+ SQSMemory -> do
3738+ s <- readFile testStoreLogFile
3739+ removeFile testStoreLogFile
3740+ writeFile testStoreLogFile $ unlines $ filter (not . (" NEW_SERVICE" `isPrefixOf` )) $ lines s
3741+ withAgentClientsServers2 (agentCfg, initAgentServersClientService) (agentCfg, initAgentServers) $ \ service user -> do
3742+ withSmpServerStoreLogOn ps testPort $ \ _ -> runRight $ do
3743+ subscribeAllConnections service False Nothing
3744+ liftIO $ getInAnyOrder service
3745+ [ \ case (" " , " " , AEvt SAENone (SERVICE_UP _ (SMP. ServiceSubResult (Just (SMP. SSErrorQueueCount 1 0 )) (SMP. ServiceSub _ 0 _)))) -> True ; _ -> False ,
3746+ \ case (" " , " " , AEvt SAENone (SERVICE_ALL _)) -> True ; _ -> False ,
3747+ \ case (" " , " " , AEvt SAENone (UP _ _)) -> True ; _ -> False
3748+ ]
3749+ subscribeAllConnections user False Nothing
3750+ (" " , " " , UP _ [_]) <- nGet user
3751+ exchangeGreetingsMsgId 4 service uId user sId
3752+ -- disable service in the client
3753+ -- The test uses True for non-existing user to make sure it's removed for user 1,
3754+ -- because if no users use services, then it won't be checking them to optimize for most clients.
3755+ withAgentClientsServers2 (agentCfg, initAgentServers {useServices = M. fromList [(100 , True )]}) (agentCfg, initAgentServers) $ \ notService user -> do
3756+ withSmpServerStoreLogOn ps testPort $ \ _ -> runRight $ do
3757+ subscribeAllConnections notService False Nothing
3758+ (" " , " " , UP _ [_]) <- nGet notService
3759+ subscribeAllConnections user False Nothing
3760+ (" " , " " , UP _ [_]) <- nGet user
3761+ exchangeGreetingsMsgId 6 notService uId user sId
3762+
37183763getSMPAgentClient' :: Int -> AgentConfig -> InitialAgentServers -> String -> IO AgentClient
37193764getSMPAgentClient' clientId cfg' initServers dbPath = do
37203765 Right st <- liftIO $ createStore dbPath
0 commit comments