-
Notifications
You must be signed in to change notification settings - Fork 332
Prevent race conditions in concurrent MLS commit requests #2525
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
Changes from all commits
bee8fa3
2e6d5c3
5126045
349c89d
1a06f8b
a257b18
b9c9f4f
d615cd6
877d001
9304d1d
9c4bef8
5ce9adc
5f94c5f
06bd07d
d7d0913
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| Prevent race conditions in concurrent MLS commit requests. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| -- 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 V68_MLSCommitLock where | ||
|
|
||
| import Cassandra.Schema | ||
| import Imports | ||
| import Text.RawString.QQ | ||
|
|
||
| migration :: Migration | ||
| migration = | ||
| Migration 68 "Add lock table for MLS commits" $ | ||
| schema' | ||
| [r| CREATE TABLE mls_commit_locks ( | ||
| group_id blob, | ||
| epoch bigint, | ||
| PRIMARY KEY (group_id, epoch) | ||
| ) | ||
| |] |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| -- 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 Galley.Cassandra.Conversation.MLS where | ||
|
|
||
| import Cassandra | ||
| import Cassandra.Settings (fromRow) | ||
| import Data.Time | ||
| import qualified Galley.Cassandra.Queries as Cql | ||
| import Galley.Data.Types | ||
| import Imports | ||
| import Wire.API.MLS.Group | ||
| import Wire.API.MLS.Message | ||
|
|
||
| acquireCommitLock :: GroupId -> Epoch -> NominalDiffTime -> Client LockAcquired | ||
| acquireCommitLock groupId epoch ttl = do | ||
| rows <- | ||
| retry x5 $ | ||
| trans | ||
| Cql.acquireCommitLock | ||
| ( params | ||
| LocalQuorum | ||
| (groupId, epoch, round ttl) | ||
| ) | ||
| pure $ | ||
| if checkTransSuccess rows | ||
| then Acquired | ||
| else NotAcquired | ||
|
|
||
| releaseCommitLock :: GroupId -> Epoch -> Client () | ||
| releaseCommitLock groupId epoch = | ||
| retry x5 $ | ||
| write | ||
| Cql.releaseCommitLock | ||
| ( params | ||
| LocalQuorum | ||
| (groupId, epoch) | ||
| ) | ||
|
|
||
| checkTransSuccess :: [Row] -> Bool | ||
| checkTransSuccess [] = False | ||
| checkTransSuccess (row : _) = either (const False) (fromMaybe False) $ fromRow 0 row |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -370,6 +370,12 @@ addLocalMLSClients = "update member set mls_clients = mls_clients + ? where conv | |
| addRemoteMLSClients :: PrepQuery W (C.Set ClientId, ConvId, Domain, UserId) () | ||
| addRemoteMLSClients = "update member_remote_user set mls_clients = mls_clients + ? where conv = ? and user_remote_domain = ? and user_remote_id = ?" | ||
|
|
||
| acquireCommitLock :: PrepQuery W (GroupId, Epoch, Int32) Row | ||
| acquireCommitLock = "insert into mls_commit_locks (group_id, epoch) values (?, ?) if not exists using ttl ?" | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm surprised that this works. I was under the impression that you can't have TTL values as "question mark" parameters.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We tried it locally by temporarily removing the finishing part of the bracket and observed the entries appearing and finally disappearing after the TTL expired. Would this manual test count or should I look deeper into it? |
||
|
|
||
| releaseCommitLock :: PrepQuery W (GroupId, Epoch) () | ||
| releaseCommitLock = "delete from mls_commit_locks where group_id = ? and epoch = ?" | ||
|
|
||
| -- Services ----------------------------------------------------------------- | ||
|
|
||
| rmSrv :: PrepQuery W (ProviderId, ServiceId) () | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not acquire the lock on the opening side of the bracket?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done.