Skip to main content

A function wrapper that helps with caching techniques which have been battle-tested with millions of users. 2 main features are as following:

  1. Utilizing redis locks to limit cache recalculation to a single thread

  2. Allow serving somewhat stale data to keep the server going

To understand the design decisions you can read the following blog posts where I justify the need for these cases.

https://eralpbayraktar.com/blog/django/2020/caching-with-django

https://eralpbayraktar.com/blog/django/2020/caching-with-django-part-II

1) Cache calculation mutex

If you have a cold cache and 1000 requests hit the endpoint, you don’t want all your gunicorn workers to calculate this exact same function. With this functionality, 1 worker will calculate and the other 999 have basically 2 options. They can either error out and release worker resources, which is healthy for the remaining endpoints, or they can serve somewhat old value if it’s available. This brings us to the next point.

2) Allow serving kind of old data

This is not ideal but sometimes it’s better to serve old cache values instead of erroring out or block all your workers. With django-function-caching you can set 2 timeout values for a given function. One is the grand timeout, that’s nothing new, after this many seconds the cache will be invalidated, and the other is freshness_timeout. This is the interesting one. One example is setting the timeout to 24 hours and freshness_timeout to 1 hour. This means workers will try to serve a cache value fresher than 1 hour, but if they cannot, then they are allowed to serve a value that’s maximum 24 hours old. This flexibility or relaxation gives us the chance to keep the server healthy. You can set the maximum even to 1 month, in ideal conditions freshness_timeout should decide the behavior. timeout is only used in extreme cases, and you should be glad when it’s used because that means it has saved you from something worse or catastrophic. If only 1 request comes and the cache value is older than freshness_timeout that worker will recalculate and update the cache.

Getting It

$ pip install django-function-caching

Settings

django-function-caching will use “default” cache backend and it should be redis. Check out how to setup django-redis (our dependency)

Usage

from functioncaching import cached_function

@cached_function(timeout=24*60*60, freshness_timeout=60*60)
def _get_top_book_ids(self):
    time.sleep(5)  # make the calculation slower for the sake of argument
    return list(Book.objects.order_by('-purchase_count').values_list('id', flat=True)[:10])

# or

@cached_function(timeout=24*60*60, freshness_timeout=60*60, prefix='Author')
def _get_top_book_ids(self):
    time.sleep(5)  # make the calculation slower for the sake of argument
    return list(Book.objects.order_by('-purchase_count').values_list('id', flat=True)[:10])

“prefix” is used to prefix the cache key.

How is the cache key calculated?

The cache_key is calculated based on the function name + string representation of all the arguments and keyword arguments. This means if you pass classes/complex objects to the function, it might not behave correctly. So I’d advise you to pass simple parameters (like making functions class methods or static methods and passing object IDs, instead of using self), the same idea when you schedule celery tasks, the simpler the parameters the better, and no unnecessary parameters since they will create additional cache keys. Because the library cannot know if they change the behavior or not. Prefix is good when you have the same function names in multiple places/classes/modules, it is optional.

Things to keep in mind

AttributeError: ‘LocMemCache’ object has no attribute ‘ttl’

This means your default cache is not redis, check django-redis installation and configurations.

I’m getting ColdCacheException

Good! The library saved you from worker clogging. This means multiple requests came to the endpoint yet you don’t even have an old/stale cache value in your cache database to serve as a back-up. Increase your timeout parameter to protect against this.

Release files for django-function-caching 0.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for django-function-caching 0.2
File Size Uploaded
django-function-caching-0.2.tar.gz 3.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for django-function-caching 0.2
File Interpreter ABI Platform
django_function_caching-0.2-py3-none-any.whl Python 3 none any Details

Total release size: 10.5 kB

Release files / django-function-caching-0.2.tar.gz

Download URL django-function-caching-0.2.tar.gz
Size 3.9 kB
Tags Source
SHA-256 checksum
How to use checksums
1e0157d1643b5dee7dc841ca7ef046488d789ee50eba86334f1f82b3534a2aa0
BLAKE2b-256 checksum
How to use checksums
c00a9d7121750fad8692afce2f18f09352e92605ee20d89d6e8a43eda3e6c17c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/1.12.1 pkginfo/1.5.0.1 requests/2.20.0 setuptools/41.0.1 requests-toolbelt/0.8.0 tqdm/4.29.1 CPython/3.7.4

Release files / django_function_caching-0.2-py3-none-any.whl

Download URL django_function_caching-0.2-py3-none-any.whl
Size 6.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
073319a297307b85f497518403f56adf461bbfd0831d9f004efd46a05a90c3e7
BLAKE2b-256 checksum
How to use checksums
58de21ae37645b948e1a351e553f203cce9a5b4deef4be4a8d9cb615c550d41a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/1.12.1 pkginfo/1.5.0.1 requests/2.20.0 setuptools/41.0.1 requests-toolbelt/0.8.0 tqdm/4.29.1 CPython/3.7.4

Release history Release notifications | RSS feed

This release

0.2 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page