Skip to content
1 change: 1 addition & 0 deletions changelog.d/18871.misc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Store the `LoggingContext` in a `ContextVar` instead of a thread-local variable.
325 changes: 53 additions & 272 deletions docs/log_contexts.md

Large diffs are not rendered by default.

7 changes: 0 additions & 7 deletions synapse/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,12 +86,5 @@ def _immutabledict_cb(d: immutabledict) -> Dict[str, Any]:

__version__ = synapse.util.SYNAPSE_VERSION

if bool(os.environ.get("SYNAPSE_TEST_PATCH_LOG_CONTEXTS", False)):
# We import here so that we don't have to install a bunch of deps when
# running the packaging tox test.
from synapse.util.patch_inline_callbacks import do_patch

do_patch()
Comment on lines -89 to -94
Copy link
Contributor Author

Choose a reason for hiding this comment

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

See #18871 (comment) for why we've removed the patch_inline_callbacks



check_rust_lib_up_to_date()
6 changes: 6 additions & 0 deletions synapse/app/_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -601,6 +601,12 @@ def run_sighup(*args: Any, **kwargs: Any) -> None:
hs.get_datastores().main.db_pool.start_profiling()
hs.get_pusherpool().start()

# Register background tasks required by this server. This must be done
# somewhat manually due to the background tasks not being registered
# unless handlers are instantiated.
if hs.config.worker.run_background_tasks:
hs.start_background_tasks()
Comment on lines +604 to +608
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Split out this change to #18886 since it seems good in any case

And this PR may get stale


