core: split group deletion into two transactions to prevent crashes on android (#865)

This commit is contained in:
JRoberts
2022-08-02 14:10:03 +04:00
committed by GitHub
parent 0b4a6cf9eb
commit 35eeac194e
2 changed files with 17 additions and 4 deletions

View File

@@ -446,6 +446,9 @@ processChatCommand = \case
withChatLock . procCmd $ do
when (memberActive membership) . void $ sendGroupMessage gInfo members XGrpDel
mapM_ deleteMemberConnection members
-- two functions below are called in separate transactions to prevent crashes on android
-- (possibly, race condition on integrity check?)
withStore' $ \db -> deleteGroupConnectionsAndFiles db userId g
withStore' $ \db -> deleteGroup db user g
pure $ CRGroupDeletedUser gInfo
CTContactRequest -> pure $ chatCmdError "not supported"

View File

@@ -70,6 +70,7 @@ module Simplex.Chat.Store
getGroupInfoByName,
getGroupMember,
getGroupMembers,
deleteGroupConnectionsAndFiles,
deleteGroup,
getUserGroups,
getUserGroupDetails,
@@ -1340,10 +1341,21 @@ getGroup db user groupId = do
members <- liftIO $ getGroupMembers db user gInfo
pure $ Group gInfo members
deleteGroup :: DB.Connection -> User -> Group -> IO ()
deleteGroup db User {userId} (Group GroupInfo {groupId, localDisplayName} members) = do
deleteGroupConnectionsAndFiles :: DB.Connection -> UserId -> Group -> IO ()
deleteGroupConnectionsAndFiles db userId (Group GroupInfo {groupId} members) = do
forM_ members $ \m -> DB.execute db "DELETE FROM connections WHERE user_id = ? AND group_member_id = ?" (userId, groupMemberId' m)
DB.execute db "DELETE FROM files WHERE user_id = ? AND group_id = ?" (userId, groupId)
deleteGroup :: DB.Connection -> User -> Group -> IO ()
deleteGroup db User {userId} (Group GroupInfo {groupId, localDisplayName} _) = do
DB.execute db "DELETE FROM chat_items WHERE user_id = ? AND group_id = ?" (userId, groupId)
DB.execute db "DELETE FROM group_members WHERE user_id = ? AND group_id = ?" (userId, groupId)
deleteGroupProfile_ db userId groupId
DB.execute db "DELETE FROM groups WHERE user_id = ? AND group_id = ?" (userId, groupId)
DB.execute db "DELETE FROM display_names WHERE user_id = ? AND local_display_name = ?" (userId, localDisplayName)
deleteGroupProfile_ :: DB.Connection -> UserId -> GroupId -> IO ()
deleteGroupProfile_ db userId groupId =
DB.execute
db
[sql|
@@ -1355,8 +1367,6 @@ deleteGroup db User {userId} (Group GroupInfo {groupId, localDisplayName} member
)
|]
(userId, groupId)
DB.execute db "DELETE FROM groups WHERE user_id = ? AND group_id = ?" (userId, groupId)
DB.execute db "DELETE FROM display_names WHERE user_id = ? AND local_display_name = ?" (userId, localDisplayName)
getUserGroups :: DB.Connection -> User -> IO [Group]
getUserGroups db user@User {userId} = do