def __init__(self, hs): self.store = hs.get_datastore() self.clock = hs.get_clock() self.notifier = hs.get_notifier() self._replication_torture_level = hs.config.replication_torture_level # Work out list of streams that this instance is the source of. self.streams = [] # type: List[Stream] if hs.config.worker_app is None: for stream in STREAMS_MAP.values(): if stream == FederationStream and hs.config.send_federation: # We only support federation stream if federation sending # hase been disabled on the master. continue self.streams.append(stream(hs)) self.streams_by_name = {stream.NAME: stream for stream in self.streams} # Only bother registering the notifier callback if we have streams to # publish. if self.streams: self.notifier.add_replication_callback(self.on_notifier_poke) # Keeps track of whether we are currently checking for updates self.is_looping = False self.pending_updates = False self.command_handler = hs.get_tcp_replication()
def __init__(self, hs): self._replication_data_handler = hs.get_replication_data_handler() self._presence_handler = hs.get_presence_handler() self._store = hs.get_datastore() self._notifier = hs.get_notifier() self._clock = hs.get_clock() self._instance_id = hs.get_instance_id() self._instance_name = hs.get_instance_name() self._streams = { stream.NAME: stream(hs) for stream in STREAMS_MAP.values() } # type: Dict[str, Stream] self._position_linearizer = Linearizer("replication_position", clock=self._clock) # Map of stream to batched updates. See RdataCommand for info on how # batching works. self._pending_batches = {} # type: Dict[str, List[Any]] # The factory used to create connections. self._factory = None # type: Optional[ReconnectingClientFactory] # The currently connected connections. (The list of places we need to send # outgoing replication commands to.) self._connections = [] # type: List[AbstractConnection] # For each connection, the incoming streams that are coming from that connection self._streams_by_connection = { } # type: Dict[AbstractConnection, Set[str]] LaterGauge( "synapse_replication_tcp_resource_total_connections", "", [], lambda: len(self._connections), ) self._is_master = hs.config.worker_app is None self._federation_sender = None if self._is_master and not hs.config.send_federation: self._federation_sender = hs.get_federation_sender() self._server_notices_sender = None if self._is_master: self._server_notices_sender = hs.get_server_notices_sender()
def get_replication_streams(self) -> Dict[str, Stream]: return {stream.NAME: stream(self) for stream in STREAMS_MAP.values()}
def __init__(self, hs: "HomeServer"): self._replication_data_handler = hs.get_replication_data_handler() self._presence_handler = hs.get_presence_handler() self._store = hs.get_datastores().main self._notifier = hs.get_notifier() self._clock = hs.get_clock() self._instance_id = hs.get_instance_id() self._instance_name = hs.get_instance_name() # Additional Redis channel suffixes to subscribe to. self._channels_to_subscribe_to: List[str] = [] self._is_presence_writer = ( hs.get_instance_name() in hs.config.worker.writers.presence ) self._streams: Dict[str, Stream] = { stream.NAME: stream(hs) for stream in STREAMS_MAP.values() } # List of streams that this instance is the source of self._streams_to_replicate: List[Stream] = [] for stream in self._streams.values(): if hs.config.redis.redis_enabled and stream.NAME == CachesStream.NAME: # All workers can write to the cache invalidation stream when # using redis. self._streams_to_replicate.append(stream) continue if isinstance(stream, (EventsStream, BackfillStream)): # Only add EventStream and BackfillStream as a source on the # instance in charge of event persistence. if hs.get_instance_name() in hs.config.worker.writers.events: self._streams_to_replicate.append(stream) continue if isinstance(stream, ToDeviceStream): # Only add ToDeviceStream as a source on instances in charge of # sending to device messages. if hs.get_instance_name() in hs.config.worker.writers.to_device: self._streams_to_replicate.append(stream) continue if isinstance(stream, TypingStream): # Only add TypingStream as a source on the instance in charge of # typing. if hs.get_instance_name() in hs.config.worker.writers.typing: self._streams_to_replicate.append(stream) continue if isinstance(stream, (AccountDataStream, TagAccountDataStream)): # Only add AccountDataStream and TagAccountDataStream as a source on the # instance in charge of account_data persistence. if hs.get_instance_name() in hs.config.worker.writers.account_data: self._streams_to_replicate.append(stream) continue if isinstance(stream, ReceiptsStream): # Only add ReceiptsStream as a source on the instance in charge of # receipts. if hs.get_instance_name() in hs.config.worker.writers.receipts: self._streams_to_replicate.append(stream) continue if isinstance(stream, (PresenceStream, PresenceFederationStream)): # Only add PresenceStream as a source on the instance in charge # of presence. if self._is_presence_writer: self._streams_to_replicate.append(stream) continue # Only add any other streams if we're on master. if hs.config.worker.worker_app is not None: continue if ( stream.NAME == FederationStream.NAME and hs.config.worker.send_federation ): # We only support federation stream if federation sending # has been disabled on the master. continue self._streams_to_replicate.append(stream) # Map of stream name to batched updates. See RdataCommand for info on # how batching works. self._pending_batches: Dict[str, List[Any]] = {} # The factory used to create connections. self._factory: Optional[ReconnectingClientFactory] = None # The currently connected connections. (The list of places we need to send # outgoing replication commands to.) self._connections: List[IReplicationConnection] = [] LaterGauge( "synapse_replication_tcp_resource_total_connections", "", [], lambda: len(self._connections), ) # When POSITION or RDATA commands arrive, we stick them in a queue and process # them in order in a separate background process. # the streams which are currently being processed by _unsafe_process_queue self._processing_streams: Set[str] = set() # for each stream, a queue of commands that are awaiting processing, and the # connection that they arrived on. self._command_queues_by_stream = { stream_name: _StreamCommandQueue() for stream_name in self._streams } # For each connection, the incoming stream names that have received a POSITION # from that connection. self._streams_by_connection: Dict[IReplicationConnection, Set[str]] = {} LaterGauge( "synapse_replication_tcp_command_queue", "Number of inbound RDATA/POSITION commands queued for processing", ["stream_name"], lambda: { (stream_name,): len(queue) for stream_name, queue in self._command_queues_by_stream.items() }, ) self._is_master = hs.config.worker.worker_app is None self._federation_sender = None if self._is_master and not hs.config.worker.send_federation: self._federation_sender = hs.get_federation_sender() self._server_notices_sender = None if self._is_master: self._server_notices_sender = hs.get_server_notices_sender() if hs.config.redis.redis_enabled: # If we're using Redis, it's the background worker that should # receive USER_IP commands and store the relevant client IPs. self._should_insert_client_ips = hs.config.worker.run_background_tasks else: # If we're NOT using Redis, this must be handled by the master self._should_insert_client_ips = hs.get_instance_name() == "master" if self._is_master or self._should_insert_client_ips: self.subscribe_to_channel("USER_IP")
def __init__(self, hs): self._replication_data_handler = hs.get_replication_data_handler() self._presence_handler = hs.get_presence_handler() self._store = hs.get_datastore() self._notifier = hs.get_notifier() self._clock = hs.get_clock() self._instance_id = hs.get_instance_id() self._instance_name = hs.get_instance_name() self._streams = { stream.NAME: stream(hs) for stream in STREAMS_MAP.values() } # type: Dict[str, Stream] # List of streams that this instance is the source of self._streams_to_replicate = [] # type: List[Stream] for stream in self._streams.values(): if stream.NAME == CachesStream.NAME: # All workers can write to the cache invalidation stream. self._streams_to_replicate.append(stream) continue if isinstance(stream, (EventsStream, BackfillStream)): # Only add EventStream and BackfillStream as a source on the # instance in charge of event persistence. if hs.get_instance_name() in hs.config.worker.writers.events: self._streams_to_replicate.append(stream) continue if isinstance(stream, TypingStream): # Only add TypingStream as a source on the instance in charge of # typing. if hs.config.worker.writers.typing == hs.get_instance_name(): self._streams_to_replicate.append(stream) continue # Only add any other streams if we're on master. if hs.config.worker_app is not None: continue if stream.NAME == FederationStream.NAME and hs.config.send_federation: # We only support federation stream if federation sending # has been disabled on the master. continue self._streams_to_replicate.append(stream) # Map of stream name to batched updates. See RdataCommand for info on # how batching works. self._pending_batches = {} # type: Dict[str, List[Any]] # The factory used to create connections. self._factory = None # type: Optional[ReconnectingClientFactory] # The currently connected connections. (The list of places we need to send # outgoing replication commands to.) self._connections = [] # type: List[AbstractConnection] LaterGauge( "synapse_replication_tcp_resource_total_connections", "", [], lambda: len(self._connections), ) # When POSITION or RDATA commands arrive, we stick them in a queue and process # them in order in a separate background process. # the streams which are currently being processed by _unsafe_process_queue self._processing_streams = set() # type: Set[str] # for each stream, a queue of commands that are awaiting processing, and the # connection that they arrived on. self._command_queues_by_stream = { stream_name: _StreamCommandQueue() for stream_name in self._streams } # For each connection, the incoming stream names that have received a POSITION # from that connection. self._streams_by_connection = { } # type: Dict[AbstractConnection, Set[str]] LaterGauge( "synapse_replication_tcp_command_queue", "Number of inbound RDATA/POSITION commands queued for processing", ["stream_name"], lambda: {(stream_name, ): len(queue) for stream_name, queue in self._command_queues_by_stream. items()}, ) self._is_master = hs.config.worker_app is None self._federation_sender = None if self._is_master and not hs.config.send_federation: self._federation_sender = hs.get_federation_sender() self._server_notices_sender = None if self._is_master: self._server_notices_sender = hs.get_server_notices_sender()
def __init__(self, hs): self._replication_data_handler = hs.get_replication_data_handler() self._presence_handler = hs.get_presence_handler() self._store = hs.get_datastore() self._notifier = hs.get_notifier() self._clock = hs.get_clock() self._instance_id = hs.get_instance_id() self._instance_name = hs.get_instance_name() self._streams = { stream.NAME: stream(hs) for stream in STREAMS_MAP.values() } # type: Dict[str, Stream] # List of streams that this instance is the source of self._streams_to_replicate = [] # type: List[Stream] for stream in self._streams.values(): if stream.NAME == CachesStream.NAME: # All workers can write to the cache invalidation stream. self._streams_to_replicate.append(stream) continue if isinstance(stream, (EventsStream, BackfillStream)): # Only add EventStream and BackfillStream as a source on the # instance in charge of event persistence. if hs.config.worker.writers.events == hs.get_instance_name(): self._streams_to_replicate.append(stream) continue # Only add any other streams if we're on master. if hs.config.worker_app is not None: continue if stream.NAME == FederationStream.NAME and hs.config.send_federation: # We only support federation stream if federation sending # has been disabled on the master. continue self._streams_to_replicate.append(stream) self._position_linearizer = Linearizer( "replication_position", clock=self._clock ) # Map of stream name to batched updates. See RdataCommand for info on # how batching works. self._pending_batches = {} # type: Dict[str, List[Any]] # The factory used to create connections. self._factory = None # type: Optional[ReconnectingClientFactory] # The currently connected connections. (The list of places we need to send # outgoing replication commands to.) self._connections = [] # type: List[AbstractConnection] # For each connection, the incoming stream names that are coming from # that connection. self._streams_by_connection = {} # type: Dict[AbstractConnection, Set[str]] LaterGauge( "synapse_replication_tcp_resource_total_connections", "", [], lambda: len(self._connections), ) self._is_master = hs.config.worker_app is None self._federation_sender = None if self._is_master and not hs.config.send_federation: self._federation_sender = hs.get_federation_sender() self._server_notices_sender = None if self._is_master: self._server_notices_sender = hs.get_server_notices_sender()
def build_replication_streams(self): return {stream.NAME: stream(self) for stream in STREAMS_MAP.values()}