3

I have one DB query that takes a couple of seconds in production. I have also a DRF ViewSet action that returns this query.

I'm already caching this action using cache_page.

@method_decorator(cache_page(settings.DEFAULT_CACHE_TIMEOUT))
@action(detail=False)
def home(self, request) -> Response:
    articles = Article.objects.home()
    return Response(serializers.ArticleListSerializer(articles, many=True).data,
                    headers={'Access-Control-Allow-Origin': '*'})

The problem is that after 15 minutes, at least one user needs to wait 15 seconds for the response. I want to pre-cache this every 5 minutes in background so that no user will need to wait.

I use the default caching mechanism.

My idea is to create a management command that will be executed using crontab. Every 5 minutes it will call the Article.objects.home() or the ViewSet.action and change it's value in the cache.

As this is only one entry, I don't hesitate to use database caching.

How would you do that?

EDIT: as the default LocMemCache is single-threaded, I'll go with the database caching. I just don't know how to manually cache the view or QuerySet.

Milano
  • 18,048
  • 37
  • 153
  • 353

1 Answers1

0

A cron or Celery beat task (if you already use celery) looks like the best option.

Calling Article.objects.home() would not do much unless you cache in home() method of the manager (which could be a valid option that could simplify automated cache refresh).

To automate the refresh of view cache you better send actual requests to the URL from the management command. You will also want to invalidate the cache before sending the request, in order to update it.

Also, keep in mind the cache timeout when planning the job frequency. You wouldn't want to refresh too early nor too late.

4140tm
  • 2,070
  • 14
  • 17