matrix-synapse 1.139.2__cp39-abi3-manylinux_2_28_aarch64.whl → 1.140.0rc1__cp39-abi3-manylinux_2_28_aarch64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of matrix-synapse might be problematic. Click here for more details.

Files changed (158) hide show
  1. {matrix_synapse-1.139.2.dist-info → matrix_synapse-1.140.0rc1.dist-info}/METADATA +5 -3
  2. {matrix_synapse-1.139.2.dist-info → matrix_synapse-1.140.0rc1.dist-info}/RECORD +157 -154
  3. synapse/_scripts/generate_workers_map.py +6 -1
  4. synapse/_scripts/synapse_port_db.py +0 -2
  5. synapse/_scripts/update_synapse_database.py +1 -6
  6. synapse/api/auth/base.py +1 -3
  7. synapse/api/auth/mas.py +6 -8
  8. synapse/api/auth/msc3861_delegated.py +6 -8
  9. synapse/api/errors.py +3 -0
  10. synapse/app/_base.py +101 -39
  11. synapse/app/admin_cmd.py +2 -4
  12. synapse/app/appservice.py +1 -1
  13. synapse/app/client_reader.py +1 -1
  14. synapse/app/event_creator.py +1 -1
  15. synapse/app/federation_reader.py +1 -1
  16. synapse/app/federation_sender.py +1 -1
  17. synapse/app/frontend_proxy.py +1 -1
  18. synapse/app/generic_worker.py +17 -11
  19. synapse/app/homeserver.py +85 -47
  20. synapse/app/media_repository.py +1 -1
  21. synapse/app/phone_stats_home.py +16 -14
  22. synapse/app/pusher.py +1 -1
  23. synapse/app/synchrotron.py +1 -1
  24. synapse/app/user_dir.py +1 -1
  25. synapse/appservice/__init__.py +29 -2
  26. synapse/appservice/scheduler.py +8 -8
  27. synapse/config/_base.py +32 -14
  28. synapse/config/_base.pyi +5 -3
  29. synapse/config/experimental.py +3 -0
  30. synapse/config/homeserver.py +27 -1
  31. synapse/config/logger.py +3 -4
  32. synapse/config/matrixrtc.py +67 -0
  33. synapse/crypto/keyring.py +18 -4
  34. synapse/events/auto_accept_invites.py +0 -1
  35. synapse/federation/federation_client.py +39 -0
  36. synapse/federation/federation_server.py +1 -1
  37. synapse/federation/send_queue.py +3 -0
  38. synapse/federation/sender/__init__.py +24 -8
  39. synapse/federation/sender/per_destination_queue.py +31 -8
  40. synapse/federation/sender/transaction_manager.py +12 -0
  41. synapse/federation/transport/client.py +29 -0
  42. synapse/handlers/account_validity.py +2 -4
  43. synapse/handlers/appservice.py +5 -7
  44. synapse/handlers/deactivate_account.py +2 -3
  45. synapse/handlers/delayed_events.py +10 -13
  46. synapse/handlers/device.py +14 -14
  47. synapse/handlers/e2e_keys.py +4 -3
  48. synapse/handlers/federation.py +7 -11
  49. synapse/handlers/federation_event.py +5 -6
  50. synapse/handlers/message.py +16 -10
  51. synapse/handlers/pagination.py +3 -7
  52. synapse/handlers/presence.py +21 -25
  53. synapse/handlers/profile.py +1 -1
  54. synapse/handlers/read_marker.py +3 -1
  55. synapse/handlers/register.py +8 -1
  56. synapse/handlers/room.py +13 -4
  57. synapse/handlers/room_member.py +11 -7
  58. synapse/handlers/room_policy.py +96 -2
  59. synapse/handlers/sso.py +1 -1
  60. synapse/handlers/stats.py +5 -3
  61. synapse/handlers/sync.py +20 -13
  62. synapse/handlers/typing.py +5 -10
  63. synapse/handlers/user_directory.py +12 -11
  64. synapse/handlers/worker_lock.py +19 -15
  65. synapse/http/client.py +18 -13
  66. synapse/http/federation/matrix_federation_agent.py +6 -1
  67. synapse/http/federation/well_known_resolver.py +3 -1
  68. synapse/http/matrixfederationclient.py +50 -11
  69. synapse/http/proxy.py +2 -2
  70. synapse/http/server.py +36 -2
  71. synapse/http/site.py +109 -17
  72. synapse/logging/context.py +165 -63
  73. synapse/logging/opentracing.py +30 -6
  74. synapse/logging/scopecontextmanager.py +161 -0
  75. synapse/media/_base.py +2 -1
  76. synapse/media/media_repository.py +20 -6
  77. synapse/media/url_previewer.py +5 -6
  78. synapse/metrics/_gc.py +3 -1
  79. synapse/metrics/background_process_metrics.py +128 -24
  80. synapse/metrics/common_usage_metrics.py +3 -5
  81. synapse/module_api/__init__.py +42 -5
  82. synapse/notifier.py +10 -3
  83. synapse/push/emailpusher.py +5 -4
  84. synapse/push/httppusher.py +6 -6
  85. synapse/push/pusherpool.py +3 -8
  86. synapse/replication/http/devices.py +0 -41
  87. synapse/replication/tcp/client.py +8 -5
  88. synapse/replication/tcp/handler.py +2 -3
  89. synapse/replication/tcp/protocol.py +14 -7
  90. synapse/replication/tcp/redis.py +16 -11
  91. synapse/replication/tcp/resource.py +5 -4
  92. synapse/replication/tcp/streams/__init__.py +2 -0
  93. synapse/res/providers.json +6 -5
  94. synapse/rest/__init__.py +2 -0
  95. synapse/rest/admin/__init__.py +4 -0
  96. synapse/rest/admin/events.py +69 -0
  97. synapse/rest/admin/media.py +70 -2
  98. synapse/rest/client/matrixrtc.py +52 -0
  99. synapse/rest/client/push_rule.py +1 -1
  100. synapse/rest/client/room.py +2 -3
  101. synapse/rest/client/sync.py +1 -0
  102. synapse/rest/client/transactions.py +1 -1
  103. synapse/server.py +271 -38
  104. synapse/server_notices/server_notices_manager.py +1 -0
  105. synapse/state/__init__.py +4 -1
  106. synapse/storage/_base.py +1 -1
  107. synapse/storage/background_updates.py +8 -3
  108. synapse/storage/controllers/persist_events.py +4 -3
  109. synapse/storage/controllers/purge_events.py +2 -3
  110. synapse/storage/controllers/state.py +5 -5
  111. synapse/storage/database.py +12 -7
  112. synapse/storage/databases/main/__init__.py +7 -2
  113. synapse/storage/databases/main/cache.py +4 -3
  114. synapse/storage/databases/main/censor_events.py +1 -1
  115. synapse/storage/databases/main/client_ips.py +9 -8
  116. synapse/storage/databases/main/deviceinbox.py +7 -6
  117. synapse/storage/databases/main/devices.py +4 -4
  118. synapse/storage/databases/main/end_to_end_keys.py +6 -3
  119. synapse/storage/databases/main/event_federation.py +7 -6
  120. synapse/storage/databases/main/event_push_actions.py +13 -13
  121. synapse/storage/databases/main/events_bg_updates.py +1 -1
  122. synapse/storage/databases/main/events_worker.py +6 -8
  123. synapse/storage/databases/main/lock.py +17 -13
  124. synapse/storage/databases/main/media_repository.py +2 -2
  125. synapse/storage/databases/main/metrics.py +6 -6
  126. synapse/storage/databases/main/monthly_active_users.py +3 -4
  127. synapse/storage/databases/main/receipts.py +1 -1
  128. synapse/storage/databases/main/registration.py +18 -19
  129. synapse/storage/databases/main/roommember.py +1 -1
  130. synapse/storage/databases/main/session.py +3 -3
  131. synapse/storage/databases/main/sliding_sync.py +2 -2
  132. synapse/storage/databases/main/transactions.py +3 -3
  133. synapse/storage/databases/state/store.py +2 -0
  134. synapse/synapse_rust/http_client.pyi +4 -0
  135. synapse/synapse_rust.abi3.so +0 -0
  136. synapse/util/async_helpers.py +36 -24
  137. synapse/util/batching_queue.py +16 -6
  138. synapse/util/caches/__init__.py +1 -1
  139. synapse/util/caches/deferred_cache.py +4 -0
  140. synapse/util/caches/descriptors.py +14 -2
  141. synapse/util/caches/dictionary_cache.py +6 -1
  142. synapse/util/caches/expiringcache.py +16 -5
  143. synapse/util/caches/lrucache.py +14 -26
  144. synapse/util/caches/response_cache.py +11 -1
  145. synapse/util/clock.py +215 -39
  146. synapse/util/constants.py +2 -0
  147. synapse/util/daemonize.py +5 -1
  148. synapse/util/distributor.py +9 -5
  149. synapse/util/metrics.py +35 -6
  150. synapse/util/ratelimitutils.py +4 -1
  151. synapse/util/retryutils.py +7 -4
  152. synapse/util/task_scheduler.py +11 -14
  153. synapse/logging/filter.py +0 -38
  154. {matrix_synapse-1.139.2.dist-info → matrix_synapse-1.140.0rc1.dist-info}/AUTHORS.rst +0 -0
  155. {matrix_synapse-1.139.2.dist-info → matrix_synapse-1.140.0rc1.dist-info}/LICENSE-AGPL-3.0 +0 -0
  156. {matrix_synapse-1.139.2.dist-info → matrix_synapse-1.140.0rc1.dist-info}/LICENSE-COMMERCIAL +0 -0
  157. {matrix_synapse-1.139.2.dist-info → matrix_synapse-1.140.0rc1.dist-info}/WHEEL +0 -0
  158. {matrix_synapse-1.139.2.dist-info → matrix_synapse-1.140.0rc1.dist-info}/entry_points.txt +0 -0
