Move unique snowflake homeserver background tasks to start_background_tasks (#19037)

(the standard pattern for this kind of thing)
This commit is contained in:
Eric Eastwood
2025-10-13 10:19:09 -05:00
committed by GitHub
parent 2d07bd7fd2
commit d2c582ef3c
14 changed files with 331 additions and 182 deletions

1
changelog.d/19037.misc Normal file
View File

@@ -0,0 +1 @@
Move unique snowflake homeserver background tasks to `start_background_tasks` (the standard pattern for this kind of thing).

View File

@@ -64,7 +64,6 @@ from twisted.web.resource import Resource
import synapse.util.caches import synapse.util.caches
from synapse.api.constants import MAX_PDU_SIZE from synapse.api.constants import MAX_PDU_SIZE
from synapse.app import check_bind_error from synapse.app import check_bind_error
from synapse.app.phone_stats_home import start_phone_stats_home
from synapse.config import ConfigError from synapse.config import ConfigError
from synapse.config._base import format_config_error from synapse.config._base import format_config_error
from synapse.config.homeserver import HomeServerConfig from synapse.config.homeserver import HomeServerConfig
@@ -683,15 +682,6 @@ async def start(hs: "HomeServer", freeze: bool = True) -> None:
if hs.config.worker.run_background_tasks: if hs.config.worker.run_background_tasks:
hs.start_background_tasks() hs.start_background_tasks()
# TODO: This should be moved to same pattern we use for other background tasks:
# Add to `REQUIRED_ON_BACKGROUND_TASK_STARTUP` and rely on
# `start_background_tasks` to start it.
await hs.get_common_usage_metrics_manager().setup()
# TODO: This feels like another pattern that should refactored as one of the
# `REQUIRED_ON_BACKGROUND_TASK_STARTUP`
start_phone_stats_home(hs)
if freeze: if freeze:
# We now freeze all allocated objects in the hopes that (almost) # We now freeze all allocated objects in the hopes that (almost)
# everything currently allocated are things that will be used for the # everything currently allocated are things that will be used for the

View File

@@ -62,7 +62,7 @@ class CommonUsageMetricsManager:
""" """
return await self._collect() return await self._collect()
async def setup(self) -> None: def setup(self) -> None:
"""Keep the gauges for common usage metrics up to date.""" """Keep the gauges for common usage metrics up to date."""
self._hs.run_as_background_process( self._hs.run_as_background_process(
desc="common_usage_metrics_update_gauges", desc="common_usage_metrics_update_gauges",

View File

@@ -62,6 +62,7 @@ from synapse.api.auth_blocking import AuthBlocking
from synapse.api.filtering import Filtering from synapse.api.filtering import Filtering
from synapse.api.ratelimiting import Ratelimiter, RequestRatelimiter from synapse.api.ratelimiting import Ratelimiter, RequestRatelimiter
from synapse.app._base import unregister_sighups from synapse.app._base import unregister_sighups
from synapse.app.phone_stats_home import start_phone_stats_home
from synapse.appservice.api import ApplicationServiceApi from synapse.appservice.api import ApplicationServiceApi
from synapse.appservice.scheduler import ApplicationServiceScheduler from synapse.appservice.scheduler import ApplicationServiceScheduler
from synapse.config.homeserver import HomeServerConfig from synapse.config.homeserver import HomeServerConfig
@@ -643,6 +644,8 @@ class HomeServer(metaclass=abc.ABCMeta):
for i in self.REQUIRED_ON_BACKGROUND_TASK_STARTUP: for i in self.REQUIRED_ON_BACKGROUND_TASK_STARTUP:
getattr(self, "get_" + i + "_handler")() getattr(self, "get_" + i + "_handler")()
self.get_task_scheduler() self.get_task_scheduler()
self.get_common_usage_metrics_manager().setup()
start_phone_stats_home(self)
def get_reactor(self) -> ISynapseReactor: def get_reactor(self) -> ISynapseReactor:
""" """

View File

@@ -214,7 +214,12 @@ class BaseStreamTestCase(unittest.HomeserverTestCase):
client_to_server_transport.loseConnection() client_to_server_transport.loseConnection()
# there should have been exactly one request # there should have been exactly one request
self.assertEqual(len(requests), 1) self.assertEqual(
len(requests),
1,
"Expected to handle exactly one HTTP replication request but saw %d - requests=%s"
% (len(requests), requests),
)
return requests[0] return requests[0]

View File

@@ -46,28 +46,39 @@ class AccountDataStreamTestCase(BaseStreamTestCase):
# check we're testing what we think we are: no rows should yet have been # check we're testing what we think we are: no rows should yet have been
# received # received
self.assertEqual([], self.test_handler.received_rdata_rows) received_account_data_rows = [
row
for row in self.test_handler.received_rdata_rows
if row[0] == AccountDataStream.NAME
]
self.assertEqual([], received_account_data_rows)
# now reconnect to pull the updates # now reconnect to pull the updates
self.reconnect() self.reconnect()
self.replicate() self.replicate()
# we should have received all the expected rows in the right order # We should have received all the expected rows in the right order
received_rows = self.test_handler.received_rdata_rows #
# Filter the updates to only include account data changes
received_account_data_rows = [
row
for row in self.test_handler.received_rdata_rows
if row[0] == AccountDataStream.NAME
]
for t in updates: for t in updates:
(stream_name, token, row) = received_rows.pop(0) (stream_name, token, row) = received_account_data_rows.pop(0)
self.assertEqual(stream_name, AccountDataStream.NAME) self.assertEqual(stream_name, AccountDataStream.NAME)
self.assertIsInstance(row, AccountDataStream.AccountDataStreamRow) self.assertIsInstance(row, AccountDataStream.AccountDataStreamRow)
self.assertEqual(row.data_type, t) self.assertEqual(row.data_type, t)
self.assertEqual(row.room_id, "test_room") self.assertEqual(row.room_id, "test_room")
(stream_name, token, row) = received_rows.pop(0) (stream_name, token, row) = received_account_data_rows.pop(0)
self.assertIsInstance(row, AccountDataStream.AccountDataStreamRow) self.assertIsInstance(row, AccountDataStream.AccountDataStreamRow)
self.assertEqual(row.data_type, "m.global") self.assertEqual(row.data_type, "m.global")
self.assertIsNone(row.room_id) self.assertIsNone(row.room_id)
self.assertEqual([], received_rows) self.assertEqual([], received_account_data_rows)
def test_update_function_global_account_data_limit(self) -> None: def test_update_function_global_account_data_limit(self) -> None:
"""Test replication with many global account data updates""" """Test replication with many global account data updates"""
@@ -85,32 +96,38 @@ class AccountDataStreamTestCase(BaseStreamTestCase):
store.add_account_data_to_room("test_user", "test_room", "m.per_room", {}) store.add_account_data_to_room("test_user", "test_room", "m.per_room", {})
) )
# tell the notifier to catch up to avoid duplicate rows.
# workaround for https://github.com/matrix-org/synapse/issues/7360
# FIXME remove this when the above is fixed
self.replicate()
# check we're testing what we think we are: no rows should yet have been # check we're testing what we think we are: no rows should yet have been
# received # received
self.assertEqual([], self.test_handler.received_rdata_rows) received_account_data_rows = [
row
for row in self.test_handler.received_rdata_rows
if row[0] == AccountDataStream.NAME
]
self.assertEqual([], received_account_data_rows)
# now reconnect to pull the updates # now reconnect to pull the updates
self.reconnect() self.reconnect()
self.replicate() self.replicate()
# we should have received all the expected rows in the right order # we should have received all the expected rows in the right order
received_rows = self.test_handler.received_rdata_rows #
# Filter the updates to only include typing changes
received_account_data_rows = [
row
for row in self.test_handler.received_rdata_rows
if row[0] == AccountDataStream.NAME
]
for t in updates: for t in updates:
(stream_name, token, row) = received_rows.pop(0) (stream_name, token, row) = received_account_data_rows.pop(0)
self.assertEqual(stream_name, AccountDataStream.NAME) self.assertEqual(stream_name, AccountDataStream.NAME)
self.assertIsInstance(row, AccountDataStream.AccountDataStreamRow) self.assertIsInstance(row, AccountDataStream.AccountDataStreamRow)
self.assertEqual(row.data_type, t) self.assertEqual(row.data_type, t)
self.assertIsNone(row.room_id) self.assertIsNone(row.room_id)
(stream_name, token, row) = received_rows.pop(0) (stream_name, token, row) = received_account_data_rows.pop(0)
self.assertIsInstance(row, AccountDataStream.AccountDataStreamRow) self.assertIsInstance(row, AccountDataStream.AccountDataStreamRow)
self.assertEqual(row.data_type, "m.per_room") self.assertEqual(row.data_type, "m.per_room")
self.assertEqual(row.room_id, "test_room") self.assertEqual(row.room_id, "test_room")
self.assertEqual([], received_rows) self.assertEqual([], received_account_data_rows)

View File

@@ -30,6 +30,7 @@ from synapse.replication.tcp.commands import RdataCommand
from synapse.replication.tcp.streams._base import _STREAM_UPDATE_TARGET_ROW_COUNT from synapse.replication.tcp.streams._base import _STREAM_UPDATE_TARGET_ROW_COUNT
from synapse.replication.tcp.streams.events import ( from synapse.replication.tcp.streams.events import (
_MAX_STATE_UPDATES_PER_ROOM, _MAX_STATE_UPDATES_PER_ROOM,
EventsStream,
EventsStreamAllStateRow, EventsStreamAllStateRow,
EventsStreamCurrentStateRow, EventsStreamCurrentStateRow,
EventsStreamEventRow, EventsStreamEventRow,
@@ -82,7 +83,12 @@ class EventsStreamTestCase(BaseStreamTestCase):
# check we're testing what we think we are: no rows should yet have been # check we're testing what we think we are: no rows should yet have been
# received # received
self.assertEqual([], self.test_handler.received_rdata_rows) received_event_rows = [
row
for row in self.test_handler.received_rdata_rows
if row[0] == EventsStream.NAME
]
self.assertEqual([], received_event_rows)
# now reconnect to pull the updates # now reconnect to pull the updates
self.reconnect() self.reconnect()
@@ -90,31 +96,34 @@ class EventsStreamTestCase(BaseStreamTestCase):
# we should have received all the expected rows in the right order (as # we should have received all the expected rows in the right order (as
# well as various cache invalidation updates which we ignore) # well as various cache invalidation updates which we ignore)
received_rows = [ #
row for row in self.test_handler.received_rdata_rows if row[0] == "events" # Filter the updates to only include event changes
received_event_rows = [
row
for row in self.test_handler.received_rdata_rows
if row[0] == EventsStream.NAME
] ]
for event in events: for event in events:
stream_name, token, row = received_rows.pop(0) stream_name, token, row = received_event_rows.pop(0)
self.assertEqual("events", stream_name) self.assertEqual(EventsStream.NAME, stream_name)
self.assertIsInstance(row, EventsStreamRow) self.assertIsInstance(row, EventsStreamRow)
self.assertEqual(row.type, "ev") self.assertEqual(row.type, "ev")
self.assertIsInstance(row.data, EventsStreamEventRow) self.assertIsInstance(row.data, EventsStreamEventRow)
self.assertEqual(row.data.event_id, event.event_id) self.assertEqual(row.data.event_id, event.event_id)
stream_name, token, row = received_rows.pop(0) stream_name, token, row = received_event_rows.pop(0)
self.assertIsInstance(row, EventsStreamRow) self.assertIsInstance(row, EventsStreamRow)
self.assertIsInstance(row.data, EventsStreamEventRow) self.assertIsInstance(row.data, EventsStreamEventRow)
self.assertEqual(row.data.event_id, state_event.event_id) self.assertEqual(row.data.event_id, state_event.event_id)
stream_name, token, row = received_rows.pop(0) stream_name, token, row = received_event_rows.pop(0)
self.assertEqual("events", stream_name) self.assertEqual("events", stream_name)
self.assertIsInstance(row, EventsStreamRow) self.assertIsInstance(row, EventsStreamRow)
self.assertEqual(row.type, "state") self.assertEqual(row.type, "state")
self.assertIsInstance(row.data, EventsStreamCurrentStateRow) self.assertIsInstance(row.data, EventsStreamCurrentStateRow)
self.assertEqual(row.data.event_id, state_event.event_id) self.assertEqual(row.data.event_id, state_event.event_id)
self.assertEqual([], received_rows) self.assertEqual([], received_event_rows)
@parameterized.expand( @parameterized.expand(
[(_STREAM_UPDATE_TARGET_ROW_COUNT, False), (_MAX_STATE_UPDATES_PER_ROOM, True)] [(_STREAM_UPDATE_TARGET_ROW_COUNT, False), (_MAX_STATE_UPDATES_PER_ROOM, True)]
@@ -170,9 +179,12 @@ class EventsStreamTestCase(BaseStreamTestCase):
self.replicate() self.replicate()
# all those events and state changes should have landed # all those events and state changes should have landed
self.assertGreaterEqual( received_event_rows = [
len(self.test_handler.received_rdata_rows), 2 * len(events) row
) for row in self.test_handler.received_rdata_rows
if row[0] == EventsStream.NAME
]
self.assertGreaterEqual(len(received_event_rows), 2 * len(events))
# disconnect, so that we can stack up the changes # disconnect, so that we can stack up the changes
self.disconnect() self.disconnect()
@@ -202,7 +214,12 @@ class EventsStreamTestCase(BaseStreamTestCase):
# check we're testing what we think we are: no rows should yet have been # check we're testing what we think we are: no rows should yet have been
# received # received
self.assertEqual([], self.test_handler.received_rdata_rows) received_event_rows = [
row
for row in self.test_handler.received_rdata_rows
if row[0] == EventsStream.NAME
]
self.assertEqual([], received_event_rows)
# now reconnect to pull the updates # now reconnect to pull the updates
self.reconnect() self.reconnect()
@@ -218,33 +235,34 @@ class EventsStreamTestCase(BaseStreamTestCase):
# of the states that got reverted. # of the states that got reverted.
# - two rows for state2 # - two rows for state2
received_rows = [ received_event_rows = [
row for row in self.test_handler.received_rdata_rows if row[0] == "events" row
for row in self.test_handler.received_rdata_rows
if row[0] == EventsStream.NAME
] ]
# first check the first two rows, which should be the state1 event. # first check the first two rows, which should be the state1 event.
stream_name, token, row = received_rows.pop(0) stream_name, token, row = received_event_rows.pop(0)
self.assertEqual("events", stream_name) self.assertEqual("events", stream_name)
self.assertIsInstance(row, EventsStreamRow) self.assertIsInstance(row, EventsStreamRow)
self.assertEqual(row.type, "ev") self.assertEqual(row.type, "ev")
self.assertIsInstance(row.data, EventsStreamEventRow) self.assertIsInstance(row.data, EventsStreamEventRow)
self.assertEqual(row.data.event_id, state1.event_id) self.assertEqual(row.data.event_id, state1.event_id)
stream_name, token, row = received_rows.pop(0) stream_name, token, row = received_event_rows.pop(0)
self.assertIsInstance(row, EventsStreamRow) self.assertIsInstance(row, EventsStreamRow)
self.assertEqual(row.type, "state") self.assertEqual(row.type, "state")
self.assertIsInstance(row.data, EventsStreamCurrentStateRow) self.assertIsInstance(row.data, EventsStreamCurrentStateRow)
self.assertEqual(row.data.event_id, state1.event_id) self.assertEqual(row.data.event_id, state1.event_id)
# now the last two rows, which should be the state2 event. # now the last two rows, which should be the state2 event.
stream_name, token, row = received_rows.pop(-2) stream_name, token, row = received_event_rows.pop(-2)
self.assertEqual("events", stream_name) self.assertEqual("events", stream_name)
self.assertIsInstance(row, EventsStreamRow) self.assertIsInstance(row, EventsStreamRow)
self.assertEqual(row.type, "ev") self.assertEqual(row.type, "ev")
self.assertIsInstance(row.data, EventsStreamEventRow) self.assertIsInstance(row.data, EventsStreamEventRow)
self.assertEqual(row.data.event_id, state2.event_id) self.assertEqual(row.data.event_id, state2.event_id)
stream_name, token, row = received_rows.pop(-1) stream_name, token, row = received_event_rows.pop(-1)
self.assertIsInstance(row, EventsStreamRow) self.assertIsInstance(row, EventsStreamRow)
self.assertEqual(row.type, "state") self.assertEqual(row.type, "state")
self.assertIsInstance(row.data, EventsStreamCurrentStateRow) self.assertIsInstance(row.data, EventsStreamCurrentStateRow)
@@ -254,16 +272,16 @@ class EventsStreamTestCase(BaseStreamTestCase):
if collapse_state_changes: if collapse_state_changes:
# that should leave us with the rows for the PL event, the state changes # that should leave us with the rows for the PL event, the state changes
# get collapsed into a single row. # get collapsed into a single row.
self.assertEqual(len(received_rows), 2) self.assertEqual(len(received_event_rows), 2)
stream_name, token, row = received_rows.pop(0) stream_name, token, row = received_event_rows.pop(0)
self.assertEqual("events", stream_name) self.assertEqual("events", stream_name)
self.assertIsInstance(row, EventsStreamRow) self.assertIsInstance(row, EventsStreamRow)
self.assertEqual(row.type, "ev") self.assertEqual(row.type, "ev")
self.assertIsInstance(row.data, EventsStreamEventRow) self.assertIsInstance(row.data, EventsStreamEventRow)
self.assertEqual(row.data.event_id, pl_event.event_id) self.assertEqual(row.data.event_id, pl_event.event_id)
stream_name, token, row = received_rows.pop(0) stream_name, token, row = received_event_rows.pop(0)
self.assertIsInstance(row, EventsStreamRow) self.assertIsInstance(row, EventsStreamRow)
self.assertEqual(row.type, "state-all") self.assertEqual(row.type, "state-all")
self.assertIsInstance(row.data, EventsStreamAllStateRow) self.assertIsInstance(row.data, EventsStreamAllStateRow)
@@ -271,9 +289,9 @@ class EventsStreamTestCase(BaseStreamTestCase):
else: else:
# that should leave us with the rows for the PL event # that should leave us with the rows for the PL event
self.assertEqual(len(received_rows), len(events) + 2) self.assertEqual(len(received_event_rows), len(events) + 2)
stream_name, token, row = received_rows.pop(0) stream_name, token, row = received_event_rows.pop(0)
self.assertEqual("events", stream_name) self.assertEqual("events", stream_name)
self.assertIsInstance(row, EventsStreamRow) self.assertIsInstance(row, EventsStreamRow)
self.assertEqual(row.type, "ev") self.assertEqual(row.type, "ev")
@@ -282,7 +300,7 @@ class EventsStreamTestCase(BaseStreamTestCase):
# the state rows are unsorted # the state rows are unsorted
state_rows: List[EventsStreamCurrentStateRow] = [] state_rows: List[EventsStreamCurrentStateRow] = []
for stream_name, _, row in received_rows: for stream_name, _, row in received_event_rows:
self.assertEqual("events", stream_name) self.assertEqual("events", stream_name)
self.assertIsInstance(row, EventsStreamRow) self.assertIsInstance(row, EventsStreamRow)
self.assertEqual(row.type, "state") self.assertEqual(row.type, "state")
@@ -346,9 +364,12 @@ class EventsStreamTestCase(BaseStreamTestCase):
self.replicate() self.replicate()
# all those events and state changes should have landed # all those events and state changes should have landed
self.assertGreaterEqual( received_event_rows = [
len(self.test_handler.received_rdata_rows), 2 * len(events) row
) for row in self.test_handler.received_rdata_rows
if row[0] == EventsStream.NAME
]
self.assertGreaterEqual(len(received_event_rows), 2 * len(events))
# disconnect, so that we can stack up the changes # disconnect, so that we can stack up the changes
self.disconnect() self.disconnect()
@@ -375,7 +396,12 @@ class EventsStreamTestCase(BaseStreamTestCase):
# check we're testing what we think we are: no rows should yet have been # check we're testing what we think we are: no rows should yet have been
# received # received
self.assertEqual([], self.test_handler.received_rdata_rows) received_event_rows = [
row
for row in self.test_handler.received_rdata_rows
if row[0] == EventsStream.NAME
]
self.assertEqual([], received_event_rows)
# now reconnect to pull the updates # now reconnect to pull the updates
self.reconnect() self.reconnect()
@@ -383,14 +409,16 @@ class EventsStreamTestCase(BaseStreamTestCase):
# we should have received all the expected rows in the right order (as # we should have received all the expected rows in the right order (as
# well as various cache invalidation updates which we ignore) # well as various cache invalidation updates which we ignore)
received_rows = [ received_event_rows = [
row for row in self.test_handler.received_rdata_rows if row[0] == "events" row
for row in self.test_handler.received_rdata_rows
if row[0] == EventsStream.NAME
] ]
self.assertGreaterEqual(len(received_rows), len(events)) self.assertGreaterEqual(len(received_event_rows), len(events))
for i in range(NUM_USERS): for i in range(NUM_USERS):
# for each user, we expect the PL event row, followed by state rows for # for each user, we expect the PL event row, followed by state rows for
# the PL event and each of the states that got reverted. # the PL event and each of the states that got reverted.
stream_name, token, row = received_rows.pop(0) stream_name, token, row = received_event_rows.pop(0)
self.assertEqual("events", stream_name) self.assertEqual("events", stream_name)
self.assertIsInstance(row, EventsStreamRow) self.assertIsInstance(row, EventsStreamRow)
self.assertEqual(row.type, "ev") self.assertEqual(row.type, "ev")
@@ -400,7 +428,7 @@ class EventsStreamTestCase(BaseStreamTestCase):
# the state rows are unsorted # the state rows are unsorted
state_rows: List[EventsStreamCurrentStateRow] = [] state_rows: List[EventsStreamCurrentStateRow] = []
for _ in range(STATES_PER_USER + 1): for _ in range(STATES_PER_USER + 1):
stream_name, token, row = received_rows.pop(0) stream_name, token, row = received_event_rows.pop(0)
self.assertEqual("events", stream_name) self.assertEqual("events", stream_name)
self.assertIsInstance(row, EventsStreamRow) self.assertIsInstance(row, EventsStreamRow)
self.assertEqual(row.type, "state") self.assertEqual(row.type, "state")
@@ -417,7 +445,7 @@ class EventsStreamTestCase(BaseStreamTestCase):
# "None" indicates the state has been deleted # "None" indicates the state has been deleted
self.assertIsNone(sr.event_id) self.assertIsNone(sr.event_id)
self.assertEqual([], received_rows) self.assertEqual([], received_event_rows)
def test_backwards_stream_id(self) -> None: def test_backwards_stream_id(self) -> None:
""" """
@@ -432,7 +460,12 @@ class EventsStreamTestCase(BaseStreamTestCase):
# check we're testing what we think we are: no rows should yet have been # check we're testing what we think we are: no rows should yet have been
# received # received
self.assertEqual([], self.test_handler.received_rdata_rows) received_event_rows = [
row
for row in self.test_handler.received_rdata_rows
if row[0] == EventsStream.NAME
]
self.assertEqual([], received_event_rows)
# now reconnect to pull the updates # now reconnect to pull the updates
self.reconnect() self.reconnect()
@@ -440,14 +473,16 @@ class EventsStreamTestCase(BaseStreamTestCase):
# We should have received the expected single row (as well as various # We should have received the expected single row (as well as various
# cache invalidation updates which we ignore). # cache invalidation updates which we ignore).
received_rows = [ received_event_rows = [
row for row in self.test_handler.received_rdata_rows if row[0] == "events" row
for row in self.test_handler.received_rdata_rows
if row[0] == EventsStream.NAME
] ]
# There should be a single received row. # There should be a single received row.
self.assertEqual(len(received_rows), 1) self.assertEqual(len(received_event_rows), 1)
stream_name, token, row = received_rows[0] stream_name, token, row = received_event_rows[0]
self.assertEqual("events", stream_name) self.assertEqual("events", stream_name)
self.assertIsInstance(row, EventsStreamRow) self.assertIsInstance(row, EventsStreamRow)
self.assertEqual(row.type, "ev") self.assertEqual(row.type, "ev")
@@ -468,10 +503,12 @@ class EventsStreamTestCase(BaseStreamTestCase):
) )
# No updates have been received (because it was discard as old). # No updates have been received (because it was discard as old).
received_rows = [ received_event_rows = [
row for row in self.test_handler.received_rdata_rows if row[0] == "events" row
for row in self.test_handler.received_rdata_rows
if row[0] == EventsStream.NAME
] ]
self.assertEqual(len(received_rows), 0) self.assertEqual(len(received_event_rows), 0)
# Ensure the stream has not gone backwards. # Ensure the stream has not gone backwards.
current_token = worker_events_stream.current_token("master") current_token = worker_events_stream.current_token("master")

View File

@@ -38,24 +38,45 @@ class FederationStreamTestCase(BaseStreamTestCase):
Makes sure that updates sent while we are offline are received later. Makes sure that updates sent while we are offline are received later.
""" """
fed_sender = self.hs.get_federation_sender() fed_sender = self.hs.get_federation_sender()
received_rows = self.test_handler.received_rdata_rows
# Send an update before we connect
fed_sender.build_and_send_edu("testdest", "m.test_edu", {"a": "b"}) fed_sender.build_and_send_edu("testdest", "m.test_edu", {"a": "b"})
# Now reconnect and pull the updates
self.reconnect() self.reconnect()
# FIXME: This seems odd, why aren't we calling `self.replicate()` here? but also
# doing so, causes other assumptions to fail (multiple HTTP replication attempts
# are made).
self.reactor.advance(0) self.reactor.advance(0)
# check we're testing what we think we are: no rows should yet have been # Check we're testing what we think we are: no rows should yet have been
# received # received
self.assertEqual(received_rows, []) #
# Filter the updates to only include typing changes
received_federation_rows = [
row
for row in self.test_handler.received_rdata_rows
if row[0] == FederationStream.NAME
]
self.assertEqual(received_federation_rows, [])
# We should now see an attempt to connect to the master # We should now see an attempt to connect to the master
request = self.handle_http_replication_attempt() request = self.handle_http_replication_attempt()
self.assert_request_is_get_repl_stream_updates(request, "federation") self.assert_request_is_get_repl_stream_updates(request, FederationStream.NAME)
# we should have received an update row # we should have received an update row
stream_name, token, row = received_rows.pop() received_federation_rows = [
self.assertEqual(stream_name, "federation") row
for row in self.test_handler.received_rdata_rows
if row[0] == FederationStream.NAME
]
self.assertEqual(
len(received_federation_rows),
1,
"Expected exactly one row for the federation stream",
)
(stream_name, token, row) = received_federation_rows[0]
self.assertEqual(stream_name, FederationStream.NAME)
self.assertIsInstance(row, FederationStream.FederationStreamRow) self.assertIsInstance(row, FederationStream.FederationStreamRow)
self.assertEqual(row.type, EduRow.TypeId) self.assertEqual(row.type, EduRow.TypeId)
edurow = EduRow.from_data(row.data) edurow = EduRow.from_data(row.data)
@@ -63,19 +84,30 @@ class FederationStreamTestCase(BaseStreamTestCase):
self.assertEqual(edurow.edu.origin, self.hs.hostname) self.assertEqual(edurow.edu.origin, self.hs.hostname)
self.assertEqual(edurow.edu.destination, "testdest") self.assertEqual(edurow.edu.destination, "testdest")
self.assertEqual(edurow.edu.content, {"a": "b"}) self.assertEqual(edurow.edu.content, {"a": "b"})
# Clear out the received rows that we've checked so we can check for new ones later
self.assertEqual(received_rows, []) self.test_handler.received_rdata_rows.clear()
# additional updates should be transferred without an HTTP hit # additional updates should be transferred without an HTTP hit
fed_sender.build_and_send_edu("testdest", "m.test1", {"c": "d"}) fed_sender.build_and_send_edu("testdest", "m.test1", {"c": "d"})
self.reactor.advance(0) # Pull in the updates
self.replicate()
# there should be no http hit # there should be no http hit
self.assertEqual(len(self.reactor.tcpClients), 0) self.assertEqual(len(self.reactor.tcpClients), 0)
# ... but we should have a row
self.assertEqual(len(received_rows), 1)
stream_name, token, row = received_rows.pop() # ... but we should have a row
self.assertEqual(stream_name, "federation") received_federation_rows = [
row
for row in self.test_handler.received_rdata_rows
if row[0] == FederationStream.NAME
]
self.assertEqual(
len(received_federation_rows),
1,
"Expected exactly one row for the federation stream",
)
(stream_name, token, row) = received_federation_rows[0]
self.assertEqual(stream_name, FederationStream.NAME)
self.assertIsInstance(row, FederationStream.FederationStreamRow) self.assertIsInstance(row, FederationStream.FederationStreamRow)
self.assertEqual(row.type, EduRow.TypeId) self.assertEqual(row.type, EduRow.TypeId)
edurow = EduRow.from_data(row.data) edurow = EduRow.from_data(row.data)

View File

@@ -20,7 +20,6 @@
# type: ignore # type: ignore
from unittest.mock import Mock
from synapse.replication.tcp.streams._base import ReceiptsStream from synapse.replication.tcp.streams._base import ReceiptsStream
@@ -30,9 +29,6 @@ USER_ID = "@feeling:blue"
class ReceiptsStreamTestCase(BaseStreamTestCase): class ReceiptsStreamTestCase(BaseStreamTestCase):
def _build_replication_data_handler(self):
return Mock(wraps=super()._build_replication_data_handler())
def test_receipt(self): def test_receipt(self):
self.reconnect() self.reconnect()
@@ -50,23 +46,30 @@ class ReceiptsStreamTestCase(BaseStreamTestCase):
self.replicate() self.replicate()
# there should be one RDATA command # there should be one RDATA command
self.test_handler.on_rdata.assert_called_once() received_receipt_rows = [
stream_name, _, token, rdata_rows = self.test_handler.on_rdata.call_args[0] row
self.assertEqual(stream_name, "receipts") for row in self.test_handler.received_rdata_rows
self.assertEqual(1, len(rdata_rows)) if row[0] == ReceiptsStream.NAME
row: ReceiptsStream.ReceiptsStreamRow = rdata_rows[0] ]
self.assertEqual(
len(received_receipt_rows),
1,
"Expected exactly one row for the receipts stream",
)
(stream_name, token, row) = received_receipt_rows[0]
self.assertEqual(stream_name, ReceiptsStream.NAME)
self.assertEqual("!room:blue", row.room_id) self.assertEqual("!room:blue", row.room_id)
self.assertEqual("m.read", row.receipt_type) self.assertEqual("m.read", row.receipt_type)
self.assertEqual(USER_ID, row.user_id) self.assertEqual(USER_ID, row.user_id)
self.assertEqual("$event:blue", row.event_id) self.assertEqual("$event:blue", row.event_id)
self.assertIsNone(row.thread_id) self.assertIsNone(row.thread_id)
self.assertEqual({"a": 1}, row.data) self.assertEqual({"a": 1}, row.data)
# Clear out the received rows that we've checked so we can check for new ones later
self.test_handler.received_rdata_rows.clear()
# Now let's disconnect and insert some data. # Now let's disconnect and insert some data.
self.disconnect() self.disconnect()
self.test_handler.on_rdata.reset_mock()
self.get_success( self.get_success(
self.hs.get_datastores().main.insert_receipt( self.hs.get_datastores().main.insert_receipt(
"!room2:blue", "!room2:blue",
@@ -79,20 +82,27 @@ class ReceiptsStreamTestCase(BaseStreamTestCase):
) )
self.replicate() self.replicate()
# Nothing should have happened as we are disconnected # Not yet connected: no rows should yet have been received
self.test_handler.on_rdata.assert_not_called() self.assertEqual([], self.test_handler.received_rdata_rows)
# Now reconnect and pull the updates
self.reconnect() self.reconnect()
self.pump(0.1) self.replicate()
# We should now have caught up and get the missing data # We should now have caught up and get the missing data
self.test_handler.on_rdata.assert_called_once() received_receipt_rows = [
stream_name, _, token, rdata_rows = self.test_handler.on_rdata.call_args[0] row
self.assertEqual(stream_name, "receipts") for row in self.test_handler.received_rdata_rows
if row[0] == ReceiptsStream.NAME
]
self.assertEqual(
len(received_receipt_rows),
1,
"Expected exactly one row for the receipts stream",
)
(stream_name, token, row) = received_receipt_rows[0]
self.assertEqual(stream_name, ReceiptsStream.NAME)
self.assertEqual(token, 3) self.assertEqual(token, 3)
self.assertEqual(1, len(rdata_rows))
row: ReceiptsStream.ReceiptsStreamRow = rdata_rows[0]
self.assertEqual("!room2:blue", row.room_id) self.assertEqual("!room2:blue", row.room_id)
self.assertEqual("m.read", row.receipt_type) self.assertEqual("m.read", row.receipt_type)
self.assertEqual(USER_ID, row.user_id) self.assertEqual(USER_ID, row.user_id)

View File

@@ -88,15 +88,15 @@ class ThreadSubscriptionsStreamTestCase(BaseStreamTestCase):
# We should have received all the expected rows in the right order # We should have received all the expected rows in the right order
# Filter the updates to only include thread subscription changes # Filter the updates to only include thread subscription changes
received_rows = [ received_thread_subscription_rows = [
upd row
for upd in self.test_handler.received_rdata_rows for row in self.test_handler.received_rdata_rows
if upd[0] == ThreadSubscriptionsStream.NAME if row[0] == ThreadSubscriptionsStream.NAME
] ]
# Verify all the thread subscription updates # Verify all the thread subscription updates
for thread_id in updates: for thread_id in updates:
(stream_name, token, row) = received_rows.pop(0) (stream_name, token, row) = received_thread_subscription_rows.pop(0)
self.assertEqual(stream_name, ThreadSubscriptionsStream.NAME) self.assertEqual(stream_name, ThreadSubscriptionsStream.NAME)
self.assertIsInstance(row, ThreadSubscriptionsStream.ROW_TYPE) self.assertIsInstance(row, ThreadSubscriptionsStream.ROW_TYPE)
self.assertEqual(row.user_id, "@test_user:example.org") self.assertEqual(row.user_id, "@test_user:example.org")
@@ -104,14 +104,14 @@ class ThreadSubscriptionsStreamTestCase(BaseStreamTestCase):
self.assertEqual(row.event_id, thread_id) self.assertEqual(row.event_id, thread_id)
# Verify the last update in the different room # Verify the last update in the different room
(stream_name, token, row) = received_rows.pop(0) (stream_name, token, row) = received_thread_subscription_rows.pop(0)
self.assertEqual(stream_name, ThreadSubscriptionsStream.NAME) self.assertEqual(stream_name, ThreadSubscriptionsStream.NAME)
self.assertIsInstance(row, ThreadSubscriptionsStream.ROW_TYPE) self.assertIsInstance(row, ThreadSubscriptionsStream.ROW_TYPE)
self.assertEqual(row.user_id, "@test_user:example.org") self.assertEqual(row.user_id, "@test_user:example.org")
self.assertEqual(row.room_id, other_room_id) self.assertEqual(row.room_id, other_room_id)
self.assertEqual(row.event_id, other_thread_root_id) self.assertEqual(row.event_id, other_thread_root_id)
self.assertEqual([], received_rows) self.assertEqual([], received_thread_subscription_rows)
def test_multiple_users_thread_subscription_updates(self) -> None: def test_multiple_users_thread_subscription_updates(self) -> None:
"""Test replication with thread subscription updates for multiple users""" """Test replication with thread subscription updates for multiple users"""
@@ -138,18 +138,18 @@ class ThreadSubscriptionsStreamTestCase(BaseStreamTestCase):
# We should have received all the expected rows # We should have received all the expected rows
# Filter the updates to only include thread subscription changes # Filter the updates to only include thread subscription changes
received_rows = [ received_thread_subscription_rows = [
upd row
for upd in self.test_handler.received_rdata_rows for row in self.test_handler.received_rdata_rows
if upd[0] == ThreadSubscriptionsStream.NAME if row[0] == ThreadSubscriptionsStream.NAME
] ]
# Should have one update per user # Should have one update per user
self.assertEqual(len(received_rows), len(users)) self.assertEqual(len(received_thread_subscription_rows), len(users))
# Verify all updates # Verify all updates
for i, user_id in enumerate(users): for i, user_id in enumerate(users):
(stream_name, token, row) = received_rows[i] (stream_name, token, row) = received_thread_subscription_rows[i]
self.assertEqual(stream_name, ThreadSubscriptionsStream.NAME) self.assertEqual(stream_name, ThreadSubscriptionsStream.NAME)
self.assertIsInstance(row, ThreadSubscriptionsStream.ROW_TYPE) self.assertIsInstance(row, ThreadSubscriptionsStream.ROW_TYPE)
self.assertEqual(row.user_id, user_id) self.assertEqual(row.user_id, user_id)

View File

@@ -21,7 +21,10 @@
import logging import logging
import synapse import synapse
from synapse.replication.tcp.streams._base import _STREAM_UPDATE_TARGET_ROW_COUNT from synapse.replication.tcp.streams._base import (
_STREAM_UPDATE_TARGET_ROW_COUNT,
ToDeviceStream,
)
from synapse.types import JsonDict from synapse.types import JsonDict
from tests.replication._base import BaseStreamTestCase from tests.replication._base import BaseStreamTestCase
@@ -82,7 +85,12 @@ class ToDeviceStreamTestCase(BaseStreamTestCase):
) )
# replication is disconnected so we shouldn't get any updates yet # replication is disconnected so we shouldn't get any updates yet
self.assertEqual([], self.test_handler.received_rdata_rows) received_to_device_rows = [
row
for row in self.test_handler.received_rdata_rows
if row[0] == ToDeviceStream.NAME
]
self.assertEqual([], received_to_device_rows)
# now reconnect to pull the updates # now reconnect to pull the updates
self.reconnect() self.reconnect()
@@ -90,7 +98,15 @@ class ToDeviceStreamTestCase(BaseStreamTestCase):
# we should receive the fact that we have to_device updates # we should receive the fact that we have to_device updates
# for user1 and user2 # for user1 and user2
received_rows = self.test_handler.received_rdata_rows received_to_device_rows = [
self.assertEqual(len(received_rows), 2) row
self.assertEqual(received_rows[0][2].entity, user1) for row in self.test_handler.received_rdata_rows
self.assertEqual(received_rows[1][2].entity, user2) if row[0] == ToDeviceStream.NAME
]
self.assertEqual(
len(received_to_device_rows),
2,
"Expected two rows in the to_device stream",
)
self.assertEqual(received_to_device_rows[0][2].entity, user1)
self.assertEqual(received_to_device_rows[1][2].entity, user2)

View File

@@ -19,7 +19,6 @@
# #
# #
import logging import logging
from unittest.mock import Mock
from synapse.handlers.typing import RoomMember, TypingWriterHandler from synapse.handlers.typing import RoomMember, TypingWriterHandler
from synapse.replication.tcp.streams import TypingStream from synapse.replication.tcp.streams import TypingStream
@@ -27,6 +26,8 @@ from synapse.util.caches.stream_change_cache import StreamChangeCache
from tests.replication._base import BaseStreamTestCase from tests.replication._base import BaseStreamTestCase
logger = logging.getLogger(__name__)
USER_ID = "@feeling:blue" USER_ID = "@feeling:blue"
USER_ID_2 = "@da-ba-dee:blue" USER_ID_2 = "@da-ba-dee:blue"
@@ -35,10 +36,6 @@ ROOM_ID_2 = "!foo:blue"
class TypingStreamTestCase(BaseStreamTestCase): class TypingStreamTestCase(BaseStreamTestCase):
def _build_replication_data_handler(self) -> Mock:
self.mock_handler = Mock(wraps=super()._build_replication_data_handler())
return self.mock_handler
def test_typing(self) -> None: def test_typing(self) -> None:
typing = self.hs.get_typing_handler() typing = self.hs.get_typing_handler()
assert isinstance(typing, TypingWriterHandler) assert isinstance(typing, TypingWriterHandler)
@@ -47,51 +44,74 @@ class TypingStreamTestCase(BaseStreamTestCase):
# update to fetch. # update to fetch.
typing._push_update(member=RoomMember(ROOM_ID, USER_ID), typing=True) typing._push_update(member=RoomMember(ROOM_ID, USER_ID), typing=True)
# Not yet connected: no rows should yet have been received
self.assertEqual([], self.test_handler.received_rdata_rows)
# Reconnect
self.reconnect() self.reconnect()
typing._push_update(member=RoomMember(ROOM_ID, USER_ID), typing=True) typing._push_update(member=RoomMember(ROOM_ID, USER_ID), typing=True)
# Pull in the updates
self.reactor.advance(0) self.replicate()
# We should now see an attempt to connect to the master # We should now see an attempt to connect to the master
request = self.handle_http_replication_attempt() request = self.handle_http_replication_attempt()
self.assert_request_is_get_repl_stream_updates(request, "typing") self.assert_request_is_get_repl_stream_updates(request, TypingStream.NAME)
self.mock_handler.on_rdata.assert_called_once() # Filter the updates to only include typing changes
stream_name, _, token, rdata_rows = self.mock_handler.on_rdata.call_args[0] received_typing_rows = [
self.assertEqual(stream_name, "typing") row
self.assertEqual(1, len(rdata_rows)) for row in self.test_handler.received_rdata_rows
row: TypingStream.TypingStreamRow = rdata_rows[0] if row[0] == TypingStream.NAME
self.assertEqual(ROOM_ID, row.room_id) ]
self.assertEqual([USER_ID], row.user_ids) self.assertEqual(
len(received_typing_rows),
1,
"Expected exactly one row for the typing stream",
)
(stream_name, token, row) = received_typing_rows[0]
self.assertEqual(stream_name, TypingStream.NAME)
self.assertIsInstance(row, TypingStream.ROW_TYPE)
self.assertEqual(row.room_id, ROOM_ID)
self.assertEqual(row.user_ids, [USER_ID])
# Clear out the received rows that we've checked so we can check for new ones later
self.test_handler.received_rdata_rows.clear()
# Now let's disconnect and insert some data. # Now let's disconnect and insert some data.
self.disconnect() self.disconnect()
self.mock_handler.on_rdata.reset_mock()
typing._push_update(member=RoomMember(ROOM_ID, USER_ID), typing=False) typing._push_update(member=RoomMember(ROOM_ID, USER_ID), typing=False)
self.mock_handler.on_rdata.assert_not_called() # Not yet connected: no rows should yet have been received
self.assertEqual([], self.test_handler.received_rdata_rows)
# Now reconnect and pull the updates
self.reconnect() self.reconnect()
self.pump(0.1) self.replicate()
# We should now see an attempt to connect to the master # We should now see an attempt to connect to the master
request = self.handle_http_replication_attempt() request = self.handle_http_replication_attempt()
self.assert_request_is_get_repl_stream_updates(request, "typing") self.assert_request_is_get_repl_stream_updates(request, TypingStream.NAME)
# The from token should be the token from the last RDATA we got. # The from token should be the token from the last RDATA we got.
assert request.args is not None assert request.args is not None
self.assertEqual(int(request.args[b"from_token"][0]), token) self.assertEqual(int(request.args[b"from_token"][0]), token)
self.mock_handler.on_rdata.assert_called_once() received_typing_rows = [
stream_name, _, token, rdata_rows = self.mock_handler.on_rdata.call_args[0] row
self.assertEqual(stream_name, "typing") for row in self.test_handler.received_rdata_rows
self.assertEqual(1, len(rdata_rows)) if row[0] == TypingStream.NAME
row = rdata_rows[0] ]
self.assertEqual(ROOM_ID, row.room_id) self.assertEqual(
self.assertEqual([], row.user_ids) len(received_typing_rows),
1,
"Expected exactly one row for the typing stream",
)
(stream_name, token, row) = received_typing_rows[0]
self.assertEqual(stream_name, TypingStream.NAME)
self.assertIsInstance(row, TypingStream.ROW_TYPE)
self.assertEqual(row.room_id, ROOM_ID)
self.assertEqual(row.user_ids, [])
def test_reset(self) -> None: def test_reset(self) -> None:
""" """
@@ -116,33 +136,47 @@ class TypingStreamTestCase(BaseStreamTestCase):
# update to fetch. # update to fetch.
typing._push_update(member=RoomMember(ROOM_ID, USER_ID), typing=True) typing._push_update(member=RoomMember(ROOM_ID, USER_ID), typing=True)
# Not yet connected: no rows should yet have been received
self.assertEqual([], self.test_handler.received_rdata_rows)
# Now reconnect to pull the updates
self.reconnect() self.reconnect()
typing._push_update(member=RoomMember(ROOM_ID, USER_ID), typing=True) typing._push_update(member=RoomMember(ROOM_ID, USER_ID), typing=True)
# Pull in the updates
self.reactor.advance(0) self.replicate()
# We should now see an attempt to connect to the master # We should now see an attempt to connect to the master
request = self.handle_http_replication_attempt() request = self.handle_http_replication_attempt()
self.assert_request_is_get_repl_stream_updates(request, "typing") self.assert_request_is_get_repl_stream_updates(request, "typing")
self.mock_handler.on_rdata.assert_called_once() received_typing_rows = [
stream_name, _, token, rdata_rows = self.mock_handler.on_rdata.call_args[0] row
self.assertEqual(stream_name, "typing") for row in self.test_handler.received_rdata_rows
self.assertEqual(1, len(rdata_rows)) if row[0] == TypingStream.NAME
row: TypingStream.TypingStreamRow = rdata_rows[0] ]
self.assertEqual(ROOM_ID, row.room_id) self.assertEqual(
self.assertEqual([USER_ID], row.user_ids) len(received_typing_rows),
1,
"Expected exactly one row for the typing stream",
)
(stream_name, token, row) = received_typing_rows[0]
self.assertEqual(stream_name, TypingStream.NAME)
self.assertIsInstance(row, TypingStream.ROW_TYPE)
self.assertEqual(row.room_id, ROOM_ID)
self.assertEqual(row.user_ids, [USER_ID])
# Push the stream forward a bunch so it can be reset. # Push the stream forward a bunch so it can be reset.
for i in range(100): for i in range(100):
typing._push_update( typing._push_update(
member=RoomMember(ROOM_ID, "@test%s:blue" % i), typing=True member=RoomMember(ROOM_ID, "@test%s:blue" % i), typing=True
) )
self.reactor.advance(0) # Pull in the updates
self.replicate()
# Disconnect. # Disconnect.
self.disconnect() self.disconnect()
self.test_handler.received_rdata_rows.clear()
# Reset the typing handler # Reset the typing handler
self.hs.get_replication_streams()["typing"].last_token = 0 self.hs.get_replication_streams()["typing"].last_token = 0
@@ -155,30 +189,34 @@ class TypingStreamTestCase(BaseStreamTestCase):
) )
typing._reset() typing._reset()
# Reconnect. # Now reconnect and pull the updates
self.reconnect() self.reconnect()
self.pump(0.1) self.replicate()
# We should now see an attempt to connect to the master # We should now see an attempt to connect to the master
request = self.handle_http_replication_attempt() request = self.handle_http_replication_attempt()
self.assert_request_is_get_repl_stream_updates(request, "typing") self.assert_request_is_get_repl_stream_updates(request, "typing")
# Reset the test code.
self.mock_handler.on_rdata.reset_mock()
self.mock_handler.on_rdata.assert_not_called()
# Push additional data. # Push additional data.
typing._push_update(member=RoomMember(ROOM_ID_2, USER_ID_2), typing=False) typing._push_update(member=RoomMember(ROOM_ID_2, USER_ID_2), typing=False)
self.reactor.advance(0) # Pull the updates
self.replicate()
self.mock_handler.on_rdata.assert_called_once()
stream_name, _, token, rdata_rows = self.mock_handler.on_rdata.call_args[0]
self.assertEqual(stream_name, "typing")
self.assertEqual(1, len(rdata_rows))
row = rdata_rows[0]
self.assertEqual(ROOM_ID_2, row.room_id)
self.assertEqual([], row.user_ids)
received_typing_rows = [
row
for row in self.test_handler.received_rdata_rows
if row[0] == TypingStream.NAME
]
self.assertEqual(
len(received_typing_rows),
1,
"Expected exactly one row for the typing stream",
)
(stream_name, token, row) = received_typing_rows[0]
self.assertEqual(stream_name, TypingStream.NAME)
self.assertIsInstance(row, TypingStream.ROW_TYPE)
self.assertEqual(row.room_id, ROOM_ID_2)
self.assertEqual(row.user_ids, [])
# The token should have been reset. # The token should have been reset.
self.assertEqual(token, 1) self.assertEqual(token, 1)
finally: finally:

View File

@@ -110,13 +110,13 @@ class MonthlyActiveUsersTestCase(unittest.HomeserverTestCase):
self.assertGreater(timestamp, 0) self.assertGreater(timestamp, 0)
# Test that users with reserved 3pids are not removed from the MAU table # Test that users with reserved 3pids are not removed from the MAU table
# XXX some of this is redundant. poking things into the config shouldn't #
# work, and in any case it's not obvious what we expect to happen when # The `start_phone_stats_home()` looping call will cause us to run
# we advance the reactor. # `reap_monthly_active_users` after the time has advanced
self.hs.config.server.max_mau_value = 0
self.reactor.advance(FORTY_DAYS) self.reactor.advance(FORTY_DAYS)
self.hs.config.server.max_mau_value = 5
# I guess we call this one more time for good measure? Perhaps because
# previously, the phone home stats weren't running in tests?
self.get_success(self.store.reap_monthly_active_users()) self.get_success(self.store.reap_monthly_active_users())
active_count = self.get_success(self.store.get_monthly_active_count()) active_count = self.get_success(self.store.get_monthly_active_count())

View File

@@ -75,7 +75,7 @@ class CommonMetricsTestCase(HomeserverTestCase):
def prepare(self, reactor: MemoryReactor, clock: Clock, hs: HomeServer) -> None: def prepare(self, reactor: MemoryReactor, clock: Clock, hs: HomeServer) -> None:
self.metrics_manager = hs.get_common_usage_metrics_manager() self.metrics_manager = hs.get_common_usage_metrics_manager()
self.get_success(self.metrics_manager.setup()) self.metrics_manager.setup()
def test_dau(self) -> None: def test_dau(self) -> None:
"""Tests that the daily active users count is correctly updated.""" """Tests that the daily active users count is correctly updated."""