-
Notifications
You must be signed in to change notification settings - Fork 334
WPB-28422 reconcile stale local memberships for deleted remote conversations #5504
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
Merged
battermann
merged 6 commits into
develop
from
WPB-28422-backend-reconcile-stale-local-memberships-for-deleted-remote-conversations
Sep 10, 2026
+240
−15
Merged
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
5c9474b
reconciliation and test
battermann 9371e6d
changelog
battermann 0caac72
fix potential PR finding
battermann deba28a
send a system event on reconciliation
battermann 4fb5d44
tests added
battermann 2495887
small clean up
battermann File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| Remove stale local memberships when a remote conversation is definitively reported as not found. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -84,6 +84,7 @@ import Wire.API.Conversation.Role | |
| import Wire.API.Conversation.Role qualified as Public | ||
| import Wire.API.Error | ||
| import Wire.API.Error.Galley | ||
| import Wire.API.Event.Conversation (SystemEvent (..), SystemEventData (EdSystemConvDelete)) | ||
| import Wire.API.Federation.API | ||
| import Wire.API.Federation.API.Galley | ||
| import Wire.API.Federation.Client (FederatorClient, getNegotiatedVersion) | ||
|
|
@@ -106,12 +107,16 @@ import Wire.ConversationSubsystem.Fetch (getConversationIdsImpl) | |
| import Wire.ConversationSubsystem.MLS | ||
| import Wire.ConversationSubsystem.MLS.Enabled (assertMLSEnabled, getMLSPrivateKeys, isMLSEnabled) | ||
| import Wire.ConversationSubsystem.MLS.One2One (localMLSOne2OneConversation, remoteMLSOne2OneConversation) | ||
| import Wire.ConversationSubsystem.Notify qualified as Notify | ||
| import Wire.ConversationSubsystem.One2One | ||
| import Wire.ConversationSubsystem.Util | ||
| import Wire.FeaturesConfigSubsystem | ||
| import Wire.FederationAPIAccess qualified as E | ||
| import Wire.HashPassword (HashPassword) | ||
| import Wire.NotificationSubsystem | ||
| import Wire.RateLimit | ||
| import Wire.Sem.Now (Now) | ||
| import Wire.Sem.Now qualified as Now | ||
| import Wire.Sem.Paging.Cassandra | ||
| import Wire.StoredConversation | ||
| import Wire.StoredConversation qualified as Data | ||
|
|
@@ -184,6 +189,8 @@ getConversation :: | |
| Member (Error FederationError) r, | ||
| Member (E.FederationAPIAccess FederatorClient) r, | ||
| Member P.TinyLog r, | ||
| Member Now r, | ||
| Member NotificationSubsystem r, | ||
| Member TeamSubsystem r | ||
| ) => | ||
| Local UserId -> | ||
|
|
@@ -205,6 +212,8 @@ getOwnConversation :: | |
| Member (Error InternalError) r, | ||
| Member (E.FederationAPIAccess FederatorClient) r, | ||
| Member P.TinyLog r, | ||
| Member Now r, | ||
| Member NotificationSubsystem r, | ||
| Member TeamSubsystem r | ||
| ) => | ||
| Local UserId -> | ||
|
|
@@ -222,7 +231,9 @@ getRemoteConversation :: | |
| Member (ErrorS ConvNotFound) r, | ||
| Member (Error FederationError) r, | ||
| Member TinyLog r, | ||
| Member (E.FederationAPIAccess FederatorClient) r | ||
| Member (E.FederationAPIAccess FederatorClient) r, | ||
| Member Now r, | ||
| Member NotificationSubsystem r | ||
| ) => | ||
| Local UserId -> | ||
| Remote ConvId -> | ||
|
|
@@ -239,7 +250,9 @@ getRemoteConversations :: | |
| Member (Error FederationError) r, | ||
| Member (ErrorS 'ConvNotFound) r, | ||
| Member (E.FederationAPIAccess FederatorClient) r, | ||
| Member P.TinyLog r | ||
| Member P.TinyLog r, | ||
| Member Now r, | ||
| Member NotificationSubsystem r | ||
| ) => | ||
| Local UserId -> | ||
| [Remote ConvId] -> | ||
|
|
@@ -308,7 +321,9 @@ partitionGetConversationFailures = bimap concat concat . partitionEithers . map | |
| getRemoteConversationsWithFailures :: | ||
| ( Member ConversationStore.ConversationStore r, | ||
| Member (E.FederationAPIAccess FederatorClient) r, | ||
| Member P.TinyLog r | ||
| Member P.TinyLog r, | ||
| Member Now r, | ||
| Member NotificationSubsystem r | ||
| ) => | ||
| Local UserId -> | ||
| [Remote ConvId] -> | ||
|
|
@@ -346,18 +361,38 @@ getRemoteConversationsWithFailures lusr convs = do | |
| rpc $ GetConversationsRequest (tUnqualified lusr) (tUnqualified someConvs) | ||
| bimap (localFailures <>) (map remoteView . concat) | ||
| . partitionEithers | ||
| <$> traverse handleFailure resp | ||
| <$> traverse (handleRequest locallyFound) resp | ||
| where | ||
| handleFailure :: | ||
| (Member P.TinyLog r) => | ||
| handleRequest :: | ||
| ( Member ConversationStore.ConversationStore r, | ||
| Member P.TinyLog r, | ||
| Member Now r, | ||
| Member NotificationSubsystem r | ||
| ) => | ||
| [Remote ConvId] -> | ||
| Either (Remote [ConvId], FederationError) (Remote GetRemoteConversationViewsResponse) -> | ||
| Sem r (Either FailedGetConversation [Remote RemoteConversationView]) | ||
| handleFailure (Left (rcids, e)) = do | ||
| handleRequest _ (Left (rcids, e)) = do | ||
| P.warn $ | ||
| Logger.msg ("Error occurred while fetching remote conversations" :: ByteString) | ||
| . Logger.field "error" (displayException e) | ||
| pure . Left $ failedGetConversationRemotely (sequenceA rcids) e | ||
| handleFailure (Right c) = pure . Right . traverse (.convs) $ c | ||
| handleRequest locallyFound (Right response) = do | ||
| let locallyFoundForDomain = Set.fromList $ filter ((== tDomain response) . tDomain) locallyFound | ||
| returnedIds = Set.fromList $ map (qualifyAs response . (.id)) (tUnqualified response).convs | ||
| missingConversations = Set.toList $ locallyFoundForDomain `Set.difference` returnedIds | ||
| unless (null missingConversations) $ do | ||
| now <- Now.get | ||
| for_ missingConversations $ \conv -> do | ||
| ConversationStore.deleteMembersInRemoteConversation conv [tUnqualified lusr] | ||
| Notify.pushSystemEvent | ||
| Nothing | ||
| (SystemEvent (tUntagged conv) Nothing now Nothing EdSystemConvDelete) | ||
| (Set.singleton $ tUnqualified lusr) | ||
| P.info $ | ||
| Logger.msg ("Removed stale local memberships for remote conversations" :: ByteString) | ||
| . Logger.field "convIds" (show $ map tUntagged missingConversations) | ||
| pure . Right . traverse (.convs) $ response | ||
|
|
||
| getConversationRoles :: | ||
| ( Member ConversationStore.ConversationStore r, | ||
|
|
@@ -505,7 +540,9 @@ listConversations :: | |
| ( Member ConversationStore.ConversationStore r, | ||
| Member (Error InternalError) r, | ||
| Member (E.FederationAPIAccess FederatorClient) r, | ||
| Member P.TinyLog r | ||
| Member P.TinyLog r, | ||
| Member Now r, | ||
| Member NotificationSubsystem r | ||
| ) => | ||
| Local UserId -> | ||
| Public.ListConversations -> | ||
|
|
@@ -529,9 +566,6 @@ listConversations luser (Public.ListConversations ids) = do | |
| fetchedOrFailedRemoteIds = Set.fromList $ map Public.cnvQualifiedId remoteConversations <> failedConvs | ||
| remoteNotFoundRemoteIds = filter (`Set.notMember` fetchedOrFailedRemoteIds) $ map tUntagged remoteIds | ||
| unless (null remoteNotFoundRemoteIds) $ | ||
| -- FUTUREWORK: This implies that the backends are out of sync. Maybe the | ||
| -- current user should be considered removed from this conversation at this | ||
| -- point. | ||
| P.warn $ | ||
| Logger.msg ("Some locally found conversation ids were not returned by remotes" :: ByteString) | ||
| . Logger.field "convIds" (show remoteNotFoundRemoteIds) | ||
|
Comment on lines
568
to
571
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we need any of this again here?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is calling the code above. |
||
|
|
@@ -591,7 +625,9 @@ getSelfMember :: | |
| Member (ErrorS ConvNotFound) r, | ||
| Member (Error FederationError) r, | ||
| Member TinyLog r, | ||
| Member (E.FederationAPIAccess FederatorClient) r | ||
| Member (E.FederationAPIAccess FederatorClient) r, | ||
| Member Now r, | ||
| Member NotificationSubsystem r | ||
| ) => | ||
| Local UserId -> | ||
| Qualified ConvId -> | ||
|
|
||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
Looks too complicated to unqualified and then qualify, doesn't
Remote ahave a functor?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.
yeah, the problem is, we need a
Set (Remote ConvId)and notRemote (Set ConvId), and I think there is no built in generic operation that does this.