88{-# LANGUAGE OverloadedLists #-}
99{-# LANGUAGE OverloadedStrings #-}
1010{-# LANGUAGE ScopedTypeVariables #-}
11- {-# LANGUAGE StandaloneDeriving #-}
1211
1312module Simplex.Messaging.Notifications.Server.Store where
1413
@@ -17,16 +16,15 @@ import Control.Monad
1716import Data.ByteString.Char8 (ByteString )
1817import Data.Functor (($>) )
1918import Data.List.NonEmpty (NonEmpty (.. ), (<|) )
20- import Data.Map.Strict (Map )
2119import qualified Data.Map.Strict as M
22- import Data.Maybe (isNothing )
20+ import Data.Maybe (catMaybes )
2321import Data.Set (Set )
2422import qualified Data.Set as S
2523import Data.Word (Word16 )
2624import qualified Simplex.Messaging.Crypto as C
2725import Simplex.Messaging.Encoding.String
2826import Simplex.Messaging.Notifications.Protocol
29- import Simplex.Messaging.Protocol (NotifierId , NtfPrivateAuthKey , NtfPublicAuthKey , SMPServer )
27+ import Simplex.Messaging.Protocol (NtfPrivateAuthKey , NtfPublicAuthKey , SMPServer )
3028import Simplex.Messaging.Server.QueueStore (RoundedSystemTime )
3129import Simplex.Messaging.TMap (TMap )
3230import qualified Simplex.Messaging.TMap as TM
@@ -37,11 +35,8 @@ data NtfStore = NtfStore
3735 -- multiple registrations exist to protect from malicious registrations if token is compromised
3836 tokenRegistrations :: TMap DeviceToken (TMap ByteString NtfTokenId ),
3937 subscriptions :: TMap NtfSubscriptionId NtfSubData ,
40- -- the first set is used to delete from `subscriptions` when token is deleted, the second - to cancel SMP subsriptions.
41- -- TODO [notifications] it can be simplified once NtfSubData is fully removed.
42- tokenSubscriptions :: TMap NtfTokenId (TMap SMPServer (TVar (Set NtfSubscriptionId ), TVar (Set NotifierId ))),
43- -- TODO [notifications] for subscriptions that "migrated" to server subscription, we may replace NtfSubData with NtfTokenId here (Either NtfSubData NtfTokenId).
44- subscriptionLookup :: TMap SMPServer (TMap NotifierId NtfSubData ),
38+ tokenSubscriptions :: TMap NtfTokenId (TVar (Set NtfSubscriptionId )),
39+ subscriptionLookup :: TMap SMPQueueNtf NtfSubscriptionId ,
4540 tokenLastNtfs :: TMap NtfTokenId (TVar (NonEmpty PNMessageData ))
4641 }
4742
@@ -139,7 +134,7 @@ removeTokenRegistration st NtfTknData {ntfTknId = tId, token, tknVerifyKey} =
139134 >>= mapM_ (\ tId' -> when (tId == tId') $ TM. delete k regs)
140135 k = C. toPubKey C. pubKeyBytes tknVerifyKey
141136
142- deleteNtfToken :: NtfStore -> NtfTokenId -> STM ( Map SMPServer ( Set NotifierId ))
137+ deleteNtfToken :: NtfStore -> NtfTokenId -> STM [ SMPQueueNtf ]
143138deleteNtfToken st tknId = do
144139 void $
145140 TM. lookupDelete tknId (tokens st) $>>= \ NtfTknData {token, tknVerifyKey} ->
@@ -152,25 +147,25 @@ deleteNtfToken st tknId = do
152147 regs = tokenRegistrations st
153148 regKey = C. toPubKey C. pubKeyBytes
154149
155- deleteTokenSubs :: NtfStore -> NtfTokenId -> STM (Map SMPServer (Set NotifierId ))
156- deleteTokenSubs st tknId =
157- TM. lookupDelete tknId (tokenSubscriptions st)
158- >>= maybe (pure M. empty) (readTVar >=> deleteSrvSubs)
150+ deleteTokenSubs :: NtfStore -> NtfTokenId -> STM [SMPQueueNtf ]
151+ deleteTokenSubs st tknId = do
152+ qs <-
153+ TM. lookupDelete tknId (tokenSubscriptions st)
154+ >>= mapM (readTVar >=> mapM deleteSub . S. toList)
155+ pure $ maybe [] catMaybes qs
159156 where
160- deleteSrvSubs :: Map SMPServer (TVar (Set NtfSubscriptionId ), TVar (Set NotifierId )) -> STM (Map SMPServer (Set NotifierId ))
161- deleteSrvSubs = M. traverseWithKey $ \ smpServer (sVar, nVar) -> do
162- sIds <- readTVar sVar
163- modifyTVar' (subscriptions st) (`M.withoutKeys` sIds)
164- nIds <- readTVar nVar
165- TM. lookup smpServer (subscriptionLookup st) >>= mapM_ (`modifyTVar'` (`M.withoutKeys` nIds))
166- pure nIds
157+ deleteSub subId = do
158+ TM. lookupDelete subId (subscriptions st)
159+ $>>= \ NtfSubData {smpQueue} ->
160+ TM. delete smpQueue (subscriptionLookup st) $> Just smpQueue
167161
168162getNtfSubscriptionIO :: NtfStore -> NtfSubscriptionId -> IO (Maybe NtfSubData )
169163getNtfSubscriptionIO st subId = TM. lookupIO subId (subscriptions st)
170164
171165findNtfSubscription :: NtfStore -> SMPQueueNtf -> STM (Maybe NtfSubData )
172- findNtfSubscription st SMPQueueNtf {smpServer, notifierId} =
173- TM. lookup smpServer (subscriptionLookup st) $>>= TM. lookup notifierId
166+ findNtfSubscription st smpQueue = do
167+ TM. lookup smpQueue (subscriptionLookup st)
168+ $>>= \ subId -> TM. lookup subId (subscriptions st)
174169
175170findNtfSubscriptionToken :: NtfStore -> SMPQueueNtf -> STM (Maybe NtfTknData )
176171findNtfSubscriptionToken st smpQueue = do
@@ -188,45 +183,30 @@ mkNtfSubData ntfSubId (NewNtfSub tokenId smpQueue notifierKey) = do
188183 subStatus <- newTVar NSNew
189184 pure NtfSubData {ntfSubId, smpQueue, tokenId, subStatus, notifierKey}
190185
191- -- returns False if subscription existed before
192- addNtfSubscription :: NtfStore -> NtfSubscriptionId -> NtfSubData -> STM Bool
193- addNtfSubscription st subId sub@ NtfSubData {smpQueue = SMPQueueNtf {smpServer, notifierId}, tokenId} =
194- TM. lookup tokenId (tokenSubscriptions st)
195- >>= maybe newTokenSubs pure
196- >>= \ ts -> TM. lookup smpServer ts
197- >>= maybe (newTokenSrvSubs ts) pure
198- >>= insertSub
186+ addNtfSubscription :: NtfStore -> NtfSubscriptionId -> NtfSubData -> STM (Maybe () )
187+ addNtfSubscription st subId sub@ NtfSubData {smpQueue, tokenId} =
188+ TM. lookup tokenId (tokenSubscriptions st) >>= maybe newTokenSub pure >>= insertSub
199189 where
200- newTokenSubs = do
201- ts <- newTVar M . empty
190+ newTokenSub = do
191+ ts <- newTVar S . empty
202192 TM. insert tokenId ts $ tokenSubscriptions st
203193 pure ts
204- newTokenSrvSubs ts = do
205- tss <- (,) <$> newTVar S. empty <*> newTVar S. empty
206- TM. insert smpServer tss ts
207- pure tss
208- insertSub :: (TVar (Set NtfSubscriptionId ), TVar (Set NotifierId )) -> STM Bool
209- insertSub (sIds, nIds) = do
210- modifyTVar' sIds $ S. insert subId
211- modifyTVar' nIds $ S. insert notifierId
194+ insertSub ts = do
195+ modifyTVar' ts $ S. insert subId
212196 TM. insert subId sub $ subscriptions st
213- TM. lookup smpServer (subscriptionLookup st)
214- >>= maybe newSubs pure
215- >>= fmap isNothing . TM. lookupInsert notifierId sub
216- newSubs = do
217- ss <- newTVar M. empty
218- TM. insert smpServer ss $ subscriptionLookup st
219- pure ss
197+ TM. insert smpQueue subId (subscriptionLookup st)
198+ -- return Nothing if subscription existed before
199+ pure $ Just ()
220200
221201deleteNtfSubscription :: NtfStore -> NtfSubscriptionId -> STM ()
222- deleteNtfSubscription st subId = TM. lookupDelete subId (subscriptions st) >>= mapM_ deleteSubIndices
223- where
224- deleteSubIndices NtfSubData {smpQueue = SMPQueueNtf {smpServer, notifierId}, tokenId} = do
225- TM. lookup smpServer (subscriptionLookup st) >>= mapM_ ( TM. delete notifierId)
226- tss_ <- TM. lookup tokenId (tokenSubscriptions st) $>>= TM. lookup smpServer
227- forM_ tss_ $ \ (sIds, nIds) -> do
228- modifyTVar' sIds $ S. delete subId
229- modifyTVar' nIds $ S. delete notifierId
202+ deleteNtfSubscription st subId = do
203+ TM. lookupDelete subId (subscriptions st)
204+ >>= mapM_
205+ ( \ NtfSubData {smpQueue, tokenId} -> do
206+ TM. delete smpQueue $ subscriptionLookup st
207+ ts_ <- TM. lookup tokenId (tokenSubscriptions st)
208+ forM_ ts_ $ \ ts -> modifyTVar' ts $ S. delete subId
209+ )
230210
231211addTokenLastNtf :: NtfStore -> NtfTokenId -> PNMessageData -> IO (NonEmpty PNMessageData )
232212addTokenLastNtf st tknId newNtf =
0 commit comments