core: RSAcknowledgedRoster relay status (#7078)

This commit is contained in:
spaced4ndy
2026-06-16 11:33:59 +00:00
committed by GitHub
parent 7fad11d89f
commit 07c566f6d7
10 changed files with 39 additions and 17 deletions
+2
View File
@@ -2734,6 +2734,7 @@ public enum RelayStatus: String, Decodable, Equatable, Hashable {
case new
case invited
case accepted
case acknowledgedRoster
case active
case inactive
case rejected
@@ -2809,6 +2810,7 @@ extension RelayStatus {
case .new: "new"
case .invited: "invited"
case .accepted: "accepted"
case .acknowledgedRoster: "acknowledged roster"
case .active: "active"
case .inactive: "inactive"
case .rejected: "rejected"
@@ -2415,6 +2415,7 @@ enum class RelayStatus {
@SerialName("new") New,
@SerialName("invited") Invited,
@SerialName("accepted") Accepted,
@SerialName("acknowledgedRoster") AcknowledgedRoster,
@SerialName("active") Active,
@SerialName("inactive") Inactive,
@SerialName("rejected") Rejected;
@@ -2423,6 +2424,7 @@ enum class RelayStatus {
New -> generalGetString(MR.strings.relay_status_new)
Invited -> generalGetString(MR.strings.relay_status_invited)
Accepted -> generalGetString(MR.strings.relay_status_accepted)
AcknowledgedRoster -> generalGetString(MR.strings.relay_status_acknowledged_roster)
Active -> generalGetString(MR.strings.relay_status_active)
Inactive -> generalGetString(MR.strings.relay_status_inactive)
Rejected -> generalGetString(MR.strings.relay_status_rejected)
@@ -3008,6 +3008,7 @@
<string name="relay_status_new">new</string>
<string name="relay_status_invited">invited</string>
<string name="relay_status_accepted">accepted</string>
<string name="relay_status_acknowledged_roster">acknowledged roster</string>
<string name="relay_status_active">active</string>
<string name="relay_status_inactive">inactive</string>
<string name="relay_status_rejected">rejected</string>
+1
View File
@@ -3453,6 +3453,7 @@ ParseError:
- "new"
- "invited"
- "accepted"
- "acknowledgedRoster"
- "active"
- "inactive"
- "rejected"
@@ -3813,6 +3813,7 @@ export enum RelayStatus {
New = "new",
Invited = "invited",
Accepted = "accepted",
AcknowledgedRoster = "acknowledgedRoster",
Active = "active",
Inactive = "inactive",
Rejected = "rejected",
@@ -2671,7 +2671,7 @@ class RelayProfile(TypedDict):
shortDescr: NotRequired[str]
image: NotRequired[str]
RelayStatus = Literal["new", "invited", "accepted", "active", "inactive", "rejected"]
RelayStatus = Literal["new", "invited", "accepted", "acknowledgedRoster", "active", "inactive", "rejected"]
ReportReason = Literal["spam", "content", "community", "profile", "other"]
+1 -1
View File
@@ -4914,7 +4914,7 @@ runRelayGroupLinkChecks user = do
then do
-- TODO [relays] emit event to UI when relay own status promoted to RSActive
-- CEvtGroupRelayUpdated requires GroupRelay (owner-side), not available on relay side
void $ withStore' $ \db -> updateRelayOwnStatusFromTo db gInfo RSAccepted RSActive
void $ withStore' $ \db -> updateRelayOwnStatus_ db gInfo RSActive
else void $ withStore' $ \db -> updateRelayOwnStatusFromTo db gInfo RSActive RSInactive
_ -> pure ()
_ -> pure ()
+12 -9
View File
@@ -1227,12 +1227,13 @@ processAgentMessageConn cxt user@User {userId} corrId agentConnId agentMessage =
relayProfile <- liftIO (decodeLinkUserData cData) >>= \case
Just RelayShortLinkData {relayProfile = p} -> pure p
Nothing -> throwChatError $ CEException "relay link: no relay link data"
confId <- withStore $ \db -> do
(confId, m', relay) <- withStore $ \db -> do
confId <- getRelayConfId db m
liftIO $ updateGroupMemberStatus db userId m GSMemAccepted
void $ setRelayKey db cxt user m (MemberKey relayKey) relayProfile
pure confId
(m', relay) <- setRelayLinkAccepted db cxt user m (MemberKey relayKey) relayProfile
pure (confId, m', relay)
allowAgentConnectionAsync user conn confId XOk
toView $ CEvtGroupRelayUpdated user gInfo m' relay
else
-- TODO [relays] owner: TBC failed RelayStatus?
messageError "relay link: relay member ID mismatch"
@@ -1399,7 +1400,7 @@ processAgentMessageConn cxt user@User {userId} corrId agentConnId agentMessage =
updateRelay db relay@GroupRelay {groupMemberId, relayLink, relayStatus} (acc, changed, newlyActiveLinks, newlyActiveGMIds) =
case relayLink of
Just rLink
| rLink `elem` relayLinks && relayStatus == RSAccepted -> do
| rLink `elem` relayLinks && relayStatus == RSAcknowledgedRoster -> do
relay' <- updateRelayStatus db relay RSActive
pure (relay' : acc, True, rLink : newlyActiveLinks, groupMemberId : newlyActiveGMIds)
| rLink `elem` relayLinks -> pure (relay : acc, changed, newlyActiveLinks, newlyActiveGMIds)
@@ -3339,8 +3340,10 @@ processAgentMessageConn cxt user@User {userId} corrId agentConnId agentMessage =
cleanupGroupRosterFile user gInfo
forM_ results_ $ \results -> do
emitRosterResults gInfo author rosterBrokerTs results
-- ack only while still setting up (own status RSAccepted); a serving relay must not ack broadcasts.
when (isRelay && relayOwnStatus gInfo == Just RSAccepted) $ sendRosterAck gInfo author pendingVer Nothing
-- ack while setting up (own status accepted/acknowledged); a serving (active) relay must not ack broadcasts.
when (isRelay && relayOwnStatus gInfo == Just RSAccepted || relayOwnStatus gInfo == Just RSAcknowledgedRoster) $ do
sendRosterAck gInfo author pendingVer Nothing
withStore' $ \db -> void $ updateRelayOwnStatusFromTo db gInfo RSAccepted RSAcknowledgedRoster
where
readAssembledRoster = case fileStatus of
RFSAccepted fp -> readAt fp
@@ -3405,18 +3408,18 @@ processAgentMessageConn cxt user@User {userId} corrId agentConnId agentMessage =
xGrpRosterAck gInfo m ackVer err = do
relay_ <- withStore' $ \db -> eitherToMaybe <$> runExceptT (getGroupRelayByGMId db (groupMemberId' m))
case relay_ of
Just relay@GroupRelay {relayStatus = RSInvited} -> case err of
Just relay@GroupRelay {relayStatus = RSAccepted} -> case err of
Nothing
| rosterVersion gInfo == Just ackVer -> do
(relay', gLink) <- withStore $ \db -> do
relay' <- liftIO $ updateRelayStatus db relay RSAccepted
relay' <- liftIO $ updateRelayStatus db relay RSAcknowledgedRoster
gLink <- getGroupLink db user gInfo
pure (relay', gLink)
setGroupLinkDataAsync user gInfo gLink
toView $ CEvtGroupRelayUpdated user gInfo m relay'
| otherwise -> messageWarning "x.grp.roster.ack: stale version, awaiting ack for the current roster"
Just e -> do
relay' <- withStore' $ \db -> updateRelayStatusFromTo db relay RSInvited RSRejected
relay' <- withStore' $ \db -> updateRelayStatusFromTo db relay RSAccepted RSRejected
toView $ CEvtGroupRelayUpdated user gInfo m relay'
messageError $ "x.grp.roster.ack: relay could not save roster, marked rejected: " <> e
_ -> pure ()
+14 -6
View File
@@ -101,7 +101,7 @@ module Simplex.Chat.Store.Groups
createRelayConnection,
updateRelayStatus,
updateRelayStatusFromTo,
setRelayKey,
setRelayLinkAccepted,
setRelayLinkConfId,
updateRelayCapabilities,
getRelayConfId,
@@ -1433,7 +1433,7 @@ getConnectedGroupRelays db GroupInfo {groupId} =
AND gr.relay_status IN (?,?)
|]
)
(groupId, GSMemConnected, RSAccepted, RSActive)
(groupId, GSMemConnected, RSAcknowledgedRoster, RSActive)
groupRelayQuery :: Query
groupRelayQuery =
@@ -1665,10 +1665,18 @@ updateRelayStatus_ db relayId relayStatus = do
currentTs <- getCurrentTime
DB.execute db "UPDATE group_relays SET relay_status = ?, updated_at = ? WHERE group_relay_id = ?" (relayStatus, currentTs, relayId)
setRelayKey :: DB.Connection -> StoreCxt -> User -> GroupMember -> MemberKey -> Profile -> ExceptT StoreError IO (GroupMember, GroupRelay)
setRelayKey db cxt user m (MemberKey relayKey) profile = do
setRelayLinkAccepted :: DB.Connection -> StoreCxt -> User -> GroupMember -> MemberKey -> Profile -> ExceptT StoreError IO (GroupMember, GroupRelay)
setRelayLinkAccepted db cxt user m (MemberKey relayKey) profile = do
let gmId = groupMemberId' m
currentTs <- liftIO getCurrentTime
liftIO $ DB.execute
db
[sql|
UPDATE group_relays
SET relay_status = ?, updated_at = ?
WHERE group_member_id = ?
|]
(RSAccepted, currentTs, gmId)
liftIO $ DB.execute
db
[sql|
@@ -1861,9 +1869,9 @@ getRelayServedGroups db cxt User {userId, userContactId} = do
<$> DB.query
db
( groupInfoQuery
<> " WHERE g.user_id = ? AND mu.contact_id = ? AND g.relay_own_status IN (?, ?)"
<> " WHERE g.user_id = ? AND mu.contact_id = ? AND g.relay_own_status IN (?, ?, ?)"
)
(userId, userContactId, RSAccepted, RSActive)
(userId, userContactId, RSAccepted, RSAcknowledgedRoster, RSActive)
getRelayInactiveGroups :: DB.Connection -> StoreCxt -> User -> NominalDiffTime -> IO [GroupInfo]
getRelayInactiveGroups db cxt User {userId, userContactId} ttl = do
+4
View File
@@ -89,6 +89,7 @@ data RelayStatus
= RSNew -- only for owner
| RSInvited
| RSAccepted
| RSAcknowledgedRoster
| RSActive
| RSInactive
| RSRejected
@@ -99,6 +100,7 @@ relayStatusText = \case
RSNew -> "new"
RSInvited -> "invited"
RSAccepted -> "accepted"
RSAcknowledgedRoster -> "acknowledged_roster"
RSActive -> "active"
RSInactive -> "inactive"
RSRejected -> "rejected"
@@ -108,6 +110,7 @@ instance TextEncoding RelayStatus where
RSNew -> "new"
RSInvited -> "invited"
RSAccepted -> "accepted"
RSAcknowledgedRoster -> "acknowledged_roster"
RSActive -> "active"
RSInactive -> "inactive"
RSRejected -> "rejected"
@@ -115,6 +118,7 @@ instance TextEncoding RelayStatus where
"new" -> Just RSNew
"invited" -> Just RSInvited
"accepted" -> Just RSAccepted
"acknowledged_roster" -> Just RSAcknowledgedRoster
"active" -> Just RSActive
"inactive" -> Just RSInactive
"rejected" -> Just RSRejected