Skip to content

Commit 2c73e8d

Browse files
authored
Allow long lived syncs to be cancelled if client has gone away (#19499)
1 parent f78d011 commit 2c73e8d

File tree

21 files changed

+703
-39
lines changed

21 files changed

+703
-39
lines changed

changelog.d/19499.misc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Cancel long-running sync requests if the client has gone away.

pyproject.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,12 @@ indent-style = "space"
411411
skip-magic-trailing-comma = false
412412
line-ending = "auto"
413413

414+
[tool.ruff.lint.flake8-bugbear]
415+
extend-immutable-calls = [
416+
# Durations are immutable
417+
"synapse.util.duration.Duration",
418+
]
419+
414420
[tool.maturin]
415421
manifest-path = "rust/Cargo.toml"
416422
module-name = "synapse.synapse_rust"

synapse/api/auth/mas.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
from synapse.types import JsonDict, Requester, UserID, create_requester
4646
from synapse.util.caches.cached_call import RetryOnExceptionCachedCall
4747
from synapse.util.caches.response_cache import ResponseCache, ResponseCacheContext
48+
from synapse.util.duration import Duration
4849
from synapse.util.json import json_decoder
4950

5051
from . import introspection_response_timer
@@ -139,7 +140,7 @@ def __init__(self, hs: "HomeServer"):
139140
clock=self._clock,
140141
name="mas_token_introspection",
141142
server_name=self.server_name,
142-
timeout_ms=120_000,
143+
timeout=Duration(minutes=2),
143144
# don't log because the keys are access tokens
144145
enable_logging=False,
145146
)

synapse/api/auth/msc3861_delegated.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
from synapse.types import Requester, UserID, create_requester
5050
from synapse.util.caches.cached_call import RetryOnExceptionCachedCall
5151
from synapse.util.caches.response_cache import ResponseCache, ResponseCacheContext
52+
from synapse.util.duration import Duration
5253
from synapse.util.json import json_decoder
5354

5455
from . import introspection_response_timer
@@ -205,7 +206,7 @@ def __init__(self, hs: "HomeServer"):
205206
clock=self._clock,
206207
name="token_introspection",
207208
server_name=self.server_name,
208-
timeout_ms=120_000,
209+
timeout=Duration(minutes=2),
209210
# don't log because the keys are access tokens
210211
enable_logging=False,
211212
)

synapse/appservice/api.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
from synapse.metrics import SERVER_NAME_LABEL
4747
from synapse.types import DeviceListUpdates, JsonDict, JsonMapping, ThirdPartyInstanceID
4848
from synapse.util.caches.response_cache import ResponseCache
49+
from synapse.util.duration import Duration
4950

5051
if TYPE_CHECKING:
5152
from synapse.server import HomeServer
@@ -132,7 +133,7 @@ def __init__(self, hs: "HomeServer"):
132133
clock=hs.get_clock(),
133134
name="as_protocol_meta",
134135
server_name=self.server_name,
135-
timeout_ms=HOUR_IN_MS,
136+
timeout=Duration(hours=1),
136137
)
137138

138139
def _get_headers(self, service: "ApplicationService") -> dict[bytes, list[bytes]]:

synapse/config/cache.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929

3030
from synapse.types import JsonDict
3131
from synapse.util.check_dependencies import check_requirements
32+
from synapse.util.duration import Duration
3233

3334
from ._base import Config, ConfigError
3435

@@ -108,7 +109,7 @@ class CacheConfig(Config):
108109
global_factor: float
109110
track_memory_usage: bool
110111
expiry_time_msec: int | None
111-
sync_response_cache_duration: int
112+
sync_response_cache_duration: Duration
112113

113114
@staticmethod
114115
def reset() -> None:
@@ -207,10 +208,14 @@ def read_config(self, config: JsonDict, **kwargs: Any) -> None:
207208
min_cache_ttl = self.cache_autotuning.get("min_cache_ttl")
208209
self.cache_autotuning["min_cache_ttl"] = self.parse_duration(min_cache_ttl)
209210

