Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/19024.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Allow Synapse modules to specify a custom threadpool when calling `defer_to_thread`.
13 changes: 11 additions & 2 deletions synapse/module_api/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@

from twisted.internet import defer
from twisted.internet.interfaces import IDelayedCall
from twisted.python.threadpool import ThreadPool
from twisted.web.resource import Resource

from synapse.api import errors
Expand Down Expand Up @@ -78,7 +79,7 @@
from synapse.http.servlet import parse_json_object_from_request
from synapse.http.site import SynapseRequest
from synapse.logging.context import (
defer_to_thread,
defer_to_threadpool,
make_deferred_yieldable,
run_in_background,
)
Expand Down Expand Up @@ -1716,6 +1717,7 @@ def run_as_background_process(
async def defer_to_thread(
self,
f: Callable[P, T],
threadpool: Optional[ThreadPool] = None,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will mess with positional args that people are already using with defer_to_thread.

For example: module_api.defer_to_thread(add, 1, 2) will be have 1 interpreted as the threadpool positional argument.

We could use a keyword argument and hope there aren't arg naming collisions with threadpool with the f function. We could further namespace the variable name like defer_to_thread_threadpool

But I think it might be better if we just introduce defer_to_threadpool to the ModuleApi. We need to rely on a new version of the ModuleApi anyway.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Argh, yes, good point.

While writing this PR, it also felt like a code smell to have the ModuleApi's defer_to_thread actually be defer_to_threadpool under the hood.

I'll rework this PR to expose defer_to_threadpool instead.

*args: P.args,
**kwargs: P.kwargs,
) -> T:
Expand All @@ -1731,7 +1733,14 @@ async def defer_to_thread(
Returns:
The return value of the function once ran in a thread.
"""
return await defer_to_thread(self._hs.get_reactor(), f, *args, **kwargs)
# If a threadpool is not provided by the module, then use the default
# reactor threadpool of the homeserver.
if threadpool is None:
threadpool = self._hs.get_reactor().getThreadPool()

return await defer_to_threadpool(
self._hs.get_reactor(), threadpool, f, *args, **kwargs
)

async def check_username(self, username: str) -> None:
"""Checks if the provided username uses the grammar defined in the Matrix
Expand Down
Loading