Skip to content
This repository has been archived by the owner on Apr 26, 2024. It is now read-only.

Commit

Permalink
Add documentation for caching in a module (#14026)
Browse files Browse the repository at this point in the history
* Add documentation for caching in a module

* Changelog

* Formatting

* Wrap lines at a length that mdbook is happier with

* Typo fix

Co-authored-by: Erik Johnston <[email protected]>

* Link to recent version of the API

In the longer term I'd like to see us generate markdown with Sphinx.

* Refer to public `cached` decorator

* Mark caching as being added in 1.74

Some of the underlying infrastructure was added in 1.69, but the
public-facing `cached` decorator was only added in 1.74. It is the
latter that I think we should be advertising.

* Update docs/modules/writing_a_module.md

Co-authored-by: Patrick Cloke <[email protected]>

---------

Co-authored-by: David Robertson <[email protected]>
Co-authored-by: Erik Johnston <[email protected]>
Co-authored-by: Patrick Cloke <[email protected]>
  • Loading branch information
4 people authored Feb 28, 2023
1 parent 93f7955 commit 5210268
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 0 deletions.
1 change: 1 addition & 0 deletions changelog.d/14026.doc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Document how to use caches in a module.
56 changes: 56 additions & 0 deletions docs/modules/writing_a_module.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,3 +83,59 @@ the callback name as the argument name and the function as its value. A

Callbacks for each category can be found on their respective page of the
[Synapse documentation website](https://matrix-org.github.io/synapse).

## Caching

_Added in Synapse 1.74.0._

Modules can leverage Synapse's caching tools to manage their own cached functions. This
can be helpful for modules that need to repeatedly request the same data from the database
or a remote service.

Functions that need to be wrapped with a cache need to be decorated with a `@cached()`
decorator (which can be imported from `synapse.module_api`) and registered with the
[`ModuleApi.register_cached_function`](https://github.com/matrix-org/synapse/blob/release-v1.77/synapse/module_api/__init__.py#L888)
API when initialising the module. If the module needs to invalidate an entry in a cache,
it needs to use the [`ModuleApi.invalidate_cache`](https://github.com/matrix-org/synapse/blob/release-v1.77/synapse/module_api/__init__.py#L904)
API, with the function to invalidate the cache of and the key(s) of the entry to
invalidate.

Below is an example of a simple module using a cached function:

```python
from typing import Any
from synapse.module_api import cached, ModuleApi

class MyModule:
def __init__(self, config: Any, api: ModuleApi):
self.api = api

# Register the cached function so Synapse knows how to correctly invalidate
# entries for it.
self.api.register_cached_function(self.get_user_from_id)

@cached()
async def get_department_for_user(self, user_id: str) -> str:
"""A function with a cache."""
# Request a department from an external service.
return await self.http_client.get_json(
"https://int.example.com/users", {"user_id": user_id)
)["department"]

async def do_something_with_users(self) -> None:
"""Calls the cached function and then invalidates an entry in its cache."""

user_id = "@alice:example.com"

# Get the user. Since get_department_for_user is wrapped with a cache,
# the return value for this user_id will be cached.
department = await self.get_department_for_user(user_id)

# Do something with `department`...

# Let's say something has changed with our user, and the entry we have for
# them in the cache is out of date, so we want to invalidate it.
await self.api.invalidate_cache(self.get_department_for_user, (user_id,))
```

See the [`cached` docstring](https://github.com/matrix-org/synapse/blob/release-v1.77/synapse/module_api/__init__.py#L190) for more details.

0 comments on commit 5210268

Please sign in to comment.