realms: Add caching to the get_seat_count calculation for upload limit.

For simiplicty's sake, we can avoid trying to do cache invalidation in
the variety of events that can cause the seat count to change - since
having an up to 1 day delay between users being added and the upload
limit going up is quite reasonable.
This commit is contained in:
Mateusz Mandera 2024-04-14 00:25:05 +02:00 committed by Tim Abbott
parent 066de96a86
commit 4a2a9176c2
3 changed files with 15 additions and 2 deletions

View File

@ -52,6 +52,7 @@ from corporate.models import (
get_customer_by_remote_realm,
get_customer_by_remote_server,
)
from zerver.lib.cache import cache_with_key, get_realm_seat_count_cache_key
from zerver.lib.exceptions import JsonableError
from zerver.lib.logging_util import log_to_file
from zerver.lib.send_email import (
@ -155,6 +156,14 @@ def get_latest_seat_count(realm: Realm) -> int:
return get_seat_count(realm, extra_non_guests_count=0, extra_guests_count=0)
@cache_with_key(lambda realm: get_realm_seat_count_cache_key(realm.id), timeout=3600 * 24)
def get_cached_seat_count(realm: Realm) -> int:
# This is a cache value we're intentionally okay with not invalidating.
# All that means is that this value will lag up to 24 hours before getting updated.
# We use this for calculating the uploaded files storage limit for paid Cloud organizations.
return get_latest_seat_count(realm)
def get_seat_count(
realm: Realm, extra_non_guests_count: int = 0, extra_guests_count: int = 0
) -> int:

View File

@ -486,6 +486,10 @@ def get_realm_used_upload_space_cache_key(realm_id: int) -> str:
return f"realm_used_upload_space:{realm_id}"
def get_realm_seat_count_cache_key(realm_id: int) -> str:
return f"realm_seat_count:{realm_id}"
def active_user_ids_cache_key(realm_id: int) -> str:
return f"active_user_ids:{realm_id}"

View File

@ -847,11 +847,11 @@ class Realm(models.Model): # type: ignore[django-manager-missing] # django-stub
elif plan_type == Realm.PLAN_TYPE_STANDARD_FREE:
return Realm.UPLOAD_QUOTA_STANDARD_FREE
elif plan_type in [Realm.PLAN_TYPE_STANDARD, Realm.PLAN_TYPE_PLUS]:
from corporate.lib.stripe import get_seat_count
from corporate.lib.stripe import get_cached_seat_count
# Paying customers with few users should get a reasonable minimum quota.
return max(
get_seat_count(self) * settings.UPLOAD_QUOTA_PER_USER_GB,
get_cached_seat_count(self) * settings.UPLOAD_QUOTA_PER_USER_GB,
Realm.UPLOAD_QUOTA_STANDARD_FREE,
)
else: