summary refs log tree commit diff
diff options
context:
space:
mode:
authorOlivier Wilkinson (reivilibre) <oliverw@matrix.org>2021-12-20 12:23:40 +0000
committerOlivier Wilkinson (reivilibre) <oliverw@matrix.org>2021-12-20 12:23:40 +0000
commit13a16f5d0397e0ed9fd638589aea79669b21ddc9 (patch)
treea0d85cf7889868b0d5aef4d4163421733733732a
parentFix up misunderstanding (fixes tests) (diff)
downloadsynapse-13a16f5d0397e0ed9fd638589aea79669b21ddc9.tar.xz
Shunt out with StateFilter.all() if many requests are made to the same group
-rw-r--r--synapse/storage/databases/state/store.py14
1 files changed, 14 insertions, 0 deletions
diff --git a/synapse/storage/databases/state/store.py b/synapse/storage/databases/state/store.py
index 75de8fe3ca..197c0bbc44 100644
--- a/synapse/storage/databases/state/store.py
+++ b/synapse/storage/databases/state/store.py
@@ -52,6 +52,7 @@ if TYPE_CHECKING:
 logger = logging.getLogger(__name__)
 
 MAX_STATE_DELTA_HOPS = 100
+MAX_INFLIGHT_REQUESTS_PER_GROUP = 5
 
 
 @attr.s(slots=True, frozen=True, auto_attribs=True)
@@ -254,6 +255,11 @@ class StateGroupDataStore(StateBackgroundUpdateStore, SQLBaseStore):
         Attempts to gather in-flight requests and re-use them to retrieve state
         for the given state group, filtered with the given state filter.
 
+        If there are more than MAX_INFLIGHT_REQUESTS_PER_GROUP in-flight requests,
+        and there *still* isn't enough information to complete the request by solely
+        reusing others, a full state filter will be requested to ensure that subsequent
+        requests can reuse this request.
+
         Returns:
             tuple (
                 sequence of ObservableDeferreds to observe,
@@ -285,6 +291,14 @@ class StateGroupDataStore(StateBackgroundUpdateStore, SQLBaseStore):
                 # to cover our StateFilter and give us the state we need.
                 break
 
+        if state_filter_left_over != StateFilter.none():
+            if len(inflight_requests) >= MAX_INFLIGHT_REQUESTS_PER_GROUP:
+                # There are too many requests for this group.
+                # To prevent even more from building up, we request the whole
+                # state filter to guarantee that we can be reused by any subsequent
+                # requests for this state group.
+                return (), StateFilter.all()
+
         return reusable_requests, state_filter_left_over
 
     async def _get_state_for_group_fire_request(