summaryrefslogtreecommitdiff
path: root/ishtar_common
diff options
context:
space:
mode:
authorÉtienne Loks <etienne.loks@iggdrasil.net>2016-09-23 12:27:43 +0200
committerÉtienne Loks <etienne.loks@iggdrasil.net>2016-09-23 12:27:43 +0200
commit3a6cc667c42d540fbab83179d82b14679967e5db (patch)
tree8736f0005a4a2c89d8b8a818a73adc310bb1ea55 /ishtar_common
parent693762168a5fdb2a44778079c57e9e6de7a384bf (diff)
downloadIshtar-3a6cc667c42d540fbab83179d82b14679967e5db.tar.bz2
Ishtar-3a6cc667c42d540fbab83179d82b14679967e5db.zip
Cache: manage long keys - immediatly refresh cache after types modifications
Diffstat (limited to 'ishtar_common')
-rw-r--r--ishtar_common/models.py64
-rw-r--r--ishtar_common/tests.py16
-rw-r--r--ishtar_common/utils.py8
3 files changed, 77 insertions, 11 deletions
diff --git a/ishtar_common/models.py b/ishtar_common/models.py
index 932beaf98..95d995a91 100644
--- a/ishtar_common/models.py
+++ b/ishtar_common/models.py
@@ -260,8 +260,33 @@ class Cached(object):
slug_field = 'txt_idx'
@classmethod
+ def refresh_cache(cls):
+ cache_ckey, current_keys = get_cache(cls, ['_current_keys'])
+ if not current_keys:
+ return
+ for keys in current_keys:
+ if len(keys) == 2 and keys[0] == '__slug':
+ cls.get_cache(keys[1], force=True)
+ if len(keys) >= 2 and keys[0] == '__get_types':
+ default = keys.pop()
+ empty_first = bool(keys.pop())
+ exclude = keys[1:]
+ cls.get_types(
+ exclude=exclude, empty_first=empty_first, default=default,
+ force=True)
+
+ @classmethod
+ def _add_cache_key_to_refresh(cls, keys):
+ cache_ckey, current_keys = get_cache(cls, ['_current_keys'])
+ if type(current_keys) != list:
+ current_keys = []
+ if keys not in current_keys:
+ current_keys.append(keys)
+ cache.set(cache_ckey, current_keys, settings.CACHE_TIMEOUT)
+
+ @classmethod
def get_cache(cls, slug, force=False):
- cache_key, value = get_cache(cls, slug)
+ cache_key, value = get_cache(cls, ['__slug', slug])
if not force and value:
return value
try:
@@ -270,12 +295,12 @@ class Cached(object):
cache.set(cache_key, obj, settings.CACHE_TIMEOUT)
return obj
except cls.DoesNotExist:
+ cache.set(cache_key, None, settings.CACHE_TIMEOUT)
return None
- def save(self, *args, **kwargs):
- ret = super(Cached, self).save(*args, **kwargs)
- self.get_cache(getattr(self, self.slug_field), force=True)
- return ret
+
+def post_save_cache(sender, **kwargs):
+ sender.refresh_cache()
class GeneralType(Cached, models.Model):
@@ -351,9 +376,9 @@ class GeneralType(Cached, models.Model):
@classmethod
def get_types(cls, dct={}, instances=False, exclude=[], empty_first=True,
- default=None, initial=None):
+ default=None, initial=None, force=False):
types = cls._pre_get_types(dct, instances, exclude, empty_first,
- default)
+ default, force)
if not initial:
return types
new_vals = cls._get_initial_types(initial, [idx for idx, lbl in types])
@@ -362,14 +387,15 @@ class GeneralType(Cached, models.Model):
@classmethod
def _pre_get_types(cls, dct={}, instances=False, exclude=[],
- empty_first=True, default=None):
+ empty_first=True, default=None, force=False):
# cache
cache_key = None
if not instances:
- keys = [u"{}".format(ex) for ex in exclude] + [
+ keys = ['__get_types']
+ keys += [u"{}".format(ex) for ex in exclude] + [
empty_first and 'empty_first' or ''] + [u"{}".format(default)]
cache_key, value = get_cache(cls, keys)
- if value:
+ if value and not force:
return value
base_dct = dct.copy()
if hasattr(cls, 'parent'):
@@ -405,7 +431,7 @@ class GeneralType(Cached, models.Model):
except cls.DoesNotExist:
pass
items = cls.objects.filter(**dct)
- if default:
+ if default and default != "None":
exclude.append(default.txt_idx)
if exclude:
items = items.exclude(txt_idx__in=exclude)
@@ -1499,6 +1525,8 @@ class OrganizationType(GeneralType):
verbose_name = _(u"Organization type")
verbose_name_plural = _(u"Organization types")
ordering = ('label',)
+post_save.connect(post_save_cache, sender=OrganizationType)
+post_delete.connect(post_save_cache, sender=OrganizationType)
IMPORTER_CLASSES = {}
@@ -2279,6 +2307,8 @@ class PersonType(GeneralType):
verbose_name = _(u"Person type")
verbose_name_plural = _(u"Person types")
ordering = ('label',)
+post_save.connect(post_save_cache, sender=PersonType)
+post_delete.connect(post_save_cache, sender=PersonType)
class TitleType(GeneralType):
@@ -2286,6 +2316,8 @@ class TitleType(GeneralType):
verbose_name = _(u"Title type")
verbose_name_plural = _(u"Title types")
ordering = ('label',)
+post_save.connect(post_save_cache, sender=TitleType)
+post_delete.connect(post_save_cache, sender=TitleType)
class Person(Address, Merge, OwnPerms, ValueGetter):
@@ -2547,6 +2579,8 @@ class AuthorType(GeneralType):
class Meta:
verbose_name = _(u"Author type")
verbose_name_plural = _(u"Author types")
+post_save.connect(post_save_cache, sender=AuthorType)
+post_delete.connect(post_save_cache, sender=AuthorType)
class Author(models.Model):
@@ -2577,18 +2611,24 @@ class SourceType(GeneralType):
class Meta:
verbose_name = _(u"Source type")
verbose_name_plural = _(u"Source types")
+post_save.connect(post_save_cache, sender=SourceType)
+post_delete.connect(post_save_cache, sender=SourceType)
class SupportType(GeneralType):
class Meta:
verbose_name = _(u"Support type")
verbose_name_plural = _(u"Support types")
+post_save.connect(post_save_cache, sender=SupportType)
+post_delete.connect(post_save_cache, sender=SupportType)
class Format(GeneralType):
class Meta:
verbose_name = _(u"Format")
verbose_name_plural = _(u"Formats")
+post_save.connect(post_save_cache, sender=Format)
+post_delete.connect(post_save_cache, sender=Format)
class Source(ImageModel, models.Model):
@@ -2737,3 +2777,5 @@ class OperationType(GeneralType):
if not key:
return op_type.preventive
return key == op_type.txt_idx
+post_save.connect(post_save_cache, sender=OperationType)
+post_delete.connect(post_save_cache, sender=OperationType)
diff --git a/ishtar_common/tests.py b/ishtar_common/tests.py
index 8c918b5a9..0c4bbda08 100644
--- a/ishtar_common/tests.py
+++ b/ishtar_common/tests.py
@@ -143,6 +143,7 @@ class WizardTest(object):
class CacheTest(TestCase):
def testAdd(self):
+ models.OrganizationType.refresh_cache()
cached = models.OrganizationType.get_cache('test')
self.assertEqual(cached, None)
orga = models.OrganizationType.objects.create(
@@ -154,6 +155,21 @@ class CacheTest(TestCase):
cached = models.OrganizationType.get_cache('testy')
self.assertEqual(cached.pk, orga.pk)
+ def testList(self):
+ models.OrganizationType.refresh_cache()
+ types = models.OrganizationType.get_types()
+ # only empty
+ self.assertTrue(len(types), 1)
+ org = models.OrganizationType.objects.create(
+ txt_idx='test', label='testy')
+ types = [
+ unicode(lbl) for idx, lbl in models.OrganizationType.get_types()]
+ self.assertTrue('testy' in types)
+ org.delete()
+ types = [
+ unicode(lbl) for idx, lbl in models.OrganizationType.get_types()]
+ self.assertFalse('testy' in types)
+
class MergeTest(TestCase):
def setUp(self):
diff --git a/ishtar_common/utils.py b/ishtar_common/utils.py
index ca9193204..60c3ac7ef 100644
--- a/ishtar_common/utils.py
+++ b/ishtar_common/utils.py
@@ -17,6 +17,7 @@
# See the file COPYING for details.
+import hashlib
import random
from django.conf import settings
@@ -41,6 +42,13 @@ def get_cache(cls, extra_args=[]):
else:
cache_key += '-' + unicode(arg)
cache_key = slugify(cache_key)
+ if not cache_key.endswith('_current_keys') \
+ and hasattr(cls, '_add_cache_key_to_refresh'):
+ cls._add_cache_key_to_refresh(extra_args)
+ if len(cache_key) >= 250:
+ m = hashlib.md5()
+ m.update(cache_key)
+ cache_key = m.hexdigest()
return cache_key, cache.get(cache_key)