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

Initial impl of capping MAU #3630

Merged
merged 19 commits into from
Aug 1, 2018
Merged

Conversation

neilisfragile
Copy link
Contributor

@neilisfragile neilisfragile commented Jul 31, 2018

Tracks Mau naiving by count(*) on user_ips.
Blocks registration and sign in if value exceeded
Publishes metrics for consumption by Prometheus

The idea here is to cap the monthly active users (MAU) on a server. This is an initial cut that simply stops registration and login for if MAU is above configured threshold - @erikjohnston

log in.
"""
if self.hs.config.limit_usage_by_mau is True:
current_mau = self.store.count_monthly_users()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method will be hit very often. So you might want to either add some cache on store.count_monthly_users() or use a value which might be generated by generate_monthly_active_users

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agreed though deliberately omitted since count_monthly_users() is really only a stepping stone method to get the rest of the infra out. In current form only called regularly in the case where the config is enabled.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok. If that is on your radar I am fine with it for now

@@ -531,3 +533,15 @@ def _join_user_to_room(self, requester, room_identifier):
remote_room_hosts=remote_room_hosts,
action="join",
)

def _check_mau_limits(self):
Copy link
Contributor

@krombel krombel Jul 31, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you might want to deduplicate this somehow

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as above, and also the calculating the total count is duped with the daily count - but likley to change structure

@erikjohnston erikjohnston changed the title Neilj/mau sign in log in limits Initial impl of capping MAU Jul 31, 2018
max_mau_value_gauge = Gauge("synapse_admin_max_mau_value", "MAU Limit")
limit_usage_by_mau_gauge = Gauge(
"synapse_admin_limit_usage_by_mau", "MAU Limiting enabled"
)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would probably not bother having limit_usage_by_mau_gauge, and simply set it to 0 or null if limit isn't enabled

limit_usage_by_mau_gauge.set(float(hs.config.limit_usage_by_mau))

generate_monthly_active_users()
clock.looping_call(generate_monthly_active_users, 5 * 60 * 1000)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it make sense for this to be done if hs.config.limit_usage_by_mau is false?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

right yes, need to be called once but the looping is a waste

count, = txn.fetchone()
return count
finally:
txn.close()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should either accept a txn argument or use runInteraction, otherwise its going to be too easy to call this on the main thread (which is bad as this method blocks)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was originally trying to keep things simple without deferring - will make the change

def generate_monthly_active_users():
count = 0
if hs.config.limit_usage_by_mau:
count = hs.get_datastore().count_monthly_users()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

count_monthly_users will need to be asynchronous and return a deferred, which we'll need to yield

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agreed as above

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This still needs a yield

@neilisfragile
Copy link
Contributor Author

review items implemented

This was referenced Aug 1, 2018
Copy link
Member

@erikjohnston erikjohnston left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just needs to have the yield added, and then its good to go

@@ -0,0 +1 @@
Blocks registration and sign in if max mau value exceeded
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, can we quickly change this to "Add ability to limit number of monthly active users on the server", or some such. Otherwise its going to be confusing for people to read the changelog who haven't had the full context.

def generate_monthly_active_users():
count = 0
if hs.config.limit_usage_by_mau:
count = hs.get_datastore().count_monthly_users()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This still needs a yield

This method should be refactored with count_daily_users - the only
reason not to is waiting on definition of mau
returns:
defered: resolves to int
Copy link
Member

@erikjohnston erikjohnston Aug 1, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW, we generally start the docstring on the sameline of the quotes, so something like:

"""Counts the number of users who used this homeserver in the last 30 days.

This method should be refactored with count_daily_users - the only
reason not to is waiting on definition of MAU.

Returns:
    Deferred[int]
"""

And that's also how you annotate return types (such that IDEs correctly interpret it)

@neilisfragile neilisfragile merged commit 085435e into develop Aug 1, 2018
@neilisfragile neilisfragile deleted the neilj/mau_sign_in_log_in_limits branch August 1, 2018 15:58
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants