Skip to content
Open
Show file tree
Hide file tree
Changes from 174 commits
Commits
Show all changes
183 commits
Select commit Hold shift + click to select a range
7a9725c
WIP on clean shutdown of SynapseHomeServer class
devonh Jul 30, 2025
c283db8
More shutdown cleanup
devonh Aug 6, 2025
61508a6
Temporarily disable all tests that call generate_latest
devonh Aug 6, 2025
df7b437
Revert "Temporarily disable all tests that call generate_latest"
devonh Aug 6, 2025
5078451
Cleanup SynapseHomeServer without weakrefs
devonh Aug 14, 2025
31a607a
Make clock capable of cleaning up it's own outstanding calls
devonh Aug 15, 2025
144bff0
Remove unused code
devonh Aug 15, 2025
5a4dd91
Merge branch 'develop' into devon/clean-shutdown
devonh Aug 15, 2025
94a1bbb
Cleanup unnecessary teardown attempts
devonh Aug 15, 2025
fe75481
Add changelog entry
devonh Aug 15, 2025
aa62ad8
Address linter errors
devonh Aug 19, 2025
adeba65
Remove unnecessary redirect
devonh Aug 19, 2025
35fc370
Add new func to MockHomeserver
devonh Aug 19, 2025
f26088b
Add import
devonh Aug 19, 2025
287fc3c
Modify tests to shutdown homeserver on teardown
devonh Aug 19, 2025
a94c483
Fix type comparison
devonh Aug 19, 2025
2b38ed0
Clean up batching queue metrics shutdown
devonh Aug 19, 2025
a316090
Add shutdown call to keyring mock
devonh Aug 19, 2025
667351a
Add manhole port to shutdown list
devonh Aug 19, 2025
470978a
Remove outdated TODO
devonh Aug 19, 2025
35ee71a
Reintroduce code that no longer blocks clean shutdown
devonh Aug 19, 2025
da4aa35
Address more TODO comments
devonh Aug 19, 2025
ad6f02e
Reset accidental constant value change
devonh Aug 19, 2025
a77e41b
Cleanly shutdown metrics servers
devonh Aug 20, 2025
44e48f6
Fix linter errors
devonh Aug 20, 2025
fa97897
Remove shutdown function override
devonh Aug 20, 2025
51d0757
Refactor shutdown handler registration function
devonh Aug 20, 2025
02112fa
Add args to registered shutdown handlers
devonh Aug 20, 2025
60c8088
Fix formatting
devonh Aug 20, 2025
42882e7
Optionally freeze gc objects at startup
devonh Aug 20, 2025
7804e16
Apply formatting fixes
devonh Aug 20, 2025
1bd2ad3
Remove unnecessary cleanup step
devonh Aug 20, 2025
25fdddd
Revert unnecessary logic changes
devonh Aug 20, 2025
b980858
PR cleanup changes
devonh Aug 20, 2025
4f1603d
Merge branch 'develop' into devon/clean-shutdown
devonh Aug 20, 2025
25e199a
Cleanly shutdown open connections to Synapse
devonh Aug 27, 2025
9607670
Update comment to reflect new variable
devonh Aug 29, 2025
e4233b9
Use instance_id instead of server_name
devonh Aug 29, 2025
4759c55
Update comment again
devonh Aug 29, 2025
947cac9
Update docstring for setup function
devonh Aug 29, 2025
849a093
Move server shutdown in tests
devonh Aug 29, 2025
4b67de5
Assert metrics aren't being clobbered
devonh Aug 29, 2025
e99f9cd
Don't renam arg
devonh Aug 30, 2025
0f26d20
Use gauge.remove
devonh Aug 30, 2025
649c182
Rename var for clarity
devonh Aug 30, 2025
93a2183
Add field descriptions to docs
devonh Aug 30, 2025
4e7ddb3
Tighten type of event trigger id
devonh Aug 30, 2025
5188a78
Merge branch 'develop' into devon/clean-shutdown
devonh Sep 3, 2025
cc598a6
Fix linter error
devonh Sep 3, 2025
b697f9a
Remove background process registration
devonh Sep 4, 2025
2619070
Make clock a required arg for Linearizer
devonh Sep 4, 2025
35f88f4
Return None instead of raising exception
devonh Sep 4, 2025
0e67230
Clarify our_server_name
devonh Sep 4, 2025
1a22e8f
Rename factory arg to site
devonh Sep 4, 2025
4d2e595
Add comment documenting SynapseSite shutdown
devonh Sep 4, 2025
a5ff83e
Add docs about using Clock instead of reactor directly
devonh Sep 4, 2025
62978f1
Remove unnecessary cleanup changes
devonh Sep 4, 2025
a7f3948
Add TODO about shutdown freeze detection
devonh Sep 5, 2025
42f3e8f
Callout full name of _FakePort in comment
devonh Sep 5, 2025
f00d90b
Reword SynapseProtocol docstrings
devonh Sep 5, 2025
57b030d
Remove unused code
devonh Sep 5, 2025
ed1b436
Add comment explaining need for type ignore
devonh Sep 5, 2025
7fc17a8
Update synapse/_scripts/synapse_port_db.py
devonh Sep 5, 2025
27f4039
Update synapse/app/_base.py
devonh Sep 5, 2025
e8a145b
More docstrings
devonh Sep 5, 2025
070f302
Fix linter errors
devonh Sep 5, 2025
073734a
Add instance_id to docstring
devonh Sep 5, 2025
a53a7df
Add return docstring
devonh Sep 5, 2025
cb2f562
Add docstring for freeze
devonh Sep 5, 2025
41734ca
Add docstring for unregister_sighups
devonh Sep 5, 2025
219d002
Update synapse/app/_base.py
devonh Sep 5, 2025
cf10f45
Rename sighup map
devonh Sep 5, 2025
7b64868
Make homeserver shutdown async
devonh Sep 5, 2025
1f334ef
Move up unregister_sighups call
devonh Sep 5, 2025
ac8ecb1
Call hs.shutdown during tests
devonh Sep 5, 2025
c3856ac
Update test shutdown comment
devonh Sep 5, 2025
4a6ead1
Further explain docstring args
devonh Sep 5, 2025
672adc2
Fix function name
devonh Sep 5, 2025
79e84eb
Update var name
devonh Sep 5, 2025
f814dd0
Fix incorrect servername change
devonh Sep 5, 2025
ccf2585
Update synapse/server.py
devonh Sep 5, 2025
0c63671
Fix linter error
devonh Sep 5, 2025
267da3e
Refactor clock variable names
devonh Sep 8, 2025
5dce393
Remove old test
devonh Sep 8, 2025
9202f50
Fully cleanup federation on shutdown
devonh Sep 8, 2025
23e587f
Merge branch 'develop' into devon/clean-shutdown
devonh Sep 9, 2025
9403bbd
Make clock variables instance specific
devonh Sep 9, 2025
4cd3d91
Merge branch 'develop' into devon/clean-shutdown
devonh Sep 9, 2025
dafba10
Readd metric_name to metrics hooks
devonh Sep 9, 2025
da6f85e
Force shutdown handler registration to use keyword arguments
devonh Sep 9, 2025
a86bfe0
Remove unnecessary TODO
devonh Sep 9, 2025
a9df2ba
Add lint for using our internal Clock
devonh Sep 10, 2025
2337b64
Change Clock to conditionally track calls for cleanup
devonh Sep 10, 2025
b117145
Document function arg
devonh Sep 10, 2025
0301675
Readd mistakenly removed test
devonh Sep 11, 2025
d03ec2f
Remove delayed calls that raise
devonh Sep 11, 2025
42d990d
Fully shutdown background updater
devonh Sep 11, 2025
d6bdce6
Add test for clean server shutdown
devonh Sep 11, 2025
83be016
Add reasoning for unregister_sighups being first
devonh Sep 12, 2025
169bc53
Make docstring more verbose
devonh Sep 12, 2025
e278d38
Update scripts-dev/mypy_synapse_plugin.py
devonh Sep 12, 2025
3da4253
Fix wording
devonh Sep 12, 2025
4023df9
Update scripts-dev/mypy_synapse_plugin.py
devonh Sep 12, 2025
fde361a
Revert log to debug
devonh Sep 12, 2025
49e0df2
Update synapse/server.py
devonh Sep 12, 2025
01c9de6
Remove unnecessary cleanup_metrics
devonh Sep 12, 2025
4d87c26
Update synapse/server.py
devonh Sep 12, 2025
996b924
Rename variable
devonh Sep 12, 2025
83680f3
Update synapse/util/__init__.py
devonh Sep 12, 2025
ad6cdf4
Rename variable
devonh Sep 12, 2025
e356024
Flush out docstring
devonh Sep 12, 2025
e7431d0
Indent docstring
devonh Sep 12, 2025
5b60064
Add docstring for delay tracking threshold
devonh Sep 12, 2025
a72ce6f
Update changelog.d/18828.feature
devonh Sep 12, 2025
0c10de3
Update docstring for freeze arg
devonh Sep 12, 2025
0337e1b
Flush out freeze comments
devonh Sep 12, 2025
3fe65ab
Explain mypy ignores
devonh Sep 12, 2025
6b643f2
Remove unused optional arg
devonh Sep 12, 2025
2a4bae5
Add comments to call_later tracking choice
devonh Sep 12, 2025
18ed2d1
Fix sleep call
devonh Sep 12, 2025
f3d8c17
Document calls to call_later
devonh Sep 16, 2025
c2d47d8
Fix call_later call cancellation
devonh Sep 16, 2025
7d5f6e0
Add comment explaining lack of tracking for response cache
devonh Sep 16, 2025
4636d1f
Propagate cancel_on_shutdown up to timeout_deferred
devonh Sep 16, 2025
83c84a0
Make timeout_deferred use kwargs
devonh Sep 16, 2025
37f9713
Extend docstring for homeserver_instance_id arg
devonh Sep 18, 2025
2465c2f
Change call_later to set default cancel arg
devonh Sep 18, 2025
fe3491b
Switch arg default to True
devonh Sep 18, 2025
5f167ff
Update synapse/notifier.py
devonh Sep 18, 2025
8f57498
Refactor sighup callbacks
devonh Sep 18, 2025
ecb2608
Add comment to clock about lints
devonh Sep 18, 2025
0bb0e6e
Update docstring
devonh Sep 18, 2025
9123ec7
Update docstring
devonh Sep 18, 2025
9fe95a4
Add comment explaining lack of shutdown
devonh Sep 18, 2025
17d012d
Remove cast
devonh Sep 18, 2025
daa6c3e
Update mypy ignore comments in tests
devonh Sep 18, 2025
da4bdfe
Change wording of freeze docstring
devonh Sep 18, 2025
a1e8414
Update docstrings around using internal Clock
devonh Sep 18, 2025
f8a5bed
Merge branch 'develop' into devon/clean-shutdown
devonh Sep 18, 2025
e383758
Remove args that aren't args anymore
devonh Sep 19, 2025
0ec5803
Line wrap lint errors
devonh Sep 19, 2025
c02f0bd
Better lint categories
devonh Sep 19, 2025
075ef10
Rename lints for clarity
devonh Sep 19, 2025
6cc2c2f
Update synapse/util/__init__.py
devonh Sep 19, 2025
3e37d95
Update synapse/util/async_helpers.py
devonh Sep 19, 2025
1c2a229
Update tests/app/test_homeserver_shutdown.py
devonh Sep 19, 2025
63e096c
Move comment next to applicable arg
devonh Sep 19, 2025
c36aaa1
Fix lint ignore renames
devonh Sep 19, 2025
490195f
Add comment about HTTP federation test
devonh Sep 19, 2025
34140b3
Add arg to setup_test_homeserver for cleanup
devonh Sep 19, 2025
9fd10db
Remove unused import
devonh Sep 19, 2025
0bd1706
Switch test hs cleanup to use weakref
devonh Sep 19, 2025
8b086c6
Return deferred from cleanup_func
devonh Sep 24, 2025
eb16eae
Add debugging info for shutdown test
devonh Sep 24, 2025
8855f4a
Override MemoryReactor in tests for clean shutdown
devonh Sep 24, 2025
d0555f9
Merge branch 'develop' into devon/clean-shutdown
devonh Sep 25, 2025
0f23e50
Fix test not follow Synapse logcontext rules
MadLittleMods Sep 25, 2025
3f5c463
Clean up test
MadLittleMods Sep 25, 2025
130dcda
Re-add call_later cancellation tracking
devonh Sep 25, 2025
30dbc2b
Add shutdown test where background updates haven't completed
devonh Sep 25, 2025
03b9594
Add assert that updates arent complete
devonh Sep 25, 2025
d7f8c1c
Initial conversion run_as_background_process to use hs
devonh Sep 26, 2025
8184e9b
Merge branch 'develop' into devon/clean-shutdown
devonh Sep 26, 2025
b1f887c
Can't subscript Deferred in python 3.9
devonh Sep 26, 2025
d6d4780
Can't subscript Deferred in python 3.9
devonh Sep 26, 2025
34d314b
Fix removeSystemEventTrigger in tests
devonh Sep 26, 2025
527bd48
Fix postgres shutdown tests
devonh Sep 26, 2025
28fdf12
Add lint for new Clock creation
devonh Sep 26, 2025
50a3cd1
Lint new Clock creation
devonh Sep 26, 2025
25c4ba8
Merge branch 'develop' into devon/clean-shutdown
devonh Sep 27, 2025
92dba44
Switch to using hs.run_as_background_process
devonh Sep 28, 2025
cb699a7
Make call_later cancellation bool optional with default logic
devonh Sep 28, 2025
8d05718
Fix appservice tests with wrap_as_background_process changes
devonh Sep 28, 2025
751cacd
Fix registered shutdown handlers
devonh Sep 28, 2025
54d2fe4
Address mypy plugin review comments
devonh Sep 29, 2025
89a133e
Update lint ignore comment
devonh Sep 29, 2025
baa066c
Apply wording to other mypy lint codes
devonh Sep 29, 2025
46e112b
Make test comments clearer
devonh Sep 29, 2025
f2f0bae
Address synmark review comments
devonh Sep 29, 2025
3ca4e98
Remove unnecessary comment
devonh Sep 29, 2025
3e92bf7
Remove unnecessary comments
devonh Sep 29, 2025
f39e212
Don't prevent module_api from cancelling background processes on shut…
devonh Sep 29, 2025
d47839e
Realy pull back untracked delayed calls
devonh Sep 29, 2025
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/18828.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Cleanly shutdown `SynapseHomeServer` object.
132 changes: 132 additions & 0 deletions scripts-dev/mypy_synapse_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,18 @@
category="per-homeserver-tenant-metrics",
)

INTERNAL_CLOCK_CALL_LATER_NOT_USED = ErrorCode(
"call-later-not-tracked",
"`synapse.util.Clock.call_later` should be used instead of `reactor.callLater`",
category="synapse-reactor-clock",
)

PREFER_SYNAPSE_CLOCK_LOOPING_CALL = ErrorCode(
"prefer-synapse-clock-looping-call",
"`synapse.util.Clock.looping_call` should be used instead of `task.LoopingCall`",
category="synapse-reactor-clock",
)

PREFER_SYNAPSE_CLOCK_CALL_WHEN_RUNNING = ErrorCode(
"prefer-synapse-clock-call-when-running",
"`synapse.util.Clock.call_when_running` should be used instead of `reactor.callWhenRunning`",
Expand All @@ -80,6 +92,18 @@
category="synapse-reactor-clock",
)

MULTIPLE_INTERNAL_CLOCKS_CREATED = ErrorCode(
"multiple-internal-clocks",
"Only one instance of `clock.Clock` should be created",
category="synapse-reactor-clock",
)

UNTRACKED_BACKGROUND_PROCESS = ErrorCode(
"untracked-background-process",
"All calls to `run_as_background_process` should use the `HomeServer` method",
category="synapse-tracked-calls",
)


class Sentinel(enum.Enum):
# defining a sentinel in this way allows mypy to correctly handle the
Expand Down Expand Up @@ -222,6 +246,18 @@ def get_function_signature_hook(
# callback, let's just pass it in while we have it.
return lambda ctx: check_prometheus_metric_instantiation(ctx, fullname)

if fullname == "twisted.internet.task.LoopingCall":
return check_looping_call

if fullname == "synapse.util.clock.Clock":
return check_clock_creation

if (
fullname
== "synapse.metrics.background_process_metrics.run_as_background_process"
):
return check_background_process

return None

def get_method_signature_hook(
Expand All @@ -241,6 +277,13 @@ def get_method_signature_hook(
):
return check_is_cacheable_wrapper

if fullname in (
"twisted.internet.interfaces.IReactorTime.callLater",
"synapse.types.ISynapseThreadlessReactor.callLater",
"synapse.types.ISynapseReactor.callLater",
):
return check_call_later

if fullname in (
"twisted.internet.interfaces.IReactorCore.callWhenRunning",
"synapse.types.ISynapseThreadlessReactor.callWhenRunning",
Expand All @@ -258,6 +301,95 @@ def get_method_signature_hook(
return None


def check_call_later(ctx: MethodSigContext) -> CallableType:
"""
Ensure that the `reactor.callLater` callsites aren't used.

`synapse.util.Clock.call_later` should always be used instead of `reactor.callLater`.
This is because the `synapse.util.Clock` tracks delayed calls in order to cancel any
outstanding calls during server shutdown. Delayed calls which are either short lived
(<~60s) or frequently called and can be tracked via other means could be candidates for
using `synapse.util.Clock.call_later` with `call_later_cancel_on_shutdown` set to
`False`. There shouldn't be a need to use `reactor.callLater` outside of tests or the
`Clock` class itself. If a need arises, you can use a type ignore comment to disable the
check, e.g. `# type: ignore[call-later-not-tracked]`.

Args:
ctx: The `FunctionSigContext` from mypy.
"""
signature: CallableType = ctx.default_signature
ctx.api.fail(
"Expected all `reactor.callLater` calls to use `synapse.util.Clock.call_later` "
"instead. This is so that long lived calls can be tracked for cancellation during "
"server shutdown",
ctx.context,
code=INTERNAL_CLOCK_CALL_LATER_NOT_USED,
)

return signature


def check_looping_call(ctx: FunctionSigContext) -> CallableType:
"""
Ensure that the `task.LoopingCall` callsites aren't used.

`synapse.util.Clock.looping_call` should always be used instead of `task.LoopingCall`.
`synapse.util.Clock` tracks looping calls in order to cancel any outstanding calls
during server shutdown.

Args:
ctx: The `FunctionSigContext` from mypy.
"""
signature: CallableType = ctx.default_signature
ctx.api.fail(
"Expected all `task.LoopingCall` instances to use `synapse.util.Clock.looping_call` "
"instead. This is so that long lived calls can be tracked for cancellation during "
"server shutdown",
ctx.context,
code=PREFER_SYNAPSE_CLOCK_LOOPING_CALL,
)

return signature


def check_clock_creation(ctx: FunctionSigContext) -> CallableType:
"""
Ensure that the only `clock.Clock` is the one used by the `HomeServer`.

Args:
ctx: The `FunctionSigContext` from mypy.
"""
signature: CallableType = ctx.default_signature
ctx.api.fail(
"Expected the only `clock.Clock` instance to be the one used by the `HomeServer`. "
"This is so that the `HomeServer` can cancel any tracked delayed or looping calls "
"during server shutdown",
ctx.context,
code=MULTIPLE_INTERNAL_CLOCKS_CREATED,
)

return signature


def check_background_process(ctx: FunctionSigContext) -> CallableType:
"""
Ensure that calls to `run_as_background_process` use the `HomeServer` method.

Args:
ctx: The `FunctionSigContext` from mypy.
"""
signature: CallableType = ctx.default_signature
ctx.api.fail(
"Expected all calls to `run_as_background_process` to use the `HomeServer` method. "
"This is so that the `HomeServer` can cancel any background processes "
"during server shutdown",
ctx.context,
code=UNTRACKED_BACKGROUND_PROCESS,
)

return signature


def check_call_when_running(ctx: MethodSigContext) -> CallableType:
"""
Ensure that the `reactor.callWhenRunning` callsites aren't used.
Expand Down
7 changes: 6 additions & 1 deletion synapse/_scripts/generate_workers_map.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,12 @@ def get_registered_paths_for_default(
# TODO We only do this to avoid an error, but don't need the database etc
hs.setup()
registered_paths = get_registered_paths_for_hs(hs)
hs.cleanup()
# NOTE: a more robust implementation would properly shutdown/cleanup each server
# to avoid resource buildup.
# However, the call to `shutdown` is `async` so it would require additional complexity here.
# We are intentionally skipping this cleanup because this is a short-lived, one-off
# utility script where the simpler approach is sufficient and we shouldn't run into
# any resource buildup issues.

return registered_paths

Expand Down
5 changes: 1 addition & 4 deletions synapse/_scripts/update_synapse_database.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
from twisted.internet import defer, reactor as reactor_

from synapse.config.homeserver import HomeServerConfig
from synapse.metrics.background_process_metrics import run_as_background_process
from synapse.server import HomeServer
from synapse.storage import DataStore
from synapse.types import ISynapseReactor
Expand All @@ -53,7 +52,6 @@ def __init__(self, config: HomeServerConfig):


def run_background_updates(hs: HomeServer) -> None:
server_name = hs.hostname
main = hs.get_datastores().main
state = hs.get_datastores().state

Expand All @@ -67,9 +65,8 @@ async def run_background_updates() -> None:
def run() -> None:
# Apply all background updates on the database.
defer.ensureDeferred(
run_as_background_process(
hs.run_as_background_process(
"background_updates",
server_name,
run_background_updates,
)
)
Expand Down
Loading
Loading