mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-05-25 14:14:39 +00:00
core: wait for delivery to avoid race between connection deletion and sending service messages about entity deletion (#3849)
This commit is contained in:
+1
-1
@@ -12,7 +12,7 @@ constraints: zip +disable-bzip2 +disable-zstd
|
||||
source-repository-package
|
||||
type: git
|
||||
location: https://github.com/simplex-chat/simplexmq.git
|
||||
tag: 050a921fbbdf21690cab7765bf6237fdc5a419cb
|
||||
tag: 294d7ec8dde9898b66188a346f6d9d17119763da
|
||||
|
||||
source-repository-package
|
||||
type: git
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"https://github.com/simplex-chat/simplexmq.git"."050a921fbbdf21690cab7765bf6237fdc5a419cb" = "0bc8x3pv3l6wjcfx06yhyydf2amaw5jjax2wcbgbxzrhqz10xf1v";
|
||||
"https://github.com/simplex-chat/simplexmq.git"."294d7ec8dde9898b66188a346f6d9d17119763da" = "06a4rzzc6ky11h6mw7ja5wb7ykq4dgvwa47wlns9wmpvbfqpmxrh";
|
||||
"https://github.com/simplex-chat/hs-socks.git"."a30cc7a79a08d8108316094f8f2f82a0c5e1ac51" = "0yasvnr7g91k76mjkamvzab2kvlb1g5pspjyjn2fr6v83swjhj38";
|
||||
"https://github.com/simplex-chat/direct-sqlcipher.git"."f814ee68b16a9447fbb467ccc8f29bdd3546bfd9" = "1ql13f4kfwkbaq7nygkxgw84213i0zm7c1a8hwvramayxl38dq5d";
|
||||
"https://github.com/simplex-chat/sqlcipher-simple.git"."a46bd361a19376c5211f1058908fc0ae6bf42446" = "1z0r78d8f0812kxbgsm735qf6xx8lvaz27k1a0b4a2m0sshpd5gl";
|
||||
|
||||
+29
-16
@@ -941,10 +941,10 @@ processChatCommand' vr = \case
|
||||
withChatLock "deleteChat direct" . procCmd $ do
|
||||
cancelFilesInProgress user filesInfo
|
||||
deleteFilesLocally filesInfo
|
||||
when (contactReady ct && contactActive ct && notify) $
|
||||
void (sendDirectContactMessage ct XDirectDel) `catchChatError` const (pure ())
|
||||
let doSendDel = contactReady ct && contactActive ct && notify
|
||||
when doSendDel $ void (sendDirectContactMessage ct XDirectDel) `catchChatError` const (pure ())
|
||||
contactConnIds <- map aConnId <$> withStore' (\db -> getContactConnections db userId ct)
|
||||
deleteAgentConnectionsAsync user contactConnIds
|
||||
deleteAgentConnectionsAsync' user contactConnIds doSendDel
|
||||
-- functions below are called in separate transactions to prevent crashes on android
|
||||
-- (possibly, race condition on integrity check?)
|
||||
withStore' $ \db -> deleteContactConnectionsAndFiles db userId ct
|
||||
@@ -965,9 +965,10 @@ processChatCommand' vr = \case
|
||||
withChatLock "deleteChat group" . procCmd $ do
|
||||
cancelFilesInProgress user filesInfo
|
||||
deleteFilesLocally filesInfo
|
||||
when (memberActive membership && isOwner) . void $ sendGroupMessage' user gInfo members XGrpDel
|
||||
let doSendDel = memberActive membership && isOwner
|
||||
when doSendDel . void $ sendGroupMessage' user gInfo members XGrpDel
|
||||
deleteGroupLinkIfExists user gInfo
|
||||
deleteMembersConnections user members
|
||||
deleteMembersConnections' user members doSendDel
|
||||
updateCIGroupInvitationStatus user gInfo CIGISRejected `catchChatError` \_ -> pure ()
|
||||
-- functions below are called in separate transactions to prevent crashes on android
|
||||
-- (possibly, race condition on integrity check?)
|
||||
@@ -1696,7 +1697,7 @@ processChatCommand' vr = \case
|
||||
(msg, _) <- sendGroupMessage user gInfo members $ XGrpMemDel mId
|
||||
ci <- saveSndChatItem user (CDGroupSnd gInfo) msg (CISndGroupEvent $ SGEMemberDeleted memberId (fromLocalProfile memberProfile))
|
||||
toView $ CRNewChatItem user (AChatItem SCTGroup SMDSnd (GroupChat gInfo) ci)
|
||||
deleteMemberConnection user m
|
||||
deleteMemberConnection' user m True
|
||||
-- undeleted "member connected" chat item will prevent deletion of member record
|
||||
deleteOrUpdateMemberRecord user m
|
||||
pure $ CRUserDeletedMember user gInfo m {memberStatus = GSMemRemoved}
|
||||
@@ -1711,7 +1712,7 @@ processChatCommand' vr = \case
|
||||
-- TODO delete direct connections that were unused
|
||||
deleteGroupLinkIfExists user gInfo
|
||||
-- member records are not deleted to keep history
|
||||
deleteMembersConnections user members
|
||||
deleteMembersConnections' user members True
|
||||
withStore' $ \db -> updateGroupMemberStatus db userId membership GSMemLeft
|
||||
pure $ CRLeftMemberUser user gInfo {membership = membership {memberStatus = GSMemLeft}}
|
||||
APIListMembers groupId -> withUser $ \user ->
|
||||
@@ -5865,17 +5866,23 @@ closeFileHandle fileId files = do
|
||||
liftIO $ mapM_ hClose h_ `catchAll_` pure ()
|
||||
|
||||
deleteMembersConnections :: ChatMonad m => User -> [GroupMember] -> m ()
|
||||
deleteMembersConnections user members = do
|
||||
deleteMembersConnections user members = deleteMembersConnections' user members False
|
||||
|
||||
deleteMembersConnections' :: ChatMonad m => User -> [GroupMember] -> Bool -> m ()
|
||||
deleteMembersConnections' user members waitDelivery = do
|
||||
let memberConns =
|
||||
filter (\Connection {connStatus} -> connStatus /= ConnDeleted) $
|
||||
mapMaybe (\GroupMember {activeConn} -> activeConn) members
|
||||
deleteAgentConnectionsAsync user $ map aConnId memberConns
|
||||
deleteAgentConnectionsAsync' user (map aConnId memberConns) waitDelivery
|
||||
void . withStoreBatch' $ \db -> map (\conn -> updateConnectionStatus db conn ConnDeleted) memberConns
|
||||
|
||||
deleteMemberConnection :: ChatMonad m => User -> GroupMember -> m ()
|
||||
deleteMemberConnection user GroupMember {activeConn} = do
|
||||
deleteMemberConnection user mem = deleteMemberConnection' user mem False
|
||||
|
||||
deleteMemberConnection' :: ChatMonad m => User -> GroupMember -> Bool -> m ()
|
||||
deleteMemberConnection' user GroupMember {activeConn} waitDelivery = do
|
||||
forM_ activeConn $ \conn -> do
|
||||
deleteAgentConnectionAsync user $ aConnId conn
|
||||
deleteAgentConnectionAsync' user (aConnId conn) waitDelivery
|
||||
withStore' $ \db -> updateConnectionStatus db conn ConnDeleted
|
||||
|
||||
deleteOrUpdateMemberRecord :: ChatMonad m => User -> GroupMember -> m ()
|
||||
@@ -6248,13 +6255,19 @@ agentAcceptContactAsync user enableNtfs invId msg subMode = do
|
||||
pure (cmdId, connId)
|
||||
|
||||
deleteAgentConnectionAsync :: ChatMonad m => User -> ConnId -> m ()
|
||||
deleteAgentConnectionAsync user acId =
|
||||
withAgent (`deleteConnectionAsync` acId) `catchChatError` (toView . CRChatError (Just user))
|
||||
deleteAgentConnectionAsync user acId = deleteAgentConnectionAsync' user acId False
|
||||
|
||||
deleteAgentConnectionAsync' :: ChatMonad m => User -> ConnId -> Bool -> m ()
|
||||
deleteAgentConnectionAsync' user acId waitDelivery = do
|
||||
withAgent (\a -> deleteConnectionAsync a waitDelivery acId) `catchChatError` (toView . CRChatError (Just user))
|
||||
|
||||
deleteAgentConnectionsAsync :: ChatMonad m => User -> [ConnId] -> m ()
|
||||
deleteAgentConnectionsAsync _ [] = pure ()
|
||||
deleteAgentConnectionsAsync user acIds =
|
||||
withAgent (`deleteConnectionsAsync` acIds) `catchChatError` (toView . CRChatError (Just user))
|
||||
deleteAgentConnectionsAsync user acIds = deleteAgentConnectionsAsync' user acIds False
|
||||
|
||||
deleteAgentConnectionsAsync' :: ChatMonad m => User -> [ConnId] -> Bool -> m ()
|
||||
deleteAgentConnectionsAsync' _ [] _ = pure ()
|
||||
deleteAgentConnectionsAsync' user acIds waitDelivery = do
|
||||
withAgent (\a -> deleteConnectionsAsync a waitDelivery acIds) `catchChatError` (toView . CRChatError (Just user))
|
||||
|
||||
agentXFTPDeleteRcvFile :: ChatMonad m => RcvFileId -> FileTransferId -> m ()
|
||||
agentXFTPDeleteRcvFile aFileId fileId = do
|
||||
|
||||
Reference in New Issue
Block a user