Leave out optional keys from /sync (#9919)

This leaves out all optional keys from /sync. This should be fine for all clients tested against conduit already, but it may break some clients, as such we should check, that at least most of them don't break horribly and maybe back out some of the individual changes. (We can probably always leave out groups for example, while the others may cause more issues.)

Signed-off-by: Nicolas Werner <nicolas.werner@hotmail.de>
pull/9931/head
DeepBlueV7.X 2021-05-05 13:37:56 +00:00 committed by GitHub
parent a61b13c0a1
commit e9eb3549d3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 51 additions and 50 deletions

1
changelog.d/9919.feature Normal file
View File

@ -0,0 +1 @@
Omit empty fields from the `/sync` response. Contributed by @deepbluev7.

View File

@ -14,6 +14,7 @@
import itertools import itertools
import logging import logging
from collections import defaultdict
from typing import TYPE_CHECKING, Tuple from typing import TYPE_CHECKING, Tuple
from synapse.api.constants import PresenceState from synapse.api.constants import PresenceState
@ -229,24 +230,49 @@ class SyncRestServlet(RestServlet):
) )
logger.debug("building sync response dict") logger.debug("building sync response dict")
return {
"account_data": {"events": sync_result.account_data}, response: dict = defaultdict(dict)
"to_device": {"events": sync_result.to_device}, response["next_batch"] = await sync_result.next_batch.to_string(self.store)
"device_lists": {
"changed": list(sync_result.device_lists.changed), if sync_result.account_data:
"left": list(sync_result.device_lists.left), response["account_data"] = {"events": sync_result.account_data}
}, if sync_result.presence:
"presence": SyncRestServlet.encode_presence(sync_result.presence, time_now), response["presence"] = SyncRestServlet.encode_presence(
"rooms": {"join": joined, "invite": invited, "leave": archived}, sync_result.presence, time_now
"groups": { )
"join": sync_result.groups.join,
"invite": sync_result.groups.invite, if sync_result.to_device:
"leave": sync_result.groups.leave, response["to_device"] = {"events": sync_result.to_device}
},
"device_one_time_keys_count": sync_result.device_one_time_keys_count, if sync_result.device_lists.changed:
"org.matrix.msc2732.device_unused_fallback_key_types": sync_result.device_unused_fallback_key_types, response["device_lists"]["changed"] = list(sync_result.device_lists.changed)
"next_batch": await sync_result.next_batch.to_string(self.store), if sync_result.device_lists.left:
} response["device_lists"]["left"] = list(sync_result.device_lists.left)
if sync_result.device_one_time_keys_count:
response[
"device_one_time_keys_count"
] = sync_result.device_one_time_keys_count
if sync_result.device_unused_fallback_key_types:
response[
"org.matrix.msc2732.device_unused_fallback_key_types"
] = sync_result.device_unused_fallback_key_types
if joined:
response["rooms"]["join"] = joined
if invited:
response["rooms"]["invite"] = invited
if archived:
response["rooms"]["leave"] = archived
if sync_result.groups.join:
response["groups"]["join"] = sync_result.groups.join
if sync_result.groups.invite:
response["groups"]["invite"] = sync_result.groups.invite
if sync_result.groups.leave:
response["groups"]["leave"] = sync_result.groups.leave
return response
@staticmethod @staticmethod
def encode_presence(events, time_now): def encode_presence(events, time_now):

View File

@ -37,35 +37,7 @@ class FilterTestCase(unittest.HomeserverTestCase):
channel = self.make_request("GET", "/sync") channel = self.make_request("GET", "/sync")
self.assertEqual(channel.code, 200) self.assertEqual(channel.code, 200)
self.assertTrue( self.assertIn("next_batch", channel.json_body)
{
"next_batch",
"rooms",
"presence",
"account_data",
"to_device",
"device_lists",
}.issubset(set(channel.json_body.keys()))
)
def test_sync_presence_disabled(self):
"""
When presence is disabled, the key does not appear in /sync.
"""
self.hs.config.use_presence = False
channel = self.make_request("GET", "/sync")
self.assertEqual(channel.code, 200)
self.assertTrue(
{
"next_batch",
"rooms",
"account_data",
"to_device",
"device_lists",
}.issubset(set(channel.json_body.keys()))
)
class SyncFilterTestCase(unittest.HomeserverTestCase): class SyncFilterTestCase(unittest.HomeserverTestCase):

View File

@ -306,8 +306,9 @@ class TestResourceLimitsServerNoticesWithRealRooms(unittest.HomeserverTestCase):
channel = self.make_request("GET", "/sync?timeout=0", access_token=tok) channel = self.make_request("GET", "/sync?timeout=0", access_token=tok)
invites = channel.json_body["rooms"]["invite"] self.assertNotIn(
self.assertEqual(len(invites), 0, invites) "rooms", channel.json_body, "Got invites without server notice"
)
def test_invite_with_notice(self): def test_invite_with_notice(self):
"""Tests that, if the MAU limit is hit, the server notices user invites each user """Tests that, if the MAU limit is hit, the server notices user invites each user
@ -364,7 +365,8 @@ class TestResourceLimitsServerNoticesWithRealRooms(unittest.HomeserverTestCase):
# We could also pick another user and sync with it, which would return an # We could also pick another user and sync with it, which would return an
# invite to a system notices room, but it doesn't matter which user we're # invite to a system notices room, but it doesn't matter which user we're
# using so we use the last one because it saves us an extra sync. # using so we use the last one because it saves us an extra sync.
invites = channel.json_body["rooms"]["invite"] if "rooms" in channel.json_body:
invites = channel.json_body["rooms"]["invite"]
# Make sure we have an invite to process. # Make sure we have an invite to process.
self.assertEqual(len(invites), 1, invites) self.assertEqual(len(invites), 1, invites)