diff --git a/ts/session/conversations/ConversationController.ts b/ts/session/conversations/ConversationController.ts index 9f7edb5c4..748931f43 100644 --- a/ts/session/conversations/ConversationController.ts +++ b/ts/session/conversations/ConversationController.ts @@ -274,8 +274,9 @@ class ConvoController { `deleteGroup: ${ed25519Str(groupPk)}, sendLeaveMessage:${sendLeaveMessage}, fromSyncMessage:${fromSyncMessage}, deletionType:${deletionType}, deleteAllMessagesOnSwarm:${deleteAllMessagesOnSwarm}, forceDestroyForAllMembers:${forceDestroyForAllMembers}, clearFetchedHashes:${clearFetchedHashes}` ); - // this deletes all messages in the conversation - const conversation = await this.deleteConvoInitialChecks(groupPk, 'Group', false); + // Keep the messages until we have effectively left the group (and managed to send our leave message)m + // because we have the "Leaving..." state (left pane) linked to the last message in conversation. + const conversation = await this.deleteConvoInitialChecks(groupPk, 'Group', true); if (!conversation || !conversation.isClosedGroup()) { return; } @@ -292,7 +293,10 @@ class ConvoController { // this is caught and is adding an interaction notification message throw new Error('Failed to send our leaving message to 03 group'); } + // now that we know we've sent the leave message, delete any remaining messages + await this.deleteConvoInitialChecks(groupPk, 'Group', false); } + // a group 03 can be removed fully or kept empty as kicked. // when it was pendingInvite, we delete it fully, // when it was not, we empty the group but keep it with the "you have been kicked" message @@ -356,6 +360,8 @@ class ConvoController { deleteAllMessagesSubRequest, extraStoreRequests: [], }); + await LibSessionUtil.saveDumpsToDb(groupPk); + if (lastPushResult !== RunJobResult.Success) { throw new Error(`Failed to destroyGroupDetails for pk ${ed25519Str(groupPk)}`); } @@ -363,7 +369,10 @@ class ConvoController { } catch (e) { // if that group was already freed this will happen. // we still want to delete it entirely though - window.log.warn(`deleteGroup: MetaGroupWrapperActions failed with: ${e.message}`); + window.log.warn( + `deleteGroup: MetaGroupWrapperActions failed with: ${e.message}... Keeping it as this should be a retryable error` + ); + throw e; } // this deletes the secretKey if we had it. If we need it for something, it has to be done before this call. diff --git a/ts/session/utils/job_runners/jobs/GroupInviteJob.ts b/ts/session/utils/job_runners/jobs/GroupInviteJob.ts index f52550afd..83f8949bd 100644 --- a/ts/session/utils/job_runners/jobs/GroupInviteJob.ts +++ b/ts/session/utils/job_runners/jobs/GroupInviteJob.ts @@ -202,6 +202,8 @@ class GroupInviteJob extends PersistedJob { extraStoreRequests: [], }); if (sequenceResult !== RunJobResult.Success) { + await LibSessionUtil.saveDumpsToDb(groupPk); + throw new Error( 'GroupInviteJob: SubaccountUnrevokeSubRequest push() did not return success' ); diff --git a/ts/state/ducks/metaGroups.ts b/ts/state/ducks/metaGroups.ts index c4e0f5e34..e35b9c70e 100644 --- a/ts/state/ducks/metaGroups.ts +++ b/ts/state/ducks/metaGroups.ts @@ -660,17 +660,26 @@ async function handleMemberAddedFromUI({ group ); - // push new members & key supplement in a single batch call - const sequenceResult = await GroupSync.pushChangesToGroupSwarmIfNeeded({ - groupPk, - supplementalKeysSubRequest, - revokeSubRequest, - unrevokeSubRequest, - extraStoreRequests, - }); - if (sequenceResult !== RunJobResult.Success) { - throw new Error( - 'handleMemberAddedFromUIOrNot: pushChangesToGroupSwarmIfNeeded did not return success' + try { + // push new members & key supplement in a single batch call + const sequenceResult = await GroupSync.pushChangesToGroupSwarmIfNeeded({ + groupPk, + supplementalKeysSubRequest, + revokeSubRequest, + unrevokeSubRequest, + extraStoreRequests, + }); + if (sequenceResult !== RunJobResult.Success) { + await LibSessionUtil.saveDumpsToDb(groupPk); + + throw new Error( + 'handleMemberAddedFromUIOrNot: pushChangesToGroupSwarmIfNeeded did not return success' + ); + } + } catch (e) { + window.log.warn( + 'handleNameChangeFromUIOrNot: pushChangesToGroupSwarmIfNeeded failed with:', + e.message ); } @@ -779,15 +788,21 @@ async function handleMemberRemovedFromUI({ [removedControlMessage], group ); - - // Send the updated config (with changes to pending_removal) and that GroupUpdateMessage request (if any) as a sequence. - const sequenceResult = await GroupSync.pushChangesToGroupSwarmIfNeeded({ - groupPk, - extraStoreRequests, - }); - if (sequenceResult !== RunJobResult.Success) { - throw new Error( - 'currentDeviceGroupMembersChange: pushChangesToGroupSwarmIfNeeded did not return success' + try { + // Send the updated config (with changes to pending_removal) and that GroupUpdateMessage request (if any) as a sequence. + const sequenceResult = await GroupSync.pushChangesToGroupSwarmIfNeeded({ + groupPk, + extraStoreRequests, + }); + if (sequenceResult !== RunJobResult.Success) { + throw new Error( + 'currentDeviceGroupMembersChange: pushChangesToGroupSwarmIfNeeded did not return success' + ); + } + } catch (e) { + window.log.warn( + 'currentDeviceGroupMembersChange: pushChangesToGroupSwarmIfNeeded failed with:', + e.message ); } @@ -859,14 +874,23 @@ async function handleNameChangeFromUI({ group ); - const batchResult = await GroupSync.pushChangesToGroupSwarmIfNeeded({ - groupPk, - extraStoreRequests, - }); + try { + const batchResult = await GroupSync.pushChangesToGroupSwarmIfNeeded({ + groupPk, + extraStoreRequests, + }); - if (batchResult !== RunJobResult.Success) { - throw new Error( - 'handleNameChangeFromUIOrNot: pushChangesToGroupSwarmIfNeeded did not return success' + if (batchResult !== RunJobResult.Success) { + await LibSessionUtil.saveDumpsToDb(groupPk); + + throw new Error( + 'handleNameChangeFromUIOrNot: pushChangesToGroupSwarmIfNeeded did not return success' + ); + } + } catch (e) { + window.log.warn( + 'handleNameChangeFromUIOrNot: pushChangesToGroupSwarmIfNeeded failed with:', + e.message ); } @@ -975,14 +999,20 @@ const triggerFakeAvatarUpdate = createAsyncThunk( [updateMsg], group ); - - const batchResult = await GroupSync.pushChangesToGroupSwarmIfNeeded({ - groupPk, - extraStoreRequests, - }); - if (!batchResult) { - window.log.warn(`failed to send avatarChange message for group ${ed25519Str(groupPk)}`); - throw new Error('failed to send avatarChange message'); + try { + const batchResult = await GroupSync.pushChangesToGroupSwarmIfNeeded({ + groupPk, + extraStoreRequests, + }); + if (!batchResult) { + window.log.warn(`failed to send avatarChange message for group ${ed25519Str(groupPk)}`); + throw new Error('failed to send avatarChange message'); + } + } catch (e) { + window.log.warn( + 'currentDeviceGroupMembersChange: pushChangesToGroupSwarmIfNeeded failed with:', + e.message + ); } } ); @@ -1024,16 +1054,22 @@ const triggerFakeDeleteMsgBeforeNow = createAsyncThunk( await MetaGroupWrapperActions.infoSet(groupPk, infoGet); const extraStoreRequests = await StoreGroupRequestFactory.makeGroupMessageSubRequest([], group); - - const batchResult = await GroupSync.pushChangesToGroupSwarmIfNeeded({ - groupPk, - extraStoreRequests, - }); - if (!batchResult) { + try { + const batchResult = await GroupSync.pushChangesToGroupSwarmIfNeeded({ + groupPk, + extraStoreRequests, + }); + if (!batchResult) { + window.log.warn( + `failed to send deleteBeforeSeconds/deleteAttachBeforeSeconds message for group ${ed25519Str(groupPk)}` + ); + throw new Error('failed to send deleteBeforeSeconds/deleteAttachBeforeSeconds message'); + } + } catch (e) { window.log.warn( - `failed to send deleteBeforeSeconds/deleteAttachBeforeSeconds message for group ${ed25519Str(groupPk)}` + 'currentDeviceGroupMembersChange: pushChangesToGroupSwarmIfNeeded failed with:', + e.message ); - throw new Error('failed to send deleteBeforeSeconds/deleteAttachBeforeSeconds message'); } } );