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

Commit eda8c88

Browse files
H-Shayrichvdh
andauthored
Add functionality to remove deactivated users from the monthly_active_users table (#10947)
* add test * add function to remove user from monthly active table in deactivate code * add function to remove user from monthly active table * add changelog entry * update changelog number * requested changes * update docstring on new function * fix lint error * Update synapse/storage/databases/main/monthly_active_users.py Co-authored-by: Richard van der Hoff <[email protected]> Co-authored-by: Richard van der Hoff <[email protected]>
1 parent 30f0240 commit eda8c88

File tree

4 files changed

+63
-3
lines changed

4 files changed

+63
-3
lines changed

changelog.d/10947.bugfix

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fixes a long-standing bug wherin deactivated users still count towards the mau limit.

synapse/handlers/deactivate_account.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,10 @@ async def deactivate_account(
133133
# delete from user directory
134134
await self.user_directory_handler.handle_local_user_deactivated(user_id)
135135

136+
# If the user is present in the monthly active users table
137+
# remove them
138+
await self.store.remove_deactivated_user_from_mau_table(user_id)
139+
136140
# Mark the user as erased, if they asked for that
137141
if erase_data:
138142
user = UserID.from_string(user_id)

synapse/storage/databases/main/monthly_active_users.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,3 +354,27 @@ async def populate_monthly_active_users(self, user_id):
354354
await self.upsert_monthly_active_user(user_id)
355355
elif now - last_seen_timestamp > LAST_SEEN_GRANULARITY:
356356
await self.upsert_monthly_active_user(user_id)
357+
358+
async def remove_deactivated_user_from_mau_table(self, user_id: str) -> None:
359+
"""
360+
Removes a deactivated user from the monthly active user
361+
table and resets affected caches.
362+
363+
Args:
364+
user_id(str): the user_id to remove
365+
"""
366+
367+
rows_deleted = await self.db_pool.simple_delete(
368+
table="monthly_active_users",
369+
keyvalues={"user_id": user_id},
370+
desc="simple_delete",
371+
)
372+
373+
if rows_deleted != 0:
374+
await self.invalidate_cache_and_stream(
375+
"user_last_seen_monthly_active", (user_id,)
376+
)
377+
await self.invalidate_cache_and_stream("get_monthly_active_count", ())
378+
await self.invalidate_cache_and_stream(
379+
"get_monthly_active_count_by_service", ()
380+
)

tests/test_mau.py

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@
1313
# limitations under the License.
1414

1515
"""Tests REST events for /rooms paths."""
16-
16+
import synapse.rest.admin
1717
from synapse.api.constants import APP_SERVICE_REGISTRATION_TYPE, LoginType
1818
from synapse.api.errors import Codes, HttpResponseException, SynapseError
1919
from synapse.appservice import ApplicationService
20-
from synapse.rest.client import register, sync
20+
from synapse.rest.client import login, profile, register, sync
2121

2222
from tests import unittest
2323
from tests.unittest import override_config
@@ -26,7 +26,13 @@
2626

2727
class TestMauLimit(unittest.HomeserverTestCase):
2828

29-
servlets = [register.register_servlets, sync.register_servlets]
29+
servlets = [
30+
register.register_servlets,
31+
sync.register_servlets,
32+
synapse.rest.admin.register_servlets_for_client_rest_resource,
33+
profile.register_servlets,
34+
login.register_servlets,
35+
]
3036

3137
def default_config(self):
3238
config = default_config("test")
@@ -229,6 +235,31 @@ def test_tracked_but_not_limited(self):
229235
self.reactor.advance(100)
230236
self.assertEqual(2, self.successResultOf(count))
231237

238+
def test_deactivated_users_dont_count_towards_mau(self):
239+
user1 = self.register_user("madonna", "password")
240+
self.register_user("prince", "password2")
241+
self.register_user("frodo", "onering", True)
242+
243+
token1 = self.login("madonna", "password")
244+
token2 = self.login("prince", "password2")
245+
admin_token = self.login("frodo", "onering")
246+
247+
self.do_sync_for_user(token1)
248+
self.do_sync_for_user(token2)
249+
250+
# Check that mau count is what we expect
251+
count = self.get_success(self.store.get_monthly_active_count())
252+
self.assertEqual(count, 2)
253+
254+
# Deactivate user1
255+
url = "/_synapse/admin/v1/deactivate/%s" % user1
256+
channel = self.make_request("POST", url, access_token=admin_token)
257+
self.assertIn("success", channel.json_body["id_server_unbind_result"])
258+
259+
# Check that deactivated user is no longer counted
260+
count = self.get_success(self.store.get_monthly_active_count())
261+
self.assertEqual(count, 1)
262+
232263
def create_user(self, localpart, token=None, appservice=False):
233264
request_data = {
234265
"username": localpart,

0 commit comments

Comments
 (0)