Skip to content
This repository was archived by the owner on Apr 26, 2024. It is now read-only.

Commit b49a5b9

Browse files
authored
Convert stats and related calls to async/await (#8192)
1 parent b71d4a0 commit b49a5b9

File tree

8 files changed

+78
-77
lines changed

8 files changed

+78
-77
lines changed

changelog.d/8192.misc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Convert various parts of the codebase to async/await.

synapse/storage/databases/main/monthly_active_users.py

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
# See the License for the specific language governing permissions and
1414
# limitations under the License.
1515
import logging
16-
from typing import List
16+
from typing import Dict, List
1717

1818
from synapse.storage._base import SQLBaseStore
1919
from synapse.storage.database import DatabasePool, make_in_list_sql_clause
@@ -33,11 +33,11 @@ def __init__(self, database: DatabasePool, db_conn, hs):
3333
self.hs = hs
3434

3535
@cached(num_args=0)
36-
def get_monthly_active_count(self):
36+
async def get_monthly_active_count(self) -> int:
3737
"""Generates current count of monthly active users
3838
3939
Returns:
40-
Defered[int]: Number of current monthly active users
40+
Number of current monthly active users
4141
"""
4242

4343
def _count_users(txn):
@@ -46,19 +46,18 @@ def _count_users(txn):
4646
(count,) = txn.fetchone()
4747
return count
4848

49-
return self.db_pool.runInteraction("count_users", _count_users)
49+
return await self.db_pool.runInteraction("count_users", _count_users)
5050

5151
@cached(num_args=0)
52-
def get_monthly_active_count_by_service(self):
52+
async def get_monthly_active_count_by_service(self) -> Dict[str, int]:
5353
"""Generates current count of monthly active users broken down by service.
5454
A service is typically an appservice but also includes native matrix users.
5555
Since the `monthly_active_users` table is populated from the `user_ips` table
5656
`config.track_appservice_user_ips` must be set to `true` for this
5757
method to return anything other than native matrix users.
5858
5959
Returns:
60-
Deferred[dict]: dict that includes a mapping between app_service_id
61-
and the number of occurrences.
60+
A mapping between app_service_id and the number of occurrences.
6261
6362
"""
6463

@@ -74,7 +73,7 @@ def _count_users_by_service(txn):
7473
result = txn.fetchall()
7574
return dict(result)
7675

77-
return self.db_pool.runInteraction(
76+
return await self.db_pool.runInteraction(
7877
"count_users_by_service", _count_users_by_service
7978
)
8079

synapse/storage/databases/main/stats.py

Lines changed: 42 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,9 @@
1515
# limitations under the License.
1616

1717
import logging
18+
from collections import Counter
1819
from itertools import chain
19-
from typing import Any, Dict, Tuple
20+
from typing import Any, Dict, List, Optional, Tuple
2021

2122
from twisted.internet.defer import DeferredLock
2223

@@ -251,21 +252,23 @@ async def update_room_state(self, room_id: str, fields: Dict[str, Any]) -> None:
251252
desc="update_room_state",
252253
)
253254

254-
def get_statistics_for_subject(self, stats_type, stats_id, start, size=100):
255+
async def get_statistics_for_subject(
256+
self, stats_type: str, stats_id: str, start: str, size: int = 100
257+
) -> List[dict]:
255258
"""
256259
Get statistics for a given subject.
257260
258261
Args:
259-
stats_type (str): The type of subject
260-
stats_id (str): The ID of the subject (e.g. room_id or user_id)
261-
start (int): Pagination start. Number of entries, not timestamp.
262-
size (int): How many entries to return.
262+
stats_type: The type of subject
263+
stats_id: The ID of the subject (e.g. room_id or user_id)
264+
start: Pagination start. Number of entries, not timestamp.
265+
size: How many entries to return.
263266
264267
Returns:
265-
Deferred[list[dict]], where the dict has the keys of
268+
A list of dicts, where the dict has the keys of
266269
ABSOLUTE_STATS_FIELDS[stats_type], and "bucket_size" and "end_ts".
267270
"""
268-
return self.db_pool.runInteraction(
271+
return await self.db_pool.runInteraction(
269272
"get_statistics_for_subject",
270273
self._get_statistics_for_subject_txn,
271274
stats_type,
@@ -319,18 +322,17 @@ async def get_earliest_token_for_stats(self, stats_type: str, id: str) -> int:
319322
allow_none=True,
320323
)
321324

322-
def bulk_update_stats_delta(self, ts, updates, stream_id):
325+
async def bulk_update_stats_delta(
326+
self, ts: int, updates: Dict[str, Dict[str, Dict[str, Counter]]], stream_id: int
327+
) -> None:
323328
"""Bulk update stats tables for a given stream_id and updates the stats
324329
incremental position.
325330
326331
Args:
327-
ts (int): Current timestamp in ms
328-
updates(dict[str, dict[str, dict[str, Counter]]]): The updates to
329-
commit as a mapping stats_type -> stats_id -> field -> delta.
330-
stream_id (int): Current position.
331-
332-
Returns:
333-
Deferred
332+
ts: Current timestamp in ms
333+
updates: The updates to commit as a mapping of
334+
stats_type -> stats_id -> field -> delta.
335+
stream_id: Current position.
334336
"""
335337

336338
def _bulk_update_stats_delta_txn(txn):
@@ -355,38 +357,37 @@ def _bulk_update_stats_delta_txn(txn):
355357
updatevalues={"stream_id": stream_id},
356358
)
357359

358-
return self.db_pool.runInteraction(
360+
await self.db_pool.runInteraction(
359361
"bulk_update_stats_delta", _bulk_update_stats_delta_txn
360362
)
361363

362-
def update_stats_delta(
364+
async def update_stats_delta(
363365
self,
364-
ts,
365-
stats_type,
366-
stats_id,
367-
fields,
368-
complete_with_stream_id,
369-
absolute_field_overrides=None,
370-
):
366+
ts: int,
367+
stats_type: str,
368+
stats_id: str,
369+
fields: Dict[str, int],
370+
complete_with_stream_id: Optional[int],
371+
absolute_field_overrides: Optional[Dict[str, int]] = None,
372+
) -> None:
371373
"""
372374
Updates the statistics for a subject, with a delta (difference/relative
373375
change).
374376
375377
Args:
376-
ts (int): timestamp of the change
377-
stats_type (str): "room" or "user" – the kind of subject
378-
stats_id (str): the subject's ID (room ID or user ID)
379-
fields (dict[str, int]): Deltas of stats values.
380-
complete_with_stream_id (int, optional):
378+
ts: timestamp of the change
379+
stats_type: "room" or "user" – the kind of subject
380+
stats_id: the subject's ID (room ID or user ID)
381+
fields: Deltas of stats values.
382+
complete_with_stream_id:
381383
If supplied, converts an incomplete row into a complete row,
382384
with the supplied stream_id marked as the stream_id where the
383385
row was completed.
384-
absolute_field_overrides (dict[str, int]): Current stats values
385-
(i.e. not deltas) of absolute fields.
386-
Does not work with per-slice fields.
386+
absolute_field_overrides: Current stats values (i.e. not deltas) of
387+
absolute fields. Does not work with per-slice fields.
387388
"""
388389

389-
return self.db_pool.runInteraction(
390+
await self.db_pool.runInteraction(
390391
"update_stats_delta",
391392
self._update_stats_delta_txn,
392393
ts,
@@ -646,19 +647,20 @@ def _upsert_copy_from_table_with_additive_relatives_txn(
646647
txn, into_table, all_dest_keyvalues, src_row
647648
)
648649

649-
def get_changes_room_total_events_and_bytes(self, min_pos, max_pos):
650+
async def get_changes_room_total_events_and_bytes(
651+
self, min_pos: int, max_pos: int
652+
) -> Dict[str, Dict[str, int]]:
650653
"""Fetches the counts of events in the given range of stream IDs.
651654
652655
Args:
653-
min_pos (int)
654-
max_pos (int)
656+
min_pos
657+
max_pos
655658
656659
Returns:
657-
Deferred[dict[str, dict[str, int]]]: Mapping of room ID to field
658-
changes.
660+
Mapping of room ID to field changes.
659661
"""
660662

661-
return self.db_pool.runInteraction(
663+
return await self.db_pool.runInteraction(
662664
"stats_incremental_total_events_and_bytes",
663665
self.get_changes_room_total_events_and_bytes_txn,
664666
min_pos,

tests/handlers/test_auth.py

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
from synapse.handlers.auth import AuthHandler
2525

2626
from tests import unittest
27+
from tests.test_utils import make_awaitable
2728
from tests.utils import setup_test_homeserver
2829

2930

@@ -142,7 +143,7 @@ def test_mau_limits_disabled(self):
142143
def test_mau_limits_exceeded_large(self):
143144
self.auth_blocking._limit_usage_by_mau = True
144145
self.hs.get_datastore().get_monthly_active_count = Mock(
145-
return_value=defer.succeed(self.large_number_of_users)
146+
side_effect=lambda: make_awaitable(self.large_number_of_users)
146147
)
147148

148149
with self.assertRaises(ResourceLimitError):
@@ -153,7 +154,7 @@ def test_mau_limits_exceeded_large(self):
153154
)
154155

155156
self.hs.get_datastore().get_monthly_active_count = Mock(
156-
return_value=defer.succeed(self.large_number_of_users)
157+
side_effect=lambda: make_awaitable(self.large_number_of_users)
157158
)
158159
with self.assertRaises(ResourceLimitError):
159160
yield defer.ensureDeferred(
@@ -168,7 +169,7 @@ def test_mau_limits_parity(self):
168169

169170
# If not in monthly active cohort
170171
self.hs.get_datastore().get_monthly_active_count = Mock(
171-
return_value=defer.succeed(self.auth_blocking._max_mau_value)
172+
side_effect=lambda: make_awaitable(self.auth_blocking._max_mau_value)
172173
)
173174
with self.assertRaises(ResourceLimitError):
174175
yield defer.ensureDeferred(
@@ -178,7 +179,7 @@ def test_mau_limits_parity(self):
178179
)
179180

180181
self.hs.get_datastore().get_monthly_active_count = Mock(
181-
return_value=defer.succeed(self.auth_blocking._max_mau_value)
182+
side_effect=lambda: make_awaitable(self.auth_blocking._max_mau_value)
182183
)
183184
with self.assertRaises(ResourceLimitError):
184185
yield defer.ensureDeferred(
@@ -188,21 +189,21 @@ def test_mau_limits_parity(self):
188189
)
189190
# If in monthly active cohort
190191
self.hs.get_datastore().user_last_seen_monthly_active = Mock(
191-
return_value=defer.succeed(self.hs.get_clock().time_msec())
192+
side_effect=lambda user_id: make_awaitable(self.hs.get_clock().time_msec())
192193
)
193194
self.hs.get_datastore().get_monthly_active_count = Mock(
194-
return_value=defer.succeed(self.auth_blocking._max_mau_value)
195+
side_effect=lambda: make_awaitable(self.auth_blocking._max_mau_value)
195196
)
196197
yield defer.ensureDeferred(
197198
self.auth_handler.get_access_token_for_user_id(
198199
"user_a", device_id=None, valid_until_ms=None
199200
)
200201
)
201202
self.hs.get_datastore().user_last_seen_monthly_active = Mock(
202-
return_value=defer.succeed(self.hs.get_clock().time_msec())
203+
side_effect=lambda user_id: make_awaitable(self.hs.get_clock().time_msec())
203204
)
204205
self.hs.get_datastore().get_monthly_active_count = Mock(
205-
return_value=defer.succeed(self.auth_blocking._max_mau_value)
206+
side_effect=lambda: make_awaitable(self.auth_blocking._max_mau_value)
206207
)
207208
yield defer.ensureDeferred(
208209
self.auth_handler.validate_short_term_login_token_and_get_user_id(
@@ -215,7 +216,7 @@ def test_mau_limits_not_exceeded(self):
215216
self.auth_blocking._limit_usage_by_mau = True
216217

217218
self.hs.get_datastore().get_monthly_active_count = Mock(
218-
return_value=defer.succeed(self.small_number_of_users)
219+
side_effect=lambda: make_awaitable(self.small_number_of_users)
219220
)
220221
# Ensure does not raise exception
221222
yield defer.ensureDeferred(
@@ -225,7 +226,7 @@ def test_mau_limits_not_exceeded(self):
225226
)
226227

227228
self.hs.get_datastore().get_monthly_active_count = Mock(
228-
return_value=defer.succeed(self.small_number_of_users)
229+
side_effect=lambda: make_awaitable(self.small_number_of_users)
229230
)
230231
yield defer.ensureDeferred(
231232
self.auth_handler.validate_short_term_login_token_and_get_user_id(

tests/handlers/test_register.py

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@
1515

1616
from mock import Mock
1717

18-
from twisted.internet import defer
19-
2018
from synapse.api.auth import Auth
2119
from synapse.api.constants import UserTypes
2220
from synapse.api.errors import Codes, ResourceLimitError, SynapseError
@@ -102,23 +100,23 @@ def test_mau_limits_when_disabled(self):
102100
def test_get_or_create_user_mau_not_blocked(self):
103101
self.hs.config.limit_usage_by_mau = True
104102
self.store.count_monthly_users = Mock(
105-
return_value=defer.succeed(self.hs.config.max_mau_value - 1)
103+
side_effect=lambda: make_awaitable(self.hs.config.max_mau_value - 1)
106104
)
107105
# Ensure does not throw exception
108106
self.get_success(self.get_or_create_user(self.requester, "c", "User"))
109107

110108
def test_get_or_create_user_mau_blocked(self):
111109
self.hs.config.limit_usage_by_mau = True
112110
self.store.get_monthly_active_count = Mock(
113-
return_value=defer.succeed(self.lots_of_users)
111+
side_effect=lambda: make_awaitable(self.lots_of_users)
114112
)
115113
self.get_failure(
116114
self.get_or_create_user(self.requester, "b", "display_name"),
117115
ResourceLimitError,
118116
)
119117

120118
self.store.get_monthly_active_count = Mock(
121-
return_value=defer.succeed(self.hs.config.max_mau_value)
119+
side_effect=lambda: make_awaitable(self.hs.config.max_mau_value)
122120
)
123121
self.get_failure(
124122
self.get_or_create_user(self.requester, "b", "display_name"),
@@ -128,14 +126,14 @@ def test_get_or_create_user_mau_blocked(self):
128126
def test_register_mau_blocked(self):
129127
self.hs.config.limit_usage_by_mau = True
130128
self.store.get_monthly_active_count = Mock(
131-
return_value=defer.succeed(self.lots_of_users)
129+
side_effect=lambda: make_awaitable(self.lots_of_users)
132130
)
133131
self.get_failure(
134132
self.handler.register_user(localpart="local_part"), ResourceLimitError
135133
)
136134

137135
self.store.get_monthly_active_count = Mock(
138-
return_value=defer.succeed(self.hs.config.max_mau_value)
136+
side_effect=lambda: make_awaitable(self.hs.config.max_mau_value)
139137
)
140138
self.get_failure(
141139
self.handler.register_user(localpart="local_part"), ResourceLimitError

tests/rest/admin/test_user.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,14 @@
2020

2121
from mock import Mock
2222

23-
from twisted.internet import defer
24-
2523
import synapse.rest.admin
2624
from synapse.api.constants import UserTypes
2725
from synapse.api.errors import HttpResponseException, ResourceLimitError
2826
from synapse.rest.client.v1 import login
2927
from synapse.rest.client.v2_alpha import sync
3028

3129
from tests import unittest
30+
from tests.test_utils import make_awaitable
3231
from tests.unittest import override_config
3332

3433

@@ -338,7 +337,7 @@ def test_register_mau_limit_reached(self):
338337

339338
# Set monthly active users to the limit
340339
store.get_monthly_active_count = Mock(
341-
return_value=defer.succeed(self.hs.config.max_mau_value)
340+
side_effect=lambda: make_awaitable(self.hs.config.max_mau_value)
342341
)
343342
# Check that the blocking of monthly active users is working as expected
344343
# The registration of a new user fails due to the limit
@@ -592,7 +591,7 @@ def test_create_user_mau_limit_reached_active_admin(self):
592591

593592
# Set monthly active users to the limit
594593
self.store.get_monthly_active_count = Mock(
595-
return_value=defer.succeed(self.hs.config.max_mau_value)
594+
side_effect=lambda: make_awaitable(self.hs.config.max_mau_value)
596595
)
597596
# Check that the blocking of monthly active users is working as expected
598597
# The registration of a new user fails due to the limit
@@ -632,7 +631,7 @@ def test_create_user_mau_limit_reached_passive_admin(self):
632631

633632
# Set monthly active users to the limit
634633
self.store.get_monthly_active_count = Mock(
635-
return_value=defer.succeed(self.hs.config.max_mau_value)
634+
side_effect=lambda: make_awaitable(self.hs.config.max_mau_value)
636635
)
637636
# Check that the blocking of monthly active users is working as expected
638637
# The registration of a new user fails due to the limit

0 commit comments

Comments
 (0)