core, ui: group members permanent connection errors (#6662)

This commit is contained in:
spaced4ndy
2026-03-06 15:24:55 +00:00
committed by GitHub
parent e0dc4366e0
commit 3f4e7f379d
17 changed files with 501 additions and 62 deletions

View File

@@ -2038,7 +2038,7 @@ memberSendAction GroupInfo {useRelays, membership} events members m@GroupMember
| otherwise = case memberConn m of
Nothing -> pendingOrForwarded
Just conn@Connection {connStatus}
| connDisabled conn || connStatus == ConnDeleted || memberStatus == GSMemRejected -> Nothing
| connDisabled conn || connStatus == ConnDeleted || isConnFailed connStatus || memberStatus == GSMemRejected -> Nothing
| connInactive conn -> Just MSAPending
| connStatus == ConnSndReady || connStatus == ConnReady -> sendBatchedOrSeparate conn
| otherwise -> pendingOrForwarded

View File

@@ -71,7 +71,7 @@ import Simplex.FileTransfer.Protocol (FilePartyI)
import qualified Simplex.FileTransfer.Transport as XFTP
import Simplex.FileTransfer.Types (FileErrorType (..), RcvFileId, SndFileId)
import Simplex.Messaging.Agent
import Simplex.Messaging.Agent.Client (getAgentWorker, waitForWork, withWork_, withWorkItems)
import Simplex.Messaging.Agent.Client (getAgentWorker, temporaryOrHostError, waitForWork, withWork_, withWorkItems)
import Simplex.Messaging.Agent.Env.SQLite (Worker (..))
import Simplex.Messaging.Agent.Protocol
import qualified Simplex.Messaging.Agent.Protocol as AP (AgentErrorType (..))
@@ -366,19 +366,20 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage =
processUserContactRequest agentMessage entity conn uc
where
updateConnStatus :: ConnectionEntity -> CM ConnectionEntity
updateConnStatus acEntity = case agentMsgConnStatus agentMessage of
updateConnStatus acEntity = case agentMsgConnStatus (entityConnection acEntity) agentMessage of
Just connStatus -> do
let conn = (entityConnection acEntity) {connStatus}
withStore' $ \db -> updateConnectionStatus db conn connStatus
pure $ updateEntityConnStatus acEntity connStatus
Nothing -> pure acEntity
agentMsgConnStatus :: AEvent e -> Maybe ConnStatus
agentMsgConnStatus = \case
agentMsgConnStatus :: Connection -> AEvent e -> Maybe ConnStatus
agentMsgConnStatus Connection {connStatus = cs} = \case
JOINED True _ -> Just ConnSndReady
CONF {} -> Just ConnRequested
INFO {} -> Just ConnSndReady
CON _ -> Just ConnReady
ERR err | cs /= ConnReady && not (temporaryOrHostError err) -> Just $ ConnFailed (tshow err)
_ -> Nothing
processCONFpqSupport :: Connection -> PQSupport -> CM Connection
@@ -1054,6 +1055,8 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage =
ERR err -> do
eToView $ ChatErrorAgent err (AgentConnId agentConnId) (Just connEntity)
when (corrId /= "") $ withCompletedCommand conn agentMsg $ \_cmdData -> pure ()
when (isConnFailed $ connStatus conn) $
toView $ CEvtGroupMemberUpdated user gInfo m m
-- TODO add debugging output
_ -> pure ()
where

View File

@@ -71,6 +71,9 @@ getChatLockEntity db agentConnId = do
ExceptT . firstRow fromOnly (SEInternalError "group member connection group_id not found") $
DB.query db "SELECT group_id FROM group_members WHERE group_member_id = ?" (Only groupMemberId)
-- TODO consider whether ConnFailed connections should be excluded:
-- - from receiving: getConnectionEntity, getContactConnEntityByConnReqHash
-- - from subscribing: getContactConnsToSub, getUCLConnsToSub, getMemberConnsToSub, getPendingConnsToSub
getConnectionEntity :: DB.Connection -> VersionRangeChat -> User -> AgentConnId -> ExceptT StoreError IO ConnectionEntity
getConnectionEntity db vr user@User {userId, userContactId} agentConnId = do
c@Connection {connType, entityId} <- getConnection_

View File

@@ -1687,19 +1687,14 @@ data ConnStatus
ConnReady
| -- | connection deleted
ConnDeleted
| -- | connection had a permanent error during handshake
ConnFailed {connError :: Text}
deriving (Eq, Show, Read)
instance FromField ConnStatus where fromField = fromTextField_ textDecode
instance ToField ConnStatus where toField = toField . textEncode
instance FromJSON ConnStatus where
parseJSON = textParseJSON "ConnStatus"
instance ToJSON ConnStatus where
toJSON = J.String . textEncode
toEncoding = JE.text . textEncode
instance TextEncoding ConnStatus where
textDecode = \case
"new" -> Just ConnNew
@@ -1710,6 +1705,7 @@ instance TextEncoding ConnStatus where
"snd-ready" -> Just ConnSndReady
"ready" -> Just ConnReady
"deleted" -> Just ConnDeleted
s | Just err <- T.stripPrefix "failed " s -> Just (ConnFailed err)
_ -> Nothing
textEncode = \case
ConnNew -> "new"
@@ -1720,6 +1716,12 @@ instance TextEncoding ConnStatus where
ConnSndReady -> "snd-ready"
ConnReady -> "ready"
ConnDeleted -> "deleted"
ConnFailed err -> "failed " <> err
isConnFailed :: ConnStatus -> Bool
isConnFailed = \case
ConnFailed {} -> True
_ -> False
data ConnType = ConnContact | ConnMember | ConnUserContact
deriving (Eq, Show)
@@ -1935,6 +1937,8 @@ $(JQ.deriveJSON defaultJSON ''GroupMemberSettings)
$(JQ.deriveJSON defaultJSON ''SecurityCode)
$(JQ.deriveJSON (sumTypeJSON $ dropPrefix "Conn") ''ConnStatus)
$(JQ.deriveJSON defaultJSON ''Connection)
$(JQ.deriveJSON defaultJSON ''PendingContactConnection)