Skip to content

Commit 4b8d31a

Browse files
authored
smp-server: remove deleted queues from store maps (#1947)
1 parent e91711c commit 4b8d31a

4 files changed

Lines changed: 73 additions & 25 deletions

File tree

‎src/Simplex/Messaging/Server/QueueStore/STM.hs‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -277,9 +277,11 @@ instance StoreQueueClass q => QueueStoreClass q (STMQueueStore q) where
277277
where
278278
rId = recipientId sq
279279
qr = queueRec sq
280-
delete q@QueueRec {senderId, rcvServiceId} = do
280+
delete q@QueueRec {senderId, queueData, rcvServiceId} = do
281281
writeTVar qr Nothing
282+
TM.delete rId $ queues st
282283
TM.delete senderId $ senders st
284+
forM_ queueData $ \(lnkId, _) -> TM.delete lnkId $ links st
283285
mapM_ (removeServiceQueue st serviceRcvQueues rId) rcvServiceId
284286
mapM_ (removeNotifier st) $ notifier q
285287
pure q

‎src/Simplex/Messaging/Server/StoreLog/ReadWrite.hs‎

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,6 @@ module Simplex.Messaging.Server.StoreLog.ReadWrite
1414

1515
import Control.Concurrent.STM
1616
import Control.Logger.Simple
17-
import Control.Monad
18-
import Control.Monad.IO.Class
19-
import Control.Monad.Trans.Except
2017
import qualified Data.ByteString.Char8 as B
2118
import qualified Data.Text as T
2219
import Data.Text.Encoding (decodeLatin1)
@@ -26,7 +23,7 @@ import Simplex.Messaging.Server.QueueStore (QueueRec, ServiceRec (..))
2623
import Simplex.Messaging.Server.QueueStore.STM (STMQueueStore (..), STMService (..), withLoadedQueues)
2724
import Simplex.Messaging.Server.QueueStore.Types
2825
import Simplex.Messaging.Server.StoreLog
29-
import Simplex.Messaging.Util (tshow)
26+
import Simplex.Messaging.Util (tshow, ($>>=))
3027
import System.IO
3128

3229
writeQueueStore :: forall q. StoreQueueClass q => StoreLog 'WriteMode -> STMQueueStore q -> IO ()
@@ -68,13 +65,7 @@ readQueueStore tty mkQ f st = readLogLines tty f $ \_ -> processLine
6865
printError :: String -> IO ()
6966
printError e = B.putStrLn $ "Error parsing log: " <> B.pack e <> " - " <> s
7067
withQueue :: forall a. RecipientId -> T.Text -> (q -> IO (Either ErrorType a)) -> IO ()
71-
withQueue qId op a = runExceptT go >>= qError qId op
72-
where
73-
go = do
74-
q <- ExceptT $ getQueue_ st mkQ SRecipient qId
75-
liftIO (readTVarIO $ queueRec q) >>= \case
76-
Nothing -> logWarn $ logPfx qId op <> "already deleted"
77-
Just _ -> void $ ExceptT $ a q
68+
withQueue qId op a = (getQueue_ st mkQ SRecipient qId $>>= a) >>= qError qId op
7869
qError qId op = \case
7970
Left e -> logError $ logPfx qId op <> tshow e
8071
Right _ -> pure ()

‎tests/CoreTests/MsgStoreTests.hs‎

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import Control.Monad.Trans.Except
2323
import Crypto.Random (ChaChaDRG)
2424
import Data.ByteString.Char8 (ByteString)
2525
import Data.Int (Int64)
26+
import qualified Data.Map.Strict as M
2627
import Data.Time.Clock.System (getSystemTime)
2728
import Simplex.Messaging.Crypto (pattern MaxLenBS)
2829
import qualified Simplex.Messaging.Crypto as C
@@ -31,7 +32,9 @@ import Simplex.Messaging.Server.MsgStore.STM
3132
import Simplex.Messaging.Server.MsgStore.Types
3233
import Simplex.Messaging.Server.QueueStore
3334
import Simplex.Messaging.Server.QueueStore.QueueInfo
35+
import Simplex.Messaging.Server.QueueStore.STM (STMQueueStore (..))
3436
import Simplex.Messaging.Server.QueueStore.Types
37+
import Simplex.Messaging.TMap (TMap)
3538
import Test.Hspec hiding (fit, it)
3639
import Util
3740

@@ -50,7 +53,9 @@ import SMPClient (testStoreDBOpts)
5053

5154
msgStoreTests :: Spec
5255
msgStoreTests = do
53-
describe "STM message store" $ someMsgStoreTests testSMTStoreConfig
56+
describe "STM message store" $ do
57+
someMsgStoreTests testSMTStoreConfig
58+
it "should remove deleted queues from queue store maps" $ withMsgStore testSMTStoreConfig testDeleteQueueMaps
5459
#if defined(dbServerPostgres)
5560
describe "Postgres-only message store" $ do
5661
someMsgStoreTests testPostgresStoreConfig
@@ -126,6 +131,18 @@ testNewQueueRecData g qm queueData = do
126131
where
127132
rndId = atomically $ EntityId <$> C.randomBytes 24 g
128133

134+
testNtfCreds :: TVar ChaChaDRG -> IO NtfCreds
135+
testNtfCreds g = do
136+
(notifierKey, _) <- atomically $ C.generateAuthKeyPair C.SX25519 g
137+
(k, pk) <- atomically $ C.generateKeyPair @'C.X25519 g
138+
pure
139+
NtfCreds
140+
{ notifierId = EntityId "ijkl",
141+
notifierKey,
142+
rcvNtfDhSecret = C.dh' k pk,
143+
ntfServiceId = Nothing
144+
}
145+
129146
testGetQueue :: MsgStoreClass s => s -> IO ()
130147
testGetQueue ms = do
131148
g <- C.newRandom
@@ -217,6 +234,56 @@ testLinkDataSecuredQueue ms = do
217234
void $ ExceptT $ deleteQueue ms q
218235
void $ ExceptT $ deleteQueue ms cq
219236

237+
-- sizes of queues, senders, links and notifiers maps
238+
type QueueMapSizes = (Int, Int, Int, Int)
239+
240+
queueMapSizes :: STMMsgStore -> IO QueueMapSizes
241+
queueMapSizes ms = (,,,) <$> size queues <*> size senders <*> size links <*> size notifiers
242+
where
243+
STMQueueStore {queues, senders, links, notifiers} = queueStore ms
244+
size :: TMap k v -> IO Int
245+
size = fmap M.size . readTVarIO
246+
247+
testDeleteQueueMaps :: STMMsgStore -> IO ()
248+
testDeleteQueueMaps ms = do
249+
g <- C.newRandom
250+
ntfCreds <- testNtfCreds g
251+
let newLinkId = atomically $ EntityId <$> C.randomBytes 24 g
252+
lnkId1 <- newLinkId
253+
lnkId2 <- newLinkId
254+
lnkId3 <- newLinkId
255+
(rId1, qr1) <- testNewQueueRec g QMMessaging
256+
(rId2, qr2) <- testNewQueueRecData g QMContact (Just (lnkId1, testLinkData))
257+
(rId3, qr3) <- testNewQueueRec g QMMessaging
258+
(rId4, qr4) <- testNewQueueRec g QMMessaging
259+
let rIds = [rId1, rId2, rId3, rId4] :: [RecipientId]
260+
sIds = map senderId [qr1, qr2, qr3, qr4]
261+
lnkIds = [lnkId1, lnkId2, lnkId3] :: [LinkId]
262+
queueMapSizes ms `shouldReturn` (0, 0, 0, 0)
263+
runRight_ $ do
264+
q1 <- ExceptT $ addQueue ms rId1 qr1 {notifier = Just ntfCreds}
265+
q2 <- ExceptT $ addQueue ms rId2 qr2
266+
q3 <- ExceptT $ addQueue ms rId3 qr3
267+
q4 <- ExceptT $ addQueue ms rId4 qr4
268+
ExceptT $ addQueueLinkData (queueStore ms) q3 lnkId2 testLinkData
269+
ExceptT $ addQueueLinkData (queueStore ms) q4 lnkId3 testLinkData
270+
forM_ sIds $ void . ExceptT . getQueue ms SSender
271+
forM_ lnkIds $ void . ExceptT . getQueue ms SSenderLink
272+
liftIO $ queueMapSizes ms `shouldReturn` (4, 4, 3, 1)
273+
ExceptT $ deleteQueueLinkData (queueStore ms) q3
274+
liftIO $ queueMapSizes ms `shouldReturn` (4, 4, 2, 1)
275+
forM_ ([q1, q2, q3, q4] :: [STMQueue]) $ void . ExceptT . deleteQueue ms
276+
queueMapSizes ms `shouldReturn` (0, 0, 0, 0)
277+
forM_ rIds $ \rId -> getQueue ms SRecipient rId >>= expectAuth
278+
forM_ sIds $ \sId -> getQueue ms SSender sId >>= expectAuth
279+
forM_ lnkIds $ \lnkId -> getQueue ms SSenderLink lnkId >>= expectAuth
280+
queueMapSizes ms `shouldReturn` (0, 0, 0, 0)
281+
where
282+
expectAuth = either (`shouldBe` AUTH) (\_ -> expectationFailure "deleted queue is still found")
283+
284+
testLinkData :: QueueLinkData
285+
testLinkData = (EncDataBytes "fixed data", EncDataBytes "user data")
286+
220287
#if defined(dbServerPostgres)
221288
testUpdateMessageCounts :: PostgresMsgStore -> IO ()
222289
testUpdateMessageCounts ms = do

‎tests/CoreTests/StoreLogTests.hs‎

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -48,18 +48,6 @@ import Simplex.Messaging.Server.Main
4848
testPublicAuthKey :: C.APublicAuthKey
4949
testPublicAuthKey = C.APublicAuthKey C.SEd25519 (C.publicKey "MC4CAQAwBQYDK2VwBCIEIDfEfevydXXfKajz3sRkcQ7RPvfWUPoq6pu1TYHV1DEe")
5050

51-
testNtfCreds :: TVar ChaChaDRG -> IO NtfCreds
52-
testNtfCreds g = do
53-
(notifierKey, _) <- atomically $ C.generateAuthKeyPair C.SX25519 g
54-
(k, pk) <- atomically $ C.generateKeyPair @'C.X25519 g
55-
pure
56-
NtfCreds
57-
{ notifierId = EntityId "ijkl",
58-
notifierKey,
59-
rcvNtfDhSecret = C.dh' k pk,
60-
ntfServiceId = Nothing
61-
}
62-
6351
data StoreLogTestCase r s = SLTC {name :: String, saved :: [r], state :: s, compacted :: [r]}
6452

6553
type SMPStoreLogTestCase = StoreLogTestCase StoreLogRecord (M.Map RecipientId QueueRec)

0 commit comments

Comments
 (0)