mirror of
https://github.com/element-hq/synapse.git
synced 2024-12-14 11:57:44 +00:00
Add a short sleep if the request is rate-limited (#17210)
This helps prevent clients from "tight-looping" retrying their request.
This commit is contained in:
parent
38f03a09ff
commit
52af16c561
6 changed files with 15 additions and 4 deletions
1
changelog.d/17210.misc
Normal file
1
changelog.d/17210.misc
Normal file
|
@ -0,0 +1 @@
|
|||
Add a short pause when rate-limiting a request.
|
|
@ -316,6 +316,10 @@ class Ratelimiter:
|
|||
)
|
||||
|
||||
if not allowed:
|
||||
# We pause for a bit here to stop clients from "tight-looping" on
|
||||
# retrying their request.
|
||||
await self.clock.sleep(0.5)
|
||||
|
||||
raise LimitExceededError(
|
||||
limiter_name=self._limiter_name,
|
||||
retry_after_ms=int(1000 * (time_allowed - time_now_s)),
|
||||
|
|
|
@ -116,8 +116,9 @@ class TestRatelimiter(unittest.HomeserverTestCase):
|
|||
# Should raise
|
||||
with self.assertRaises(LimitExceededError) as context:
|
||||
self.get_success_or_raise(
|
||||
limiter.ratelimit(None, key="test_id", _time_now_s=5)
|
||||
limiter.ratelimit(None, key="test_id", _time_now_s=5), by=0.5
|
||||
)
|
||||
|
||||
self.assertEqual(context.exception.retry_after_ms, 5000)
|
||||
|
||||
# Shouldn't raise
|
||||
|
@ -192,7 +193,7 @@ class TestRatelimiter(unittest.HomeserverTestCase):
|
|||
# Second attempt, 1s later, will fail
|
||||
with self.assertRaises(LimitExceededError) as context:
|
||||
self.get_success_or_raise(
|
||||
limiter.ratelimit(None, key=("test_id",), _time_now_s=1)
|
||||
limiter.ratelimit(None, key=("test_id",), _time_now_s=1), by=0.5
|
||||
)
|
||||
self.assertEqual(context.exception.retry_after_ms, 9000)
|
||||
|
||||
|
|
|
@ -483,6 +483,7 @@ class FederationTestCase(unittest.FederatingHomeserverTestCase):
|
|||
event.room_version,
|
||||
),
|
||||
exc=LimitExceededError,
|
||||
by=0.5,
|
||||
)
|
||||
|
||||
def _build_and_send_join_event(
|
||||
|
|
|
@ -70,6 +70,7 @@ class TestJoinsLimitedByPerRoomRateLimiter(FederatingHomeserverTestCase):
|
|||
action=Membership.JOIN,
|
||||
),
|
||||
LimitExceededError,
|
||||
by=0.5,
|
||||
)
|
||||
|
||||
@override_config({"rc_joins_per_room": {"per_second": 0, "burst_count": 2}})
|
||||
|
@ -206,6 +207,7 @@ class TestJoinsLimitedByPerRoomRateLimiter(FederatingHomeserverTestCase):
|
|||
remote_room_hosts=[self.OTHER_SERVER_NAME],
|
||||
),
|
||||
LimitExceededError,
|
||||
by=0.5,
|
||||
)
|
||||
|
||||
# TODO: test that remote joins to a room are rate limited.
|
||||
|
@ -273,6 +275,7 @@ class TestReplicatedJoinsLimitedByPerRoomRateLimiter(BaseMultiWorkerStreamTestCa
|
|||
action=Membership.JOIN,
|
||||
),
|
||||
LimitExceededError,
|
||||
by=0.5,
|
||||
)
|
||||
|
||||
# Try to join as Chris on the original worker. Should get denied because Alice
|
||||
|
@ -285,6 +288,7 @@ class TestReplicatedJoinsLimitedByPerRoomRateLimiter(BaseMultiWorkerStreamTestCa
|
|||
action=Membership.JOIN,
|
||||
),
|
||||
LimitExceededError,
|
||||
by=0.5,
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -637,13 +637,13 @@ class HomeserverTestCase(TestCase):
|
|||
return self.successResultOf(deferred)
|
||||
|
||||
def get_failure(
|
||||
self, d: Awaitable[Any], exc: Type[_ExcType]
|
||||
self, d: Awaitable[Any], exc: Type[_ExcType], by: float = 0.0
|
||||
) -> _TypedFailure[_ExcType]:
|
||||
"""
|
||||
Run a Deferred and get a Failure from it. The failure must be of the type `exc`.
|
||||
"""
|
||||
deferred: Deferred[Any] = ensureDeferred(d) # type: ignore[arg-type]
|
||||
self.pump()
|
||||
self.pump(by)
|
||||
return self.failureResultOf(deferred, exc)
|
||||
|
||||
def get_success_or_raise(self, d: Awaitable[TV], by: float = 0.0) -> TV:
|
||||
|
|
Loading…
Reference in a new issue