diff --git a/oml/cache.py b/oml/cache.py new file mode 100644 index 0000000..88c8443 --- /dev/null +++ b/oml/cache.py @@ -0,0 +1,20 @@ +import time + +class Cache(dict): + + def __init__(self, ttl=10): + self._ttl = ttl + self._added = {} + + def get(self, key): + if key in self._added: + if self._added[key] < time.time(): + del self._added[key] + del self[key] + return + return dict.__getitem__(self, key) + + def set(self, key, value, ttl=None): + ttl = ttl or self._ttl + self._added[key] = time.time() + ttl + dict.__setitem__(self, key, value) diff --git a/oml/item/api.py b/oml/item/api.py index b19fed3..b2ed0a5 100644 --- a/oml/item/api.py +++ b/oml/item/api.py @@ -4,6 +4,7 @@ from __future__ import division import os import json +import hashlib from oxtornado import actions @@ -44,24 +45,28 @@ def find(data): if 'group' in q: names = {} groups = {} - items = [i.id for i in q['qs'].options(load_only('id'))] - qs = models.Find.query.filter_by(key=q['group']) - if items: - qs = qs.filter(models.Find.item_id.in_(items)) - for f in qs.values('value', 'findvalue'): - value = f[0] - findvalue = f[1] - if findvalue not in groups: - groups[findvalue] = 0 - groups[findvalue] += 1 - names[findvalue] = value - g = [{'name': names[k], 'items': groups[k]} for k in groups] - else: - g = [] - if 'sort' in q: - g.sort(key=lambda k: k[q['sort'][0]['key']]) - if q['sort'][0]['operator'] == '-': - g.reverse() + key = 'group:' + hashlib.sha1(json.dumps(data)).hexdigest() + g = state.cache.get(key) + if g is None: + items = [i.id for i in q['qs'].options(load_only('id'))] + qs = models.Find.query.filter_by(key=q['group']) + if items: + qs = qs.filter(models.Find.item_id.in_(items)) + for f in qs.values('value', 'findvalue'): + value = f[0] + findvalue = f[1] + if findvalue not in groups: + groups[findvalue] = 0 + groups[findvalue] += 1 + names[findvalue] = value + g = [{'name': names[k], 'items': groups[k]} for k in groups] + else: + g = [] + if 'sort' in q: + g.sort(key=lambda k: k[q['sort'][0]['key']]) + if q['sort'][0]['operator'] == '-': + g.reverse() + state.cache.set(key, g) if 'positions' in data: response['positions'] = {} ids = [k['name'] for k in g] diff --git a/oml/server.py b/oml/server.py index bf37f03..55774a9 100644 --- a/oml/server.py +++ b/oml/server.py @@ -15,6 +15,7 @@ import websocket import state import node.server import oxtornado +from cache import Cache from item.icons import IconHandler from item.handlers import EpubHandler, ReaderHandler, FileHandler @@ -59,6 +60,7 @@ def run(): pid.write('%s' % os.getpid()) state.main = IOLoop.instance() + state.cache = Cache(ttl=10) def start_node(): import user diff --git a/oml/user/models.py b/oml/user/models.py index 1373592..839b3b6 100644 --- a/oml/user/models.py +++ b/oml/user/models.py @@ -276,12 +276,17 @@ class List(db.Model): return self.public_id.encode('utf-8') def items_count(self): - from item.models import Item - if self._query: - data = self._query - return Parser(Item).find({'query': data}).count() - else: - return len(self.items) + key = 'list:' + self.public_id + value = state.cache.get(key) + if key is None: + from item.models import Item + if self._query: + data = self._query + value = Parser(Item).find({'query': data}).count() + else: + value = len(self.items) + state.cache.set(key, value) + return value def json(self): r = {