From 14aa12bd0182d9d0e20f4e54672c8e700349ebe9 Mon Sep 17 00:00:00 2001 From: Griatch Date: Sat, 3 Sep 2016 14:54:34 +0200 Subject: [PATCH] Started exploring a different caching scheme for Attributes as per issues #1034 and #1033. --- evennia/typeclasses/attributes.py | 38 ++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/evennia/typeclasses/attributes.py b/evennia/typeclasses/attributes.py index 488fcb82e4..18fabbb8b6 100644 --- a/evennia/typeclasses/attributes.py +++ b/evennia/typeclasses/attributes.py @@ -11,6 +11,7 @@ which is a non-db version of Attributes. from builtins import object import re import weakref +from collections import defaultdict from django.db import models from django.conf import settings @@ -206,7 +207,8 @@ class AttributeHandler(object): self.obj = obj self._objid = obj.id self._model = to_str(obj.__dbclass__.__name__.lower()) - self._cache = None + self._cache = {} + self._catcache = defaultdict(list) def _recache(self): "Cache all attributes of this object" @@ -217,6 +219,40 @@ class AttributeHandler(object): attr.db_category.lower() if attr.db_category else None), attr) for attr in attrs) + def _get(self, key=None, category=None): + "Retrieve from cache or do a db query and then cache" + key, category = key.lower() if key else None, category.lower() if category else None + if key: + cachekey = "%s-%s" % (key, category) + attr = self._cache.get(cachekey, None) + if attr: + return attr # return cached entity + query = {"%s__id" % self._model : self._objid, + "attribute__db_attrtype" : self._attrtype, + "attribute__db_key__iexact" : key.lower(), + "attribute__db_category__iexact" : category.lower() if category else None} + conn = getattr(self.obj, self._m2m_fieldname).through.objects.filter(**query) + if conn: + attr = conn[0].attribute + self._cache[cachekey] = attr + self._catcache[category].append(attr) + return attr + elif category: + # only category given + attrs = self._catcache.get(category, None) + if attrs: + return attrs # return cached attrs + query = {"%s__id" % self._model : self._objid, + "attribute__db_attrtype" : self._attrtype, + "attribute__db_category__iexact" : category.lower() if category else None} + attrs = [conn.attribute for conn in getattr(self.obj, self._m2m_fieldname).through.objects.filter(**query)] + for attr in attrs: + cachekey = "%s-%s" % (attr.db_key, category) + self._cache[cachekey] = attr + self._catcache[category].append(attr) + + + def has(self, key, category=None): """ Checks if the given Attribute (or list of Attributes) exists on