-
Notifications
You must be signed in to change notification settings - Fork 333
WPB-240: Generate and fan out events about stopping to federate #3397
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 250 commits
a478868
dfa644d
66e6969
cdf3650
ef149e3
f9f0e87
1044124
5c22938
02c1432
7dfb4e8
6f9b9cf
beba208
0008020
3b8b383
d508cb9
167083a
8cd69f1
0ede02d
adbf7d9
236c2fd
1a6a103
950867e
676862a
fc00935
d39dd45
6f5ee22
db39702
1a90c97
3846ae3
8b45f0f
708bec2
e89b052
5638e5e
417e368
ce50aa2
5bed564
4199dc5
728567a
f5c1b3e
a6e9255
64b2420
8f348c8
1e086c2
d7f60e3
6a583bf
1d05c84
c0df89a
ea18bcb
4b79d4b
2f3ec7b
84e78f0
6d1f719
e85c97d
6327def
5915c82
f2e998d
012f39d
aa52e91
9c17a69
1d38803
e2015dc
3374dd6
411f03d
96521f5
e474e0b
af21829
3287003
166e2ba
bad86a1
6390674
b49a742
f02819f
15ec903
dd061ae
a6bab56
8f553bd
e44cfe9
19f2732
d662c85
bea0419
f6ae0c7
f0bfa62
2e959b0
37b4f09
8f8af7c
236f4bb
fff9883
1a76c9c
4efa58e
0a122f3
9c68bd8
c8cac98
ca572dd
7c39b34
d3997dc
17ab5da
fbfac87
8cdd041
1ffaab2
e8a7f8b
25ad1af
56f7954
db19f40
9c6836d
01ef6ff
1f0d1ab
b630396
a12cf1b
c8fbb4d
05b692f
e779c86
ced3efb
82ebc0e
803b0df
f2cf2da
5c1b3d1
13b448c
9b44c5e
689b5e9
0e0487c
28d27d6
d334aa6
171a31e
125ba0a
98bf16a
6f77d21
26aa9ef
03153e0
3466906
5571ca2
87455fa
9f0a323
ad83b45
0990d32
d49da1a
b976f94
81e1278
827e155
7e56c4a
8e9d364
781cacd
5cd4559
61a5c87
87b2e52
e6a48e2
3a35a64
1dc2112
a9519eb
74caf82
6c1ecd7
28d87c9
977fd77
0080e89
ab9c14a
57746ee
046b87b
f577998
4f28941
5908f7a
8ea7eb6
582b654
a5e4840
bb5455c
ac6a5c2
f44ff72
a753af5
b0f24b5
c1588b4
9494a19
d348831
553ee0d
d1b4f1c
d649710
0008cf8
37baaf6
131b12b
8d8242a
0a1b730
75ec8e6
2988c1a
57fb696
7b8d78c
81ae556
22e7798
866f52b
372c71c
88bf195
2ba8dd6
a20a21a
354252d
a2432df
3318c4a
47ae909
a830cdb
47b2c24
3931f89
5d8c001
4ed00ce
4e58cbb
0f83de8
f3b57ea
f1a47fe
ae58130
88b1e43
92b777b
6439de9
0513524
28ceb08
e397f76
642af64
c90889c
772aad3
4b105c5
3123028
c352e1b
ec51ff2
cbbf535
42b04b4
2394deb
9a2df02
020bf6c
8be415a
9bd4816
37cbed9
3048b3d
92da980
049d526
2af54f5
456235a
8692dfd
32b5e05
b0355f7
c376e07
c4c28aa
48cb312
2085ed9
4494d06
17ae61f
d0cabf2
a8c8b51
bebc4ad
7a67199
d5952e7
0b33f11
692e851
097e6b9
5a5ed57
2f0b500
9e0349a
a41a371
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,3 @@ | ||
Added a new notification event type, "federation.delete". | ||
This event contains a single domain for a remote server that the local server is de-federating from. | ||
This notification is sent twice during de-federation. Once before and once after cleaning up and removing references to the remote server from the local database. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
De-federating from a remote server sends a pair of notifications to clients, announcing which server will no longer be federated with. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
module Wire.API.Event.Federation | ||
( Event (..), | ||
EventType (..), | ||
) | ||
where | ||
|
||
import Data.Aeson (FromJSON, ToJSON) | ||
import qualified Data.Aeson as A | ||
import qualified Data.Aeson.KeyMap as KeyMap | ||
import Data.Domain | ||
import Data.Json.Util (ToJSONObject (toJSONObject)) | ||
import Data.Schema | ||
import qualified Data.Swagger as S | ||
import Imports | ||
import Wire.Arbitrary | ||
|
||
data Event = Event | ||
{ _eventType :: EventType, | ||
_eventDomain :: Domain | ||
} | ||
deriving (Eq, Show, Ord, Generic) | ||
|
||
instance Arbitrary Event where | ||
arbitrary = | ||
Event | ||
<$> arbitrary | ||
<*> arbitrary | ||
|
||
data EventType | ||
= FederationDelete | ||
deriving (Eq, Show, Ord, Generic) | ||
deriving (Arbitrary) via (GenericUniform EventType) | ||
deriving (A.FromJSON, A.ToJSON, S.ToSchema) via Schema EventType | ||
|
||
instance ToSchema EventType where | ||
schema = | ||
enum @Text "EventType" $ | ||
mconcat | ||
[ element "federation.delete" FederationDelete | ||
] | ||
|
||
eventObjectSchema :: ObjectSchema SwaggerDoc Event | ||
eventObjectSchema = | ||
Event | ||
<$> _eventType .= field "type" schema | ||
<*> _eventDomain .= field "domain" schema | ||
|
||
instance ToSchema Event where | ||
schema = object "Event" eventObjectSchema | ||
|
||
instance ToJSONObject Event where | ||
toJSONObject = | ||
KeyMap.fromList | ||
. fromMaybe [] | ||
. schemaOut eventObjectSchema | ||
|
||
instance S.ToSchema Event where | ||
declareNamedSchema = schemaToSwagger | ||
|
||
instance FromJSON Event where | ||
parseJSON = schemaParseJSON | ||
|
||
instance ToJSON Event where | ||
toJSON = schemaToJSON |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -26,6 +26,7 @@ module Galley.API.Internal | |
) | ||
where | ||
|
||
import Cassandra (ClientState, Consistency (LocalQuorum), Page (..), paramsP) | ||
import Control.Exception | ||
import Control.Exception.Safe (catchAny) | ||
import Control.Lens hiding (Getter, Setter, (.=)) | ||
|
@@ -39,6 +40,7 @@ import Data.Range | |
import Data.Singletons | ||
import Data.Text (unpack) | ||
import Data.Time | ||
import Database.CQL.IO (paginate) | ||
import Galley.API.Action | ||
import qualified Galley.API.Clients as Clients | ||
import qualified Galley.API.Create as Create | ||
|
@@ -59,12 +61,16 @@ import Galley.API.Teams.Features | |
import qualified Galley.API.Update as Update | ||
import Galley.API.Util | ||
import Galley.App | ||
import Galley.Cassandra.Conversation.Members | ||
import Galley.Cassandra.Queries | ||
import Galley.Cassandra.Store (embedClient) | ||
import qualified Galley.Data.Conversation as Data | ||
import Galley.Data.Conversation.Types | ||
import Galley.Effects | ||
import Galley.Effects.BackendNotificationQueueAccess | ||
import Galley.Effects.ClientStore | ||
import Galley.Effects.ConversationStore | ||
import Galley.Effects.ExternalAccess | ||
import Galley.Effects.FederatorAccess | ||
import Galley.Effects.GundeckAccess | ||
import Galley.Effects.LegalHoldStore as LegalHoldStore | ||
|
@@ -73,7 +79,9 @@ import qualified Galley.Effects.MemberStore as E | |
import Galley.Effects.ProposalStore | ||
import Galley.Effects.TeamStore | ||
import qualified Galley.Effects.TeamStore as E | ||
import Galley.Env (currentFanoutLimit, _options) | ||
import qualified Galley.Intra.Push as Intra | ||
import Galley.Intra.Push.Internal (pushEventJson) | ||
import Galley.Monad | ||
import Galley.Options | ||
import qualified Galley.Queue as Q | ||
|
@@ -85,8 +93,8 @@ import Imports hiding (head) | |
import qualified Network.AMQP as Q | ||
import Network.HTTP.Types | ||
import Network.Wai | ||
import Network.Wai.Predicate hiding (Error, err, setStatus) | ||
import qualified Network.Wai.Predicate as Predicate | ||
import Network.Wai.Predicate hiding (Error, err, result, setStatus) | ||
import qualified Network.Wai.Predicate as Predicate hiding (result) | ||
import Network.Wai.Routing hiding (App, route, toList) | ||
import Network.Wai.Utilities hiding (Error) | ||
import Network.Wai.Utilities.ZAuth | ||
|
@@ -106,6 +114,7 @@ import Wire.API.CustomBackend | |
import Wire.API.Error | ||
import Wire.API.Error.Galley | ||
import Wire.API.Event.Conversation | ||
import qualified Wire.API.Event.Federation as Federation | ||
import Wire.API.Federation.API | ||
import Wire.API.Federation.API.Galley | ||
import qualified Wire.API.Federation.API.Galley as F | ||
|
@@ -534,6 +543,7 @@ internalDeleteFederationDomainH :: | |
Member MemberStore r, | ||
Member ConversationStore r, | ||
Member (Embed IO) r, | ||
Member (Input ClientState) r, | ||
Member CodeStore r, | ||
Member TeamStore r, | ||
Member BrigAccess r, | ||
|
@@ -543,8 +553,35 @@ internalDeleteFederationDomainH :: | |
Domain ::: JSON -> | ||
Sem r Response | ||
internalDeleteFederationDomainH (domain ::: _) = do | ||
-- We have to send the same event twice. | ||
-- Once before and once after defederation work. | ||
-- https://wearezeta.atlassian.net/wiki/spaces/ENGINEERIN/pages/809238539/Use+case+Stopping+to+federate+with+a+domain | ||
void sendNotifications | ||
deleteFederationDomain domain | ||
void sendNotifications | ||
pure (empty & setStatus status200) | ||
where | ||
sendNotifications = do | ||
maxPage <- inputs $ fromRange . currentFanoutLimit . _options -- This is based on the limits in removeIfLargeFanout | ||
page <- embedClient $ paginate selectAllMembers (paramsP LocalQuorum () maxPage) | ||
sendNotificationPage page | ||
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. Shouldn't we void here instead of the call sites? 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've moved the void in front of this call. |
||
pushEvents results = do | ||
let (bots, mems) = localBotsAndUsers results | ||
recipients = Intra.recipient <$> mems | ||
event = Intra.FederationEvent $ Federation.Event Federation.FederationDelete domain | ||
for_ (Intra.newPush ListComplete Nothing event recipients) $ \p -> do | ||
-- TODO: Transient or not? | ||
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. TODO or Futurework? 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. Futurework, I think. |
||
-- RouteAny is used as it will wake up mobile clients | ||
-- and notify them of the changes to federation state. | ||
push1 $ p & Intra.pushRoute .~ Intra.RouteAny | ||
deliverAsync (bots `zip` repeat (pushEventJson event)) | ||
sendNotificationPage page = do | ||
let res = result page | ||
mems = mapMaybe toMember res | ||
pushEvents mems | ||
when (hasMore page) $ do | ||
page' <- embedClient $ nextPage page | ||
sendNotificationPage page' | ||
|
||
-- Remove remote members from local conversations | ||
deleteFederationDomainRemoteUserFromLocalConversations :: | ||
|
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.
Feels like this should be an effect, instead of accessed directly, but I'm not sure what we want to do.
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.
I've made a new effect for this.