# Log when we start the shut down process.
hs.get_reactor().addSystemEventTrigger(
"before", "shutdown", logger.info, "Shutting down..."
Expand Down
99 changes: 9 additions & 90 deletions synapse/logging/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import threading
import typing
import warnings
from contextvars import ContextVar
from types import TracebackType
from typing import (
TYPE_CHECKING,
Expand Down Expand Up @@ -653,13 +654,12 @@ def __exit__(
)


_thread_local = threading.local()
_thread_local.current_context = SENTINEL_CONTEXT
_current_context: ContextVar[LoggingContextOrSentinel] = ContextVar("current_context")
Copy link
Contributor Author

@MadLittleMods MadLittleMods Sep 3, 2025

Choose a reason for hiding this comment

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

Error: Called stop on logcontext POST-0 without recording a start rusage

There is a problem where the POST-0 LoggingContext is somehow becoming the current context without a corresponding set_current_context(POST-0) call.

See the lines marked red in the snippet below.

SYNAPSE_TEST_LOG_LEVEL=INFO poetry run trial tests.rest.client.test_rooms.RoomStateTestCase.test_get_state_event_cancellation

_trial_temp/test.log

  2025-09-02 19:12:06-0500 [-] synapse.http.site - 304 - INFO - sentinel - asdf SynapseRequest render
  2025-09-02 19:12:06-0500 [-] synapse.logging.context - 662 - INFO - sentinel - asdf PreserveLoggingContext(POST-0).__enter__ nonce=meZAG
+ 2025-09-02 19:12:06-0500 [-] synapse.logging.context - 723 - INFO - sentinel - asdf set_current_context(POST-0) (previous=sentinel)
+ 2025-09-02 19:12:06-0500 [-] synapse.logging.context - 454 - INFO - POST-0 - asdf LoggingContext(POST-0).start  usage_start=True
+ 2025-09-02 19:12:06-0500 [-] synapse.logging.context - 675 - INFO - POST-0 - asdf PreserveLoggingContext(POST-0).__exit__ nonce=meZAG restoring old_context=sentinel
+ 2025-09-02 19:12:06-0500 [-] synapse.logging.context - 723 - INFO - POST-0 - asdf set_current_context(sentinel) (previous=POST-0)
+ 2025-09-02 19:12:06-0500 [-] synapse.logging.context - 471 - INFO - POST-0 - asdf LoggingContext(POST-0).stop usage_start=True rusage=True
  2025-09-02 19:12:06-0500 [-] synapse.logging.context - 662 - INFO - sentinel - asdf PreserveLoggingContext(sentinel).__enter__ nonce=xQsLm
  2025-09-02 19:12:06-0500 [-] synapse.logging.context - 723 - INFO - sentinel - asdf set_current_context(sentinel) (previous=sentinel)
  2025-09-02 19:12:06-0500 [-] synapse.logging.context - 723 - INFO - sentinel - asdf set_current_context(_handle_new_device_update_async-0) (previous=sentinel)
  2025-09-02 19:12:06-0500 [-] synapse.logging.context - 454 - INFO - _handle_new_device_update_async-0 - asdf LoggingContext(_handle_new_device_update_async-0).start  usage_start=True
  2025-09-02 19:12:06-0500 [-] synapse.logging.context - 675 - INFO - sentinel - asdf PreserveLoggingContext(sentinel).__exit__ nonce=xQsLm restoring old_context=sentinel
  2025-09-02 19:12:06-0500 [-] synapse.logging.context - 723 - INFO - sentinel - asdf set_current_context(sentinel) (previous=sentinel)
  2025-09-02 19:12:06-0500 [-] synapse.logging.context - 723 - INFO - sentinel - asdf set_current_context(db-POST-0) (previous=sentinel)
  2025-09-02 19:12:06-0500 [-] synapse.logging.context - 454 - INFO - db-POST-0 - asdf LoggingContext(db-POST-0).start  usage_start=True
  2025-09-02 19:12:06-0500 [-] synapse.logging.context - 723 - INFO - db-POST-0 - asdf set_current_context(sentinel) (previous=db-POST-0)
  2025-09-02 19:12:06-0500 [-] synapse.logging.context - 471 - INFO - db-POST-0 - asdf LoggingContext(db-POST-0).stop usage_start=True rusage=True
  2025-09-02 19:12:06-0500 [-] synapse.logging.context - 723 - INFO - sentinel - asdf set_current_context(db-_handle_new_device_update_async-0) (previous=sentinel)
  2025-09-02 19:12:06-0500 [-] synapse.logging.context - 454 - INFO - db-_handle_new_device_update_async-0 - asdf LoggingContext(db-_handle_new_device_update_async-0).start  usage_start=True
  2025-09-02 19:12:06-0500 [-] synapse.logging.context - 723 - INFO - db-_handle_new_device_update_async-0 - asdf set_current_context(sentinel) (previous=db-_handle_new_device_update_async-0)
  2025-09-02 19:12:06-0500 [-] synapse.logging.context - 471 - INFO - db-_handle_new_device_update_async-0 - asdf LoggingContext(db-_handle_new_device_update_async-0).stop usage_start=True rusage=True
  2025-09-02 19:12:06-0500 [-] synapse.logging.context - 723 - INFO - sentinel - asdf set_current_context(db-POST-0) (previous=sentinel)
  2025-09-02 19:12:06-0500 [-] synapse.logging.context - 454 - INFO - db-POST-0 - asdf LoggingContext(db-POST-0).start  usage_start=True
  2025-09-02 19:12:06-0500 [-] synapse.logging.context - 723 - INFO - db-POST-0 - asdf set_current_context(sentinel) (previous=db-POST-0)
  2025-09-02 19:12:06-0500 [-] synapse.logging.context - 471 - INFO - db-POST-0 - asdf LoggingContext(db-POST-0).stop usage_start=True rusage=True
  2025-09-02 19:12:06-0500 [-] synapse.logging.context - 723 - INFO - sentinel - asdf set_current_context(db-_handle_new_device_update_async-0) (previous=sentinel)
  2025-09-02 19:12:06-0500 [-] synapse.logging.context - 454 - INFO - db-_handle_new_device_update_async-0 - asdf LoggingContext(db-_handle_new_device_update_async-0).start  usage_start=True
  2025-09-02 19:12:06-0500 [-] synapse.logging.context - 723 - INFO - db-_handle_new_device_update_async-0 - asdf set_current_context(sentinel) (previous=db-_handle_new_device_update_async-0)
  2025-09-02 19:12:06-0500 [-] synapse.logging.context - 471 - INFO - db-_handle_new_device_update_async-0 - asdf LoggingContext(db-_handle_new_device_update_async-0).stop usage_start=True rusage=True
  2025-09-02 19:12:06-0500 [-] synapse.logging.context - 723 - INFO - sentinel - asdf set_current_context(db-POST-0) (previous=sentinel)
  2025-09-02 19:12:06-0500 [-] synapse.logging.context - 454 - INFO - db-POST-0 - asdf LoggingContext(db-POST-0).start  usage_start=True
  2025-09-02 19:12:06-0500 [-] synapse.logging.context - 723 - INFO - db-POST-0 - asdf set_current_context(sentinel) (previous=db-POST-0)
  2025-09-02 19:12:06-0500 [-] synapse.logging.context - 471 - INFO - db-POST-0 - asdf LoggingContext(db-POST-0).stop usage_start=True rusage=True
  2025-09-02 19:12:06-0500 [-] synapse.logging.context - 723 - INFO - _handle_new_device_update_async-0 - asdf set_current_context(sentinel) (previous=_handle_new_device_update_async-0)
  2025-09-02 19:12:06-0500 [-] synapse.logging.context - 471 - INFO - _handle_new_device_update_async-0 - asdf LoggingContext(_handle_new_device_update_async-0).stop usage_start=True rusage=True
  2025-09-02 19:12:06-0500 [-] synapse.logging.context - 723 - INFO - sentinel - asdf set_current_context(db-POST-0) (previous=sentinel)
  2025-09-02 19:12:06-0500 [-] synapse.logging.context - 454 - INFO - db-POST-0 - asdf LoggingContext(db-POST-0).start  usage_start=True
  2025-09-02 19:12:06-0500 [-] synapse.logging.context - 723 - INFO - db-POST-0 - asdf set_current_context(sentinel) (previous=db-POST-0)
  2025-09-02 19:12:06-0500 [-] synapse.logging.context - 471 - INFO - db-POST-0 - asdf LoggingContext(db-POST-0).stop usage_start=True rusage=True
  2025-09-02 19:12:06-0500 [-] synapse.logging.context - 723 - INFO - sentinel - asdf set_current_context(db-POST-0) (previous=sentinel)
  2025-09-02 19:12:06-0500 [-] synapse.logging.context - 454 - INFO - db-POST-0 - asdf LoggingContext(db-POST-0).start  usage_start=True
  2025-09-02 19:12:06-0500 [-] synapse.logging.context - 723 - INFO - db-POST-0 - asdf set_current_context(sentinel) (previous=db-POST-0)
  2025-09-02 19:12:06-0500 [-] synapse.logging.context - 471 - INFO - db-POST-0 - asdf LoggingContext(db-POST-0).stop usage_start=True rusage=True
  2025-09-02 19:12:06-0500 [-] synapse.logging.context - 723 - INFO - sentinel - asdf set_current_context(db-POST-0) (previous=sentinel)
  2025-09-02 19:12:06-0500 [-] synapse.logging.context - 454 - INFO - db-POST-0 - asdf LoggingContext(db-POST-0).start  usage_start=True
  2025-09-02 19:12:06-0500 [-] synapse.logging.context - 723 - INFO - db-POST-0 - asdf set_current_context(sentinel) (previous=db-POST-0)
  2025-09-02 19:12:06-0500 [-] synapse.logging.context - 471 - INFO - db-POST-0 - asdf LoggingContext(db-POST-0).stop usage_start=True rusage=True
  2025-09-02 19:12:06-0500 [-] synapse.logging.context - 723 - INFO - sentinel - asdf set_current_context(db-POST-0) (previous=sentinel)
  2025-09-02 19:12:06-0500 [-] synapse.logging.context - 454 - INFO - db-POST-0 - asdf LoggingContext(db-POST-0).start  usage_start=True
  2025-09-02 19:12:06-0500 [-] synapse.logging.context - 723 - INFO - db-POST-0 - asdf set_current_context(sentinel) (previous=db-POST-0)
  2025-09-02 19:12:06-0500 [-] synapse.logging.context - 471 - INFO - db-POST-0 - asdf LoggingContext(db-POST-0).stop usage_start=True rusage=True
  2025-09-02 19:12:06-0500 [-] synapse.logging.context - 723 - INFO - sentinel - asdf set_current_context(db-POST-0) (previous=sentinel)
  2025-09-02 19:12:06-0500 [-] synapse.logging.context - 454 - INFO - db-POST-0 - asdf LoggingContext(db-POST-0).start  usage_start=True
  2025-09-02 19:12:06-0500 [-] synapse.logging.context - 723 - INFO - db-POST-0 - asdf set_current_context(sentinel) (previous=db-POST-0)
  2025-09-02 19:12:06-0500 [-] synapse.logging.context - 471 - INFO - db-POST-0 - asdf LoggingContext(db-POST-0).stop usage_start=True rusage=True
  2025-09-02 19:12:06-0500 [-] synapse.logging.context - 723 - INFO - sentinel - asdf set_current_context(db-POST-0) (previous=sentinel)
  2025-09-02 19:12:06-0500 [-] synapse.logging.context - 454 - INFO - db-POST-0 - asdf LoggingContext(db-POST-0).start  usage_start=True
  2025-09-02 19:12:06-0500 [-] synapse.logging.context - 723 - INFO - db-POST-0 - asdf set_current_context(sentinel) (previous=db-POST-0)
  2025-09-02 19:12:06-0500 [-] synapse.logging.context - 471 - INFO - db-POST-0 - asdf LoggingContext(db-POST-0).stop usage_start=True rusage=True
  2025-09-02 19:12:06-0500 [-] synapse.logging.context - 723 - INFO - sentinel - asdf set_current_context(db-POST-0) (previous=sentinel)
  2025-09-02 19:12:06-0500 [-] synapse.logging.context - 454 - INFO - db-POST-0 - asdf LoggingContext(db-POST-0).start  usage_start=True
  2025-09-02 19:12:06-0500 [-] synapse.logging.context - 723 - INFO - db-POST-0 - asdf set_current_context(sentinel) (previous=db-POST-0)
  2025-09-02 19:12:06-0500 [-] synapse.logging.context - 471 - INFO - db-POST-0 - asdf LoggingContext(db-POST-0).stop usage_start=True rusage=True
- 2025-09-02 19:12:06-0500 [-] synapse.logging.context - 662 - INFO - POST-0 - asdf PreserveLoggingContext(sentinel).__enter__ nonce=JvLjU
- 2025-09-02 19:12:06-0500 [-] synapse.logging.context - 723 - INFO - POST-0 - asdf set_current_context(sentinel) (previous=POST-0)
- 2025-09-02 19:12:06-0500 [-] synapse.logging.context - 471 - INFO - POST-0 - asdf LoggingContext(POST-0).stop usage_start=False rusage=True
- 2025-09-02 19:12:06-0500 [-] synapse.logging.context - 488 - ERROR - POST-0 - asdf Called stop on logcontext POST-0 without recording a start rusage

Copy link
Contributor Author

@MadLittleMods MadLittleMods Sep 3, 2025

Choose a reason for hiding this comment

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

Perhaps this is a Twisted bug?

I was under the impression that Twisted supported ContextVar's but now I'm not sure. All of the issues mentioned in matrix-org/synapse#10342 are resolved but there are other things in the Twisted tracker:

Unresolved issues:

Resolved issues:

And we could even be running into something unreported 🤷 Need to investigate more.

Copy link
Contributor Author

@MadLittleMods MadLittleMods Sep 4, 2025

Choose a reason for hiding this comment

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

From some more debugging, I think the ContextVar is acting normally.

And this may just be the case that the LoggingContext start/stop pattern isn't compatible with the ContextVar we're using now. We'd have to maintain the log context rules 🤔.

In this case, it's the SynapseRequest.logcontext where stop is called because we have a PreserveLoggingContext around SynapseRequest.render which only kicks off the render and doesn't wait for it to finish so we stop way before the request is done. And it's never re-started. So when other LoggingContext utilities are used in the downstream code to set_current_context, it will stop the already stopped SynapseRequest.logcontext.

I go back and forth on whether we can update things to work correctly. If I naively try to manage the lifetime myself by calling self.logcontext.__enter__ manually in SynapseRequest.render, it still doesn't work out.



def current_context() -> LoggingContextOrSentinel:
"""Get the current logging context from thread local storage"""
return getattr(_thread_local, "current_context", SENTINEL_CONTEXT)
return _current_context.get(SENTINEL_CONTEXT)


def set_current_context(context: LoggingContextOrSentinel) -> LoggingContextOrSentinel:
Copy link
Contributor Author

Choose a reason for hiding this comment

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

TODO: The docstring needs to be updated

Expand All @@ -680,7 +680,7 @@ def set_current_context(context: LoggingContextOrSentinel) -> LoggingContextOrSe
if current is not context:
rusage = get_thread_resource_usage()
current.stop(rusage)
_thread_local.current_context = context
_current_context.set(context)
context.start(rusage)

return current
Expand Down Expand Up @@ -796,7 +796,6 @@ def run_in_background(
CRITICAL error about an unhandled error will be logged without much
indication about where it came from.
"""
current = current_context()
try:
res = f(*args, **kwargs)
except Exception:
Expand Down Expand Up @@ -825,23 +824,6 @@ def run_in_background(
# optimise out the messing about
return d

# The function may have reset the context before returning, so
# we need to restore it now.
ctx = set_current_context(current)

# The original context will be restored when the deferred
# completes, but there is nothing waiting for it, so it will
# get leaked into the reactor or some other function which
# wasn't expecting it. We therefore need to reset the context
# here.
#
# (If this feels asymmetric, consider it this way: we are
# effectively forking a new thread of execution. We are
# probably currently within a ``with LoggingContext()`` block,
# which is supposed to have a single entry and exit point. But
# by spawning off another deferred, we are effectively
# adding a new exit point.)
d.addBoth(_set_context_cb, ctx)
return d


Expand All @@ -861,65 +843,20 @@ def run_coroutine_in_background(
cannot change the log contexts.
"""

current = current_context()
d = defer.ensureDeferred(coroutine)

# The function may have reset the context before returning, so
# we need to restore it now.
ctx = set_current_context(current)

# The original context will be restored when the deferred
# completes, but there is nothing waiting for it, so it will
# get leaked into the reactor or some other function which
# wasn't expecting it. We therefore need to reset the context
# here.
#
# (If this feels asymmetric, consider it this way: we are
# effectively forking a new thread of execution. We are
# probably currently within a ``with LoggingContext()`` block,
# which is supposed to have a single entry and exit point. But
# by spawning off another deferred, we are effectively
# adding a new exit point.)
d.addBoth(_set_context_cb, ctx)
return d
return defer.ensureDeferred(coroutine)


T = TypeVar("T")


# TODO: This function is a no-op now and should be removed in a follow-up PR.
def make_deferred_yieldable(deferred: "defer.Deferred[T]") -> "defer.Deferred[T]":
Comment on lines +852 to 853
Copy link
Contributor Author

Choose a reason for hiding this comment

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

make_deferred_yieldable no longer does anything (no-op) but there a lot of references to clean-up. I think it would be better to do this in a follow-up PR than bulk up with this diff with changes that will cloud the main change we're trying to introduce.

"""Given a deferred, make it follow the Synapse logcontext rules:

If the deferred has completed, essentially does nothing (just returns another
completed deferred with the result/failure).

If the deferred has not yet completed, resets the logcontext before
returning a deferred. Then, when the deferred completes, restores the
current logcontext before running callbacks/errbacks.

(This is more-or-less the opposite operation to run_in_background.)
"""
if deferred.called and not deferred.paused:
# it looks like this deferred is ready to run any callbacks we give it
# immediately. We may as well optimise out the logcontext faffery.
return deferred

# ok, we can't be sure that a yield won't block, so let's reset the
# logcontext, and add a callback to the deferred to restore it.
prev_context = set_current_context(SENTINEL_CONTEXT)
deferred.addBoth(_set_context_cb, prev_context)
return deferred


ResultT = TypeVar("ResultT")


def _set_context_cb(result: ResultT, context: LoggingContextOrSentinel) -> ResultT:
"""A callback function which just sets the logging context"""
set_current_context(context)
return result


def defer_to_thread(
reactor: "ISynapseReactor", f: Callable[P, R], *args: P.args, **kwargs: P.kwargs
) -> "defer.Deferred[R]":
Expand All @@ -931,9 +868,6 @@ def defer_to_thread(
logcontext (so its CPU usage metrics will get attributed to the current
logcontext). `f` should preserve the logcontext it is given.

The result deferred follows the Synapse logcontext rules: you should `yield`
on it.

Args:
reactor: The reactor in whose main thread the Deferred will be invoked,
and whose threadpool we should use for the function.
Expand Down Expand Up @@ -971,9 +905,6 @@ def defer_to_threadpool(
logcontext (so its CPU usage metrics will get attributed to the current
logcontext). `f` should preserve the logcontext it is given.

The result deferred follows the Synapse logcontext rules: you should `yield`
on it.

Args:
reactor: The reactor in whose main thread the Deferred will be invoked.
Normally this will be hs.get_reactor().
Expand All @@ -991,18 +922,6 @@ def defer_to_threadpool(
A Deferred which fires a callback with the result of `f`, or an
errback if `f` throws an exception.
"""
curr_context = current_context()
if not curr_context:
logger.warning(
"Calling defer_to_threadpool from sentinel context: metrics will be lost"
)
parent_context = None
else:
assert isinstance(curr_context, LoggingContext)
parent_context = curr_context

def g() -> R:
with LoggingContext(str(curr_context), parent_context=parent_context):
return f(*args, **kwargs)

return make_deferred_yieldable(threads.deferToThreadPool(reactor, threadpool, g))
return make_deferred_yieldable(
threads.deferToThreadPool(reactor, threadpool, f, *args, **kwargs)
)
9 changes: 3 additions & 6 deletions synapse/metrics/background_process_metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -223,10 +223,9 @@ def run_as_background_process(
This should be used to wrap processes which are fired off to run in the
background, instead of being associated with a particular request.

It returns a Deferred which completes when the function completes, but it doesn't
follow the synapse logcontext rules, which makes it appropriate for passing to
clock.looping_call and friends (or for firing-and-forgetting in the middle of a
normal synapse async function).
It returns a Deferred which completes when the function completes, which makes it
appropriate for passing to clock.looping_call and friends (or for
firing-and-forgetting in the middle of a normal synapse async function).

Args:
desc: a description for this background process type
Expand All @@ -241,8 +240,6 @@ def run_as_background_process(

Returns:
Deferred which returns the result of func, or `None` if func raises.
Note that the returned Deferred does not follow the synapse logcontext
rules.
"""

async def run() -> Optional[R]:
Expand Down
26 changes: 8 additions & 18 deletions synapse/module_api/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -237,10 +237,9 @@ def run_as_background_process(
This should be used to wrap processes which are fired off to run in the
background, instead of being associated with a particular request.

It returns a Deferred which completes when the function completes, but it doesn't
follow the synapse logcontext rules, which makes it appropriate for passing to
clock.looping_call and friends (or for firing-and-forgetting in the middle of a
normal synapse async function).
It returns a Deferred which completes when the function completes, which makes it
appropriate for passing to clock.looping_call and friends (or for
firing-and-forgetting in the middle of a normal synapse async function).

Args:
desc: a description for this background process type
Expand All @@ -255,8 +254,6 @@ def run_as_background_process(

Returns:
Deferred which returns the result of func, or `None` if func raises.
Note that the returned Deferred does not follow the synapse logcontext
rules.
"""

logger.warning(
Expand Down Expand Up @@ -1375,9 +1372,7 @@ def looping_background_call(

Args:
f: The function to call repeatedly. f can be either synchronous or
asynchronous, and must follow Synapse's logcontext rules.
More info about logcontexts is available at
https://element-hq.github.io/synapse/latest/log_contexts.html
asynchronous.
msec: How long to wait between calls in milliseconds.
*args: Positional arguments to pass to function.
desc: The background task's description. Default to the function's name.
Expand Down Expand Up @@ -1431,9 +1426,7 @@ def delayed_background_call(
Args:
msec: How long to wait before calling, in milliseconds.
f: The function to call once. f can be either synchronous or
asynchronous, and must follow Synapse's logcontext rules.
More info about logcontexts is available at
https://element-hq.github.io/synapse/latest/log_contexts.html
asynchronous.
*args: Positional arguments to pass to function.
desc: The background task's description. Default to the function's name.
**kwargs: Keyword arguments to pass to function.
Expand Down Expand Up @@ -1668,10 +1661,9 @@ def run_as_background_process(
This should be used to wrap processes which are fired off to run in the
background, instead of being associated with a particular request.

It returns a Deferred which completes when the function completes, but it doesn't
follow the synapse logcontext rules, which makes it appropriate for passing to
clock.looping_call and friends (or for firing-and-forgetting in the middle of a
normal synapse async function).
It returns a Deferred which completes when the function completes, which makes
it appropriate for passing to clock.looping_call and friends (or for
firing-and-forgetting in the middle of a normal synapse async function).

Args:
desc: a description for this background process type
Expand All @@ -1686,8 +1678,6 @@ def run_as_background_process(

Returns:
Deferred which returns the result of func, or `None` if func raises.
Note that the returned Deferred does not follow the synapse logcontext
rules.
"""
return _run_as_background_process(
desc, self.server_name, func, *args, bg_start_span=bg_start_span, **kwargs
Expand Down
8 changes: 1 addition & 7 deletions synapse/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -366,12 +366,6 @@ def setup(self) -> None:
self.datastores = Databases(self.DATASTORE_CLASS, self)
logger.info("Finished setting up.")

# Register background tasks required by this server. This must be done
# somewhat manually due to the background tasks not being registered
# unless handlers are instantiated.
if self.config.worker.run_background_tasks:
self.setup_background_tasks()

def __del__(self) -> None:
"""
Called when an the homeserver is garbage collected.
Expand Down Expand Up @@ -410,7 +404,7 @@ def start_listening(self) -> None: # noqa: B027 (no-op by design)
appropriate listeners.
"""

def setup_background_tasks(self) -> None:
def start_background_tasks(self) -> None:
"""
Some handlers have side effects on instantiation (like registering
background updates). This function causes them to be fetched, and
Expand Down
21 changes: 2 additions & 19 deletions synapse/util/async_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,6 @@ def observe(self) -> "defer.Deferred[_T]":
This returns a brand new deferred that is resolved when the underlying
deferred is resolved. Interacting with the returned deferred does not
effect the underlying deferred.

Note that the returned Deferred doesn't follow the Synapse logcontext rules -
you will probably want to `make_deferred_yieldable` it.
"""
...

Expand All @@ -100,11 +97,6 @@ class ObservableDeferred(Generic[_T], AbstractObservableDeferred[_T]):

Cancelling or otherwise resolving an observer will not affect the original
ObservableDeferred.

NB that it does not attempt to do anything with logcontexts; in general
you should probably make_deferred_yieldable the deferreds
returned by `observe`, and ensure that the original deferred runs its
callbacks in the sentinel logcontext.
"""

__slots__ = ["_deferred", "_observers", "_result"]
Expand Down Expand Up @@ -861,16 +853,12 @@ def stop_cancellation(deferred: "defer.Deferred[T]") -> "defer.Deferred[T]":
"""Prevent a `Deferred` from being cancelled by wrapping it in another `Deferred`.

Args:
deferred: The `Deferred` to protect against cancellation. Must not follow the
Synapse logcontext rules.
deferred: The `Deferred` to protect against cancellation.

Returns:
A new `Deferred`, which will contain the result of the original `Deferred`.
The new `Deferred` will not propagate cancellation through to the original.
When cancelled, the new `Deferred` will fail with a `CancelledError`.

The new `Deferred` will not follow the Synapse logcontext rules and should be
wrapped with `make_deferred_yieldable`.
"""
new_deferred: "defer.Deferred[T]" = defer.Deferred()
deferred.chainDeferred(new_deferred)
Expand All @@ -896,8 +884,7 @@ def delay_cancellation(awaitable: Awaitable[T]) -> Awaitable[T]:
resolve with a `CancelledError` until the original awaitable resolves.

Args:
deferred: The coroutine or `Deferred` to protect against cancellation. May
optionally follow the Synapse logcontext rules.
deferred: The coroutine or `Deferred` to protect against cancellation.

Returns:
A new `Deferred`, which will contain the result of the original coroutine or
Expand All @@ -906,10 +893,6 @@ def delay_cancellation(awaitable: Awaitable[T]) -> Awaitable[T]:

When cancelled, the new `Deferred` will wait until the original coroutine or
`Deferred` resolves before failing with a `CancelledError`.

The new `Deferred` will follow the Synapse logcontext rules if `awaitable`
follows the Synapse logcontext rules. Otherwise the new `Deferred` should be
wrapped with `make_deferred_yieldable`.
"""

# First, convert the awaitable into a `Deferred`.
Expand Down
3 changes: 0 additions & 3 deletions synapse/util/caches/deferred_cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -295,9 +295,6 @@ def set(
*original* `value`, (c) any future calls to `get()` will complete with the
result from the *new* `value`.

It is expected that `value` does *not* follow the synapse logcontext rules - ie,
if it is incomplete, it runs its callbacks in the sentinel context.

Args:
key: Key to be set
value: a deferred which will complete with a result to add to the cache
Expand Down
Loading
Loading