Skip to content
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

Use MLS member table indexed by group id #2859

Merged
merged 10 commits into from
Nov 25, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,10 @@ git-add-cassandra-schema: db-reset git-add-cassandra-schema-impl
.PHONY: git-add-cassandra-schema-impl
git-add-cassandra-schema-impl:
$(eval CASSANDRA_CONTAINER := $(shell docker ps | grep '/cassandra:' | perl -ne '/^(\S+)\s/ && print $$1'))
( echo '-- automatically generated with `make git-add-cassandra-schema`' ; docker exec -i $(CASSANDRA_CONTAINER) /usr/bin/cqlsh -e "DESCRIBE schema;" ) > ./cassandra-schema.cql
( echo '-- automatically generated with `make git-add-cassandra-schema`'; \
docker exec -i $(CASSANDRA_CONTAINER) /usr/bin/cqlsh -e "DESCRIBE schema;" ) \
| sed "s/CREATE TABLE galley_test.member_client/-- NOTE: this table is unused. It was replaced by mls_group_member_client\nCREATE TABLE galley_test.member_client/g" \
> ./cassandra-schema.cql
git add ./cassandra-schema.cql

.PHONY: cqlsh
Expand Down
24 changes: 24 additions & 0 deletions cassandra-schema.cql
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,7 @@ CREATE TABLE galley_test.group_id_conv_id (
AND read_repair_chance = 0.0
AND speculative_retry = '99PERCENTILE';

-- NOTE: this table is unused. It was replaced by mls_group_member_client
CREATE TABLE galley_test.member_client (
conv uuid,
user_domain text,
Expand Down Expand Up @@ -430,6 +431,29 @@ CREATE TABLE galley_test.conversation_codes (
AND read_repair_chance = 0.0
AND speculative_retry = '99PERCENTILE';

CREATE TABLE galley_test.mls_group_member_client (
group_id blob,
user_domain text,
user uuid,
client text,
key_package_ref blob,
PRIMARY KEY (group_id, user_domain, user, client)
) WITH CLUSTERING ORDER BY (user_domain ASC, user ASC, client ASC)
AND bloom_filter_fp_chance = 0.01
AND caching = {'keys': 'ALL', 'rows_per_partition': 'NONE'}
AND comment = ''
AND compaction = {'class': 'org.apache.cassandra.db.compaction.SizeTieredCompactionStrategy', 'max_threshold': '32', 'min_threshold': '4'}
AND compression = {'chunk_length_in_kb': '64', 'class': 'org.apache.cassandra.io.compress.LZ4Compressor'}
AND crc_check_chance = 1.0
AND dclocal_read_repair_chance = 0.1
AND default_time_to_live = 0
AND gc_grace_seconds = 864000
AND max_index_interval = 2048
AND memtable_flush_period_in_ms = 0
AND min_index_interval = 128
AND read_repair_chance = 0.0
AND speculative_retry = '99PERCENTILE';

CREATE TABLE galley_test.clients (
user uuid PRIMARY KEY,
clients set<text>
Expand Down
1 change: 1 addition & 0 deletions changelog.d/0-release-notes/member_clients_migration
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
This realease migrates data from `galley.member_client` to `galley.mls_group_member_client`. When upgrading wire-server no manual steps are required.
6 changes: 6 additions & 0 deletions services/galley/galley.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -538,11 +538,15 @@ executable galley-integration

executable galley-migrate-data
main-is: Main.hs

-- cabal-fmt: expand migrate-data/src
other-modules:
Galley.DataMigration
Galley.DataMigration.Types
Main
Paths_galley
V1_BackfillBillingTeamMembers
V2_MigrateMLSMembers

hs-source-dirs: migrate-data/src
default-extensions:
Expand Down Expand Up @@ -598,6 +602,7 @@ executable galley-migrate-data
, exceptions
, extended
, extra >=1.3
, galley
, galley-types
, imports
, lens
Expand Down Expand Up @@ -685,6 +690,7 @@ executable galley-schema
V74_ExposeInvitationsToTeamAdmin
V75_MLSGroupInfo
V76_ProposalOrigin
V77_MLSGroupMemberClient

hs-source-dirs: schema/src
default-extensions:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ newtype MigrationActionT m a = MigrationActionT {unMigrationAction :: ReaderT En
Monad,
MonadIO,
MonadThrow,
MonadReader Env
MonadReader Env,
MonadUnliftIO
)

instance MonadTrans MigrationActionT where
Expand Down
8 changes: 7 additions & 1 deletion services/galley/migrate-data/src/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,17 @@ import Imports
import Options.Applicative
import qualified System.Logger.Extended as Log
import qualified V1_BackfillBillingTeamMembers
import qualified V2_MigrateMLSMembers

main :: IO ()
main = do
o <- execParser (info (helper <*> cassandraSettingsParser) desc)
l <- Log.mkLogger Log.Debug Nothing Nothing
migrate l o [V1_BackfillBillingTeamMembers.migration]
migrate
l
o
[ V1_BackfillBillingTeamMembers.migration,
V2_MigrateMLSMembers.migration
]
where
desc = header "Galley Cassandra Data Migrations" <> fullDesc
101 changes: 101 additions & 0 deletions services/galley/migrate-data/src/V2_MigrateMLSMembers.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
-- This file is part of the Wire Server implementation.
--
-- Copyright (C) 2022 Wire Swiss GmbH <opensource@wire.com>
--
-- This program is free software: you can redistribute it and/or modify it under
-- the terms of the GNU Affero General Public License as published by the Free
-- Software Foundation, either version 3 of the License, or (at your option) any
-- later version.
--
-- This program is distributed in the hope that it will be useful, but WITHOUT
-- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-- FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
-- details.
--
-- You should have received a copy of the GNU Affero General Public License along
-- with this program. If not, see <https://www.gnu.org/licenses/>.

module V2_MigrateMLSMembers where

import Cassandra
import Conduit
import Data.Conduit.Internal (zipSources)
import qualified Data.Conduit.List as C
import Data.Domain
import Data.Id
import Data.Map.Strict (lookup)
import qualified Data.Map.Strict as Map
import Galley.Cassandra.Instances ()
import Galley.DataMigration.Types
import Imports hiding (lookup)
import qualified System.Logger.Class as Log
import UnliftIO (pooledMapConcurrentlyN_)
import UnliftIO.Async (pooledMapConcurrentlyN)
import Wire.API.MLS.Group
import Wire.API.MLS.KeyPackage

migration :: Migration
migration =
Migration
{ version = MigrationVersion 2,
text = "Migrating from member_client to mls_group_member_client",
action =
runConduit $
zipSources
(C.sourceList [(1 :: Int32) ..])
getMemberClientsFromLegacy
.| C.mapM_
( \(i, rows) -> do
Log.info (Log.field "Entries " (show (i * pageSize)))
let convIds = map rowConvId rows
m <- lookupGroupIds convIds
let newRows = flip mapMaybe rows $ \(conv, domain, uid, client, ref) ->
conv `lookup` m >>= \groupId -> pure (groupId, domain, uid, client, ref)
insertMemberClients newRows
)
}

rowConvId :: (ConvId, Domain, UserId, ClientId, KeyPackageRef) -> ConvId
rowConvId (conv, _, _, _, _) = conv

pageSize :: Int32
pageSize = 1000

getMemberClientsFromLegacy :: MonadClient m => ConduitM () [(ConvId, Domain, UserId, ClientId, KeyPackageRef)] m ()
getMemberClientsFromLegacy = paginateC cql (paramsP LocalQuorum () pageSize) x5
where
cql :: PrepQuery R () (ConvId, Domain, UserId, ClientId, KeyPackageRef)
cql = "SELECT conv, user_domain, user, client, key_package_ref from member_client"

lookupGroupIds :: [ConvId] -> MigrationActionT IO (Map ConvId GroupId)
lookupGroupIds convIds = do
rows <- pooledMapConcurrentlyN 8 (\convId -> retry x5 (query1 cql (params LocalQuorum (Identity convId)))) convIds
rows' <-
rows
& mapM
( \case
(Just (c, mg)) -> do
case mg of
Nothing -> do
Log.warn (Log.msg ("No group found for conv " <> show c))
pure Nothing
Just g -> pure (Just (c, g))
Nothing -> do
Log.warn (Log.msg ("Conversation is missing for entry" :: Text))
pure Nothing
)

rows'
& catMaybes
& Map.fromList
& pure
where
cql :: PrepQuery R (Identity ConvId) (ConvId, Maybe GroupId)
cql = "SELECT conv, group_id from conversation where conv = ?"

insertMemberClients :: (MonadUnliftIO m, MonadClient m) => [(GroupId, Domain, UserId, ClientId, KeyPackageRef)] -> m ()
insertMemberClients rows = do
pooledMapConcurrentlyN_ 8 (\row -> retry x5 (write cql (params LocalQuorum row))) rows
where
cql :: PrepQuery W (GroupId, Domain, UserId, ClientId, KeyPackageRef) ()
cql = "INSERT INTO mls_group_member_client (group_id, user_domain, user, client, key_package_ref) VALUES (?, ?, ?, ?, ?)"
4 changes: 3 additions & 1 deletion services/galley/schema/src/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ import qualified V73_MemberClientTable
import qualified V74_ExposeInvitationsToTeamAdmin
import qualified V75_MLSGroupInfo
import qualified V76_ProposalOrigin
import qualified V77_MLSGroupMemberClient

main :: IO ()
main = do
Expand Down Expand Up @@ -143,7 +144,8 @@ main = do
V73_MemberClientTable.migration,
V74_ExposeInvitationsToTeamAdmin.migration,
V75_MLSGroupInfo.migration,
V76_ProposalOrigin.migration
V76_ProposalOrigin.migration,
V77_MLSGroupMemberClient.migration
-- When adding migrations here, don't forget to update
-- 'schemaVersion' in Galley.Cassandra
smatting marked this conversation as resolved.
Show resolved Hide resolved
-- (see also docs/developer/cassandra-interaction.md)
Expand Down
36 changes: 36 additions & 0 deletions services/galley/schema/src/V77_MLSGroupMemberClient.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
-- This file is part of the Wire Server implementation.
--
-- Copyright (C) 2022 Wire Swiss GmbH <opensource@wire.com>
--
-- This program is free software: you can redistribute it and/or modify it under
-- the terms of the GNU Affero General Public License as published by the Free
-- Software Foundation, either version 3 of the License, or (at your option) any
-- later version.
--
-- This program is distributed in the hope that it will be useful, but WITHOUT
-- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-- FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
-- details.
--
-- You should have received a copy of the GNU Affero General Public License along
-- with this program. If not, see <https://www.gnu.org/licenses/>.

module V77_MLSGroupMemberClient (migration) where

import Cassandra.Schema
import Imports
import Text.RawString.QQ

migration :: Migration
migration =
Migration 77 "Add table mls_group_member_client which replaces member_client" $ do
schema'
[r| CREATE TABLE mls_group_member_client (
group_id blob,
user_domain text,
user uuid,
client text,
key_package_ref blob,
PRIMARY KEY (group_id, user_domain, user, client)
);
|]
10 changes: 5 additions & 5 deletions services/galley/src/Galley/API/Create.hs
Original file line number Diff line number Diff line change
Expand Up @@ -126,11 +126,11 @@ createGroupConversation lusr conn newConv = do
conv <- E.createConversation lcnv nc

-- set creator client for MLS conversations
case (newConvProtocol newConv, newConvCreatorClient newConv) of
(ProtocolProteusTag, _) -> pure ()
(ProtocolMLSTag, Just c) ->
E.addMLSClients lcnv (qUntagged lusr) (Set.singleton (c, nullKeyPackageRef))
(ProtocolMLSTag, Nothing) ->
case (convProtocol conv, newConvCreatorClient newConv) of
(ProtocolProteus, _) -> pure ()
(ProtocolMLS mlsMeta, Just c) ->
E.addMLSClients (cnvmlsGroupId mlsMeta) (qUntagged lusr) (Set.singleton (c, nullKeyPackageRef))
(ProtocolMLS _mlsMeta, Nothing) ->
throw (InvalidPayload "Missing creator_client field when creating an MLS conversation")

now <- input
Expand Down
Loading