From 35eeac194e00bc609cae5b1c8afa2e061608b700 Mon Sep 17 00:00:00 2001 From: JRoberts <8711996+jr-simplex@users.noreply.github.com> Date: Tue, 2 Aug 2022 14:10:03 +0400 Subject: [PATCH] core: split group deletion into two transactions to prevent crashes on android (#865) --- src/Simplex/Chat.hs | 3 +++ src/Simplex/Chat/Store.hs | 18 ++++++++++++++---- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/Simplex/Chat.hs b/src/Simplex/Chat.hs index 4524760bbc..eef3c38b3a 100644 --- a/src/Simplex/Chat.hs +++ b/src/Simplex/Chat.hs @@ -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" diff --git a/src/Simplex/Chat/Store.hs b/src/Simplex/Chat/Store.hs index 31cf52c72b..21b43fd351 100644 --- a/src/Simplex/Chat/Store.hs +++ b/src/Simplex/Chat/Store.hs @@ -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