210-
self.sync_response_cache_duration = self.parse_duration(
211+
sync_response_cache_duration_ms = self.parse_duration(
211212
cache_config.get("sync_response_cache_duration", "2m")
212213
)
213214

215+
self.sync_response_cache_duration = Duration(
216+
milliseconds=sync_response_cache_duration_ms
217+
)
218+
214219
def resize_all_caches(self) -> None:
215220
"""Ensure all cache sizes are up-to-date.
216221

synapse/federation/federation_server.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ def __init__(self, hs: "HomeServer"):
166166
clock=hs.get_clock(),
167167
name="fed_txn_handler",
168168
server_name=self.server_name,
169-
timeout_ms=30000,
169+
timeout=Duration(seconds=30),
170170
)
171171

172172
self.transaction_actions = TransactionActions(self.store)
@@ -179,13 +179,13 @@ def __init__(self, hs: "HomeServer"):
179179
clock=hs.get_clock(),
180180
name="state_resp",
181181
server_name=self.server_name,
182-
timeout_ms=30000,
182+
timeout=Duration(seconds=30),
183183
)
184184
self._state_ids_resp_cache: ResponseCache[tuple[str, str]] = ResponseCache(
185185
clock=hs.get_clock(),
186186
name="state_ids_resp",
187187
server_name=self.server_name,
188-
timeout_ms=30000,
188+
timeout=Duration(seconds=30),
189189
)
190190

191191
self._federation_metrics_domains = (

synapse/handlers/room.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ def __init__(self, hs: "HomeServer"):
185185
clock=hs.get_clock(),
186186
name="room_upgrade",
187187
server_name=self.server_name,
188-
timeout_ms=FIVE_MINUTES_IN_MS,
188+
timeout=Duration(minutes=5),
189189
)
190190
self._server_notices_mxid = hs.config.servernotices.server_notices_mxid
191191

synapse/handlers/room_list.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
from synapse.types import JsonDict, JsonMapping, ThirdPartyInstanceID
4545
from synapse.util.caches.descriptors import _CacheContext, cached
4646
from synapse.util.caches.response_cache import ResponseCache
47+
from synapse.util.duration import Duration
4748

4849
if TYPE_CHECKING:
4950
from synapse.server import HomeServer
@@ -79,7 +80,7 @@ def __init__(self, hs: "HomeServer"):
7980
clock=hs.get_clock(),
8081
name="remote_room_list",
8182
server_name=self.server_name,
82-
timeout_ms=30 * 1000,
83+
timeout=Duration(seconds=30),
8384
)
8485

8586
async def get_local_public_room_list(

synapse/handlers/sync.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@
7777
from synapse.util.caches.expiringcache import ExpiringCache
7878
from synapse.util.caches.lrucache import LruCache
7979
from synapse.util.caches.response_cache import ResponseCache, ResponseCacheContext
80+
from synapse.util.cancellation import cancellable
8081
from synapse.util.metrics import Measure
8182
from synapse.visibility import filter_and_transform_events_for_client
8283

@@ -307,7 +308,7 @@ def __init__(self, hs: "HomeServer"):
307308
clock=hs.get_clock(),
308309
name="sync",
309310
server_name=self.server_name,
310-
timeout_ms=hs.config.caches.sync_response_cache_duration,
311+
timeout=hs.config.caches.sync_response_cache_duration,
311312
)
312313

313314
# ExpiringCache((User, Device)) -> LruCache(user_id => event_id)
@@ -367,6 +368,10 @@ async def wait_for_sync_for_user(
367368
logger.debug("Returning sync response for %s", user_id)
368369
return res
369370

371+
# TODO: We mark this as cancellable, and we have tests for it, but we
372+
# haven't gone through and exhaustively checked that all the code paths in
373+
# this method are actually cancellable.
374+
@cancellable
370375
async def _wait_for_sync_for_user(
371376
self,
372377
sync_config: SyncConfig,

0 commit comments

Comments
 (0)