Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature add simple family cache management #152

Open
wants to merge 16 commits into
base: develop
Choose a base branch
from

Conversation

mngoe
Copy link

@mngoe mngoe commented Oct 21, 2024

Add simple Family cache management as a start for GraphQL cache test.

Not so much performance impact at this stage, but I can imagine that each database request removed is an improvement.

We will still have few changes to implement :

  • Delete Cache value on FHIR family mutation
  • Manage cache version to manage field requests (if family detail requested field change from one request to another this implementation will not work).

@mngoe mngoe changed the title Feature add simple cache management Feature add simple family cache management Oct 21, 2024
@delcroip
Copy link
Member

here perplexity answer regarding additionnal sub fields:

Yes, you can cache a Django object along with its first level of related resources. Here's how you can implement this:

Caching Strategy

To cache a Django object with its first level of related resources, you can use Django's low-level cache API. This approach allows you to cache the main object and its related objects together.

Implementation

  1. Create a custom caching function:
from django.core.cache import cache
from django.db import models

def cache_object_with_relations(obj, timeout=3600):
    key = f"{obj._meta.model_name}:{obj.pk}"
    cached_data = {
        'main': obj,
        'relations': {}
    }

    for field in obj._meta.get_fields():
        if isinstance(field, models.ForeignKey) or isinstance(field, models.OneToOneField):
            related_obj = getattr(obj, field.name)
            if related_obj:
                cached_data['relations'][field.name] = related_obj
        elif isinstance(field, models.ManyToManyField):
            related_objs = getattr(obj, field.name).all()
            cached_data['relations'][field.name] = list(related_objs)

    cache.set(key, cached_data, timeout)
    return cached_data
  1. Use the caching function:
def get_cached_object_with_relations(model, pk):
    key = f"{model._meta.model_name}:{pk}"
    cached_data = cache.get(key)

    if cached_data is None:
        try:
            obj = model.objects.get(pk=pk)
            cached_data = cache_object_with_relations(obj)
        except model.DoesNotExist:
            return None

    return cached_data
  1. Implement in your views or services:
def my_view(request, object_id):
    cached_data = get_cached_object_with_relations(MyModelA, object_id)
    if cached_data:
        my_model_a = cached_data['main']
        related_b = cached_data['relations'].get('model_b')
        # Use my_model_a and related_b as needed
    else:
        # Handle case when object is not found
    # Rest of your view logic

Key Points

  • This approach caches the main object and its first-level related objects together[4][7].
  • The cache key is constructed using the model name and primary key[4].
  • Related objects are stored in a separate 'relations' dictionary within the cached data[4].
  • This method works for ForeignKey, OneToOneField, and ManyToManyField relationships[4].
  • The cache timeout is set to 1 hour (3600 seconds) by default, but you can adjust this as needed[4].

Considerations

  • Cache Invalidation: Implement a method to invalidate the cache when objects are updated or deleted[4].
  • Performance: This approach may increase memory usage but can significantly reduce database queries[4][7].
  • Consistency: Ensure that your cache invalidation strategy keeps the cached data consistent with the database[4].

By using this caching strategy, you can efficiently cache Django objects along with their first-level related resources, potentially improving your application's performance by reducing database queries[4][7].

Citations:
[1] https://docs.djangoproject.com/en/5.1/topics/cache/
[2] https://www.honeybadger.io/blog/caching-in-django/
[3] https://buildwithstudio.com/knowledge/a-deepdive-on-caching-strategies-using-django-rest-framework/
[4] https://testdriven.io/blog/django-caching/
[5] https://dev.to/pragativerma18/django-caching-101-understanding-the-basics-and-beyond-49p
[6] https://blog.sentry.io/django-performance-improvements-part-4-caching-in-django-applications/
[7] https://stackoverflow.com/questions/73531279/caching-at-queryset-level-in-django
[8] https://forum.djangoproject.com/t/help-with-caching-related-objects/32266

@delcroip
Copy link
Member

delcroip commented Jan 8, 2025

to be rework to use the named cache instead

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants