#33573: Add native async support to redis cache backend -------------------------------------+------------------------------------- Reporter: Christopher Bailey | Owner: Ahmed | Ibrahim Type: New feature | Status: assigned Component: Core (Cache system) | Version: dev Severity: Normal | Resolution: Keywords: | Triage Stage: | Someday/Maybe Has patch: 0 | Needs documentation: 0 Needs tests: 0 | Patch needs improvement: 0 Easy pickings: 0 | UI/UX: 0 -------------------------------------+------------------------------------- Comment (by amirreza):
hi 🙌🏼 so after a good amount of time to investigate things, i'm back to talk more on the subject in this commecnt i'll try to share what an async client would look like in django, and leave it to you to decide if this is desired or not == so the first problem that needs solving is the [https://github.com/django/django/blob/main/django/core/cache/__init__.py#L61-L64) cleaup] discussed in #36047 since this is a signal receiver and signal receiver can be [https://docs.djangoproject.com/en/5.1/topics/signals/#receiver-functions async] since django 5, i can see this fixed like this: 1. add a `is_async` attribute to cache clients, similar to [https://github.com/django/django/blob/main/django/utils/deprecation.py#L87-L88 middlewares] 2. change the receiver to be async, like this: {{{ async def close_caches(**kwargs): # Some caches need to do a cleanup at the end of a request cycle. If not # implemented in a particular backend cache.close() is a no-op. await caches.close_all() }}} where `close_all()` is as follows: {{{ async def close_all(self): for conn in self.all(initialized_only=True): if conn.is_async: await conn.aclose() else: conn.close() }}} == second matter in hand is how to design the async cache backend i personally suggest that async backend should be in a different class, i hope by the end of this comment you'd agree too so i would do something like this: 1. a base class with common functionality 2. two (less)base classes for sync and async functionality 3. two redis backends for sync and async async methods would have `a` prefixed to their name (even tho there are no sync equivelents) for two reason: 1. to be compatible with rest of django 2. so if someone wants (for whatever reason), they can combine the two class and have a backend that supports both tho if you allow me to be naughty a bit🫣, i'll define a `__getattr__` that only works in the async backend and allows people to access methods without the `a` i've planned a similar thing with [https://github.com/amirreza8002/django- valkey/blob/commands/django_valkey/base.py#L342-L349 django-valkey] so both `await cache.aset()` and `await cache.set()` work == some things to have in mind: ❕the following problems are not essential part of this ticket, an async cache backend can exists without these even a 3rd-party can handle these issues, i'm only mentioning for refrence 1. cache middlewares do not accept an async only cache backend to solve this we either have to combine the two backends (as discussed above) (in this case the async methods won't even be called, it just doesn't break), or have new middlewares that support async (i like this one, but i guess others don't) 2. if we decide to make an async middleware, [https://github.com/django/django/blob/main/django/utils/decorators.py#L124 make_middleware_decorator] might not be very happy, since it expects sync methods, which don't make sense in an async middleware i have made an async only option in a [https://github.com/django-utils /django-async- extensions/blob/main/django_async_extensions/utils/decorators.py#L31 3rd- party] before 3. again if we move for an async middleware, [https://github.com/django/django/blob/main/django/views/decorators/cache.py#L10, cache_page] decorator won't work, needs another one 4. these two caching utils expect a sync backend [https://github.com/django/django/blob/main/django/utils/cache.py#L377] and [https://github.com/django/django/blob/main/django/utils/cache.py#L399] 5. if cache server is used for sessions, the session middleware doesn't support async operations the solutions mentionedfor cache middleware also applies here i hope this can give some calrity on how this would work as before, i can implement this, if this is a feature that people want, and if not, well at least this can be used as refrence for other people with best of wishes♥️ -- Ticket URL: <https://code.djangoproject.com/ticket/33573#comment:19> Django <https://code.djangoproject.com/> The Web framework for perfectionists with deadlines. -- You received this message because you are subscribed to the Google Groups "Django updates" group. To unsubscribe from this group and stop receiving emails from it, send an email to django-updates+unsubscr...@googlegroups.com. To view this discussion visit https://groups.google.com/d/msgid/django-updates/010701961318afdc-9cd825b1-349c-4c4a-898d-f28c3158066d-000000%40eu-central-1.amazonses.com.