-
-
Notifications
You must be signed in to change notification settings - Fork 81
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: new group membership update algorithm #4185
Conversation
is this still implementing #3782 ? -- please try to add a bit more context to PRs. Was expecting to read a description of the new algorithm that is in the PR title somewhere .... :) |
d23186d
to
3a75706
Compare
src/receive_imf.rs
Outdated
true | ||
} else { | ||
match mime_parser.get_header(HeaderDef::InReplyTo) { | ||
// If we don't know the referenced message, we missed some messages which could be add/delete |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And also we can miss messages about an addition of ourselves. So, this code should have a preference over "self" checks done above. And also a comment would be good on why these "self" checks are needed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When self is added, the recreate_membership_list flag is set and apply_groupchanges aswell. This will lead to a new better_msg in the header-handling code, so a stockstring should be created.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But what if we did't receive a ChatGroupMemberAdded message about "self"? Afaiu, this PR is fixing problems when messages can be missed because of delivery problems. I don't get why "self" is a special case in ragards to handling of InReplyTo
which references a missed message
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I moved it outwards where it belongs
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Anyway, consider the following scenario:
- We left the group
- Then we were re-added, but missed the addition message
- We receive a message with InReplyTo referencing a message we don't have (the message adding us to the group). But above there's the check:
if !chat::is_contact_in_chat(context, chat_id, ContactId::SELF).await? && !self_added {
So, we're not in the group and don't handle this scenario. Is it correct? Why is it special for SELF?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that current problems with unintentional re-additions come from the current approach that u described:
* If the message has a Chat-Group-Member-Removed header, then we completely recreate the group member list (i.e. use the member list of the incoming message). * If the message has a Chat-Group-Member-Added, then we recreate the group member list, but don't remove anyone (i.e. add recipients of the incoming messages as members).
It's not difficult to see how each of the both arms above can lead to an unintentional re-addition.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Hocuri, i still don't get why we can't just use the algo you suggested initially in #3782 (comment). For me it looks more simple and straightforward. Also it was discussed in the "DC Core Rust" chat, just search for "InReplyTo" (starting from Apr 17)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIRC at some point, there were lots of complaints that people couldn't leave a group because they were constantly re-added.
The problem was that some users in a large group kept reinstalling DC and restored an old backup with old member list. Then they immediately left some groups, sending a Chat-Group-Member-Removed header, which caused recreation of the member list and readdition of self to the group for you and other members. Other members also tried to leave the group, sending lots of "... left the group" messages to some broken group. It was difficult to teach everyone not to leave the group, but to delete it or block it and forget about it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reading the thread here, tbh, I don't remember anymore what the problems discussed here were. But I think it's fine, IIRC we discussed pretty minor edge cases, time will tell if there are problems we should fix (and whether the new algo is an improvement at all). @iequidoo I hope you don't feel like we missed your concerns?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The problem is that the current algo is not resillent to missed messages about addition of SELF. If it happens, the only way to fix the group is to remove the member and re-add them again. The algo you suggested in #3782 (comment) fixes this inconsistency when we receive a message with orphaned InReplyTo. Also it looks simpler. And as for the problem with messages from a Delta Chat that restored an old backup, it will ignore them as well because they will reference a known message in InReplyTo.
I think it's not very important right now, but i'd prefer to try your "truly consistent" algo and if it doesn't bring new problems, why not use it?
91db9c7
to
a279f96
Compare
a7da289
to
5284f25
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I reviewed the new logic, directly pushed some changes with explanation (please have a look if they seem good), and have one (blocking) comment.
So, only the tests need to be reviewed still. Edit: The tests also look good; in many places, they could use some newer APIs from test_utils.rs
in order to be a lot shorter / more concise, but it would also be OK-ish to merge as-is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎉🎉🎉!
Before merging, let's
- wait for @link2xt to review / have a glance on it
- make sure that nobody is going to make a release right afterwards
Ty for rebasing @link2xt |
f41ffde
to
69ef783
Compare
New algorithm improves group consistency in cases of missing messages, restored old backups and replies from classic MUAs. Co-authored-by: Hocuri <hocuri@gmx.de> Co-authored-by: link2xt <link2xt@testrun.org>
69ef783
to
6eb8abe
Compare
I have added some logs, removed unnecessary |
The changes are incremental and only add tests without modifying existing tests, so I think it is ok to get this into 1.117.0 and turn 1.117 into a stable branch. |
Finally done! Thanks everybody for the great effort! |
}; | ||
|
||
if let Some(removed_addr) = mime_parser.get_header(HeaderDef::ChatGroupMemberRemoved) { | ||
removed_id = Contact::lookup_id_by_addr(context, removed_addr, Origin::Unknown).await?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This may fail to load the contact if the contact is blocked. In this case all the code below is skipped and better_msg
is not used.
Found this while looking for the reason of #4528
Replacement for #3807.
This PR implements the idea sketched in #3782 by acting along these guidlines:
self
is no in chat, reject the membership update.By always discarding outdated membership messages there might occur situations in which two people simultaneously change members and the updates come in out of order, leading to the discard of one of the messages. It is to note though, that this is only a problem when there was no synchronisation between the two senders because otherwise the membership-list will be rebuild because of 4.
This problem also occures in the current master' implementation because it usese the same logic as 2 and is hard to mitigate because there is no obvious way to decide whether to accept an old update or not. There is maybe a way by storing a timestamp per group member which would allow us to reason better about the membership of individual users instead of membership changes on a group-level, but this can be part of future work.
Tests
This PR also introduces some new tests: