diff --git a/changelog.d/14663.feature b/changelog.d/14663.feature
new file mode 100644
index 0000000000..b03f3ee54e
--- /dev/null
+++ b/changelog.d/14663.feature
@@ -0,0 +1 @@
+Add a `cached` function to `synapse.module_api` that returns a decorator to cache return values of functions.
diff --git a/synapse/module_api/__init__.py b/synapse/module_api/__init__.py
index 0092a03c59..6f4a934b05 100644
--- a/synapse/module_api/__init__.py
+++ b/synapse/module_api/__init__.py
@@ -18,6 +18,7 @@ from typing import (
TYPE_CHECKING,
Any,
Callable,
+ Collection,
Dict,
Generator,
Iterable,
@@ -126,7 +127,7 @@ from synapse.types import (
from synapse.types.state import StateFilter
from synapse.util import Clock
from synapse.util.async_helpers import maybe_awaitable
-from synapse.util.caches.descriptors import CachedFunction, cached
+from synapse.util.caches.descriptors import CachedFunction, cached as _cached
from synapse.util.frozenutils import freeze
if TYPE_CHECKING:
@@ -136,6 +137,7 @@ if TYPE_CHECKING:
T = TypeVar("T")
P = ParamSpec("P")
+F = TypeVar("F", bound=Callable[..., Any])
"""
This package defines the 'stable' API which can be used by extension modules which
@@ -185,6 +187,42 @@ class UserIpAndAgent:
last_seen: int
+def cached(
+ *,
+ max_entries: int = 1000,
+ num_args: Optional[int] = None,
+ uncached_args: Optional[Collection[str]] = None,
+) -> Callable[[F], CachedFunction[F]]:
+ """Returns a decorator that applies a memoizing cache around the function. This
+ decorator behaves similarly to functools.lru_cache.
+
+ Example:
+
+ @cached()
+ def foo('a', 'b'):
+ ...
+
+ Added in Synapse v1.74.0.
+
+ Args:
+ max_entries: The maximum number of entries in the cache. If the cache is full
+ and a new entry is added, the least recently accessed entry will be evicted
+ from the cache.
+ num_args: The number of positional arguments (excluding `self`) to use as cache
+ keys. Defaults to all named args of the function.
+ uncached_args: A list of argument names to not use as the cache key. (`self` is
+ always ignored.) Cannot be used with num_args.
+
+ Returns:
+ A decorator that applies a memoizing cache around the function.
+ """
+ return _cached(
+ max_entries=max_entries,
+ num_args=num_args,
+ uncached_args=uncached_args,
+ )
+
+
class ModuleApi:
"""A proxy object that gets passed to various plugin modules so they
can register new users etc if necessary.
|