From 97d1e4164bf5526c3b63570d27c8377b4dfcac46 Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Wed, 13 Oct 2010 18:11:28 -0500 Subject: Connect post_save signals where they will always be triggered We need to do this in the models.py files, otherwise the post_save signal might not be connected right away on launch of the application. Move them over there, add a dispatch_uid so it only gets hooked up once, and do some other function moving around so we don't have circular imports. Signed-off-by: Dan McGee --- feeds.py | 25 ++----------------------- main/models.py | 6 ++++++ main/utils.py | 24 +++++++++++++++++++++++- news/models.py | 6 ++++++ 4 files changed, 37 insertions(+), 24 deletions(-) diff --git a/feeds.py b/feeds.py index 9d1418b..e7462bc 100644 --- a/feeds.py +++ b/feeds.py @@ -4,19 +4,14 @@ from decimal import Decimal, ROUND_HALF_DOWN from django.contrib.syndication.views import Feed from django.core.cache import cache from django.db.models import Q -from django.db.models.signals import post_save from django.utils.hashcompat import md5_constructor from django.views.decorators.http import condition from main.models import Arch, Repo, Package +from main.utils import CACHE_TIMEOUT, INVALIDATE_TIMEOUT +from main.utils import CACHE_PACKAGE_KEY, CACHE_NEWS_KEY from news.models import News -CACHE_TIMEOUT = 1800 -INVALIDATE_TIMEOUT = 15 - -CACHE_PACKAGE_KEY = 'cache_package_latest' -CACHE_NEWS_KEY = 'cache_news_latest' - def utc_offset(): '''Calculate the UTC offset from local time. Useful for converting values stored in local time to things like cache last modifed headers.''' @@ -47,14 +42,6 @@ def retrieve_package_latest(): pass return None -def refresh_package_latest(**kwargs): - # We could delete the value, but that could open a race condition - # where the new data wouldn't have been committed yet by the calling - # thread. Instead, explicitly set it to None for a short amount of time. - # Hopefully by the time it expires we will have committed, and the cache - # will be valid again. See "Scaling Django" by Mike Malone, slide 30. - cache.set(CACHE_PACKAGE_KEY, None, INVALIDATE_TIMEOUT) - def package_etag(request, *args, **kwargs): latest = retrieve_package_latest() if latest: @@ -134,10 +121,6 @@ def retrieve_news_latest(): pass return None -def refresh_news_latest(**kwargs): - # same thoughts apply as in refresh_package_latest - cache.set(CACHE_NEWS_KEY, None, INVALIDATE_TIMEOUT) - def news_etag(request, *args, **kwargs): latest = retrieve_news_latest() if latest: @@ -168,8 +151,4 @@ class NewsFeed(Feed): def item_author_name(self, item): return item.author.get_full_name() -# connect signals needed to keep cache in line with reality -post_save.connect(refresh_package_latest, sender=Package) -post_save.connect(refresh_news_latest, sender=News) - # vim: set ts=4 sw=4 et: diff --git a/main/models.py b/main/models.py index dc700fb..888f0b8 100644 --- a/main/models.py +++ b/main/models.py @@ -325,4 +325,10 @@ class TodolistPkg(models.Model): db_table = 'todolist_pkgs' unique_together = (('list','pkg'),) +# connect signals needed to keep cache in line with reality +from main.utils import refresh_package_latest +from django.db.models.signals import post_save +post_save.connect(refresh_package_latest, sender=Package, + dispatch_uid="main.models") + # vim: set ts=4 sw=4 et: diff --git a/main/utils.py b/main/utils.py index ae446ab..d7681cb 100644 --- a/main/utils.py +++ b/main/utils.py @@ -5,6 +5,12 @@ except ImportError: from django.core.cache import cache from django.utils.hashcompat import md5_constructor +CACHE_TIMEOUT = 1800 +INVALIDATE_TIMEOUT = 15 + +CACHE_PACKAGE_KEY = 'cache_package_latest' +CACHE_NEWS_KEY = 'cache_news_latest' + def cache_function_key(func, args, kwargs): raw = [func.__name__, func.__module__, args, kwargs] pickled = pickle.dumps(raw, protocol=pickle.HIGHEST_PROTOCOL) @@ -40,7 +46,23 @@ def clear_cache_function(func, args, kwargs): key = cache_function_key(func, args, kwargs) cache.delete(key) -#utility to make a pair of django choices +# utility to make a pair of django choices make_choice = lambda l: [(str(m), str(m)) for m in l] +# These are in here because we would be jumping around in some import circles +# and hoops otherwise. The only thing currently using these keys is the feed +# caching stuff. + +def refresh_package_latest(**kwargs): + # We could delete the value, but that could open a race condition + # where the new data wouldn't have been committed yet by the calling + # thread. Instead, explicitly set it to None for a short amount of time. + # Hopefully by the time it expires we will have committed, and the cache + # will be valid again. See "Scaling Django" by Mike Malone, slide 30. + cache.set(CACHE_PACKAGE_KEY, None, INVALIDATE_TIMEOUT) + +def refresh_news_latest(**kwargs): + # same thoughts apply as in refresh_package_latest + cache.set(CACHE_NEWS_KEY, None, INVALIDATE_TIMEOUT) + # vim: set ts=4 sw=4 et: diff --git a/news/models.py b/news/models.py index 6c8a703..e2486c9 100644 --- a/news/models.py +++ b/news/models.py @@ -23,4 +23,10 @@ class News(models.Model): get_latest_by = 'postdate' ordering = ['-postdate'] +# connect signals needed to keep cache in line with reality +from main.utils import refresh_news_latest +from django.db.models.signals import post_save +post_save.connect(refresh_news_latest, sender=News, + dispatch_uid="news.models") + # vim: set ts=4 sw=4 et: -- cgit v1.2.3-24-g4f1b