mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-09-01 17:58:37 +00:00
core: re-use link owner members when connecting to a group again
Connecting to a prepared group creates the link owner members from the link data inside withFastStore, before the relay loop, and throws when every relay connection fails. That error is an agent BROKER error, which the clients treat as retryable: they offer Retry and re-send the same command, which inserted the same owner members a second time - UNIQUE constraint failed: group_members.group_id, group_members.member_id so joining a channel over a flaky network and retrying failed on a raw SQLite error. Owner member creation was the only step in the command that was not already idempotent: connectToRelay re-uses the relay member record via getCreateRelayForMember, and a join that failed leaves the connection at ConnPrepared for joinPreparedConn' to resume, because joinContact advances the status only after the agent call returns.
This commit is contained in:
@@ -2272,7 +2272,7 @@ processChatCommand cxt nm = \case
|
||||
Just GroupOwnerContact {contactId, memberId}
|
||||
| memberId == MemberId ownerId -> Just contactId
|
||||
_ -> Nothing
|
||||
void $ createLinkOwnerMember db cxt user gInfo' ctId_ (MemberId ownerId) ownerKey
|
||||
void $ getCreateLinkOwnerMember db cxt user gInfo' ctId_ (MemberId ownerId) ownerKey
|
||||
pure gInfo'
|
||||
rs <- withGroupLock "connectPreparedGroup" groupId $
|
||||
mapConcurrently (connectToRelay user gInfo') relays
|
||||
|
||||
@@ -193,7 +193,7 @@ module Simplex.Chat.Store.Groups
|
||||
getXGrpLinkMemReceived,
|
||||
setXGrpLinkMemReceived,
|
||||
createNewUnknownGroupMember,
|
||||
createLinkOwnerMember,
|
||||
getCreateLinkOwnerMember,
|
||||
updatePreparedChannelMember,
|
||||
updateUnknownMemberAnnounced,
|
||||
updateRosterMemberAnnounced,
|
||||
@@ -3505,6 +3505,15 @@ createNewUnknownGroupMember db cxt user@User {userId, userContactId} GroupInfo {
|
||||
where
|
||||
VersionRange minV maxV = vr cxt
|
||||
|
||||
-- Re-use owner member record on retry: owners are created before the relay loop,
|
||||
-- which is what fails when the network does (see getCreateRelayForMember)
|
||||
getCreateLinkOwnerMember :: DB.Connection -> StoreCxt -> User -> GroupInfo -> Maybe ContactId -> MemberId -> C.PublicKeyEd25519 -> ExceptT StoreError IO GroupMember
|
||||
getCreateLinkOwnerMember db cxt user gInfo contactId_ memberId ownerKey =
|
||||
liftIO (runExceptT $ getGroupMemberByMemberId db cxt user gInfo memberId) >>= \case
|
||||
Right m -> pure m
|
||||
Left (SEGroupMemberNotFoundByMemberId _) -> createLinkOwnerMember db cxt user gInfo contactId_ memberId ownerKey
|
||||
Left e -> throwError e
|
||||
|
||||
createLinkOwnerMember :: DB.Connection -> StoreCxt -> User -> GroupInfo -> Maybe ContactId -> MemberId -> C.PublicKeyEd25519 -> ExceptT StoreError IO GroupMember
|
||||
createLinkOwnerMember db cxt user@User {userId, userContactId} GroupInfo {groupId} contactId_ memberId ownerKey = do
|
||||
currentTs <- liftIO getCurrentTime
|
||||
|
||||
Reference in New Issue
Block a user