mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-08-29 01:09:15 +00:00
wip
This commit is contained in:
@@ -144,6 +144,7 @@ library
|
||||
Simplex.Chat.Store.Postgres.Migrations.M20260531_member_removed_at
|
||||
Simplex.Chat.Store.Postgres.Migrations.M20260601_relay_sent_web_domain
|
||||
Simplex.Chat.Store.Postgres.Migrations.M20260602_group_roster
|
||||
Simplex.Chat.Store.Postgres.Migrations.M20260629_member_roster_served
|
||||
else
|
||||
exposed-modules:
|
||||
Simplex.Chat.Archive
|
||||
@@ -306,6 +307,7 @@ library
|
||||
Simplex.Chat.Store.SQLite.Migrations.M20260531_member_removed_at
|
||||
Simplex.Chat.Store.SQLite.Migrations.M20260601_relay_sent_web_domain
|
||||
Simplex.Chat.Store.SQLite.Migrations.M20260602_group_roster
|
||||
Simplex.Chat.Store.SQLite.Migrations.M20260629_member_roster_served
|
||||
other-modules:
|
||||
Paths_simplex_chat
|
||||
hs-source-dirs:
|
||||
|
||||
@@ -1186,8 +1186,9 @@ serveRoster :: User -> GroupInfo -> GroupMember -> CM ()
|
||||
serveRoster user gInfo member =
|
||||
when (member `supportsVersion` groupRosterVersion) $ do
|
||||
cxt <- chatStoreCxt
|
||||
withStore' (\db -> getGroupRoster db gInfo) >>= \case
|
||||
Just (ownerGMId, brokerTs, sm@SignedMsg {signedBody}, blob_) ->
|
||||
-- read the served version with the blob, so the recorded served version matches what is served
|
||||
withStore' (\db -> (,) <$> getGroupRoster db gInfo <*> getGroupRosterVersion db gInfo) >>= \case
|
||||
(Just (ownerGMId, brokerTs, sm@SignedMsg {signedBody}, blob_), rosterVer_) ->
|
||||
case J.eitherDecodeStrict' signedBody :: Either String (ChatMessage 'Json) of
|
||||
Left e -> logError $ "serveRoster: cannot decode saved roster message: " <> tshow e
|
||||
Right chatMsg@ChatMessage {msgId} ->
|
||||
@@ -1197,8 +1198,10 @@ serveRoster user gInfo member =
|
||||
sendFwdMemberMessage member fwd (VMSigned MSSVerified sm chatMsg)
|
||||
forM_ ((,) <$> msgId <*> blob_) $ \(sid, blob) ->
|
||||
sendInlineBlobChunks user gInfo [member] sid blob
|
||||
-- record the served version so a member can't re-trigger a full serve at a version it already got
|
||||
forM_ rosterVer_ $ \v -> withStore' $ \db -> setMemberRosterServedVersion db member v
|
||||
Left e -> logError $ "serveRoster: roster owner not found: " <> tshow e
|
||||
Nothing -> pure ()
|
||||
(Nothing, _) -> pure ()
|
||||
|
||||
-- Used in groups with relays to introduce moderators and above to a new member,
|
||||
-- and to announce the new member to moderators and above.
|
||||
|
||||
@@ -3497,13 +3497,16 @@ processAgentMessageConn cxt user@User {userId} corrId agentConnId agentMessage =
|
||||
_ -> pure ()
|
||||
|
||||
-- A relay re-serves the full roster to a subscriber that detected a version gap, but only when it holds
|
||||
-- something newer than the requester's pre-gap version (rate-limiting same-version requests). serveRoster
|
||||
-- is the join/resume path: signed header + inline blob chunks to the one requester; a no-op without a roster.
|
||||
-- something newer than BOTH the requester's claimed version and the version it last served this member -
|
||||
-- the latter bounds reflected amplification (a member can't re-trigger a full serve with reqVer = 0).
|
||||
-- serveRoster records the served version (on all serve paths) and is a no-op without a roster.
|
||||
xGrpRosterRequest :: GroupInfo -> GroupMember -> VersionRoster -> CM ()
|
||||
xGrpRosterRequest gInfo m reqVer =
|
||||
when (isUserGrpFwdRelay gInfo) $ do
|
||||
cur <- withStore' $ \db -> getGroupRosterVersion db gInfo
|
||||
when (maybe True (> reqVer) cur) $ serveRoster user gInfo m
|
||||
(cur_, served_) <- withStore' $ \db ->
|
||||
(,) <$> getGroupRosterVersion db gInfo <*> getMemberRosterServedVersion db m
|
||||
forM_ cur_ $ \cur ->
|
||||
when (cur > reqVer && maybe True (cur >) served_) $ serveRoster user gInfo m
|
||||
|
||||
checkHostRole :: GroupMember -> GroupMemberRole -> CM ()
|
||||
checkHostRole GroupMember {memberRole, localDisplayName} memRole =
|
||||
|
||||
@@ -90,6 +90,8 @@ module Simplex.Chat.Store.Groups
|
||||
getPublishableGroupRelays,
|
||||
setGroupRosterVersion,
|
||||
getGroupRosterVersion,
|
||||
setMemberRosterServedVersion,
|
||||
getMemberRosterServedVersion,
|
||||
getGroupRoster,
|
||||
RcvRosterTransfer (..),
|
||||
createRosterTransfer,
|
||||
@@ -1478,6 +1480,18 @@ getGroupRosterVersion db GroupInfo {groupId} =
|
||||
fmap join . maybeFirstRow fromOnly $
|
||||
DB.query db "SELECT roster_version FROM groups WHERE group_id = ?" (Only groupId)
|
||||
|
||||
-- The newest roster version a relay re-served to this member on its catch-up request: bounds reflected
|
||||
-- amplification, so a member can't re-trigger a full serve at a version it was already served.
|
||||
setMemberRosterServedVersion :: DB.Connection -> GroupMember -> VersionRoster -> IO ()
|
||||
setMemberRosterServedVersion db GroupMember {groupMemberId} v = do
|
||||
currentTs <- getCurrentTime
|
||||
DB.execute db "UPDATE group_members SET roster_served_version = ?, updated_at = ? WHERE group_member_id = ?" (v, currentTs, groupMemberId)
|
||||
|
||||
getMemberRosterServedVersion :: DB.Connection -> GroupMember -> IO (Maybe VersionRoster)
|
||||
getMemberRosterServedVersion db GroupMember {groupMemberId} =
|
||||
fmap join . maybeFirstRow fromOnly $
|
||||
DB.query db "SELECT roster_served_version FROM group_members WHERE group_member_id = ?" (Only groupMemberId)
|
||||
|
||||
-- The live roster header a relay re-serves to joiners, with the completed blob served alongside it
|
||||
-- (both are written together at completion, so the blob is present whenever the header is).
|
||||
getGroupRoster :: DB.Connection -> GroupInfo -> IO (Maybe (GroupMemberId, UTCTime, SignedMsg, Maybe ByteString))
|
||||
|
||||
@@ -38,6 +38,7 @@ import Simplex.Chat.Store.Postgres.Migrations.M20260530_client_services
|
||||
import Simplex.Chat.Store.Postgres.Migrations.M20260531_member_removed_at
|
||||
import Simplex.Chat.Store.Postgres.Migrations.M20260601_relay_sent_web_domain
|
||||
import Simplex.Chat.Store.Postgres.Migrations.M20260602_group_roster
|
||||
import Simplex.Chat.Store.Postgres.Migrations.M20260629_member_roster_served
|
||||
import Simplex.Messaging.Agent.Store.Shared (Migration (..))
|
||||
|
||||
schemaMigrations :: [(String, Text, Maybe Text)]
|
||||
@@ -75,7 +76,8 @@ schemaMigrations =
|
||||
("20260530_client_services", m20260530_client_services, Just down_m20260530_client_services),
|
||||
("20260531_member_removed_at", m20260531_member_removed_at, Just down_m20260531_member_removed_at),
|
||||
("20260601_relay_sent_web_domain", m20260601_relay_sent_web_domain, Just down_m20260601_relay_sent_web_domain),
|
||||
("20260602_group_roster", m20260602_group_roster, Just down_m20260602_group_roster)
|
||||
("20260602_group_roster", m20260602_group_roster, Just down_m20260602_group_roster),
|
||||
("20260629_member_roster_served", m20260629_member_roster_served, Just down_m20260629_member_roster_served)
|
||||
]
|
||||
|
||||
-- | The list of migrations in ascending order by date
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
{-# LANGUAGE QuasiQuotes #-}
|
||||
|
||||
module Simplex.Chat.Store.Postgres.Migrations.M20260629_member_roster_served where
|
||||
|
||||
import Data.Text (Text)
|
||||
import Text.RawString.QQ (r)
|
||||
|
||||
m20260629_member_roster_served :: Text
|
||||
m20260629_member_roster_served =
|
||||
[r|
|
||||
ALTER TABLE group_members ADD COLUMN roster_served_version BIGINT;
|
||||
|]
|
||||
|
||||
down_m20260629_member_roster_served :: Text
|
||||
down_m20260629_member_roster_served =
|
||||
[r|
|
||||
ALTER TABLE group_members DROP COLUMN roster_served_version;
|
||||
|]
|
||||
@@ -161,6 +161,7 @@ import Simplex.Chat.Store.SQLite.Migrations.M20260530_client_services
|
||||
import Simplex.Chat.Store.SQLite.Migrations.M20260531_member_removed_at
|
||||
import Simplex.Chat.Store.SQLite.Migrations.M20260601_relay_sent_web_domain
|
||||
import Simplex.Chat.Store.SQLite.Migrations.M20260602_group_roster
|
||||
import Simplex.Chat.Store.SQLite.Migrations.M20260629_member_roster_served
|
||||
import Simplex.Messaging.Agent.Store.Shared (Migration (..))
|
||||
|
||||
schemaMigrations :: [(String, Query, Maybe Query)]
|
||||
@@ -321,7 +322,8 @@ schemaMigrations =
|
||||
("20260530_client_services", m20260530_client_services, Just down_m20260530_client_services),
|
||||
("20260531_member_removed_at", m20260531_member_removed_at, Just down_m20260531_member_removed_at),
|
||||
("20260601_relay_sent_web_domain", m20260601_relay_sent_web_domain, Just down_m20260601_relay_sent_web_domain),
|
||||
("20260602_group_roster", m20260602_group_roster, Just down_m20260602_group_roster)
|
||||
("20260602_group_roster", m20260602_group_roster, Just down_m20260602_group_roster),
|
||||
("20260629_member_roster_served", m20260629_member_roster_served, Just down_m20260629_member_roster_served)
|
||||
]
|
||||
|
||||
-- | The list of migrations in ascending order by date
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
{-# LANGUAGE QuasiQuotes #-}
|
||||
|
||||
module Simplex.Chat.Store.SQLite.Migrations.M20260629_member_roster_served where
|
||||
|
||||
import Database.SQLite.Simple (Query)
|
||||
import Database.SQLite.Simple.QQ (sql)
|
||||
|
||||
m20260629_member_roster_served :: Query
|
||||
m20260629_member_roster_served =
|
||||
[sql|
|
||||
ALTER TABLE group_members ADD COLUMN roster_served_version INTEGER;
|
||||
|]
|
||||
|
||||
down_m20260629_member_roster_served :: Query
|
||||
down_m20260629_member_roster_served =
|
||||
[sql|
|
||||
ALTER TABLE group_members DROP COLUMN roster_served_version;
|
||||
|]
|
||||
Reference in New Issue
Block a user