Skip to content

Commit

Permalink
Cache more wisely
Browse files Browse the repository at this point in the history
This doesn't actually matter since the data being saved in redis is very
small, but this change caches more wisely. Previously each key+domain
combo would have a cached key, even though in most cases, a domain will
not have a unique value from the global value. This change only stores a
key+domain value in cache when necessary.
  • Loading branch information
gherceg committed Feb 19, 2025
1 parent 6221041 commit de45dc7
Showing 1 changed file with 26 additions and 11 deletions.
37 changes: 26 additions & 11 deletions corehq/project_limits/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,23 +103,38 @@ def __str__(self):

def save(self, *args, **kwargs):
super().save(*args, **kwargs)
self.for_key.clear(self.__class__, self.key, self.domain)
self._get_global_limit.clear(self.__class__, self.key)
self._get_domain_specific_limit.clear(self.__class__, self.key, self.domain)

def delete(self, *args, **kwargs):
super().delete(*args, **kwargs)
self.for_key.clear(self.__class__, self.key, self.domain)
self._get_global_limit.clear(self.__class__, self.key)
self._get_domain_specific_limit.clear(self.__class__, self.key, self.domain)

@classmethod
@quickcache(
['key', 'domain'], timeout=7 * 24 * 60 * 60, skip_arg=lambda *args, **kwargs: settings.UNIT_TESTING
)
def for_key(cls, key, domain=''):
"""
Return the value associated with the given key, prioritizing the domain specific entry over the general one
The timeout is long because this is a small table that is effectively storing key/value pairs in redis
"""
domain_filter = models.Q(domain="")
if domain:
domain_filter |= models.Q(domain=domain)
filters = models.Q(key=key) & domain_filter
return SystemLimit.objects.filter(filters).order_by("-domain").values_list("limit", flat=True).first()
domain_limit = cls._get_domain_specific_limit(key, domain) if domain else None
if domain_limit is not None:
return domain_limit
return cls._get_global_limit(key)

@classmethod
@quickcache(['key'], timeout=7 * 24 * 60 * 60, skip_arg=lambda *args, **kwargs: settings.UNIT_TESTING)
def _get_global_limit(cls, key):
try:
return SystemLimit.objects.get(key=key, domain='').limit
except SystemLimit.DoesNotExist:
return None

@classmethod
@quickcache(
['key', 'domain'], timeout=7 * 24 * 60 * 60, skip_arg=lambda *args, **kwargs: settings.UNIT_TESTING
)
def _get_domain_specific_limit(cls, key, domain):
try:
return SystemLimit.objects.get(key=key, domain=domain).limit
except SystemLimit.DoesNotExist:
return None

0 comments on commit de45dc7

Please sign in to comment.