From 37ea1ae686529bf685e7076d7870636db3ef7936 Mon Sep 17 00:00:00 2001 From: Eric Eastwood Date: Mon, 25 Aug 2025 15:00:19 -0500 Subject: [PATCH 1/4] Split loading config vs setting up the homeserver This allows us to get access to `server_name` before which we may want to use in the `with LoggingContext("main"):` call early on. This also allows us more flexibility to parse config however we want and setup a Synapse homeserver. Like what we do in Synapse Pro for Small Hosts. --- synapse/app/homeserver.py | 28 ++++++++++++++++++++---- synapse/config/_base.py | 8 +++++-- tests/app/test_homeserver_start.py | 5 ++++- tests/config/test_registration_config.py | 5 ++++- 4 files changed, 38 insertions(+), 8 deletions(-) diff --git a/synapse/app/homeserver.py b/synapse/app/homeserver.py index dfc4a007197..36a9844876b 100644 --- a/synapse/app/homeserver.py +++ b/synapse/app/homeserver.py @@ -308,17 +308,21 @@ def start_listening(self) -> None: logger.warning("Unrecognized listener type: %s", listener.type) -def setup(config_options: List[str]) -> SynapseHomeServer: +def load_or_generate_config(argv_options: List[str]) -> HomeServerConfig: """ + Parse the commandline and config files + + Supports generation of config files, so is used for the main homeserver app. + Args: - config_options_options: The options passed to Synapse. Usually `sys.argv[1:]`. + argv_options: The options passed to Synapse. Usually `sys.argv[1:]`. Returns: A homeserver instance. """ try: config = HomeServerConfig.load_or_generate_config( - "Synapse Homeserver", config_options + "Synapse Homeserver", argv_options ) except ConfigError as e: sys.stderr.write("\n") @@ -332,6 +336,20 @@ def setup(config_options: List[str]) -> SynapseHomeServer: # generating config files and shouldn't try to continue. sys.exit(0) + return config + + +def setup(config: HomeServerConfig) -> SynapseHomeServer: + """ + Create and setup a Synapse homeserver instance given a configuration. + + Args: + config: The configuration for the homeserver. + + Returns: + A homeserver instance. + """ + if config.worker.worker_app: raise ConfigError( "You have specified `worker_app` in the config but are attempting to start a non-worker " @@ -407,10 +425,12 @@ def run(hs: HomeServer) -> None: def main() -> None: + homeserver_config = load_or_generate_config(sys.argv[1:]) + with LoggingContext("main"): # check base requirements check_requirements() - hs = setup(sys.argv[1:]) + hs = setup(homeserver_config) # redirect stdio to the logs, if configured. if not hs.config.logging.no_redirect_stdio: diff --git a/synapse/config/_base.py b/synapse/config/_base.py index 191253dddaf..f3b6e9f887c 100644 --- a/synapse/config/_base.py +++ b/synapse/config/_base.py @@ -646,12 +646,16 @@ def load_config_with_parser( @classmethod def load_or_generate_config( - cls: Type[TRootConfig], description: str, argv: List[str] + cls: Type[TRootConfig], description: str, argv_options: List[str] ) -> Optional[TRootConfig]: """Parse the commandline and config files Supports generation of config files, so is used for the main homeserver app. + Args: + description: TODO + argv_options: The options passed to Synapse. Usually `sys.argv[1:]`. + Returns: Config object, or None if --generate-config or --generate-keys was set """ @@ -747,7 +751,7 @@ def load_or_generate_config( ) cls.invoke_all_static("add_arguments", parser) - config_args = parser.parse_args(argv) + config_args = parser.parse_args(argv_options) config_files = find_config_files(search_paths=config_args.config_path) diff --git a/tests/app/test_homeserver_start.py b/tests/app/test_homeserver_start.py index 9dc20800b22..0d257c98aaa 100644 --- a/tests/app/test_homeserver_start.py +++ b/tests/app/test_homeserver_start.py @@ -37,4 +37,7 @@ def test_wrong_start_caught(self) -> None: self.add_lines_to_config([" main:", " host: 127.0.0.1", " port: 1234"]) # Ensure that starting master process with worker config raises an exception with self.assertRaises(ConfigError): - synapse.app.homeserver.setup(["-c", self.config_file]) + homeserver_config = synapse.app.homeserver.load_or_generate_config( + ["-c", self.config_file] + ) + synapse.app.homeserver.setup(homeserver_config) diff --git a/tests/config/test_registration_config.py b/tests/config/test_registration_config.py index 7fd6df2f93f..a8520c91d13 100644 --- a/tests/config/test_registration_config.py +++ b/tests/config/test_registration_config.py @@ -112,4 +112,7 @@ def test_refuse_to_start_if_open_registration_and_no_verification(self) -> None: # Test that allowing open registration without verification raises an error with self.assertRaises(ConfigError): - synapse.app.homeserver.setup(["-c", self.config_file]) + homeserver_config = synapse.app.homeserver.load_or_generate_config( + ["-c", self.config_file] + ) + synapse.app.homeserver.setup(homeserver_config) From c076082191a81991dc12f6bb8b94a3551629430d Mon Sep 17 00:00:00 2001 From: Eric Eastwood Date: Wed, 17 Sep 2025 13:42:04 -0500 Subject: [PATCH 2/4] Fill out other entrypoints Changes from https://github.com/element-hq/synapse/pull/18868/commits/3a5bab7a130ade541e05ed01429281a8c0db0e7c ``` git checkout 3a5bab7a130ade541e05ed01429281a8c0db0e7c -- synapse/app/admin_cmd.py synapse/app/appservice.py synapse/app/client_reader.py synapse/app/event_creator.py synapse/app/federation_reader.py synapse/app/federation_sender.py synapse/app/frontend_proxy.py synapse/app/generic_worker.py synapse/app/media_repository.py synapse/app/pusher.py synapse/app/synchrotron.py synapse/app/user_dir.py ``` --- synapse/app/admin_cmd.py | 17 +++++++++++------ synapse/app/appservice.py | 7 ++++--- synapse/app/client_reader.py | 7 ++++--- synapse/app/event_creator.py | 7 ++++--- synapse/app/federation_reader.py | 7 ++++--- synapse/app/federation_sender.py | 7 ++++--- synapse/app/frontend_proxy.py | 7 ++++--- synapse/app/generic_worker.py | 29 +++++++++++++++++++---------- synapse/app/media_repository.py | 7 ++++--- synapse/app/pusher.py | 7 ++++--- synapse/app/synchrotron.py | 7 ++++--- synapse/app/user_dir.py | 7 ++++--- 12 files changed, 70 insertions(+), 46 deletions(-) diff --git a/synapse/app/admin_cmd.py b/synapse/app/admin_cmd.py index 7c9b94c65ce..bc84dbdf494 100644 --- a/synapse/app/admin_cmd.py +++ b/synapse/app/admin_cmd.py @@ -24,7 +24,7 @@ import os import sys import tempfile -from typing import List, Mapping, Optional, Sequence +from typing import List, Mapping, Optional, Sequence, Tuple from twisted.internet import defer, task @@ -256,7 +256,7 @@ def finished(self) -> str: return self.base_directory -def start(config_options: List[str]) -> None: +def load_config(argv_options: List[str]) -> Tuple[HomeServerConfig, argparse.Namespace]: parser = argparse.ArgumentParser(description="Synapse Admin Command") HomeServerConfig.add_arguments_to_parser(parser) @@ -282,11 +282,15 @@ def start(config_options: List[str]) -> None: export_data_parser.set_defaults(func=export_data_command) try: - config, args = HomeServerConfig.load_config_with_parser(parser, config_options) + config, args = HomeServerConfig.load_config_with_parser(parser, argv_options) except ConfigError as e: sys.stderr.write("\n" + str(e) + "\n") sys.exit(1) + return config, args + + +def start(config: HomeServerConfig, args: argparse.Namespace) -> None: if config.worker.worker_app is not None: assert config.worker.worker_app == "synapse.app.admin_cmd" @@ -325,7 +329,7 @@ def start(config_options: List[str]) -> None: # command. async def run() -> None: - with LoggingContext("command"): + with LoggingContext(name="command", server_name=config.server.server_name): await _base.start(ss) await args.func(ss, args) @@ -337,5 +341,6 @@ async def run() -> None: if __name__ == "__main__": - with LoggingContext("main"): - start(sys.argv[1:]) + homeserver_config, args = load_config(sys.argv[1:]) + with LoggingContext(name="main", server_name=homeserver_config.server.server_name): + start(homeserver_config, args) diff --git a/synapse/app/appservice.py b/synapse/app/appservice.py index c85ce2869a2..823e1908b52 100644 --- a/synapse/app/appservice.py +++ b/synapse/app/appservice.py @@ -21,13 +21,14 @@ import sys -from synapse.app.generic_worker import start +from synapse.app.generic_worker import load_config, start from synapse.util.logcontext import LoggingContext def main() -> None: - with LoggingContext("main"): - start(sys.argv[1:]) + homeserver_config = load_config(sys.argv[1:]) + with LoggingContext(name="main", server_name=homeserver_config.server.server_name): + start(homeserver_config) if __name__ == "__main__": diff --git a/synapse/app/client_reader.py b/synapse/app/client_reader.py index c85ce2869a2..823e1908b52 100644 --- a/synapse/app/client_reader.py +++ b/synapse/app/client_reader.py @@ -21,13 +21,14 @@ import sys -from synapse.app.generic_worker import start +from synapse.app.generic_worker import load_config, start from synapse.util.logcontext import LoggingContext def main() -> None: - with LoggingContext("main"): - start(sys.argv[1:]) + homeserver_config = load_config(sys.argv[1:]) + with LoggingContext(name="main", server_name=homeserver_config.server.server_name): + start(homeserver_config) if __name__ == "__main__": diff --git a/synapse/app/event_creator.py b/synapse/app/event_creator.py index f0d41ed22ce..1a9b0ad1550 100644 --- a/synapse/app/event_creator.py +++ b/synapse/app/event_creator.py @@ -20,13 +20,14 @@ import sys -from synapse.app.generic_worker import start +from synapse.app.generic_worker import load_config, start from synapse.util.logcontext import LoggingContext def main() -> None: - with LoggingContext("main"): - start(sys.argv[1:]) + homeserver_config = load_config(sys.argv[1:]) + with LoggingContext(name="main", server_name=homeserver_config.server.server_name): + start(homeserver_config) if __name__ == "__main__": diff --git a/synapse/app/federation_reader.py b/synapse/app/federation_reader.py index c85ce2869a2..823e1908b52 100644 --- a/synapse/app/federation_reader.py +++ b/synapse/app/federation_reader.py @@ -21,13 +21,14 @@ import sys -from synapse.app.generic_worker import start +from synapse.app.generic_worker import load_config, start from synapse.util.logcontext import LoggingContext def main() -> None: - with LoggingContext("main"): - start(sys.argv[1:]) + homeserver_config = load_config(sys.argv[1:]) + with LoggingContext(name="main", server_name=homeserver_config.server.server_name): + start(homeserver_config) if __name__ == "__main__": diff --git a/synapse/app/federation_sender.py b/synapse/app/federation_sender.py index c85ce2869a2..823e1908b52 100644 --- a/synapse/app/federation_sender.py +++ b/synapse/app/federation_sender.py @@ -21,13 +21,14 @@ import sys -from synapse.app.generic_worker import start +from synapse.app.generic_worker import load_config, start from synapse.util.logcontext import LoggingContext def main() -> None: - with LoggingContext("main"): - start(sys.argv[1:]) + homeserver_config = load_config(sys.argv[1:]) + with LoggingContext(name="main", server_name=homeserver_config.server.server_name): + start(homeserver_config) if __name__ == "__main__": diff --git a/synapse/app/frontend_proxy.py b/synapse/app/frontend_proxy.py index c85ce2869a2..823e1908b52 100644 --- a/synapse/app/frontend_proxy.py +++ b/synapse/app/frontend_proxy.py @@ -21,13 +21,14 @@ import sys -from synapse.app.generic_worker import start +from synapse.app.generic_worker import load_config, start from synapse.util.logcontext import LoggingContext def main() -> None: - with LoggingContext("main"): - start(sys.argv[1:]) + homeserver_config = load_config(sys.argv[1:]) + with LoggingContext(name="main", server_name=homeserver_config.server.server_name): + start(homeserver_config) if __name__ == "__main__": diff --git a/synapse/app/generic_worker.py b/synapse/app/generic_worker.py index 543b26d8ba8..7150a46ee27 100644 --- a/synapse/app/generic_worker.py +++ b/synapse/app/generic_worker.py @@ -310,13 +310,26 @@ def start_listening(self) -> None: self.get_replication_command_handler().start_replication(self) -def start(config_options: List[str]) -> None: +def load_config(argv_options: List[str]) -> HomeServerConfig: + """ + Parse the commandline and config files (does not generate config) + + Args: + argv_options: The options passed to Synapse. Usually `sys.argv[1:]`. + + Returns: + Config object. + """ try: - config = HomeServerConfig.load_config("Synapse worker", config_options) + config = HomeServerConfig.load_config("Synapse worker", argv_options) except ConfigError as e: sys.stderr.write("\n" + str(e) + "\n") sys.exit(1) + return config + + +def start(config: HomeServerConfig) -> None: # For backwards compatibility let any of the old app names. assert config.worker.worker_app in ( "synapse.app.appservice", @@ -355,12 +368,7 @@ def start(config_options: List[str]) -> None: except Exception as e: handle_startup_exception(e) - async def start() -> None: - # Re-establish log context now that we're back from the reactor - with LoggingContext("start"): - await _base.start(hs) - - register_start(start) + register_start(_base.start, hs) # redirect stdio to the logs, if configured. if not hs.config.logging.no_redirect_stdio: @@ -370,8 +378,9 @@ async def start() -> None: def main() -> None: - with LoggingContext("main"): - start(sys.argv[1:]) + homeserver_config = load_config(sys.argv[1:]) + with LoggingContext(name="main", server_name=homeserver_config.server.server_name): + start(homeserver_config) if __name__ == "__main__": diff --git a/synapse/app/media_repository.py b/synapse/app/media_repository.py index c85ce2869a2..823e1908b52 100644 --- a/synapse/app/media_repository.py +++ b/synapse/app/media_repository.py @@ -21,13 +21,14 @@ import sys -from synapse.app.generic_worker import start +from synapse.app.generic_worker import load_config, start from synapse.util.logcontext import LoggingContext def main() -> None: - with LoggingContext("main"): - start(sys.argv[1:]) + homeserver_config = load_config(sys.argv[1:]) + with LoggingContext(name="main", server_name=homeserver_config.server.server_name): + start(homeserver_config) if __name__ == "__main__": diff --git a/synapse/app/pusher.py b/synapse/app/pusher.py index c85ce2869a2..823e1908b52 100644 --- a/synapse/app/pusher.py +++ b/synapse/app/pusher.py @@ -21,13 +21,14 @@ import sys -from synapse.app.generic_worker import start +from synapse.app.generic_worker import load_config, start from synapse.util.logcontext import LoggingContext def main() -> None: - with LoggingContext("main"): - start(sys.argv[1:]) + homeserver_config = load_config(sys.argv[1:]) + with LoggingContext(name="main", server_name=homeserver_config.server.server_name): + start(homeserver_config) if __name__ == "__main__": diff --git a/synapse/app/synchrotron.py b/synapse/app/synchrotron.py index c85ce2869a2..823e1908b52 100644 --- a/synapse/app/synchrotron.py +++ b/synapse/app/synchrotron.py @@ -21,13 +21,14 @@ import sys -from synapse.app.generic_worker import start +from synapse.app.generic_worker import load_config, start from synapse.util.logcontext import LoggingContext def main() -> None: - with LoggingContext("main"): - start(sys.argv[1:]) + homeserver_config = load_config(sys.argv[1:]) + with LoggingContext(name="main", server_name=homeserver_config.server.server_name): + start(homeserver_config) if __name__ == "__main__": diff --git a/synapse/app/user_dir.py b/synapse/app/user_dir.py index dadcc487794..f64d82e41f4 100644 --- a/synapse/app/user_dir.py +++ b/synapse/app/user_dir.py @@ -21,13 +21,14 @@ import sys -from synapse.app.generic_worker import start +from synapse.app.generic_worker import load_config, start from synapse.util.logcontext import LoggingContext def main() -> None: - with LoggingContext("main"): - start(sys.argv[1:]) + homeserver_config = load_config(sys.argv[1:]) + with LoggingContext(name="main", server_name=homeserver_config.server.server_name): + start(homeserver_config) if __name__ == "__main__": From 1d731ec93d9480e54b6b2a54018f967b5ca5566e Mon Sep 17 00:00:00 2001 From: Eric Eastwood Date: Wed, 17 Sep 2025 13:46:34 -0500 Subject: [PATCH 3/4] Remove `server_name` changes From https://github.com/element-hq/synapse/pull/18868 --- synapse/app/admin_cmd.py | 4 ++-- synapse/app/appservice.py | 2 +- synapse/app/client_reader.py | 2 +- synapse/app/event_creator.py | 2 +- synapse/app/federation_reader.py | 2 +- synapse/app/federation_sender.py | 2 +- synapse/app/frontend_proxy.py | 2 +- synapse/app/generic_worker.py | 2 +- synapse/app/media_repository.py | 2 +- synapse/app/pusher.py | 2 +- synapse/app/synchrotron.py | 2 +- synapse/app/user_dir.py | 2 +- 12 files changed, 13 insertions(+), 13 deletions(-) diff --git a/synapse/app/admin_cmd.py b/synapse/app/admin_cmd.py index bc84dbdf494..c0c594577e5 100644 --- a/synapse/app/admin_cmd.py +++ b/synapse/app/admin_cmd.py @@ -329,7 +329,7 @@ def start(config: HomeServerConfig, args: argparse.Namespace) -> None: # command. async def run() -> None: - with LoggingContext(name="command", server_name=config.server.server_name): + with LoggingContext(name="command"): await _base.start(ss) await args.func(ss, args) @@ -342,5 +342,5 @@ async def run() -> None: if __name__ == "__main__": homeserver_config, args = load_config(sys.argv[1:]) - with LoggingContext(name="main", server_name=homeserver_config.server.server_name): + with LoggingContext(name="main"): start(homeserver_config, args) diff --git a/synapse/app/appservice.py b/synapse/app/appservice.py index 823e1908b52..95a253dbb9d 100644 --- a/synapse/app/appservice.py +++ b/synapse/app/appservice.py @@ -27,7 +27,7 @@ def main() -> None: homeserver_config = load_config(sys.argv[1:]) - with LoggingContext(name="main", server_name=homeserver_config.server.server_name): + with LoggingContext(name="main"): start(homeserver_config) diff --git a/synapse/app/client_reader.py b/synapse/app/client_reader.py index 823e1908b52..95a253dbb9d 100644 --- a/synapse/app/client_reader.py +++ b/synapse/app/client_reader.py @@ -27,7 +27,7 @@ def main() -> None: homeserver_config = load_config(sys.argv[1:]) - with LoggingContext(name="main", server_name=homeserver_config.server.server_name): + with LoggingContext(name="main"): start(homeserver_config) diff --git a/synapse/app/event_creator.py b/synapse/app/event_creator.py index 1a9b0ad1550..351cf93b760 100644 --- a/synapse/app/event_creator.py +++ b/synapse/app/event_creator.py @@ -26,7 +26,7 @@ def main() -> None: homeserver_config = load_config(sys.argv[1:]) - with LoggingContext(name="main", server_name=homeserver_config.server.server_name): + with LoggingContext(name="main"): start(homeserver_config) diff --git a/synapse/app/federation_reader.py b/synapse/app/federation_reader.py index 823e1908b52..95a253dbb9d 100644 --- a/synapse/app/federation_reader.py +++ b/synapse/app/federation_reader.py @@ -27,7 +27,7 @@ def main() -> None: homeserver_config = load_config(sys.argv[1:]) - with LoggingContext(name="main", server_name=homeserver_config.server.server_name): + with LoggingContext(name="main"): start(homeserver_config) diff --git a/synapse/app/federation_sender.py b/synapse/app/federation_sender.py index 823e1908b52..95a253dbb9d 100644 --- a/synapse/app/federation_sender.py +++ b/synapse/app/federation_sender.py @@ -27,7 +27,7 @@ def main() -> None: homeserver_config = load_config(sys.argv[1:]) - with LoggingContext(name="main", server_name=homeserver_config.server.server_name): + with LoggingContext(name="main"): start(homeserver_config) diff --git a/synapse/app/frontend_proxy.py b/synapse/app/frontend_proxy.py index 823e1908b52..95a253dbb9d 100644 --- a/synapse/app/frontend_proxy.py +++ b/synapse/app/frontend_proxy.py @@ -27,7 +27,7 @@ def main() -> None: homeserver_config = load_config(sys.argv[1:]) - with LoggingContext(name="main", server_name=homeserver_config.server.server_name): + with LoggingContext(name="main"): start(homeserver_config) diff --git a/synapse/app/generic_worker.py b/synapse/app/generic_worker.py index 7150a46ee27..b0e0176bdf6 100644 --- a/synapse/app/generic_worker.py +++ b/synapse/app/generic_worker.py @@ -379,7 +379,7 @@ def start(config: HomeServerConfig) -> None: def main() -> None: homeserver_config = load_config(sys.argv[1:]) - with LoggingContext(name="main", server_name=homeserver_config.server.server_name): + with LoggingContext(name="main"): start(homeserver_config) diff --git a/synapse/app/media_repository.py b/synapse/app/media_repository.py index 823e1908b52..95a253dbb9d 100644 --- a/synapse/app/media_repository.py +++ b/synapse/app/media_repository.py @@ -27,7 +27,7 @@ def main() -> None: homeserver_config = load_config(sys.argv[1:]) - with LoggingContext(name="main", server_name=homeserver_config.server.server_name): + with LoggingContext(name="main"): start(homeserver_config) diff --git a/synapse/app/pusher.py b/synapse/app/pusher.py index 823e1908b52..95a253dbb9d 100644 --- a/synapse/app/pusher.py +++ b/synapse/app/pusher.py @@ -27,7 +27,7 @@ def main() -> None: homeserver_config = load_config(sys.argv[1:]) - with LoggingContext(name="main", server_name=homeserver_config.server.server_name): + with LoggingContext(name="main"): start(homeserver_config) diff --git a/synapse/app/synchrotron.py b/synapse/app/synchrotron.py index 823e1908b52..95a253dbb9d 100644 --- a/synapse/app/synchrotron.py +++ b/synapse/app/synchrotron.py @@ -27,7 +27,7 @@ def main() -> None: homeserver_config = load_config(sys.argv[1:]) - with LoggingContext(name="main", server_name=homeserver_config.server.server_name): + with LoggingContext(name="main"): start(homeserver_config) diff --git a/synapse/app/user_dir.py b/synapse/app/user_dir.py index f64d82e41f4..b6385381b40 100644 --- a/synapse/app/user_dir.py +++ b/synapse/app/user_dir.py @@ -27,7 +27,7 @@ def main() -> None: homeserver_config = load_config(sys.argv[1:]) - with LoggingContext(name="main", server_name=homeserver_config.server.server_name): + with LoggingContext(name="main"): start(homeserver_config) From 4b3d923a475bcb3bf7978759b7c095aef568f374 Mon Sep 17 00:00:00 2001 From: Eric Eastwood Date: Wed, 17 Sep 2025 13:52:19 -0500 Subject: [PATCH 4/4] Add changelog --- changelog.d/18933.misc | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/18933.misc diff --git a/changelog.d/18933.misc b/changelog.d/18933.misc new file mode 100644 index 00000000000..3308d367e70 --- /dev/null +++ b/changelog.d/18933.misc @@ -0,0 +1 @@ +Split loading config from homeserver `setup`.