synapse/app/homeserver.py CHANGED
@@ -22,14 +22,13 @@
22
22
  import logging
23
23
  import os
24
24
  import sys
25
- from typing import Dict, Iterable, List
25
+ from typing import Dict, Iterable, List, Optional
26
26
 
27
27
  from twisted.internet.tcp import Port
28
28
  from twisted.web.resource import EncodingResourceWrapper, Resource
29
29
  from twisted.web.server import GzipEncoderFactory
30
30
 
31
31
  import synapse
32
- import synapse.config.logger
33
32
  from synapse import events
34
33
  from synapse.api.urls import (
35
34
  CLIENT_API_PREFIX,
@@ -50,6 +49,7 @@ from synapse.app._base import (
50
49
  )
51
50
  from synapse.config._base import ConfigError, format_config_error
52
51
  from synapse.config.homeserver import HomeServerConfig
52
+ from synapse.config.logger import setup_logging
53
53
  from synapse.config.server import ListenerConfig, TCPListenerConfig
54
54
  from synapse.federation.transport.server import TransportLayerServer
55
55
  from synapse.http.additional_resource import AdditionalResource
@@ -60,6 +60,7 @@ from synapse.http.server import (
60
60
  StaticResource,
61
61
  )
62
62
  from synapse.logging.context import LoggingContext
63
+ from synapse.logging.opentracing import init_tracer
63
64
  from synapse.metrics import METRICS_PREFIX, MetricsResource, RegistryProxy
64
65
  from synapse.replication.http import REPLICATION_PREFIX, ReplicationRestResource
65
66
  from synapse.rest import ClientRestResource, admin
@@ -69,7 +70,8 @@ from synapse.rest.synapse.client import build_synapse_client_resource_tree
69
70
  from synapse.rest.well_known import well_known_resource
70
71
  from synapse.server import HomeServer
71
72
  from synapse.storage import DataStore
72
- from synapse.util.check_dependencies import VERSION, check_requirements
73
+ from synapse.types import ISynapseReactor
74
+ from synapse.util.check_dependencies import check_requirements
73
75
  from synapse.util.httpresourcetree import create_resource_tree
74
76
  from synapse.util.module_loader import load_module
75
77
 
@@ -81,6 +83,10 @@ def gz_wrap(r: Resource) -> Resource:
81
83
 
82
84
 
83
85
  class SynapseHomeServer(HomeServer):
86
+ """
87
+ Homeserver class for the main Synapse process.
88
+ """
89
+
84
90
  DATASTORE_CLASS = DataStore
85
91
 
86
92
  def _listener_http(
@@ -276,11 +282,13 @@ class SynapseHomeServer(HomeServer):
276
282
  )
277
283
  elif listener.type == "manhole":
278
284
  if isinstance(listener, TCPListenerConfig):
279
- _base.listen_manhole(
280
- listener.bind_addresses,
281
- listener.port,
282
- manhole_settings=self.config.server.manhole_settings,
283
- manhole_globals={"hs": self},
285
+ self._listening_services.extend(
286
+ _base.listen_manhole(
287
+ listener.bind_addresses,
288
+ listener.port,
289
+ manhole_settings=self.config.server.manhole_settings,
290
+ manhole_globals={"hs": self},
291
+ )
284
292
  )
285
293
  else:
286
294
  raise ConfigError(
@@ -293,9 +301,11 @@ class SynapseHomeServer(HomeServer):
293
301
  )
294
302
  else:
295
303
  if isinstance(listener, TCPListenerConfig):
296
- _base.listen_metrics(
297
- listener.bind_addresses,
298
- listener.port,
304
+ self._metrics_listeners.extend(
305
+ _base.listen_metrics(
306
+ listener.bind_addresses,
307
+ listener.port,
308
+ )
299
309
  )
300
310
  else:
301
311
  raise ConfigError(
@@ -339,12 +349,17 @@ def load_or_generate_config(argv_options: List[str]) -> HomeServerConfig:
339
349
  return config
340
350
 
341
351
 
342
- def setup(config: HomeServerConfig) -> SynapseHomeServer:
352
+ def create_homeserver(
353
+ config: HomeServerConfig,
354
+ reactor: Optional[ISynapseReactor] = None,
355
+ ) -> SynapseHomeServer:
343
356
  """
344
- Create and setup a Synapse homeserver instance given a configuration.
357
+ Create a homeserver instance for the Synapse main process.
345
358
 
346
359
  Args:
347
360
  config: The configuration for the homeserver.
361
+ reactor: Optionally provide a reactor to use. Can be useful in different
362
+ scenarios that you want control over the reactor, such as tests.
348
363
 
349
364
  Returns:
350
365
  A homeserver instance.
@@ -352,10 +367,9 @@ def setup(config: HomeServerConfig) -> SynapseHomeServer:
352
367
 
353
368
  if config.worker.worker_app:
354
369
  raise ConfigError(
355
- "You have specified `worker_app` in the config but are attempting to start a non-worker "
370
+ "You have specified `worker_app` in the config but are attempting to setup a non-worker "
356
371
  "instance. Please use `python -m synapse.app.generic_worker` instead (or remove the option if this is the main process)."
357
372
  )
358
- sys.exit(1)
359
373
 
360
374
  events.USE_FROZEN_DICTS = config.server.use_frozen_dicts
361
375
  synapse.util.caches.TRACK_MEMORY_USAGE = config.caches.track_memory_usage
@@ -363,61 +377,84 @@ def setup(config: HomeServerConfig) -> SynapseHomeServer:
363
377
  if config.server.gc_seconds:
364
378
  synapse.metrics.MIN_TIME_BETWEEN_GCS = config.server.gc_seconds
365
379
 
366
- if (
367
- config.registration.enable_registration
368
- and not config.registration.enable_registration_without_verification
369
- ):
370
- if (
371
- not config.captcha.enable_registration_captcha
372
- and not config.registration.registrations_require_3pid
373
- and not config.registration.registration_requires_token
374
- ):
375
- raise ConfigError(
376
- "You have enabled open registration without any verification. This is a known vector for "
377
- "spam and abuse. If you would like to allow public registration, please consider adding email, "
378
- "captcha, or token-based verification. Otherwise this check can be removed by setting the "
379
- "`enable_registration_without_verification` config option to `true`."
380
- )
381
-
382
380
  hs = SynapseHomeServer(
383
- config.server.server_name,
381
+ hostname=config.server.server_name,
384
382
  config=config,
385
- version_string=f"Synapse/{VERSION}",
383
+ reactor=reactor,
386
384
  )
387
385
 
388
- synapse.config.logger.setup_logging(hs, config, use_worker_options=False)
386
+ return hs
387
+
388
+
389
+ def setup(
390
+ hs: SynapseHomeServer,
391
+ *,
392
+ freeze: bool = True,
393
+ ) -> None:
394
+ """
395
+ Setup a Synapse homeserver instance given a configuration.
389
396
 
397
+ Args:
398
+ hs: The homeserver to setup.
399
+ freeze: whether to freeze the homeserver base objects in the garbage collector.
400
+ May improve garbage collection performance by marking objects with an effectively
401
+ static lifetime as frozen so they don't need to be considered for cleanup.
402
+ If you ever want to `shutdown` the homeserver, this needs to be
403
+ False otherwise the homeserver cannot be garbage collected after `shutdown`.
404
+
405
+ Returns:
406
+ A homeserver instance.
407
+ """
408
+
409
+ setup_logging(hs, hs.config, use_worker_options=False)
410
+
411
+ # Log after we've configured logging.
390
412
  logger.info("Setting up server")
391
413
 
414
+ # Start the tracer
415
+ init_tracer(hs) # noqa
416
+
392
417
  try:
393
418
  hs.setup()
394
419
  except Exception as e:
395
420
  handle_startup_exception(e)
396
421
 
397
- async def start() -> None:
422
+ async def _start_when_reactor_running() -> None:
423
+ # TODO: Feels like this should be moved somewhere else.
424
+ #
398
425
  # Load the OIDC provider metadatas, if OIDC is enabled.
399
426
  if hs.config.oidc.oidc_enabled:
400
427
  oidc = hs.get_oidc_handler()
401
428
  # Loading the provider metadata also ensures the provider config is valid.
402
429
  await oidc.load_metadata()
403
430
 
404
- await _base.start(hs)
431
+ await _base.start(hs, freeze)
405
432
 
433
+ # TODO: This should be moved to `SynapseHomeServer.start_background_tasks` (not
434
+ # `HomeServer.start_background_tasks`) (this way it matches the behavior of only
435
+ # running on `main`)
406
436
  hs.get_datastores().main.db_pool.updates.start_doing_background_updates()
407
437
 
408
- register_start(hs, start)
438
+ # Register a callback to be invoked once the reactor is running
439
+ register_start(hs, _start_when_reactor_running)
409
440
 
410
- return hs
411
441
 
442
+ def start_reactor(
443
+ config: HomeServerConfig,
444
+ ) -> None:
445
+ """
446
+ Start the reactor (Twisted event-loop).
412
447
 
413
- def run(hs: HomeServer) -> None:
448
+ Args:
449
+ config: The configuration for the homeserver.
450
+ """
414
451
  _base.start_reactor(
415
452
  "synapse-homeserver",
416
- soft_file_limit=hs.config.server.soft_file_limit,
417
- gc_thresholds=hs.config.server.gc_thresholds,
418
- pid_file=hs.config.server.pid_file,
419
- daemonize=hs.config.server.daemonize,
420
- print_pidfile=hs.config.server.print_pidfile,
453
+ soft_file_limit=config.server.soft_file_limit,
454
+ gc_thresholds=config.server.gc_thresholds,
455
+ pid_file=config.server.pid_file,
456
+ daemonize=config.server.daemonize,
457
+ print_pidfile=config.server.print_pidfile,
421
458
  logger=logger,
422
459
  )
423
460
 
@@ -425,16 +462,17 @@ def run(hs: HomeServer) -> None:
425
462
  def main() -> None:
426
463
  homeserver_config = load_or_generate_config(sys.argv[1:])
427
464
 
428
- with LoggingContext("main"):
465
+ with LoggingContext(name="main", server_name=homeserver_config.server.server_name):
429
466
  # check base requirements
430
467
  check_requirements()
431
- hs = setup(homeserver_config)
468
+ hs = create_homeserver(homeserver_config)
469
+ setup(hs)
432
470
 
433
471
  # redirect stdio to the logs, if configured.
434
472
  if not hs.config.logging.no_redirect_stdio:
435
473
  redirect_stdio_to_logs()
436
474
 
437
- run(hs)
475
+ start_reactor(homeserver_config)
438
476
 
439
477
 
440
478
  if __name__ == "__main__":
@@ -27,7 +27,7 @@ from synapse.util.logcontext import LoggingContext
27
27
 
28
28
  def main() -> None:
29
29
  homeserver_config = load_config(sys.argv[1:])
30
- with LoggingContext(name="main"):
30
+ with LoggingContext(name="main", server_name=homeserver_config.server.server_name):
31
31
  start(homeserver_config)
32
32
 
33
33
 
@@ -29,19 +29,18 @@ from prometheus_client import Gauge
29
29
  from twisted.internet import defer
30
30
 
31
31
  from synapse.metrics import SERVER_NAME_LABEL
32
- from synapse.metrics.background_process_metrics import (
33
- run_as_background_process,
34
- )
35
32
  from synapse.types import JsonDict
36
- from synapse.util.constants import ONE_HOUR_SECONDS, ONE_MINUTE_SECONDS
33
+ from synapse.util.constants import (
34
+ MILLISECONDS_PER_SECOND,
35
+ ONE_HOUR_SECONDS,
36
+ ONE_MINUTE_SECONDS,
37
+ )
37
38
 
38
39
  if TYPE_CHECKING:
39
40
  from synapse.server import HomeServer
40
41
 
41
42
  logger = logging.getLogger("synapse.app.homeserver")
42
43
 
43
- MILLISECONDS_PER_SECOND = 1000
44
-
45
44
  INITIAL_DELAY_BEFORE_FIRST_PHONE_HOME_SECONDS = 5 * ONE_MINUTE_SECONDS
46
45
  """
47
46
  We wait 5 minutes to send the first set of stats as the server can be quite busy the
@@ -85,8 +84,6 @@ def phone_stats_home(
85
84
  stats: JsonDict,
86
85
  stats_process: List[Tuple[int, "resource.struct_rusage"]] = _stats_process,
87
86
  ) -> "defer.Deferred[None]":
88
- server_name = hs.hostname
89
-
90
87
  async def _phone_stats_home(
91
88
  hs: "HomeServer",
92
89
  stats: JsonDict,
@@ -200,8 +197,8 @@ def phone_stats_home(
200
197
  except Exception as e:
201
198
  logger.warning("Error reporting stats: %s", e)
202
199
 
203
- return run_as_background_process(
204
- "phone_stats_home", server_name, _phone_stats_home, hs, stats, stats_process
200
+ return hs.run_as_background_process(
201
+ "phone_stats_home", _phone_stats_home, hs, stats, stats_process
205
202
  )
206
203
 
207
204
 
@@ -263,9 +260,8 @@ def start_phone_stats_home(hs: "HomeServer") -> None:
263
260
  float(hs.config.server.max_mau_value)
264
261
  )
265
262
 
266
- return run_as_background_process(
263
+ return hs.run_as_background_process(
267
264
  "generate_monthly_active_users",
268
- server_name,
269
265
  _generate_monthly_active_users,
270
266
  )
271
267
 
@@ -285,10 +281,16 @@ def start_phone_stats_home(hs: "HomeServer") -> None:
285
281
 
286
282
  # We need to defer this init for the cases that we daemonize
287
283
  # otherwise the process ID we get is that of the non-daemon process
288
- clock.call_later(0, performance_stats_init)
284
+ clock.call_later(
285
+ 0,
286
+ performance_stats_init,
287
+ )
289
288
 
290
289
  # We wait 5 minutes to send the first set of stats as the server can
291
290
  # be quite busy the first few minutes
292
291
  clock.call_later(
293
- INITIAL_DELAY_BEFORE_FIRST_PHONE_HOME_SECONDS, phone_stats_home, hs, stats
292
+ INITIAL_DELAY_BEFORE_FIRST_PHONE_HOME_SECONDS,
293
+ phone_stats_home,
294
+ hs,
295
+ stats,
294
296
  )
synapse/app/pusher.py CHANGED
@@ -27,7 +27,7 @@ from synapse.util.logcontext import LoggingContext
27
27
 
28
28
  def main() -> None:
29
29
  homeserver_config = load_config(sys.argv[1:])
30
- with LoggingContext(name="main"):
30
+ with LoggingContext(name="main", server_name=homeserver_config.server.server_name):
31
31
  start(homeserver_config)
32
32
 
33
33
 
@@ -27,7 +27,7 @@ from synapse.util.logcontext import LoggingContext
27
27
 
28
28
  def main() -> None:
29
29
  homeserver_config = load_config(sys.argv[1:])
30
- with LoggingContext(name="main"):
30
+ with LoggingContext(name="main", server_name=homeserver_config.server.server_name):
31
31
  start(homeserver_config)
32
32
 
33
33
 
synapse/app/user_dir.py CHANGED
@@ -27,7 +27,7 @@ from synapse.util.logcontext import LoggingContext
27
27
 
28
28
  def main() -> None:
29
29
  homeserver_config = load_config(sys.argv[1:])
30
- with LoggingContext(name="main"):
30
+ with LoggingContext(name="main", server_name=homeserver_config.server.server_name):
31
31
  start(homeserver_config)
32
32
 
33
33
 
@@ -23,15 +23,33 @@
23
23
  import logging
24
24
  import re
25
25
  from enum import Enum
26
- from typing import TYPE_CHECKING, Dict, Iterable, List, Optional, Pattern, Sequence
26
+ from typing import (
27
+ TYPE_CHECKING,
28
+ Dict,
29
+ Iterable,
30
+ List,
31
+ Optional,
32
+ Pattern,
33
+ Sequence,
34
+ cast,
35
+ )
27
36
 
28
37
  import attr
29
38
  from netaddr import IPSet
30
39
 
40
+ from twisted.internet import reactor
41
+
31
42
  from synapse.api.constants import EventTypes
32
43
  from synapse.events import EventBase
33
- from synapse.types import DeviceListUpdates, JsonDict, JsonMapping, UserID
44
+ from synapse.types import (
45
+ DeviceListUpdates,
46
+ ISynapseThreadlessReactor,
47
+ JsonDict,
48
+ JsonMapping,
49
+ UserID,
50
+ )
34
51
  from synapse.util.caches.descriptors import _CacheContext, cached
52
+ from synapse.util.clock import Clock
35
53
 
36
54
  if TYPE_CHECKING:
37
55
  from synapse.appservice.api import ApplicationServiceApi
@@ -98,6 +116,15 @@ class ApplicationService:
98
116
  self.sender = sender
99
117
  # The application service user should be part of the server's domain.
100
118
  self.server_name = sender.domain # nb must be called this for @cached
119
+
120
+ # Ideally we would require passing in the `HomeServer` `Clock` instance.
121
+ # However this is not currently possible as there are places which use
122
+ # `@cached` that aren't aware of the `HomeServer` instance.
123
+ # nb must be called this for @cached
124
+ self.clock = Clock(
125
+ cast(ISynapseThreadlessReactor, reactor), server_name=self.server_name
126
+ ) # type: ignore[multiple-internal-clocks]
127
+
101
128
  self.namespaces = self._check_namespaces(namespaces)
102
129
  self.id = id
103
130
  self.ip_range_whitelist = ip_range_whitelist
@@ -81,7 +81,6 @@ from synapse.appservice import (
81
81
  from synapse.appservice.api import ApplicationServiceApi
82
82
  from synapse.events import EventBase
83
83
  from synapse.logging.context import run_in_background
84
- from synapse.metrics.background_process_metrics import run_as_background_process
85
84
  from synapse.storage.databases.main import DataStore
86
85
  from synapse.types import DeviceListUpdates, JsonMapping
87
86
  from synapse.util.clock import Clock
@@ -200,6 +199,7 @@ class _ServiceQueuer:
200
199
  )
201
200
  self.server_name = hs.hostname
202
201
  self.clock = hs.get_clock()
202
+ self.hs = hs
203
203
  self._store = hs.get_datastores().main
204
204
 
205
205
  def start_background_request(self, service: ApplicationService) -> None:
@@ -207,9 +207,7 @@ class _ServiceQueuer:
207
207
  if service.id in self.requests_in_flight:
208
208
  return
209
209
 
210
- run_as_background_process(
211
- "as-sender", self.server_name, self._send_request, service
212
- )
210
+ self.hs.run_as_background_process("as-sender", self._send_request, service)
213
211
 
214
212
  async def _send_request(self, service: ApplicationService) -> None:
215
213
  # sanity-check: we shouldn't get here if this service already has a sender
@@ -361,6 +359,7 @@ class _TransactionController:
361
359
  def __init__(self, hs: "HomeServer"):
362
360
  self.server_name = hs.hostname
363
361
  self.clock = hs.get_clock()
362
+ self.hs = hs
364
363
  self.store = hs.get_datastores().main
365
364
  self.as_api = hs.get_application_service_api()
366
365
 
@@ -448,6 +447,7 @@ class _TransactionController:
448
447
  recoverer = self.RECOVERER_CLASS(
449
448
  self.server_name,
450
449
  self.clock,
450
+ self.hs,
451
451
  self.store,
452
452
  self.as_api,
453
453
  service,
@@ -494,6 +494,7 @@ class _Recoverer:
494
494
  self,
495
495
  server_name: str,
496
496
  clock: Clock,
497
+ hs: "HomeServer",
497
498
  store: DataStore,
498
499
  as_api: ApplicationServiceApi,
499
500
  service: ApplicationService,
@@ -501,6 +502,7 @@ class _Recoverer:
501
502
  ):
502
503
  self.server_name = server_name
503
504
  self.clock = clock
505
+ self.hs = hs
504
506
  self.store = store
505
507
  self.as_api = as_api
506
508
  self.service = service
@@ -513,9 +515,8 @@ class _Recoverer:
513
515
  logger.info("Scheduling retries on %s in %fs", self.service.id, delay)
514
516
  self.scheduled_recovery = self.clock.call_later(
515
517
  delay,
516
- run_as_background_process,
518
+ self.hs.run_as_background_process,
517
519
  "as-recoverer",
518
- self.server_name,
519
520
  self.retry,
520
521
  )
521
522
 
@@ -535,9 +536,8 @@ class _Recoverer:
535
536
  if self.scheduled_recovery:
536
537
  self.clock.cancel_call_later(self.scheduled_recovery)
537
538
  # Run a retry, which will resechedule a recovery if it fails.
538
- run_as_background_process(
539
+ self.hs.run_as_background_process(
539
540
  "retry",
540
- self.server_name,
541
541
  self.retry,
542
542
  )
543
543
 
synapse/config/_base.py CHANGED
@@ -545,18 +545,22 @@ class RootConfig:
545
545
 
546
546
  @classmethod
547
547
  def load_config(
548
- cls: Type[TRootConfig], description: str, argv: List[str]
548
+ cls: Type[TRootConfig], description: str, argv_options: List[str]
549
549
  ) -> TRootConfig:
550
550
  """Parse the commandline and config files
551
551
 
552
552
  Doesn't support config-file-generation: used by the worker apps.
553
553
 
554
+ Args:
555
+ description: TODO
556
+ argv_options: The options passed to Synapse. Usually `sys.argv[1:]`.
557
+
554
558
  Returns:
555
559
  Config object.
556
560
  """
557
561
  config_parser = argparse.ArgumentParser(description=description)
558
562
  cls.add_arguments_to_parser(config_parser)
559
- obj, _ = cls.load_config_with_parser(config_parser, argv)
563
+ obj, _ = cls.load_config_with_parser(config_parser, argv_options)
560
564
 
561
565
  return obj
562
566
 
@@ -601,7 +605,7 @@ class RootConfig:
601
605
 
602
606
  @classmethod
603
607
  def load_config_with_parser(
604
- cls: Type[TRootConfig], parser: argparse.ArgumentParser, argv: List[str]
608
+ cls: Type[TRootConfig], parser: argparse.ArgumentParser, argv_options: List[str]
605
609
  ) -> Tuple[TRootConfig, argparse.Namespace]:
606
610
  """Parse the commandline and config files with the given parser
607
611
 
@@ -609,16 +613,20 @@ class RootConfig:
609
613
 
610
614
  Used for workers where we want to add extra flags/subcommands.
611
615
 
616
+ Note: This is the common denominator for loading config and is also used by
617
+ `load_config` and `load_or_generate_config`. Which is why we call
618
+ `validate_config()` here.
619
+
612
620
  Args:
613
621
  parser
614
- argv
622
+ argv_options: The options passed to Synapse. Usually `sys.argv[1:]`.
615
623
 
616
624
  Returns:
617
625
  Returns the parsed config object and the parsed argparse.Namespace
618
626
  object from parser.parse_args(..)`
619
627
  """
620
628
 
621
- config_args = parser.parse_args(argv)
629
+ config_args = parser.parse_args(argv_options)
622
630
 
623
631
  config_files = find_config_files(search_paths=config_args.config_path)
624
632
  obj = cls(config_files)
@@ -642,6 +650,10 @@ class RootConfig:
642
650
 
643
651
  obj.invoke_all("read_arguments", config_args)
644
652
 
653
+ # Now that we finally have the full config sections parsed, allow subclasses to
654
+ # do some extra validation across the entire config.
655
+ obj.validate_config()
656
+
645
657
  return obj, config_args
646
658
 
647
659
  @classmethod
@@ -842,15 +854,7 @@ class RootConfig:
842
854
  ):
843
855
  return None
844
856
 
845
- obj.parse_config_dict(
846
- config_dict,
847
- config_dir_path=config_dir_path,
848
- data_dir_path=data_dir_path,
849
- allow_secrets_in_config=config_args.secrets_in_config,
850
- )
851
- obj.invoke_all("read_arguments", config_args)
852
-
853
- return obj
857
+ return cls.load_config(description, argv_options)
854
858
 
855
859
  def parse_config_dict(
856
860
  self,
@@ -911,6 +915,20 @@ class RootConfig:
911
915
  existing_config.root = None
912
916
  return existing_config
913
917
 
918
+ def validate_config(self) -> None:
919
+ """
920
+ Additional config validation across all config sections.
921
+
922
+ Override this in subclasses to add extra validation. This is called once all
923
+ config option values have been populated.
924
+
925
+ XXX: This should only validate, not modify the configuration, as the final
926
+ config state is required for proper validation across all config sections.
927
+
928
+ Raises:
929
+ ConfigError: if the config is invalid.
930
+ """
931
+
914
932
 
915
933
  def read_config_files(config_files: Iterable[str]) -> Dict[str, Any]:
916
934
  """Read the config files and shallowly merge them into a dict.
synapse/config/_base.pyi CHANGED
@@ -37,6 +37,7 @@ from synapse.config import ( # noqa: F401
37
37
  key,
38
38
  logger,
39
39
  mas,
40
+ matrixrtc,
40
41
  metrics,
41
42
  modules,
42
43
  oembed,
@@ -126,6 +127,7 @@ class RootConfig:
126
127
  auto_accept_invites: auto_accept_invites.AutoAcceptInvitesConfig
127
128
  user_types: user_types.UserTypesConfig
128
129
  mas: mas.MasConfig
130
+ matrix_rtc: matrixrtc.MatrixRtcConfig
129
131
 
130
132
  config_classes: List[Type["Config"]] = ...
131
133
  config_files: List[str]
@@ -156,11 +158,11 @@ class RootConfig:
156
158
  ) -> str: ...
157
159
  @classmethod
158
160
  def load_or_generate_config(
159
- cls: Type[TRootConfig], description: str, argv: List[str]
161
+ cls: Type[TRootConfig], description: str, argv_options: List[str]
160
162
  ) -> Optional[TRootConfig]: ...
161
163
  @classmethod
162
164
  def load_config(
163
- cls: Type[TRootConfig], description: str, argv: List[str]
165
+ cls: Type[TRootConfig], description: str, argv_options: List[str]
164
166
  ) -> TRootConfig: ...
165
167
  @classmethod
166
168
  def add_arguments_to_parser(
@@ -168,7 +170,7 @@ class RootConfig:
168
170
  ) -> None: ...
169
171
  @classmethod
170
172
  def load_config_with_parser(
171
- cls: Type[TRootConfig], parser: argparse.ArgumentParser, argv: List[str]
173
+ cls: Type[TRootConfig], parser: argparse.ArgumentParser, argv_options: List[str]
172
174
  ) -> Tuple[TRootConfig, argparse.Namespace]: ...
173
175
  def generate_missing_files(
174
176
  self, config_dict: dict, config_dir_path: str
@@ -556,6 +556,9 @@ class ExperimentalConfig(Config):
556
556
  # MSC4133: Custom profile fields
557
557
  self.msc4133_enabled: bool = experimental.get("msc4133_enabled", False)
558
558
 
559
+ # MSC4143: Matrix RTC Transport using Livekit Backend
560
+ self.msc4143_enabled: bool = experimental.get("msc4143_enabled", False)
561
+
559
562
  # MSC4169: Backwards-compatible redaction sending using `/send`
560
563
  self.msc4169_enabled: bool = experimental.get("msc4169_enabled", False)
561
564