Merge pull request #8060 from matrix-org/erikj/type_server
Change HomeServer definition to work with typing.
This commit is contained in:
commit
6ba621d786
|
@ -0,0 +1 @@
|
|||
Improve typing information on `HomeServer` object.
|
|
@ -125,7 +125,7 @@ from synapse.rest.client.v2_alpha.register import RegisterRestServlet
|
|||
from synapse.rest.client.versions import VersionsRestServlet
|
||||
from synapse.rest.health import HealthResource
|
||||
from synapse.rest.key.v2 import KeyApiV2Resource
|
||||
from synapse.server import HomeServer
|
||||
from synapse.server import HomeServer, cache_in_self
|
||||
from synapse.storage.databases.main.censor_events import CensorEventsStore
|
||||
from synapse.storage.databases.main.media_repository import MediaRepositoryStore
|
||||
from synapse.storage.databases.main.monthly_active_users import (
|
||||
|
@ -635,10 +635,12 @@ class GenericWorkerServer(HomeServer):
|
|||
async def remove_pusher(self, app_id, push_key, user_id):
|
||||
self.get_tcp_replication().send_remove_pusher(app_id, push_key, user_id)
|
||||
|
||||
def build_replication_data_handler(self):
|
||||
@cache_in_self
|
||||
def get_replication_data_handler(self):
|
||||
return GenericWorkerReplicationHandler(self)
|
||||
|
||||
def build_presence_handler(self):
|
||||
@cache_in_self
|
||||
def get_presence_handler(self):
|
||||
return GenericWorkerPresence(self)
|
||||
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
# limitations under the License.
|
||||
import json
|
||||
import logging
|
||||
from typing import Dict, Generic, List, Optional, Tuple, TypeVar
|
||||
from typing import TYPE_CHECKING, Dict, Generic, List, Optional, Tuple, TypeVar
|
||||
from urllib.parse import urlencode
|
||||
|
||||
import attr
|
||||
|
@ -39,9 +39,11 @@ from synapse.http.server import respond_with_html
|
|||
from synapse.http.site import SynapseRequest
|
||||
from synapse.logging.context import make_deferred_yieldable
|
||||
from synapse.push.mailer import load_jinja2_templates
|
||||
from synapse.server import HomeServer
|
||||
from synapse.types import UserID, map_username_to_mxid_localpart
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from synapse.server import HomeServer
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
SESSION_COOKIE_NAME = b"oidc_session"
|
||||
|
@ -91,7 +93,7 @@ class OidcHandler:
|
|||
"""Handles requests related to the OpenID Connect login flow.
|
||||
"""
|
||||
|
||||
def __init__(self, hs: HomeServer):
|
||||
def __init__(self, hs: "HomeServer"):
|
||||
self._callback_url = hs.config.oidc_callback_url # type: str
|
||||
self._scopes = hs.config.oidc_scopes # type: List[str]
|
||||
self._client_auth = ClientAuth(
|
||||
|
|
|
@ -25,8 +25,12 @@ import sys
|
|||
if sys.version_info[0:2] >= (3, 6):
|
||||
import secrets
|
||||
|
||||
def Secrets():
|
||||
return secrets
|
||||
class Secrets:
|
||||
def token_bytes(self, nbytes=32):
|
||||
return secrets.token_bytes(nbytes)
|
||||
|
||||
def token_hex(self, nbytes=32):
|
||||
return secrets.token_hex(nbytes)
|
||||
|
||||
|
||||
else:
|
||||
|
|
|
@ -22,10 +22,14 @@
|
|||
|
||||
# Imports required for the default HomeServer() implementation
|
||||
import abc
|
||||
import functools
|
||||
import logging
|
||||
import os
|
||||
from typing import TYPE_CHECKING, Any, Callable, Dict, List, Optional, TypeVar, cast
|
||||
|
||||
import twisted
|
||||
from twisted.mail.smtp import sendmail
|
||||
from twisted.web.iweb import IPolicyForHTTPS
|
||||
|
||||
from synapse.api.auth import Auth
|
||||
from synapse.api.filtering import Filtering
|
||||
|
@ -93,7 +97,7 @@ from synapse.push.pusherpool import PusherPool
|
|||
from synapse.replication.tcp.client import ReplicationDataHandler
|
||||
from synapse.replication.tcp.handler import ReplicationCommandHandler
|
||||
from synapse.replication.tcp.resource import ReplicationStreamer
|
||||
from synapse.replication.tcp.streams import STREAMS_MAP
|
||||
from synapse.replication.tcp.streams import STREAMS_MAP, Stream
|
||||
from synapse.rest.media.v1.media_repository import (
|
||||
MediaRepository,
|
||||
MediaRepositoryResource,
|
||||
|
@ -107,30 +111,72 @@ from synapse.server_notices.worker_server_notices_sender import (
|
|||
from synapse.state import StateHandler, StateResolutionHandler
|
||||
from synapse.storage import Databases, DataStore, Storage
|
||||
from synapse.streams.events import EventSources
|
||||
from synapse.types import DomainSpecificString
|
||||
from synapse.util import Clock
|
||||
from synapse.util.distributor import Distributor
|
||||
from synapse.util.stringutils import random_string
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from synapse.handlers.oidc_handler import OidcHandler
|
||||
from synapse.handlers.saml_handler import SamlHandler
|
||||
|
||||
class HomeServer(object):
|
||||
|
||||
T = TypeVar("T", bound=Callable[..., Any])
|
||||
|
||||
|
||||
def cache_in_self(builder: T) -> T:
|
||||
"""Wraps a function called e.g. `get_foo`, checking if `self.foo` exists and
|
||||
returning if so. If not, calls the given function and sets `self.foo` to it.
|
||||
|
||||
Also ensures that dependency cycles throw an exception correctly, rather
|
||||
than overflowing the stack.
|
||||
"""
|
||||
|
||||
if not builder.__name__.startswith("get_"):
|
||||
raise Exception(
|
||||
"@cache_in_self can only be used on functions starting with `get_`"
|
||||
)
|
||||
|
||||
depname = builder.__name__[len("get_") :]
|
||||
|
||||
building = [False]
|
||||
|
||||
@functools.wraps(builder)
|
||||
def _get(self):
|
||||
try:
|
||||
return getattr(self, depname)
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
# Prevent cyclic dependencies from deadlocking
|
||||
if building[0]:
|
||||
raise ValueError("Cyclic dependency while building %s" % (depname,))
|
||||
|
||||
building[0] = True
|
||||
try:
|
||||
dep = builder(self)
|
||||
setattr(self, depname, dep)
|
||||
finally:
|
||||
building[0] = False
|
||||
|
||||
return dep
|
||||
|
||||
# We cast here as we need to tell mypy that `_get` has the same signature as
|
||||
# `builder`.
|
||||
return cast(T, _get)
|
||||
|
||||
|
||||
class HomeServer(metaclass=abc.ABCMeta):
|
||||
"""A basic homeserver object without lazy component builders.
|
||||
|
||||
This will need all of the components it requires to either be passed as
|
||||
constructor arguments, or the relevant methods overriding to create them.
|
||||
Typically this would only be used for unit tests.
|
||||
|
||||
For every dependency in the DEPENDENCIES list below, this class creates one
|
||||
method,
|
||||
def get_DEPENDENCY(self)
|
||||
which returns the value of that dependency. If no value has yet been set
|
||||
nor was provided to the constructor, it will attempt to call a lazy builder
|
||||
method called
|
||||
def build_DEPENDENCY(self)
|
||||
which must be implemented by the subclass. This code may call any of the
|
||||
required "get" methods on the instance to obtain the sub-dependencies that
|
||||
one requires.
|
||||
Dependencies should be added by creating a `def get_<depname>(self)`
|
||||
function, wrapping it in `@cache_in_self`.
|
||||
|
||||
Attributes:
|
||||
config (synapse.config.homeserver.HomeserverConfig):
|
||||
|
@ -138,86 +184,6 @@ class HomeServer(object):
|
|||
we are listening on to provide HTTP services.
|
||||
"""
|
||||
|
||||
__metaclass__ = abc.ABCMeta
|
||||
|
||||
DEPENDENCIES = [
|
||||
"http_client",
|
||||
"federation_client",
|
||||
"federation_server",
|
||||
"handlers",
|
||||
"auth",
|
||||
"room_creation_handler",
|
||||
"room_shutdown_handler",
|
||||
"state_handler",
|
||||
"state_resolution_handler",
|
||||
"presence_handler",
|
||||
"sync_handler",
|
||||
"typing_handler",
|
||||
"room_list_handler",
|
||||
"acme_handler",
|
||||
"auth_handler",
|
||||
"device_handler",
|
||||
"stats_handler",
|
||||
"e2e_keys_handler",
|
||||
"e2e_room_keys_handler",
|
||||
"event_handler",
|
||||
"event_stream_handler",
|
||||
"initial_sync_handler",
|
||||
"application_service_api",
|
||||
"application_service_scheduler",
|
||||
"application_service_handler",
|
||||
"device_message_handler",
|
||||
"profile_handler",
|
||||
"event_creation_handler",
|
||||
"deactivate_account_handler",
|
||||
"set_password_handler",
|
||||
"notifier",
|
||||
"event_sources",
|
||||
"keyring",
|
||||
"pusherpool",
|
||||
"event_builder_factory",
|
||||
"filtering",
|
||||
"http_client_context_factory",
|
||||
"simple_http_client",
|
||||
"proxied_http_client",
|
||||
"media_repository",
|
||||
"media_repository_resource",
|
||||
"federation_transport_client",
|
||||
"federation_sender",
|
||||
"receipts_handler",
|
||||
"macaroon_generator",
|
||||
"tcp_replication",
|
||||
"read_marker_handler",
|
||||
"action_generator",
|
||||
"user_directory_handler",
|
||||
"groups_local_handler",
|
||||
"groups_server_handler",
|
||||
"groups_attestation_signing",
|
||||
"groups_attestation_renewer",
|
||||
"secrets",
|
||||
"spam_checker",
|
||||
"third_party_event_rules",
|
||||
"room_member_handler",
|
||||
"federation_registry",
|
||||
"server_notices_manager",
|
||||
"server_notices_sender",
|
||||
"message_handler",
|
||||
"pagination_handler",
|
||||
"room_context_handler",
|
||||
"sendmail",
|
||||
"registration_handler",
|
||||
"account_validity_handler",
|
||||
"cas_handler",
|
||||
"saml_handler",
|
||||
"oidc_handler",
|
||||
"event_client_serializer",
|
||||
"password_policy_handler",
|
||||
"storage",
|
||||
"replication_streamer",
|
||||
"replication_data_handler",
|
||||
"replication_streams",
|
||||
]
|
||||
|
||||
REQUIRED_ON_MASTER_STARTUP = ["user_directory_handler", "stats_handler"]
|
||||
|
||||
# This is overridden in derived application classes
|
||||
|
@ -232,16 +198,17 @@ class HomeServer(object):
|
|||
config: The full config for the homeserver.
|
||||
"""
|
||||
if not reactor:
|
||||
from twisted.internet import reactor
|
||||
from twisted.internet import reactor as _reactor
|
||||
|
||||
reactor = _reactor
|
||||
|
||||
self._reactor = reactor
|
||||
self.hostname = hostname
|
||||
# the key we use to sign events and requests
|
||||
self.signing_key = config.key.signing_key[0]
|
||||
self.config = config
|
||||
self._building = {}
|
||||
self._listening_services = []
|
||||
self.start_time = None
|
||||
self._listening_services = [] # type: List[twisted.internet.tcp.Port]
|
||||
self.start_time = None # type: Optional[int]
|
||||
|
||||
self._instance_id = random_string(5)
|
||||
self._instance_name = config.worker_name or "master"
|
||||
|
@ -255,13 +222,13 @@ class HomeServer(object):
|
|||
burst_count=config.rc_registration.burst_count,
|
||||
)
|
||||
|
||||
self.datastores = None
|
||||
self.datastores = None # type: Optional[Databases]
|
||||
|
||||
# Other kwargs are explicit dependencies
|
||||
for depname in kwargs:
|
||||
setattr(self, depname, kwargs[depname])
|
||||
|
||||
def get_instance_id(self):
|
||||
def get_instance_id(self) -> str:
|
||||
"""A unique ID for this synapse process instance.
|
||||
|
||||
This is used to distinguish running instances in worker-based
|
||||
|
@ -277,13 +244,13 @@ class HomeServer(object):
|
|||
"""
|
||||
return self._instance_name
|
||||
|
||||
def setup(self):
|
||||
def setup(self) -> None:
|
||||
logger.info("Setting up.")
|
||||
self.start_time = int(self.get_clock().time())
|
||||
self.datastores = Databases(self.DATASTORE_CLASS, self)
|
||||
logger.info("Finished setting up.")
|
||||
|
||||
def setup_master(self):
|
||||
def setup_master(self) -> None:
|
||||
"""
|
||||
Some handlers have side effects on instantiation (like registering
|
||||
background updates). This function causes them to be fetched, and
|
||||
|
@ -292,192 +259,242 @@ class HomeServer(object):
|
|||
for i in self.REQUIRED_ON_MASTER_STARTUP:
|
||||
getattr(self, "get_" + i)()
|
||||
|
||||
def get_reactor(self):
|
||||
def get_reactor(self) -> twisted.internet.base.ReactorBase:
|
||||
"""
|
||||
Fetch the Twisted reactor in use by this HomeServer.
|
||||
"""
|
||||
return self._reactor
|
||||
|
||||
def get_ip_from_request(self, request):
|
||||
def get_ip_from_request(self, request) -> str:
|
||||
# X-Forwarded-For is handled by our custom request type.
|
||||
return request.getClientIP()
|
||||
|
||||
def is_mine(self, domain_specific_string):
|
||||
def is_mine(self, domain_specific_string: DomainSpecificString) -> bool:
|
||||
return domain_specific_string.domain == self.hostname
|
||||
|
||||
def is_mine_id(self, string):
|
||||
def is_mine_id(self, string: str) -> bool:
|
||||
return string.split(":", 1)[1] == self.hostname
|
||||
|
||||
def get_clock(self):
|
||||
def get_clock(self) -> Clock:
|
||||
return self.clock
|
||||
|
||||
def get_datastore(self) -> DataStore:
|
||||
if not self.datastores:
|
||||
raise Exception("HomeServer.setup must be called before getting datastores")
|
||||
|
||||
return self.datastores.main
|
||||
|
||||
def get_datastores(self):
|
||||
def get_datastores(self) -> Databases:
|
||||
if not self.datastores:
|
||||
raise Exception("HomeServer.setup must be called before getting datastores")
|
||||
|
||||
return self.datastores
|
||||
|
||||
def get_config(self):
|
||||
def get_config(self) -> HomeServerConfig:
|
||||
return self.config
|
||||
|
||||
def get_distributor(self):
|
||||
def get_distributor(self) -> Distributor:
|
||||
return self.distributor
|
||||
|
||||
def get_registration_ratelimiter(self) -> Ratelimiter:
|
||||
return self.registration_ratelimiter
|
||||
|
||||
def build_federation_client(self):
|
||||
@cache_in_self
|
||||
def get_federation_client(self) -> FederationClient:
|
||||
return FederationClient(self)
|
||||
|
||||
def build_federation_server(self):
|
||||
@cache_in_self
|
||||
def get_federation_server(self) -> FederationServer:
|
||||
return FederationServer(self)
|
||||
|
||||
def build_handlers(self):
|
||||
@cache_in_self
|
||||
def get_handlers(self) -> Handlers:
|
||||
return Handlers(self)
|
||||
|
||||
def build_notifier(self):
|
||||
@cache_in_self
|
||||
def get_notifier(self) -> Notifier:
|
||||
return Notifier(self)
|
||||
|
||||
def build_auth(self):
|
||||
@cache_in_self
|
||||
def get_auth(self) -> Auth:
|
||||
return Auth(self)
|
||||
|
||||
def build_http_client_context_factory(self):
|
||||
@cache_in_self
|
||||
def get_http_client_context_factory(self) -> IPolicyForHTTPS:
|
||||
return (
|
||||
InsecureInterceptableContextFactory()
|
||||
if self.config.use_insecure_ssl_client_just_for_testing_do_not_use
|
||||
else RegularPolicyForHTTPS()
|
||||
)
|
||||
|
||||
def build_simple_http_client(self):
|
||||
@cache_in_self
|
||||
def get_simple_http_client(self) -> SimpleHttpClient:
|
||||
return SimpleHttpClient(self)
|
||||
|
||||
def build_proxied_http_client(self):
|
||||
@cache_in_self
|
||||
def get_proxied_http_client(self) -> SimpleHttpClient:
|
||||
return SimpleHttpClient(
|
||||
self,
|
||||
http_proxy=os.getenvb(b"http_proxy"),
|
||||
https_proxy=os.getenvb(b"HTTPS_PROXY"),
|
||||
)
|
||||
|
||||
def build_room_creation_handler(self):
|
||||
@cache_in_self
|
||||
def get_room_creation_handler(self) -> RoomCreationHandler:
|
||||
return RoomCreationHandler(self)
|
||||
|
||||
def build_room_shutdown_handler(self):
|
||||
@cache_in_self
|
||||
def get_room_shutdown_handler(self) -> RoomShutdownHandler:
|
||||
return RoomShutdownHandler(self)
|
||||
|
||||
def build_sendmail(self):
|
||||
@cache_in_self
|
||||
def get_sendmail(self) -> sendmail:
|
||||
return sendmail
|
||||
|
||||
def build_state_handler(self):
|
||||
@cache_in_self
|
||||
def get_state_handler(self) -> StateHandler:
|
||||
return StateHandler(self)
|
||||
|
||||
def build_state_resolution_handler(self):
|
||||
@cache_in_self
|
||||
def get_state_resolution_handler(self) -> StateResolutionHandler:
|
||||
return StateResolutionHandler(self)
|
||||
|
||||
def build_presence_handler(self):
|
||||
@cache_in_self
|
||||
def get_presence_handler(self) -> PresenceHandler:
|
||||
return PresenceHandler(self)
|
||||
|
||||
def build_typing_handler(self):
|
||||
@cache_in_self
|
||||
def get_typing_handler(self):
|
||||
if self.config.worker.writers.typing == self.get_instance_name():
|
||||
return TypingWriterHandler(self)
|
||||
else:
|
||||
return FollowerTypingHandler(self)
|
||||
|
||||
def build_sync_handler(self):
|
||||
@cache_in_self
|
||||
def get_sync_handler(self) -> SyncHandler:
|
||||
return SyncHandler(self)
|
||||
|
||||
def build_room_list_handler(self):
|
||||
@cache_in_self
|
||||
def get_room_list_handler(self) -> RoomListHandler:
|
||||
return RoomListHandler(self)
|
||||
|
||||
def build_auth_handler(self):
|
||||
@cache_in_self
|
||||
def get_auth_handler(self) -> AuthHandler:
|
||||
return AuthHandler(self)
|
||||
|
||||
def build_macaroon_generator(self):
|
||||
@cache_in_self
|
||||
def get_macaroon_generator(self) -> MacaroonGenerator:
|
||||
return MacaroonGenerator(self)
|
||||
|
||||
def build_device_handler(self):
|
||||
@cache_in_self
|
||||
def get_device_handler(self):
|
||||
if self.config.worker_app:
|
||||
return DeviceWorkerHandler(self)
|
||||
else:
|
||||
return DeviceHandler(self)
|
||||
|
||||
def build_device_message_handler(self):
|
||||
@cache_in_self
|
||||
def get_device_message_handler(self) -> DeviceMessageHandler:
|
||||
return DeviceMessageHandler(self)
|
||||
|
||||
def build_e2e_keys_handler(self):
|
||||
@cache_in_self
|
||||
def get_e2e_keys_handler(self) -> E2eKeysHandler:
|
||||
return E2eKeysHandler(self)
|
||||
|
||||
def build_e2e_room_keys_handler(self):
|
||||
@cache_in_self
|
||||
def get_e2e_room_keys_handler(self) -> E2eRoomKeysHandler:
|
||||
return E2eRoomKeysHandler(self)
|
||||
|
||||
def build_acme_handler(self):
|
||||
@cache_in_self
|
||||
def get_acme_handler(self) -> AcmeHandler:
|
||||
return AcmeHandler(self)
|
||||
|
||||
def build_application_service_api(self):
|
||||
@cache_in_self
|
||||
def get_application_service_api(self) -> ApplicationServiceApi:
|
||||
return ApplicationServiceApi(self)
|
||||
|
||||
def build_application_service_scheduler(self):
|
||||
@cache_in_self
|
||||
def get_application_service_scheduler(self) -> ApplicationServiceScheduler:
|
||||
return ApplicationServiceScheduler(self)
|
||||
|
||||
def build_application_service_handler(self):
|
||||
@cache_in_self
|
||||
def get_application_service_handler(self) -> ApplicationServicesHandler:
|
||||
return ApplicationServicesHandler(self)
|
||||
|
||||
def build_event_handler(self):
|
||||
@cache_in_self
|
||||
def get_event_handler(self) -> EventHandler:
|
||||
return EventHandler(self)
|
||||
|
||||
def build_event_stream_handler(self):
|
||||
@cache_in_self
|
||||
def get_event_stream_handler(self) -> EventStreamHandler:
|
||||
return EventStreamHandler(self)
|
||||
|
||||
def build_initial_sync_handler(self):
|
||||
@cache_in_self
|
||||
def get_initial_sync_handler(self) -> InitialSyncHandler:
|
||||
return InitialSyncHandler(self)
|
||||
|
||||
def build_profile_handler(self):
|
||||
@cache_in_self
|
||||
def get_profile_handler(self):
|
||||
if self.config.worker_app:
|
||||
return BaseProfileHandler(self)
|
||||
else:
|
||||
return MasterProfileHandler(self)
|
||||
|
||||
def build_event_creation_handler(self):
|
||||
@cache_in_self
|
||||
def get_event_creation_handler(self) -> EventCreationHandler:
|
||||
return EventCreationHandler(self)
|
||||
|
||||
def build_deactivate_account_handler(self):
|
||||
@cache_in_self
|
||||
def get_deactivate_account_handler(self) -> DeactivateAccountHandler:
|
||||
return DeactivateAccountHandler(self)
|
||||
|
||||
def build_set_password_handler(self):
|
||||
@cache_in_self
|
||||
def get_set_password_handler(self) -> SetPasswordHandler:
|
||||
return SetPasswordHandler(self)
|
||||
|
||||
def build_event_sources(self):
|
||||
@cache_in_self
|
||||
def get_event_sources(self) -> EventSources:
|
||||
return EventSources(self)
|
||||
|
||||
def build_keyring(self):
|
||||
@cache_in_self
|
||||
def get_keyring(self) -> Keyring:
|
||||
return Keyring(self)
|
||||
|
||||
def build_event_builder_factory(self):
|
||||
@cache_in_self
|
||||
def get_event_builder_factory(self) -> EventBuilderFactory:
|
||||
return EventBuilderFactory(self)
|
||||
|
||||
def build_filtering(self):
|
||||
@cache_in_self
|
||||
def get_filtering(self) -> Filtering:
|
||||
return Filtering(self)
|
||||
|
||||
def build_pusherpool(self):
|
||||
@cache_in_self
|
||||
def get_pusherpool(self) -> PusherPool:
|
||||
return PusherPool(self)
|
||||
|
||||
def build_http_client(self):
|
||||
@cache_in_self
|
||||
def get_http_client(self) -> MatrixFederationHttpClient:
|
||||
tls_client_options_factory = context_factory.FederationPolicyForHTTPS(
|
||||
self.config
|
||||
)
|
||||
return MatrixFederationHttpClient(self, tls_client_options_factory)
|
||||
|
||||
def build_media_repository_resource(self):
|
||||
@cache_in_self
|
||||
def get_media_repository_resource(self) -> MediaRepositoryResource:
|
||||
# build the media repo resource. This indirects through the HomeServer
|
||||
# to ensure that we only have a single instance of
|
||||
return MediaRepositoryResource(self)
|
||||
|
||||
def build_media_repository(self):
|
||||
@cache_in_self
|
||||
def get_media_repository(self) -> MediaRepository:
|
||||
return MediaRepository(self)
|
||||
|
||||
def build_federation_transport_client(self):
|
||||
@cache_in_self
|
||||
def get_federation_transport_client(self) -> TransportLayerClient:
|
||||
return TransportLayerClient(self)
|
||||
|
||||
def build_federation_sender(self):
|
||||
@cache_in_self
|
||||
def get_federation_sender(self):
|
||||
if self.should_send_federation():
|
||||
return FederationSender(self)
|
||||
elif not self.config.worker_app:
|
||||
|
@ -485,156 +502,152 @@ class HomeServer(object):
|
|||
else:
|
||||
raise Exception("Workers cannot send federation traffic")
|
||||
|
||||
def build_receipts_handler(self):
|
||||
@cache_in_self
|
||||
def get_receipts_handler(self) -> ReceiptsHandler:
|
||||
return ReceiptsHandler(self)
|
||||
|
||||
def build_read_marker_handler(self):
|
||||
@cache_in_self
|
||||
def get_read_marker_handler(self) -> ReadMarkerHandler:
|
||||
return ReadMarkerHandler(self)
|
||||
|
||||
def build_tcp_replication(self):
|
||||
@cache_in_self
|
||||
def get_tcp_replication(self) -> ReplicationCommandHandler:
|
||||
return ReplicationCommandHandler(self)
|
||||
|
||||
def build_action_generator(self):
|
||||
@cache_in_self
|
||||
def get_action_generator(self) -> ActionGenerator:
|
||||
return ActionGenerator(self)
|
||||
|
||||
def build_user_directory_handler(self):
|
||||
@cache_in_self
|
||||
def get_user_directory_handler(self) -> UserDirectoryHandler:
|
||||
return UserDirectoryHandler(self)
|
||||
|
||||
def build_groups_local_handler(self):
|
||||
@cache_in_self
|
||||
def get_groups_local_handler(self):
|
||||
if self.config.worker_app:
|
||||
return GroupsLocalWorkerHandler(self)
|
||||
else:
|
||||
return GroupsLocalHandler(self)
|
||||
|
||||
def build_groups_server_handler(self):
|
||||
@cache_in_self
|
||||
def get_groups_server_handler(self):
|
||||
if self.config.worker_app:
|
||||
return GroupsServerWorkerHandler(self)
|
||||
else:
|
||||
return GroupsServerHandler(self)
|
||||
|
||||
def build_groups_attestation_signing(self):
|
||||
@cache_in_self
|
||||
def get_groups_attestation_signing(self) -> GroupAttestationSigning:
|
||||
return GroupAttestationSigning(self)
|
||||
|
||||
def build_groups_attestation_renewer(self):
|
||||
@cache_in_self
|
||||
def get_groups_attestation_renewer(self) -> GroupAttestionRenewer:
|
||||
return GroupAttestionRenewer(self)
|
||||
|
||||
def build_secrets(self):
|
||||
@cache_in_self
|
||||
def get_secrets(self) -> Secrets:
|
||||
return Secrets()
|
||||
|
||||
def build_stats_handler(self):
|
||||
@cache_in_self
|
||||
def get_stats_handler(self) -> StatsHandler:
|
||||
return StatsHandler(self)
|
||||
|
||||
def build_spam_checker(self):
|
||||
@cache_in_self
|
||||
def get_spam_checker(self):
|
||||
return SpamChecker(self)
|
||||
|
||||
def build_third_party_event_rules(self):
|
||||
@cache_in_self
|
||||
def get_third_party_event_rules(self) -> ThirdPartyEventRules:
|
||||
return ThirdPartyEventRules(self)
|
||||
|
||||
def build_room_member_handler(self):
|
||||
@cache_in_self
|
||||
def get_room_member_handler(self):
|
||||
if self.config.worker_app:
|
||||
return RoomMemberWorkerHandler(self)
|
||||
return RoomMemberMasterHandler(self)
|
||||
|
||||
def build_federation_registry(self):
|
||||
@cache_in_self
|
||||
def get_federation_registry(self) -> FederationHandlerRegistry:
|
||||
return FederationHandlerRegistry(self)
|
||||
|
||||
def build_server_notices_manager(self):
|
||||
@cache_in_self
|
||||
def get_server_notices_manager(self):
|
||||
if self.config.worker_app:
|
||||
raise Exception("Workers cannot send server notices")
|
||||
return ServerNoticesManager(self)
|
||||
|
||||
def build_server_notices_sender(self):
|
||||
@cache_in_self
|
||||
def get_server_notices_sender(self):
|
||||
if self.config.worker_app:
|
||||
return WorkerServerNoticesSender(self)
|
||||
return ServerNoticesSender(self)
|
||||
|
||||
def build_message_handler(self):
|
||||
@cache_in_self
|
||||
def get_message_handler(self) -> MessageHandler:
|
||||
return MessageHandler(self)
|
||||
|
||||
def build_pagination_handler(self):
|
||||
@cache_in_self
|
||||
def get_pagination_handler(self) -> PaginationHandler:
|
||||
return PaginationHandler(self)
|
||||
|
||||
def build_room_context_handler(self):
|
||||
@cache_in_self
|
||||
def get_room_context_handler(self) -> RoomContextHandler:
|
||||
return RoomContextHandler(self)
|
||||
|
||||
def build_registration_handler(self):
|
||||
@cache_in_self
|
||||
def get_registration_handler(self) -> RegistrationHandler:
|
||||
return RegistrationHandler(self)
|
||||
|
||||
def build_account_validity_handler(self):
|
||||
@cache_in_self
|
||||
def get_account_validity_handler(self) -> AccountValidityHandler:
|
||||
return AccountValidityHandler(self)
|
||||
|
||||
def build_cas_handler(self):
|
||||
@cache_in_self
|
||||
def get_cas_handler(self) -> CasHandler:
|
||||
return CasHandler(self)
|
||||
|
||||
def build_saml_handler(self):
|
||||
@cache_in_self
|
||||
def get_saml_handler(self) -> "SamlHandler":
|
||||
from synapse.handlers.saml_handler import SamlHandler
|
||||
|
||||
return SamlHandler(self)
|
||||
|
||||
def build_oidc_handler(self):
|
||||
@cache_in_self
|
||||
def get_oidc_handler(self) -> "OidcHandler":
|
||||
from synapse.handlers.oidc_handler import OidcHandler
|
||||
|
||||
return OidcHandler(self)
|
||||
|
||||
def build_event_client_serializer(self):
|
||||
@cache_in_self
|
||||
def get_event_client_serializer(self) -> EventClientSerializer:
|
||||
return EventClientSerializer(self)
|
||||
|
||||
def build_password_policy_handler(self):
|
||||
@cache_in_self
|
||||
def get_password_policy_handler(self) -> PasswordPolicyHandler:
|
||||
return PasswordPolicyHandler(self)
|
||||
|
||||
def build_storage(self) -> Storage:
|
||||
return Storage(self, self.datastores)
|
||||
@cache_in_self
|
||||
def get_storage(self) -> Storage:
|
||||
return Storage(self, self.get_datastores())
|
||||
|
||||
def build_replication_streamer(self) -> ReplicationStreamer:
|
||||
@cache_in_self
|
||||
def get_replication_streamer(self) -> ReplicationStreamer:
|
||||
return ReplicationStreamer(self)
|
||||
|
||||
def build_replication_data_handler(self):
|
||||
@cache_in_self
|
||||
def get_replication_data_handler(self) -> ReplicationDataHandler:
|
||||
return ReplicationDataHandler(self)
|
||||
|
||||
def build_replication_streams(self):
|
||||
@cache_in_self
|
||||
def get_replication_streams(self) -> Dict[str, Stream]:
|
||||
return {stream.NAME: stream(self) for stream in STREAMS_MAP.values()}
|
||||
|
||||
def remove_pusher(self, app_id, push_key, user_id):
|
||||
return self.get_pusherpool().remove_pusher(app_id, push_key, user_id)
|
||||
async def remove_pusher(self, app_id: str, push_key: str, user_id: str):
|
||||
return await self.get_pusherpool().remove_pusher(app_id, push_key, user_id)
|
||||
|
||||
def should_send_federation(self):
|
||||
def should_send_federation(self) -> bool:
|
||||
"Should this server be sending federation traffic directly?"
|
||||
return self.config.send_federation and (
|
||||
not self.config.worker_app
|
||||
or self.config.worker_app == "synapse.app.federation_sender"
|
||||
)
|
||||
|
||||
|
||||
def _make_dependency_method(depname):
|
||||
def _get(hs):
|
||||
try:
|
||||
return getattr(hs, depname)
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
try:
|
||||
builder = getattr(hs, "build_%s" % (depname))
|
||||
except AttributeError:
|
||||
raise NotImplementedError(
|
||||
"%s has no %s nor a builder for it" % (type(hs).__name__, depname)
|
||||
)
|
||||
|
||||
# Prevent cyclic dependencies from deadlocking
|
||||
if depname in hs._building:
|
||||
raise ValueError("Cyclic dependency while building %s" % (depname,))
|
||||
|
||||
hs._building[depname] = 1
|
||||
try:
|
||||
dep = builder()
|
||||
setattr(hs, depname, dep)
|
||||
finally:
|
||||
del hs._building[depname]
|
||||
|
||||
return dep
|
||||
|
||||
setattr(HomeServer, "get_%s" % (depname), _get)
|
||||
|
||||
|
||||
# Build magic accessors for every dependency
|
||||
for depname in HomeServer.DEPENDENCIES:
|
||||
_make_dependency_method(depname)
|
||||
|
|
|
@ -1,161 +0,0 @@
|
|||
from typing import Dict
|
||||
|
||||
import twisted.internet
|
||||
|
||||
import synapse.api.auth
|
||||
import synapse.config.homeserver
|
||||
import synapse.crypto.keyring
|
||||
import synapse.federation.federation_server
|
||||
import synapse.federation.sender
|
||||
import synapse.federation.transport.client
|
||||
import synapse.handlers
|
||||
import synapse.handlers.auth
|
||||
import synapse.handlers.deactivate_account
|
||||
import synapse.handlers.device
|
||||
import synapse.handlers.e2e_keys
|
||||
import synapse.handlers.message
|
||||
import synapse.handlers.presence
|
||||
import synapse.handlers.register
|
||||
import synapse.handlers.room
|
||||
import synapse.handlers.room_member
|
||||
import synapse.handlers.set_password
|
||||
import synapse.http.client
|
||||
import synapse.http.matrixfederationclient
|
||||
import synapse.notifier
|
||||
import synapse.push.pusherpool
|
||||
import synapse.replication.tcp.client
|
||||
import synapse.replication.tcp.handler
|
||||
import synapse.rest.media.v1.media_repository
|
||||
import synapse.server_notices.server_notices_manager
|
||||
import synapse.server_notices.server_notices_sender
|
||||
import synapse.state
|
||||
import synapse.storage
|
||||
from synapse.events.builder import EventBuilderFactory
|
||||
from synapse.handlers.appservice import ApplicationServicesHandler
|
||||
from synapse.handlers.typing import FollowerTypingHandler
|
||||
from synapse.replication.tcp.streams import Stream
|
||||
from synapse.streams.events import EventSources
|
||||
|
||||
class HomeServer(object):
|
||||
@property
|
||||
def config(self) -> synapse.config.homeserver.HomeServerConfig:
|
||||
pass
|
||||
@property
|
||||
def hostname(self) -> str:
|
||||
pass
|
||||
def get_auth(self) -> synapse.api.auth.Auth:
|
||||
pass
|
||||
def get_auth_handler(self) -> synapse.handlers.auth.AuthHandler:
|
||||
pass
|
||||
def get_datastore(self) -> synapse.storage.DataStore:
|
||||
pass
|
||||
def get_device_handler(self) -> synapse.handlers.device.DeviceHandler:
|
||||
pass
|
||||
def get_e2e_keys_handler(self) -> synapse.handlers.e2e_keys.E2eKeysHandler:
|
||||
pass
|
||||
def get_handlers(self) -> synapse.handlers.Handlers:
|
||||
pass
|
||||
def get_state_handler(self) -> synapse.state.StateHandler:
|
||||
pass
|
||||
def get_state_resolution_handler(self) -> synapse.state.StateResolutionHandler:
|
||||
pass
|
||||
def get_simple_http_client(self) -> synapse.http.client.SimpleHttpClient:
|
||||
"""Fetch an HTTP client implementation which doesn't do any blacklisting
|
||||
or support any HTTP_PROXY settings"""
|
||||
pass
|
||||
def get_proxied_http_client(self) -> synapse.http.client.SimpleHttpClient:
|
||||
"""Fetch an HTTP client implementation which doesn't do any blacklisting
|
||||
but does support HTTP_PROXY settings"""
|
||||
pass
|
||||
def get_deactivate_account_handler(
|
||||
self,
|
||||
) -> synapse.handlers.deactivate_account.DeactivateAccountHandler:
|
||||
pass
|
||||
def get_room_creation_handler(self) -> synapse.handlers.room.RoomCreationHandler:
|
||||
pass
|
||||
def get_room_member_handler(self) -> synapse.handlers.room_member.RoomMemberHandler:
|
||||
pass
|
||||
def get_room_shutdown_handler(self) -> synapse.handlers.room.RoomShutdownHandler:
|
||||
pass
|
||||
def get_event_creation_handler(
|
||||
self,
|
||||
) -> synapse.handlers.message.EventCreationHandler:
|
||||
pass
|
||||
def get_set_password_handler(
|
||||
self,
|
||||
) -> synapse.handlers.set_password.SetPasswordHandler:
|
||||
pass
|
||||
def get_federation_sender(self) -> synapse.federation.sender.FederationSender:
|
||||
pass
|
||||
def get_federation_transport_client(
|
||||
self,
|
||||
) -> synapse.federation.transport.client.TransportLayerClient:
|
||||
pass
|
||||
def get_media_repository_resource(
|
||||
self,
|
||||
) -> synapse.rest.media.v1.media_repository.MediaRepositoryResource:
|
||||
pass
|
||||
def get_media_repository(
|
||||
self,
|
||||
) -> synapse.rest.media.v1.media_repository.MediaRepository:
|
||||
pass
|
||||
def get_server_notices_manager(
|
||||
self,
|
||||
) -> synapse.server_notices.server_notices_manager.ServerNoticesManager:
|
||||
pass
|
||||
def get_server_notices_sender(
|
||||
self,
|
||||
) -> synapse.server_notices.server_notices_sender.ServerNoticesSender:
|
||||
pass
|
||||
def get_notifier(self) -> synapse.notifier.Notifier:
|
||||
pass
|
||||
def get_presence_handler(self) -> synapse.handlers.presence.BasePresenceHandler:
|
||||
pass
|
||||
def get_clock(self) -> synapse.util.Clock:
|
||||
pass
|
||||
def get_reactor(self) -> twisted.internet.base.ReactorBase:
|
||||
pass
|
||||
def get_keyring(self) -> synapse.crypto.keyring.Keyring:
|
||||
pass
|
||||
def get_tcp_replication(
|
||||
self,
|
||||
) -> synapse.replication.tcp.handler.ReplicationCommandHandler:
|
||||
pass
|
||||
def get_replication_data_handler(
|
||||
self,
|
||||
) -> synapse.replication.tcp.client.ReplicationDataHandler:
|
||||
pass
|
||||
def get_federation_registry(
|
||||
self,
|
||||
) -> synapse.federation.federation_server.FederationHandlerRegistry:
|
||||
pass
|
||||
def is_mine_id(self, domain_id: str) -> bool:
|
||||
pass
|
||||
def get_instance_id(self) -> str:
|
||||
pass
|
||||
def get_instance_name(self) -> str:
|
||||
pass
|
||||
def get_event_builder_factory(self) -> EventBuilderFactory:
|
||||
pass
|
||||
def get_storage(self) -> synapse.storage.Storage:
|
||||
pass
|
||||
def get_registration_handler(self) -> synapse.handlers.register.RegistrationHandler:
|
||||
pass
|
||||
def get_macaroon_generator(self) -> synapse.handlers.auth.MacaroonGenerator:
|
||||
pass
|
||||
def get_pusherpool(self) -> synapse.push.pusherpool.PusherPool:
|
||||
pass
|
||||
def get_replication_streams(self) -> Dict[str, Stream]:
|
||||
pass
|
||||
def get_http_client(
|
||||
self,
|
||||
) -> synapse.http.matrixfederationclient.MatrixFederationHttpClient:
|
||||
pass
|
||||
def should_send_federation(self) -> bool:
|
||||
pass
|
||||
def get_typing_handler(self) -> FollowerTypingHandler:
|
||||
pass
|
||||
def get_event_sources(self) -> EventSources:
|
||||
pass
|
||||
def get_application_service_handler(self):
|
||||
return ApplicationServicesHandler(self)
|
|
@ -38,9 +38,9 @@ class Databases(object):
|
|||
# store.
|
||||
|
||||
self.databases = []
|
||||
self.main = None
|
||||
self.state = None
|
||||
self.persist_events = None
|
||||
main = None
|
||||
state = None
|
||||
persist_events = None
|
||||
|
||||
for database_config in hs.config.database.databases:
|
||||
db_name = database_config.name
|
||||
|
@ -61,27 +61,25 @@ class Databases(object):
|
|||
|
||||
# Sanity check we don't try and configure the main store on
|
||||
# multiple databases.
|
||||
if self.main:
|
||||
if main:
|
||||
raise Exception("'main' data store already configured")
|
||||
|
||||
self.main = main_store_class(database, db_conn, hs)
|
||||
main = main_store_class(database, db_conn, hs)
|
||||
|
||||
# If we're on a process that can persist events also
|
||||
# instantiate a `PersistEventsStore`
|
||||
if hs.config.worker.writers.events == hs.get_instance_name():
|
||||
self.persist_events = PersistEventsStore(
|
||||
hs, database, self.main
|
||||
)
|
||||
persist_events = PersistEventsStore(hs, database, main)
|
||||
|
||||
if "state" in database_config.databases:
|
||||
logger.info("Starting 'state' data store")
|
||||
|
||||
# Sanity check we don't try and configure the state store on
|
||||
# multiple databases.
|
||||
if self.state:
|
||||
if state:
|
||||
raise Exception("'state' data store already configured")
|
||||
|
||||
self.state = StateGroupDataStore(database, db_conn, hs)
|
||||
state = StateGroupDataStore(database, db_conn, hs)
|
||||
|
||||
db_conn.commit()
|
||||
|
||||
|
@ -90,8 +88,14 @@ class Databases(object):
|
|||
logger.info("Database %r prepared", db_name)
|
||||
|
||||
# Sanity check that we have actually configured all the required stores.
|
||||
if not self.main:
|
||||
if not main:
|
||||
raise Exception("No 'main' data store configured")
|
||||
|
||||
if not self.state:
|
||||
if not state:
|
||||
raise Exception("No 'main' data store configured")
|
||||
|
||||
# We use local variables here to ensure that the databases do not have
|
||||
# optional types.
|
||||
self.main = main
|
||||
self.state = state
|
||||
self.persist_events = persist_events
|
||||
|
|
Loading…
Reference in New Issue