mirror of
https://github.com/simplex-chat/simplexmq.git
synced 2026-09-01 20:18:26 +00:00
SMP router specs
This commit is contained in:
@@ -247,6 +247,7 @@ smpServer started cfg@ServerConfig {transports, transportConfig = tCfg, startOpt
|
||||
closeServer :: M s ()
|
||||
closeServer = asks (smpAgent . proxyAgent) >>= liftIO . closeSMPClientAgent
|
||||
|
||||
-- spec: spec/modules/Simplex/Messaging/Server.md#serverthread--subscription-lifecycle-with-split-stm
|
||||
serverThread ::
|
||||
forall sub. String ->
|
||||
Server s ->
|
||||
@@ -1223,6 +1224,7 @@ disconnectTransport THandle {connection, params = THandleParams {sessionId}} rcv
|
||||
|
||||
data VerificationResult s = VRVerified (Maybe (StoreQueue s, QueueRec)) | VRFailed ErrorType
|
||||
|
||||
-- spec: spec/modules/Simplex/Messaging/Server.md#constant-time-authorization--dummy-keys
|
||||
-- This function verifies queue command authorization, with the objective to have constant time between the three AUTH error scenarios:
|
||||
-- - the queue and party key exist, and the provided authorization has type matching queue key, but it is made with the different key.
|
||||
-- - the queue and party key exist, but the provided authorization has incorrect type.
|
||||
@@ -1982,6 +1984,7 @@ client
|
||||
-- If the queue is not full, then the thread is created where these checks are made:
|
||||
-- - it is the same subscribed client (in case it was reconnected it would receive message via SUB command)
|
||||
-- - nothing was delivered to this subscription (to avoid race conditions with the recipient).
|
||||
-- spec: spec/modules/Simplex/Messaging/Server.md#trydelivermessage--syncasync-split-delivery
|
||||
tryDeliverMessage :: Message -> IO ()
|
||||
tryDeliverMessage msg =
|
||||
-- the subscribed client var is read outside of STM to avoid transaction cost
|
||||
@@ -2063,6 +2066,7 @@ client
|
||||
encNMsgMeta = C.cbEncrypt rcvNtfDhSecret ntfNonce (smpEncode msgMeta) 128
|
||||
pure $ MsgNtf {ntfMsgId = msgId, ntfTs = msgTs, ntfNonce, ntfEncMeta = fromRight "" encNMsgMeta}
|
||||
|
||||
-- spec: spec/modules/Simplex/Messaging/Server.md#proxy-forwarding--single-transmission-no-service-identity
|
||||
processForwardedCommand :: EncFwdTransmission -> M s BrokerMsg
|
||||
processForwardedCommand (EncFwdTransmission s) = fmap (either ERR RRES) . runExceptT $ do
|
||||
THAuthServer {serverPrivKey, sessSecret'} <- maybe (throwE $ transportErr TENoServerAuth) pure (thAuth thParams')
|
||||
|
||||
@@ -368,6 +368,7 @@ data ServerSubscribers s = ServerSubscribers
|
||||
pendingEvents :: TVar (IntMap (NonEmpty (EntityId, BrokerMsg)))
|
||||
}
|
||||
|
||||
-- spec: spec/modules/Simplex/Messaging/Server/Env/STM.md#subscribedclients--tvar-of-maybe-pattern
|
||||
-- not exported, to prevent accidental concurrent Map lookups inside STM transactions.
|
||||
-- Map stores TVars with pointers to the clients rather than client ID to allow reading the same TVar
|
||||
-- inside transactions to ensure that transaction is re-evaluated in case subscriber changes.
|
||||
|
||||
@@ -76,6 +76,7 @@ data PostgresQueue = PostgresQueue
|
||||
queueRec' :: TVar (Maybe QueueRec)
|
||||
}
|
||||
|
||||
-- spec: spec/modules/Simplex/Messaging/Server/MsgStore/Postgres.md#msgqueue-is-unit-type
|
||||
instance StoreQueueClass PostgresQueue where
|
||||
recipientId = recipientId'
|
||||
{-# INLINE recipientId #-}
|
||||
|
||||
@@ -49,6 +49,7 @@ import Simplex.Messaging.Server.QueueStore
|
||||
import Simplex.Messaging.Server.QueueStore.Types
|
||||
import Simplex.Messaging.Util ((<$$>), ($>>=))
|
||||
|
||||
-- spec: spec/modules/Simplex/Messaging/Server/MsgStore/Types.md#injective-type-families--unambiguous-type-resolution
|
||||
class (Monad (StoreMonad s), QueueStoreClass (StoreQueue s) (QueueStore s)) => MsgStoreClass s where
|
||||
type StoreMonad s = (m :: Type -> Type) | m -> s
|
||||
type MsgStoreConfig s = c | c -> s
|
||||
|
||||
@@ -169,6 +169,7 @@ instance StoreQueueClass q => QueueStoreClass q (PostgresQueueStore q) where
|
||||
(SRMessaging, SRNotifier)
|
||||
pure EntityCounts {queueCount, notifierCount, rcvServiceCount, ntfServiceCount, rcvServiceQueuesCount, ntfServiceQueuesCount}
|
||||
|
||||
-- spec: spec/modules/Simplex/Messaging/Server/QueueStore/Postgres.md#addqueue_--no-in-memory-duplicate-check-relies-on-db-constraint
|
||||
-- this implementation assumes that the lock is already taken by addQueue
|
||||
-- and relies on unique constraints in the database to prevent duplicate IDs.
|
||||
addQueue_ :: PostgresQueueStore q -> (RecipientId -> QueueRec -> IO q) -> RecipientId -> QueueRec -> IO (Either ErrorType q)
|
||||
|
||||
@@ -116,6 +116,7 @@ instance StoreQueueClass q => QueueStoreClass q (STMQueueStore q) where
|
||||
serviceCount role = M.foldl' (\ !n s -> if serviceRole (serviceRec s) == role then n + 1 else n) 0
|
||||
serviceQueuesCount serviceSel = foldM (\n s -> (n +) . S.size . fst <$> readTVarIO (serviceSel s)) 0
|
||||
|
||||
-- spec: spec/modules/Simplex/Messaging/Server/QueueStore/STM.md#addqueue_--atomic-multi-id-duplicate-check
|
||||
addQueue_ :: STMQueueStore q -> (RecipientId -> QueueRec -> IO q) -> RecipientId -> QueueRec -> IO (Either ErrorType q)
|
||||
addQueue_ st mkQ rId qr@QueueRec {senderId = sId, notifier, queueData, rcvServiceId} = do
|
||||
sq <- mkQ rId qr
|
||||
|
||||
@@ -96,6 +96,7 @@ data SLRTag
|
||||
| NewService_
|
||||
| QueueService_
|
||||
|
||||
-- spec: spec/modules/Simplex/Messaging/Server/StoreLog.md#queuerec-strencoding--backward-compatible-parsing
|
||||
instance StrEncoding QueueRec where
|
||||
strEncode QueueRec {recipientKeys, rcvDhSecret, rcvServiceId, senderId, senderKey, queueMode, queueData, notifier, status, updatedAt} =
|
||||
B.concat
|
||||
@@ -242,6 +243,7 @@ closeStoreLog = \case
|
||||
where
|
||||
close_ h = hClose h `catchAny` \e -> logError ("STORE: closeStoreLog, error closing, " <> tshow e)
|
||||
|
||||
-- spec: spec/modules/Simplex/Messaging/Server/StoreLog.md#writestorelogrecord--atomicity-via-manual-write
|
||||
writeStoreLogRecord :: StrEncoding r => StoreLog 'WriteMode -> r -> IO ()
|
||||
writeStoreLogRecord (WriteStoreLog _ h) r = E.uninterruptibleMask_ $ do
|
||||
B.hPut h $ strEncode r `B.snoc` '\n' -- hPutStrLn makes write non-atomic for length > 1024
|
||||
@@ -289,6 +291,7 @@ logNewService s = writeStoreLogRecord s . NewService
|
||||
logQueueService :: (PartyI p, ServiceParty p) => StoreLog 'WriteMode -> RecipientId -> SParty p -> Maybe ServiceId -> IO ()
|
||||
logQueueService s rId party = writeStoreLogRecord s . QueueService rId (ASP party)
|
||||
|
||||
-- spec: spec/modules/Simplex/Messaging/Server/StoreLog.md#readwritestorelog--crash-recovery-state-machine
|
||||
readWriteStoreLog :: (FilePath -> s -> IO ()) -> (StoreLog 'WriteMode -> s -> IO ()) -> FilePath -> s -> IO (StoreLog 'WriteMode)
|
||||
readWriteStoreLog readStore writeStore f st =
|
||||
ifM
|
||||
|
||||
Reference in New Issue
Block a user