mirror of
https://github.com/simplex-chat/simplexmq.git
synced 2026-04-27 21:35:13 +00:00
SMPClient returns errors via ExceptT (#13)
This commit is contained in:
committed by
GitHub
parent
c72deeda28
commit
3ad0bffaab
@@ -27,6 +27,7 @@ dependencies:
|
||||
- template-haskell == 2.15.*
|
||||
- text == 1.2.*
|
||||
- time == 1.9.*
|
||||
- transformers == 0.5.*
|
||||
- unliftio == 0.2.*
|
||||
- unliftio-core == 0.1.*
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ import Control.Monad.Except
|
||||
import Control.Monad.IO.Unlift
|
||||
import Control.Monad.Reader
|
||||
import Crypto.Random
|
||||
import Data.Bifunctor (first)
|
||||
import qualified Data.Map as M
|
||||
import Simplex.Messaging.Agent.Env.SQLite
|
||||
import Simplex.Messaging.Agent.Store
|
||||
@@ -79,6 +80,15 @@ withStore action = do
|
||||
handleInternal :: (MonadError StoreError m') => SomeException -> m' a
|
||||
handleInternal _ = throwError SEInternal
|
||||
|
||||
liftSMP :: (MonadUnliftIO m, MonadError ErrorType m) => ExceptT SMPClientError IO a -> m a
|
||||
liftSMP action =
|
||||
liftIO (first smpClientError <$> runExceptT action) >>= liftEither
|
||||
where
|
||||
smpClientError :: SMPClientError -> ErrorType
|
||||
smpClientError = \case
|
||||
SMPServerError e -> SMP e
|
||||
_ -> INTERNAL -- TODO handle other errors
|
||||
|
||||
processCommand ::
|
||||
forall m.
|
||||
(MonadUnliftIO m, MonadReader Env m, MonadError ErrorType m) =>
|
||||
@@ -97,10 +107,7 @@ processCommand AgentClient {sndQ, smpClients} (corrId, connAlias, cmd) =
|
||||
g <- asks idsDrg
|
||||
recipientKey <- atomically $ randomBytes 16 g -- TODO replace with cryptographic key pair
|
||||
let rcvPrivateKey = recipientKey
|
||||
(recipientId, senderId) <-
|
||||
liftIO (createSMPQueue c recipientKey)
|
||||
`E.catch` smpClientError
|
||||
`E.catch` replyError INTERNAL
|
||||
(recipientId, senderId) <- liftSMP $ createSMPQueue c recipientKey
|
||||
encryptKey <- atomically $ randomBytes 16 g -- TODO replace with cryptographic key pair
|
||||
let decryptKey = encryptKey
|
||||
withStore $ \st ->
|
||||
@@ -140,22 +147,10 @@ processCommand AgentClient {sndQ, smpClients} (corrId, connAlias, cmd) =
|
||||
status = New,
|
||||
ackMode = AckMode On
|
||||
}
|
||||
liftIO (sendSMPMessage c "" senderId msg)
|
||||
`E.catch` smpClientError
|
||||
-- `E.catch` replyError INTERNAL
|
||||
-- TODO the problem here is that while the intention of the 2nd catch was to catch
|
||||
-- all other exceptions, because smpClientError "throwError" via left channel
|
||||
-- and of how ExceptT instance of UnliftIO is implemented, the second `catch` catches
|
||||
-- Left channel... The only solution is to use runtime exceptions and not ExceptT
|
||||
liftSMP $ sendSMPMessage c "" senderId msg
|
||||
withStore $ \st -> updateQueueStatus st connAlias SND Confirmed
|
||||
respond OK
|
||||
|
||||
smpClientError :: SMPClientError -> m a
|
||||
smpClientError = \case
|
||||
SMPServerError e -> throwError $ SMP e
|
||||
_ -> throwError INTERNAL
|
||||
-- TODO
|
||||
|
||||
replyError :: ErrorType -> SomeException -> m a
|
||||
replyError err e = do
|
||||
liftIO . putStrLn $ "Exception: " ++ show e -- TODO remove
|
||||
|
||||
@@ -21,6 +21,7 @@ import Control.Concurrent.Async
|
||||
import Control.Concurrent.STM
|
||||
import Control.Exception
|
||||
import Control.Monad
|
||||
import Control.Monad.Trans.Except
|
||||
import qualified Data.ByteString.Char8 as B
|
||||
import Data.Map.Strict (Map)
|
||||
import qualified Data.Map.Strict as M
|
||||
@@ -84,7 +85,10 @@ getSMPClient SMPServer {host, port} SMPClientConfig {qSize, defaultPort} = do
|
||||
modifyTVar sentCommands $ M.delete corrId
|
||||
putTMVar responseVar $
|
||||
if queueId == qId
|
||||
then either (Left . SMPResponseError) Right respOrErr
|
||||
then case respOrErr of
|
||||
Left e -> Left $ SMPResponseError e
|
||||
Right (Cmd _ (ERR e)) -> Left $ SMPServerError e
|
||||
Right r -> Right r
|
||||
else Left SMPQueueIdError
|
||||
|
||||
data SMPClientError
|
||||
@@ -96,25 +100,23 @@ data SMPClientError
|
||||
| SMPClientError
|
||||
deriving (Eq, Show, Exception)
|
||||
|
||||
createSMPQueue :: SMPClient -> RecipientKey -> IO (RecipientId, SenderId)
|
||||
createSMPQueue :: SMPClient -> RecipientKey -> ExceptT SMPClientError IO (RecipientId, SenderId)
|
||||
createSMPQueue c rKey = do
|
||||
sendSMPCommand c "" "" (Cmd SRecipient $ NEW rKey) >>= \case
|
||||
Cmd _ (IDS rId sId) -> return (rId, sId)
|
||||
Cmd _ (ERR e) -> throwIO $ SMPServerError e
|
||||
_ -> throwIO SMPUnexpectedResponse
|
||||
_ -> throwE SMPUnexpectedResponse
|
||||
|
||||
sendSMPMessage :: SMPClient -> SenderKey -> QueueId -> MsgBody -> IO ()
|
||||
sendSMPMessage :: SMPClient -> SenderKey -> QueueId -> MsgBody -> ExceptT SMPClientError IO ()
|
||||
sendSMPMessage c sKey qId msg = do
|
||||
sendSMPCommand c sKey qId (Cmd SSender $ SEND msg) >>= \case
|
||||
Cmd _ OK -> return ()
|
||||
Cmd _ (ERR e) -> throwIO $ SMPServerError e
|
||||
_ -> throwIO SMPUnexpectedResponse
|
||||
_ -> throwE SMPUnexpectedResponse
|
||||
|
||||
sendSMPCommand :: SMPClient -> PrivateKey -> QueueId -> Cmd -> IO Cmd
|
||||
sendSMPCommand SMPClient {sndQ, sentCommands, clientCorrId} pKey qId cmd = do
|
||||
sendSMPCommand :: SMPClient -> PrivateKey -> QueueId -> Cmd -> ExceptT SMPClientError IO Cmd
|
||||
sendSMPCommand SMPClient {sndQ, sentCommands, clientCorrId} pKey qId cmd = ExceptT $ do
|
||||
corrId <- atomically getNextCorrId
|
||||
t <- signTransmission (corrId, qId, cmd)
|
||||
atomically (send corrId t) >>= atomically . takeTMVar >>= either throwIO return
|
||||
atomically (send corrId t) >>= atomically . takeTMVar
|
||||
where
|
||||
getNextCorrId :: STM CorrId
|
||||
getNextCorrId = do
|
||||
|
||||
Reference in New Issue
Block a user