From 1d62a0758c7508f5546661e8afa52db3d8619d64 Mon Sep 17 00:00:00 2001 From: Brendan Abolivier Date: Tue, 3 May 2022 10:22:33 +0100 Subject: [PATCH 01/15] Prevent expired events from being filtered out when retention is disabled --- synapse/storage/databases/main/room.py | 5 +++++ tests/rest/client/test_relations.py | 6 +++--- tests/rest/client/test_retention.py | 23 ++++++++++++++++++++++- 3 files changed, 30 insertions(+), 4 deletions(-) diff --git a/synapse/storage/databases/main/room.py b/synapse/storage/databases/main/room.py index 87e9482c6054..1f3ef6ee8fa4 100644 --- a/synapse/storage/databases/main/room.py +++ b/synapse/storage/databases/main/room.py @@ -713,6 +713,11 @@ async def get_retention_policy_for_room(self, room_id: str) -> Dict[str, int]: Returns: A dict containing "min_lifetime" and "max_lifetime" for this room. """ + # If the room retention feature is disabled, return a policy with no minimum nor + # maximum, in order not to filter out events we should filter out when sending to + # the client. + if not self.config.retention.retention_enabled: + return {"min_lifetime": None, "max_lifetime": None} def get_retention_policy_for_room_txn( txn: LoggingTransaction, diff --git a/tests/rest/client/test_relations.py b/tests/rest/client/test_relations.py index 39667e3225e2..251991cd16a5 100644 --- a/tests/rest/client/test_relations.py +++ b/tests/rest/client/test_relations.py @@ -982,7 +982,7 @@ def assert_annotations(bundled_aggregations: JsonDict) -> None: bundled_aggregations, ) - self._test_bundled_aggregations(RelationTypes.ANNOTATION, assert_annotations, 7) + self._test_bundled_aggregations(RelationTypes.ANNOTATION, assert_annotations, 6) def test_reference(self) -> None: """ @@ -1000,7 +1000,7 @@ def assert_annotations(bundled_aggregations: JsonDict) -> None: bundled_aggregations, ) - self._test_bundled_aggregations(RelationTypes.REFERENCE, assert_annotations, 7) + self._test_bundled_aggregations(RelationTypes.REFERENCE, assert_annotations, 6) def test_thread(self) -> None: """ @@ -1029,7 +1029,7 @@ def assert_thread(bundled_aggregations: JsonDict) -> None: bundled_aggregations.get("latest_event"), ) - self._test_bundled_aggregations(RelationTypes.THREAD, assert_thread, 9) + self._test_bundled_aggregations(RelationTypes.THREAD, assert_thread, 8) def test_thread_edit_latest_event(self) -> None: """Test that editing the latest event in a thread works.""" diff --git a/tests/rest/client/test_retention.py b/tests/rest/client/test_retention.py index 7b8fe6d02522..eec364d588bd 100644 --- a/tests/rest/client/test_retention.py +++ b/tests/rest/client/test_retention.py @@ -254,10 +254,14 @@ class RetentionNoDefaultPolicyTestCase(unittest.HomeserverTestCase): def make_homeserver(self, reactor: MemoryReactor, clock: Clock) -> HomeServer: config = self.default_config() - config["retention"] = { + + retention_config = { "enabled": True, } + retention_config.update(config.get("retention", {})) + config["retention"] = retention_config + mock_federation_client = Mock(spec=["backfill"]) self.hs = self.setup_test_homeserver( @@ -295,6 +299,23 @@ def test_state_policy(self) -> None: self._test_retention(room_id, expected_code_for_first_event=404) + @unittest.override_config({"retention": {"enabled": False}}) + def test_visibility_when_disabled(self) -> None: + room_id = self.helper.create_room_as(self.user_id, tok=self.token) + + self.helper.send_state( + room_id=room_id, + event_type=EventTypes.Retention, + body={"max_lifetime": one_day_ms}, + tok=self.token, + ) + + resp = self.helper.send(room_id=room_id, body="test", tok=self.token) + + self.reactor.advance(one_day_ms * 2 / 1000) + + self.get_event(room_id, resp["event_id"]) + def _test_retention( self, room_id: str, expected_code_for_first_event: int = 200 ) -> None: From 44f048dae9369dbec24a6b200e0550f02a073780 Mon Sep 17 00:00:00 2001 From: Brendan Abolivier Date: Tue, 3 May 2022 10:29:30 +0100 Subject: [PATCH 02/15] Changelog --- changelog.d/12611.bugfix | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/12611.bugfix diff --git a/changelog.d/12611.bugfix b/changelog.d/12611.bugfix new file mode 100644 index 000000000000..46e9918ce0e2 --- /dev/null +++ b/changelog.d/12611.bugfix @@ -0,0 +1 @@ +Fix a long-standing bug introduced in Synapse 1.7.0 that would prevent events from being sent to clients if there's a retention policy in the room and the support for retention policies is disabled. From 4fdc44ede23850490ed8ca39c4ce5218c2d8b2a0 Mon Sep 17 00:00:00 2001 From: Brendan Abolivier Date: Tue, 3 May 2022 10:32:01 +0100 Subject: [PATCH 03/15] Fix return type --- synapse/storage/databases/main/room.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/synapse/storage/databases/main/room.py b/synapse/storage/databases/main/room.py index 1f3ef6ee8fa4..ec2fa1c2b2d9 100644 --- a/synapse/storage/databases/main/room.py +++ b/synapse/storage/databases/main/room.py @@ -699,7 +699,7 @@ def delete_ratelimit_txn(txn: LoggingTransaction) -> None: await self.db_pool.runInteraction("delete_ratelimit", delete_ratelimit_txn) @cached() - async def get_retention_policy_for_room(self, room_id: str) -> Dict[str, int]: + async def get_retention_policy_for_room(self, room_id: str) -> Dict[str, Optional[int]]: """Get the retention policy for a given room. If no retention policy has been found for this room, returns a policy defined From 77f65b012942e1a4cd58907d7f64e3d59ded0c87 Mon Sep 17 00:00:00 2001 From: Brendan Abolivier Date: Tue, 3 May 2022 10:33:56 +0100 Subject: [PATCH 04/15] Lint --- synapse/storage/databases/main/room.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/synapse/storage/databases/main/room.py b/synapse/storage/databases/main/room.py index ec2fa1c2b2d9..5a54a42e3dad 100644 --- a/synapse/storage/databases/main/room.py +++ b/synapse/storage/databases/main/room.py @@ -699,7 +699,9 @@ def delete_ratelimit_txn(txn: LoggingTransaction) -> None: await self.db_pool.runInteraction("delete_ratelimit", delete_ratelimit_txn) @cached() - async def get_retention_policy_for_room(self, room_id: str) -> Dict[str, Optional[int]]: + async def get_retention_policy_for_room( + self, room_id: str + ) -> Dict[str, Optional[int]]: """Get the retention policy for a given room. If no retention policy has been found for this room, returns a policy defined From 0a8c7831d7b583e04bb2744f16c163fff65474a4 Mon Sep 17 00:00:00 2001 From: Brendan Abolivier Date: Tue, 3 May 2022 11:44:33 +0100 Subject: [PATCH 05/15] Kick the CI awake From b734482afdde856275f8d66ae7ef898ba68e8404 Mon Sep 17 00:00:00 2001 From: Brendan Abolivier Date: Tue, 3 May 2022 13:35:45 +0100 Subject: [PATCH 06/15] Fix changelog wording --- changelog.d/12611.bugfix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog.d/12611.bugfix b/changelog.d/12611.bugfix index 46e9918ce0e2..337be292492c 100644 --- a/changelog.d/12611.bugfix +++ b/changelog.d/12611.bugfix @@ -1 +1 @@ -Fix a long-standing bug introduced in Synapse 1.7.0 that would prevent events from being sent to clients if there's a retention policy in the room and the support for retention policies is disabled. +Fix a long-standing bug introduced in Synapse 1.7.0 that would prevent events from being sent to clients if there's a retention policy in the room when the support for retention policies is disabled. From 6a9f36395217ae6cc65a33971dcb9d50ddc8b9ff Mon Sep 17 00:00:00 2001 From: Brendan Abolivier Date: Fri, 13 May 2022 15:36:53 +0200 Subject: [PATCH 07/15] Apply suggestions from code review Co-authored-by: Richard van der Hoff <1389908+richvdh@users.noreply.github.com> Co-authored-by: Patrick Cloke --- changelog.d/12611.bugfix | 2 +- synapse/storage/databases/main/room.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/changelog.d/12611.bugfix b/changelog.d/12611.bugfix index 337be292492c..093c45a20b7f 100644 --- a/changelog.d/12611.bugfix +++ b/changelog.d/12611.bugfix @@ -1 +1 @@ -Fix a long-standing bug introduced in Synapse 1.7.0 that would prevent events from being sent to clients if there's a retention policy in the room when the support for retention policies is disabled. +Fix a bug introduced in Synapse 1.7.0 that would prevent events from being sent to clients if there's a retention policy in the room when the support for retention policies is disabled. diff --git a/synapse/storage/databases/main/room.py b/synapse/storage/databases/main/room.py index 5a54a42e3dad..b3c6a34a9034 100644 --- a/synapse/storage/databases/main/room.py +++ b/synapse/storage/databases/main/room.py @@ -716,7 +716,7 @@ async def get_retention_policy_for_room( A dict containing "min_lifetime" and "max_lifetime" for this room. """ # If the room retention feature is disabled, return a policy with no minimum nor - # maximum, in order not to filter out events we should filter out when sending to + # maximum. This prevents incorrectly filtering out events when sending to # the client. if not self.config.retention.retention_enabled: return {"min_lifetime": None, "max_lifetime": None} From 77c0b45164c893a241bce62698687b2593b024e9 Mon Sep 17 00:00:00 2001 From: Brendan Abolivier Date: Fri, 13 May 2022 15:41:35 +0200 Subject: [PATCH 08/15] Apply suggestions from code review Co-authored-by: Patrick Cloke --- tests/rest/client/test_retention.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/rest/client/test_retention.py b/tests/rest/client/test_retention.py index eec364d588bd..50a84135a2c5 100644 --- a/tests/rest/client/test_retention.py +++ b/tests/rest/client/test_retention.py @@ -301,6 +301,7 @@ def test_state_policy(self) -> None: @unittest.override_config({"retention": {"enabled": False}}) def test_visibility_when_disabled(self) -> None: + """Retention policies should be ignored when the retention feature is disabled.""" room_id = self.helper.create_room_as(self.user_id, tok=self.token) self.helper.send_state( From dfcf15f9da69dcef6417dcfe3f3d14a152ec4a74 Mon Sep 17 00:00:00 2001 From: Brendan Abolivier Date: Fri, 13 May 2022 14:58:17 +0100 Subject: [PATCH 09/15] Incorporate review --- synapse/storage/databases/main/room.py | 3 +++ tests/rest/client/test_retention.py | 11 ++++++++--- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/synapse/storage/databases/main/room.py b/synapse/storage/databases/main/room.py index b3c6a34a9034..40d753bd909f 100644 --- a/synapse/storage/databases/main/room.py +++ b/synapse/storage/databases/main/room.py @@ -709,6 +709,9 @@ async def get_retention_policy_for_room( the 'max_lifetime' if no default policy has been defined in the server's configuration). + If support for retention policies is disabled, a policy without any bound is + returned. + Args: room_id: The ID of the room to get the retention policy of. diff --git a/tests/rest/client/test_retention.py b/tests/rest/client/test_retention.py index 50a84135a2c5..886fad29bd3c 100644 --- a/tests/rest/client/test_retention.py +++ b/tests/rest/client/test_retention.py @@ -11,6 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +from typing import Dict, Any from unittest.mock import Mock from twisted.test.proto_helpers import MemoryReactor @@ -252,20 +253,24 @@ class RetentionNoDefaultPolicyTestCase(unittest.HomeserverTestCase): room.register_servlets, ] - def make_homeserver(self, reactor: MemoryReactor, clock: Clock) -> HomeServer: - config = self.default_config() + def default_config(self) -> Dict[str, Any]: + config = super().default_config() retention_config = { "enabled": True, } + # Update this config with what's in the default config so that + # override_config works as expected. retention_config.update(config.get("retention", {})) config["retention"] = retention_config + return config + + def make_homeserver(self, reactor: MemoryReactor, clock: Clock) -> HomeServer: mock_federation_client = Mock(spec=["backfill"]) self.hs = self.setup_test_homeserver( - config=config, federation_client=mock_federation_client, ) return self.hs From ca885db4b646b3d1eaf1672ea573f4ee3c85f513 Mon Sep 17 00:00:00 2001 From: Brendan Abolivier Date: Fri, 13 May 2022 15:03:01 +0100 Subject: [PATCH 10/15] Lint --- tests/rest/client/test_retention.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/rest/client/test_retention.py b/tests/rest/client/test_retention.py index 886fad29bd3c..2cd7a9e6c5f8 100644 --- a/tests/rest/client/test_retention.py +++ b/tests/rest/client/test_retention.py @@ -11,7 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from typing import Dict, Any +from typing import Any, Dict from unittest.mock import Mock from twisted.test.proto_helpers import MemoryReactor From 85ac0a0e7c852df30208e7c3b8471c83940ecae3 Mon Sep 17 00:00:00 2001 From: Brendan Abolivier Date: Mon, 23 May 2022 18:03:56 +0200 Subject: [PATCH 11/15] Update synapse/storage/databases/main/room.py Co-authored-by: Patrick Cloke --- synapse/storage/databases/main/room.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/synapse/storage/databases/main/room.py b/synapse/storage/databases/main/room.py index 40d753bd909f..01c984ec9b58 100644 --- a/synapse/storage/databases/main/room.py +++ b/synapse/storage/databases/main/room.py @@ -709,8 +709,8 @@ async def get_retention_policy_for_room( the 'max_lifetime' if no default policy has been defined in the server's configuration). - If support for retention policies is disabled, a policy without any bound is - returned. + If support for retention policies is disabled, a policy with a 'min_lifetime' and 'max_lifetime' + of None is returned. Args: room_id: The ID of the room to get the retention policy of. From 456f61ca499f13c719f7fb722b998674c0d6171d Mon Sep 17 00:00:00 2001 From: Brendan Abolivier Date: Mon, 23 May 2022 17:26:24 +0100 Subject: [PATCH 12/15] Use an attr class for retention policies --- synapse/handlers/pagination.py | 2 +- synapse/storage/databases/main/room.py | 39 ++++++++++++-------------- synapse/types.py | 6 ++++ synapse/visibility.py | 6 ++-- 4 files changed, 28 insertions(+), 25 deletions(-) diff --git a/synapse/handlers/pagination.py b/synapse/handlers/pagination.py index 2e30180094d2..abad883e9695 100644 --- a/synapse/handlers/pagination.py +++ b/synapse/handlers/pagination.py @@ -239,7 +239,7 @@ async def purge_history_for_rooms_in_range( # defined in the server's configuration, we can safely assume that's the # case and use it for this room. max_lifetime = ( - retention_policy["max_lifetime"] or self._retention_default_max_lifetime + retention_policy.max_lifetime or self._retention_default_max_lifetime ) # Cap the effective max_lifetime to be within the range allowed in the diff --git a/synapse/storage/databases/main/room.py b/synapse/storage/databases/main/room.py index 01c984ec9b58..0f7976ad43e5 100644 --- a/synapse/storage/databases/main/room.py +++ b/synapse/storage/databases/main/room.py @@ -45,7 +45,7 @@ from synapse.storage.databases.main.cache import CacheInvalidationWorkerStore from synapse.storage.types import Cursor from synapse.storage.util.id_generators import IdGenerator -from synapse.types import JsonDict, ThirdPartyInstanceID +from synapse.types import JsonDict, ThirdPartyInstanceID, RetentionPolicy from synapse.util import json_encoder from synapse.util.caches.descriptors import cached from synapse.util.stringutils import MXC_REGEX @@ -709,8 +709,8 @@ async def get_retention_policy_for_room( the 'max_lifetime' if no default policy has been defined in the server's configuration). - If support for retention policies is disabled, a policy with a 'min_lifetime' and 'max_lifetime' - of None is returned. + If support for retention policies is disabled, a policy with a 'min_lifetime' and + 'max_lifetime' of None is returned. Args: room_id: The ID of the room to get the retention policy of. @@ -722,7 +722,7 @@ async def get_retention_policy_for_room( # maximum. This prevents incorrectly filtering out events when sending to # the client. if not self.config.retention.retention_enabled: - return {"min_lifetime": None, "max_lifetime": None} + return RetentionPolicy() def get_retention_policy_for_room_txn( txn: LoggingTransaction, @@ -746,10 +746,10 @@ def get_retention_policy_for_room_txn( # If we don't know this room ID, ret will be None, in this case return the default # policy. if not ret: - return { - "min_lifetime": self.config.retention.retention_default_min_lifetime, - "max_lifetime": self.config.retention.retention_default_max_lifetime, - } + return RetentionPolicy( + min_lifetime=self.config.retention.retention_default_min_lifetime, + max_lifetime=self.config.retention.retention_default_max_lifetime, + ) min_lifetime = ret[0]["min_lifetime"] max_lifetime = ret[0]["max_lifetime"] @@ -764,10 +764,10 @@ def get_retention_policy_for_room_txn( if max_lifetime is None: max_lifetime = self.config.retention.retention_default_max_lifetime - return { - "min_lifetime": min_lifetime, - "max_lifetime": max_lifetime, - } + return RetentionPolicy( + min_lifetime=min_lifetime, + max_lifetime=max_lifetime, + ) async def get_media_mxcs_in_room(self, room_id: str) -> Tuple[List[str], List[str]]: """Retrieves all the local and remote media MXC URIs in a given room @@ -1004,7 +1004,7 @@ def _quarantine_media_txn( async def get_rooms_for_retention_period_in_range( self, min_ms: Optional[int], max_ms: Optional[int], include_null: bool = False - ) -> Dict[str, Dict[str, Optional[int]]]: + ) -> Dict[str, RetentionPolicy]: """Retrieves all of the rooms within the given retention range. Optionally includes the rooms which don't have a retention policy. @@ -1057,10 +1057,10 @@ def get_rooms_for_retention_period_in_range_txn( rooms_dict = {} for row in rows: - rooms_dict[row["room_id"]] = { - "min_lifetime": row["min_lifetime"], - "max_lifetime": row["max_lifetime"], - } + rooms_dict[row["room_id"]] = RetentionPolicy( + min_lifetime=row["min_lifetime"], + max_lifetime=row["max_lifetime"], + ) if include_null: # If required, do a second query that retrieves all of the rooms we know @@ -1075,10 +1075,7 @@ def get_rooms_for_retention_period_in_range_txn( # policy in its state), add it with a null policy. for row in rows: if row["room_id"] not in rooms_dict: - rooms_dict[row["room_id"]] = { - "min_lifetime": None, - "max_lifetime": None, - } + rooms_dict[row["room_id"]] = RetentionPolicy() return rooms_dict diff --git a/synapse/types.py b/synapse/types.py index 325332a6e00f..6e3b2b7a9539 100644 --- a/synapse/types.py +++ b/synapse/types.py @@ -916,3 +916,9 @@ class UserProfile(TypedDict): user_id: str display_name: Optional[str] avatar_url: Optional[str] + + +@attr.s(auto_attribs=True, frozen=True) +class RetentionPolicy: + min_lifetime: Optional[int] = None + max_lifetime: Optional[int] = None diff --git a/synapse/visibility.py b/synapse/visibility.py index de6d2ffc526a..0ce2cc095cf6 100644 --- a/synapse/visibility.py +++ b/synapse/visibility.py @@ -22,7 +22,7 @@ from synapse.events.utils import prune_event from synapse.storage import Storage from synapse.storage.state import StateFilter -from synapse.types import StateMap, get_domain_from_id +from synapse.types import StateMap, get_domain_from_id, RetentionPolicy logger = logging.getLogger(__name__) @@ -94,7 +94,7 @@ async def filter_events_for_client( if filter_send_to_client: room_ids = {e.room_id for e in events} - retention_policies = {} + retention_policies: Dict[str, RetentionPolicy] = {} for room_id in room_ids: retention_policies[ @@ -137,7 +137,7 @@ def allowed(event: EventBase) -> Optional[EventBase]: # events. if not event.is_state(): retention_policy = retention_policies[event.room_id] - max_lifetime = retention_policy.get("max_lifetime") + max_lifetime = retention_policy.max_lifetime if max_lifetime is not None: oldest_allowed_ts = storage.main.clock.time_msec() - max_lifetime From 4901b9e084caec5a3db028a82bc894d9df4e289c Mon Sep 17 00:00:00 2001 From: Brendan Abolivier Date: Mon, 23 May 2022 18:33:18 +0200 Subject: [PATCH 13/15] Update synapse/types.py Co-authored-by: Patrick Cloke --- synapse/types.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/synapse/types.py b/synapse/types.py index 6e3b2b7a9539..287e837f766f 100644 --- a/synapse/types.py +++ b/synapse/types.py @@ -918,7 +918,7 @@ class UserProfile(TypedDict): avatar_url: Optional[str] -@attr.s(auto_attribs=True, frozen=True) +@attr.s(auto_attribs=True, frozen=True, slots=True) class RetentionPolicy: min_lifetime: Optional[int] = None max_lifetime: Optional[int] = None From b9991bbb67c96b1eca663d52d2078e705e5d184e Mon Sep 17 00:00:00 2001 From: Brendan Abolivier Date: Mon, 23 May 2022 17:41:07 +0100 Subject: [PATCH 14/15] Lint and types --- synapse/storage/databases/main/room.py | 6 +++--- synapse/visibility.py | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/synapse/storage/databases/main/room.py b/synapse/storage/databases/main/room.py index 0f7976ad43e5..7cb6434d4ae4 100644 --- a/synapse/storage/databases/main/room.py +++ b/synapse/storage/databases/main/room.py @@ -45,7 +45,7 @@ from synapse.storage.databases.main.cache import CacheInvalidationWorkerStore from synapse.storage.types import Cursor from synapse.storage.util.id_generators import IdGenerator -from synapse.types import JsonDict, ThirdPartyInstanceID, RetentionPolicy +from synapse.types import JsonDict, RetentionPolicy, ThirdPartyInstanceID from synapse.util import json_encoder from synapse.util.caches.descriptors import cached from synapse.util.stringutils import MXC_REGEX @@ -701,7 +701,7 @@ def delete_ratelimit_txn(txn: LoggingTransaction) -> None: @cached() async def get_retention_policy_for_room( self, room_id: str - ) -> Dict[str, Optional[int]]: + ) -> RetentionPolicy: """Get the retention policy for a given room. If no retention policy has been found for this room, returns a policy defined @@ -1026,7 +1026,7 @@ async def get_rooms_for_retention_period_in_range( def get_rooms_for_retention_period_in_range_txn( txn: LoggingTransaction, - ) -> Dict[str, Dict[str, Optional[int]]]: + ) -> Dict[str, RetentionPolicy]: range_conditions = [] args = [] diff --git a/synapse/visibility.py b/synapse/visibility.py index 0ce2cc095cf6..da4af02796c3 100644 --- a/synapse/visibility.py +++ b/synapse/visibility.py @@ -22,7 +22,7 @@ from synapse.events.utils import prune_event from synapse.storage import Storage from synapse.storage.state import StateFilter -from synapse.types import StateMap, get_domain_from_id, RetentionPolicy +from synapse.types import RetentionPolicy, StateMap, get_domain_from_id logger = logging.getLogger(__name__) From 4addea5a22813e1668b53de0d9b011cb6e21ea8e Mon Sep 17 00:00:00 2001 From: Brendan Abolivier Date: Mon, 23 May 2022 17:44:49 +0100 Subject: [PATCH 15/15] Lint --- synapse/storage/databases/main/room.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/synapse/storage/databases/main/room.py b/synapse/storage/databases/main/room.py index 7cb6434d4ae4..ded15b92ef84 100644 --- a/synapse/storage/databases/main/room.py +++ b/synapse/storage/databases/main/room.py @@ -699,9 +699,7 @@ def delete_ratelimit_txn(txn: LoggingTransaction) -> None: await self.db_pool.runInteraction("delete_ratelimit", delete_ratelimit_txn) @cached() - async def get_retention_policy_for_room( - self, room_id: str - ) -> RetentionPolicy: + async def get_retention_policy_for_room(self, room_id: str) -> RetentionPolicy: """Get the retention policy for a given room. If no retention policy has been found for this room, returns a policy defined