mirror of
https://git.anonymousland.org/anonymousland/synapse.git
synced 2025-05-02 13:46:02 -04:00
Merge pull request #2115 from matrix-org/erikj/dedupe_federation_repl
Reduce federation replication traffic
This commit is contained in:
commit
247c736b9b
7 changed files with 203 additions and 130 deletions
|
@ -53,18 +53,19 @@ class FederationRemoteSendQueue(object):
|
|||
self.server_name = hs.hostname
|
||||
self.clock = hs.get_clock()
|
||||
self.notifier = hs.get_notifier()
|
||||
self.is_mine_id = hs.is_mine_id
|
||||
|
||||
self.presence_map = {}
|
||||
self.presence_changed = sorteddict()
|
||||
self.presence_map = {} # Pending presence map user_id -> UserPresenceState
|
||||
self.presence_changed = sorteddict() # Stream position -> user_id
|
||||
|
||||
self.keyed_edu = {}
|
||||
self.keyed_edu_changed = sorteddict()
|
||||
self.keyed_edu = {} # (destination, key) -> EDU
|
||||
self.keyed_edu_changed = sorteddict() # stream position -> (destination, key)
|
||||
|
||||
self.edus = sorteddict()
|
||||
self.edus = sorteddict() # stream position -> Edu
|
||||
|
||||
self.failures = sorteddict()
|
||||
self.failures = sorteddict() # stream position -> (destination, Failure)
|
||||
|
||||
self.device_messages = sorteddict()
|
||||
self.device_messages = sorteddict() # stream position -> destination
|
||||
|
||||
self.pos = 1
|
||||
self.pos_time = sorteddict()
|
||||
|
@ -120,7 +121,9 @@ class FederationRemoteSendQueue(object):
|
|||
del self.presence_changed[key]
|
||||
|
||||
user_ids = set(
|
||||
user_id for uids in self.presence_changed.values() for _, user_id in uids
|
||||
user_id
|
||||
for uids in self.presence_changed.itervalues()
|
||||
for user_id in uids
|
||||
)
|
||||
|
||||
to_del = [
|
||||
|
@ -187,18 +190,20 @@ class FederationRemoteSendQueue(object):
|
|||
|
||||
self.notifier.on_new_replication_data()
|
||||
|
||||
def send_presence(self, destination, states):
|
||||
"""As per TransactionQueue"""
|
||||
def send_presence(self, states):
|
||||
"""As per TransactionQueue
|
||||
|
||||
Args:
|
||||
states (list(UserPresenceState))
|
||||
"""
|
||||
pos = self._next_pos()
|
||||
|
||||
self.presence_map.update({
|
||||
state.user_id: state
|
||||
for state in states
|
||||
})
|
||||
# We only want to send presence for our own users, so lets always just
|
||||
# filter here just in case.
|
||||
local_states = filter(lambda s: self.is_mine_id(s.user_id), states)
|
||||
|
||||
self.presence_changed[pos] = [
|
||||
(destination, state.user_id) for state in states
|
||||
]
|
||||
self.presence_map.update({state.user_id: state for state in local_states})
|
||||
self.presence_changed[pos] = [state.user_id for state in local_states]
|
||||
|
||||
self.notifier.on_new_replication_data()
|
||||
|
||||
|
@ -251,15 +256,14 @@ class FederationRemoteSendQueue(object):
|
|||
keys = self.presence_changed.keys()
|
||||
i = keys.bisect_right(from_token)
|
||||
j = keys.bisect_right(to_token) + 1
|
||||
dest_user_ids = set(
|
||||
(pos, dest_user_id)
|
||||
dest_user_ids = [
|
||||
(pos, user_id)
|
||||
for pos in keys[i:j]
|
||||
for dest_user_id in self.presence_changed[pos]
|
||||
)
|
||||
for user_id in self.presence_changed[pos]
|
||||
]
|
||||
|
||||
for (key, (dest, user_id)) in dest_user_ids:
|
||||
for (key, user_id) in dest_user_ids:
|
||||
rows.append((key, PresenceRow(
|
||||
destination=dest,
|
||||
state=self.presence_map[user_id],
|
||||
)))
|
||||
|
||||
|
@ -357,7 +361,6 @@ class BaseFederationRow(object):
|
|||
|
||||
|
||||
class PresenceRow(BaseFederationRow, namedtuple("PresenceRow", (
|
||||
"destination", # str
|
||||
"state", # UserPresenceState
|
||||
))):
|
||||
TypeId = "p"
|
||||
|
@ -365,18 +368,14 @@ class PresenceRow(BaseFederationRow, namedtuple("PresenceRow", (
|
|||
@staticmethod
|
||||
def from_data(data):
|
||||
return PresenceRow(
|
||||
destination=data["destination"],
|
||||
state=UserPresenceState.from_dict(data["state"])
|
||||
state=UserPresenceState.from_dict(data)
|
||||
)
|
||||
|
||||
def to_data(self):
|
||||
return {
|
||||
"destination": self.destination,
|
||||
"state": self.state.as_dict()
|
||||
}
|
||||
return self.state.as_dict()
|
||||
|
||||
def add_to_buffer(self, buff):
|
||||
buff.presence.setdefault(self.destination, []).append(self.state)
|
||||
buff.presence.append(self.state)
|
||||
|
||||
|
||||
class KeyedEduRow(BaseFederationRow, namedtuple("KeyedEduRow", (
|
||||
|
@ -487,7 +486,7 @@ TypeToRow = {
|
|||
|
||||
|
||||
ParsedFederationStreamData = namedtuple("ParsedFederationStreamData", (
|
||||
"presence", # dict of destination -> [UserPresenceState]
|
||||
"presence", # list(UserPresenceState)
|
||||
"keyed_edus", # dict of destination -> { key -> Edu }
|
||||
"edus", # dict of destination -> [Edu]
|
||||
"failures", # dict of destination -> [failures]
|
||||
|
@ -509,7 +508,7 @@ def process_rows_for_federation(transaction_queue, rows):
|
|||
# them into the appropriate collection and then send them off.
|
||||
|
||||
buff = ParsedFederationStreamData(
|
||||
presence={},
|
||||
presence=[],
|
||||
keyed_edus={},
|
||||
edus={},
|
||||
failures={},
|
||||
|
@ -526,8 +525,8 @@ def process_rows_for_federation(transaction_queue, rows):
|
|||
parsed_row = RowType.from_data(row.data)
|
||||
parsed_row.add_to_buffer(buff)
|
||||
|
||||
for destination, states in buff.presence.iteritems():
|
||||
transaction_queue.send_presence(destination, states)
|
||||
if buff.presence:
|
||||
transaction_queue.send_presence(buff.presence)
|
||||
|
||||
for destination, edu_map in buff.keyed_edus.iteritems():
|
||||
for key, edu in edu_map.items():
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue