Make use of caching

This commit is contained in:
Raphael Michel
2014-10-07 00:41:41 +02:00
parent 73e49e6423
commit e1decb0dea
4 changed files with 84 additions and 22 deletions

View File

@@ -12,11 +12,14 @@ class EventRelatedCache:
you store data in this cache, it is only stored for this event. The
main purpose of this is to be able to flush all cached data related
to this event at once.
The object is stateless, all state is in the cache, so you can
instantiate it as many times as you want.
"""
def __init__(self, event, cache='default'):
self.cache = caches[cache]
self.prefix = self._build_prefix()
self.event = event
self.prefixkey = 'event:%d' % self.event.pk
def _prefix_key(self, original_key):
@@ -42,7 +45,7 @@ class EventRelatedCache:
prefix = int(time.time())
self.cache.set(self.prefixkey, prefix)
def set(self, key, value, timeout=300):
def set(self, key, value, timeout=3600):
return self.cache.set(self._prefix_key(key), value, timeout)
def get(self, key):
@@ -51,7 +54,7 @@ class EventRelatedCache:
def get_many(self, keys):
return self.cache.get_many([self._prefix_key(key) for key in keys])
def set_many(self, values, timeout=300):
def set_many(self, values, timeout=3600):
newvalues = {}
for i in values.items():
newvalues[self._prefix_key(i[0])] = i[1]

View File

@@ -285,8 +285,9 @@ class Event(models.Model):
return self.name
def save(self, *args, **kwargs):
obj = super().save(*args, **kwargs)
self.get_cache().clear()
return super().save(self, *args, **kwargs)
return obj
def get_date_from_display(self):
return _date(
@@ -364,7 +365,7 @@ class ItemCategory(models.Model):
def save(self, *args, **kwargs):
if self.event:
self.event.get_cache().clear()
return super().save(self, *args, **kwargs)
return super().save(*args, **kwargs)
class Property(models.Model):
@@ -393,7 +394,7 @@ class Property(models.Model):
def save(self, *args, **kwargs):
if self.event:
self.event.get_cache().clear()
return super().save(self, *args, **kwargs)
return super().save(*args, **kwargs)
class PropertyValue(models.Model):
@@ -426,7 +427,7 @@ class PropertyValue(models.Model):
def save(self, *args, **kwargs):
if self.prop:
self.prop.event.get_cache().clear()
return super().save(self, *args, **kwargs)
return super().save(*args, **kwargs)
class Question(models.Model):
@@ -472,7 +473,7 @@ class Question(models.Model):
def save(self, *args, **kwargs):
if self.event:
self.event.get_cache().clear()
return super().save(self, *args, **kwargs)
return super().save(*args, **kwargs)
class Item(models.Model):
@@ -560,7 +561,7 @@ class Item(models.Model):
def save(self, *args, **kwargs):
if self.event:
self.event.get_cache().clear()
return super().save(self, *args, **kwargs)
return super().save(*args, **kwargs)
def delete(self):
self.deleted = True
@@ -647,7 +648,7 @@ class ItemVariation(models.Model):
def save(self, *args, **kwargs):
if self.item:
self.item.event.get_cache().clear()
return super().save(self, *args, **kwargs)
return super().save(*args, **kwargs)
class BaseRestriction(models.Model):
@@ -679,4 +680,4 @@ class BaseRestriction(models.Model):
def save(self, *args, **kwargs):
if self.event:
self.event.get_cache().clear()
return super().save(self, *args, **kwargs)
return super().save(*args, **kwargs)

View File

@@ -11,7 +11,7 @@ def availability_handler(sender, **kwargs):
# Handle the signal's input arguments
item = kwargs['item']
variations = kwargs['variations']
cache = kwargs['cache'] # NOQA
cache = kwargs['cache']
context = kwargs['context'] # NOQA
# Fetch all restriction objects applied to this item
@@ -29,6 +29,25 @@ def availability_handler(sender, **kwargs):
# interfere with other plugins.
variations = [d.copy() for d in variations]
# The maximum validity of our cached values is the next date, one of our
# timeframe_from or tiemframe_to actions happens
def timediff(restrictions):
for r in restrictions:
if r.timeframe_from >= now():
yield (r.timeframe_from - now()).total_seconds()
if r.timeframe_to >= now():
yield (r.timeframe_to - now()).total_seconds()
try:
cache_validity = min(timediff(restrictions))
except ValueError:
# empty sequence
# If we get here, there are restrictions available but nothing will
# change about them any more. If it were not for the case of no
# restriction for the base item but restrictions for special
# variations, we could quit here with 'item not available'.
cache_validity = 3600
# Walk through all variations we are asked for
for v in variations:
# If this point is reached, there ARE time restrictions for this item
@@ -36,6 +55,23 @@ def availability_handler(sender, **kwargs):
# without any timeframe
available = False
price = None
# Make up some unique key for this variation
cachekey = 'timerestriction:%d:%s' % (
item.pk,
",".join(sorted([str(v[1].pk) for v in v.items() if v[0] != 'variation']))
)
# Fetch from cache, if available
cached = cache.get(cachekey)
if cached is not None:
v['available'] = (cached.split(":")[0] == 'True')
try:
v['price'] = float(cached.split(":")[1])
except ValueError:
v['price'] = None
continue
# Walk through all restriction objects applied to this item
for restriction in restrictions:
applied_to = list(restriction.variations.all())
@@ -57,5 +93,10 @@ def availability_handler(sender, **kwargs):
v['available'] = available
v['price'] = price
cache.set(
cachekey,
'%s:%s' % ('True' if available else 'False', str(price) if price else ''),
cache_validity
)
return variations

View File

@@ -33,7 +33,7 @@ class TimeRestrictionTest(TestCase):
def test_nothing(self):
result = signals.availability_handler(
None, item=self.item,
variations=self.event.get_all_variations(),
variations=self.item.get_all_variations(),
context=None, cache=self.event.get_cache()
)
self.assertEqual(len(result), 1)
@@ -43,12 +43,13 @@ class TimeRestrictionTest(TestCase):
r = TimeRestriction.objects.create(
timeframe_from=now() - timedelta(days=3),
timeframe_to=now() + timedelta(days=3),
event=self.event,
price=12
)
r.items.add(self.item)
result = signals.availability_handler(
None, item=self.item,
variations=self.event.get_all_variations(),
variations=self.item.get_all_variations(),
context=None, cache=self.event.get_cache()
)
self.assertEqual(len(result), 1)
@@ -60,12 +61,13 @@ class TimeRestrictionTest(TestCase):
r = TimeRestriction.objects.create(
timeframe_from=now() - timedelta(days=5),
timeframe_to=now() - timedelta(days=3),
event=self.event,
price=12
)
r.items.add(self.item)
result = signals.availability_handler(
None, item=self.item,
variations=self.event.get_all_variations(),
variations=self.item.get_all_variations(),
context=None, cache=self.event.get_cache()
)
self.assertEqual(len(result), 1)
@@ -76,18 +78,20 @@ class TimeRestrictionTest(TestCase):
r1 = TimeRestriction.objects.create(
timeframe_from=now() - timedelta(days=5),
timeframe_to=now() + timedelta(days=3),
event=self.event,
price=12
)
r1.items.add(self.item)
r2 = TimeRestriction.objects.create(
timeframe_from=now() - timedelta(days=3),
timeframe_to=now() + timedelta(days=5),
event=self.event,
price=8
)
r2.items.add(self.item)
result = signals.availability_handler(
None, item=self.item,
variations=self.event.get_all_variations(),
variations=self.item.get_all_variations(),
context=None, cache=self.event.get_cache()
)
self.assertEqual(len(result), 1)
@@ -99,18 +103,20 @@ class TimeRestrictionTest(TestCase):
r1 = TimeRestriction.objects.create(
timeframe_from=now() - timedelta(days=5),
timeframe_to=now() + timedelta(days=5),
event=self.event,
price=12
)
r1.items.add(self.item)
r2 = TimeRestriction.objects.create(
timeframe_from=now() + timedelta(days=1),
timeframe_to=now() + timedelta(days=7),
event=self.event,
price=8
)
r2.items.add(self.item)
result = signals.availability_handler(
None, item=self.item,
variations=self.event.get_all_variations(),
variations=self.item.get_all_variations(),
context=None, cache=self.event.get_cache()
)
self.assertEqual(len(result), 1)
@@ -122,18 +128,20 @@ class TimeRestrictionTest(TestCase):
r1 = TimeRestriction.objects.create(
timeframe_from=now() - timedelta(days=5),
timeframe_to=now() + timedelta(days=2),
event=self.event,
price=12
)
r1.items.add(self.item)
r2 = TimeRestriction.objects.create(
timeframe_from=now() + timedelta(days=4),
timeframe_to=now() + timedelta(days=7),
event=self.event,
price=8
)
r2.items.add(self.item)
result = signals.availability_handler(
None, item=self.item,
variations=self.event.get_all_variations(),
variations=self.item.get_all_variations(),
context=None, cache=self.event.get_cache()
)
self.assertEqual(len(result), 1)
@@ -145,18 +153,20 @@ class TimeRestrictionTest(TestCase):
r1 = TimeRestriction.objects.create(
timeframe_from=now() - timedelta(days=5),
timeframe_to=now() - timedelta(days=1),
event=self.event,
price=12
)
r1.items.add(self.item)
r2 = TimeRestriction.objects.create(
timeframe_from=now() + timedelta(days=4),
timeframe_to=now() + timedelta(days=7),
event=self.event,
price=8
)
r2.items.add(self.item)
result = signals.availability_handler(
None, item=self.item,
variations=self.event.get_all_variations(),
variations=self.item.get_all_variations(),
context=None, cache=self.event.get_cache()
)
self.assertEqual(len(result), 1)
@@ -173,13 +183,14 @@ class TimeRestrictionTest(TestCase):
r1 = TimeRestriction.objects.create(
timeframe_from=now() - timedelta(days=5),
timeframe_to=now() + timedelta(days=1),
event=self.event,
price=12
)
r1.items.add(self.item)
r1.variations.add(v1)
result = signals.availability_handler(
None, item=self.item,
variations=self.event.get_all_variations(),
variations=self.item.get_all_variations(),
context=None, cache=self.event.get_cache()
)
self.assertEqual(len(result), 3)
@@ -200,12 +211,14 @@ class TimeRestrictionTest(TestCase):
r1 = TimeRestriction.objects.create(
timeframe_from=now() - timedelta(days=5),
timeframe_to=now() + timedelta(days=1),
event=self.event,
price=12
)
r1.items.add(self.item)
r2 = TimeRestriction.objects.create(
timeframe_from=now() - timedelta(days=5),
timeframe_to=now() + timedelta(days=1),
event=self.event,
price=8
)
r2.items.add(self.item)
@@ -213,13 +226,14 @@ class TimeRestrictionTest(TestCase):
r3 = TimeRestriction.objects.create(
timeframe_from=now() - timedelta(days=5),
timeframe_to=now() - timedelta(days=1),
event=self.event,
price=10
)
r3.items.add(self.item)
r3.variations.add(v2)
result = signals.availability_handler(
None, item=self.item,
variations=self.event.get_all_variations(),
variations=self.item.get_all_variations(),
context=None, cache=self.event.get_cache()
)
self.assertEqual(len(result), 3)
@@ -241,6 +255,7 @@ class TimeRestrictionTest(TestCase):
r1 = TimeRestriction.objects.create(
timeframe_from=now() - timedelta(days=5),
timeframe_to=now() + timedelta(days=1),
event=self.event,
price=12
)
r1.items.add(self.item)
@@ -248,6 +263,7 @@ class TimeRestrictionTest(TestCase):
r2 = TimeRestriction.objects.create(
timeframe_from=now() - timedelta(days=5),
timeframe_to=now() + timedelta(days=1),
event=self.event,
price=8
)
r2.items.add(self.item)
@@ -255,13 +271,14 @@ class TimeRestrictionTest(TestCase):
r3 = TimeRestriction.objects.create(
timeframe_from=now() - timedelta(days=5),
timeframe_to=now() - timedelta(days=1),
event=self.event,
price=8
)
r3.items.add(self.item)
r3.variations.add(v2)
result = signals.availability_handler(
None, item=self.item,
variations=self.event.get_all_variations(),
variations=self.item.get_all_variations(),
context=None, cache=self.event.get_cache()
)
self.assertEqual(len(result), 3)