diff --git a/synapse/util/__init__.py b/synapse/util/__init__.py
index 6323d452e7..a90f08dd4c 100644
--- a/synapse/util/__init__.py
+++ b/synapse/util/__init__.py
@@ -20,6 +20,7 @@ from typing import Any, Callable, Dict, Generator, Optional
import attr
from frozendict import frozendict
from matrix_common.versionstring import get_distribution_version_string
+from typing_extensions import ParamSpec
from twisted.internet import defer, task
from twisted.internet.defer import Deferred
@@ -82,6 +83,9 @@ def unwrapFirstError(failure: Failure) -> Failure:
return failure.value.subFailure # type: ignore[union-attr] # Issue in Twisted's annotations
+P = ParamSpec("P")
+
+
@attr.s(slots=True)
class Clock:
"""
@@ -110,7 +114,7 @@ class Clock:
return int(self.time() * 1000)
def looping_call(
- self, f: Callable, msec: float, *args: Any, **kwargs: Any
+ self, f: Callable[P, object], msec: float, *args: P.args, **kwargs: P.kwargs
) -> LoopingCall:
"""Call a function repeatedly.
diff --git a/synapse/util/caches/lrucache.py b/synapse/util/caches/lrucache.py
index a3b60578e3..8ed5325c5d 100644
--- a/synapse/util/caches/lrucache.py
+++ b/synapse/util/caches/lrucache.py
@@ -109,7 +109,7 @@ GLOBAL_ROOT = ListNode["_Node"].create_root_node()
@wrap_as_background_process("LruCache._expire_old_entries")
async def _expire_old_entries(
- clock: Clock, expiry_seconds: int, autotune_config: Optional[dict]
+ clock: Clock, expiry_seconds: float, autotune_config: Optional[dict]
) -> None:
"""Walks the global cache list to find cache entries that haven't been
accessed in the given number of seconds, or if a given memory threshold has been breached.
|