|
@@ -1,80 +1,102 @@
|
|
|
from datetime import timedelta
|
|
|
from django.core.cache import cache
|
|
|
from django.utils import timezone
|
|
|
-from misago.models import MonitorItem
|
|
|
+from misago.thread import local
|
|
|
+
|
|
|
+_thread_local = local()
|
|
|
+
|
|
|
+def load_monitor():
|
|
|
+ from misago.models import MonitorItem
|
|
|
+ monitor = cache.get('monitor', {})
|
|
|
+ if not monitor:
|
|
|
+ for i in MonitorItem.objects.all():
|
|
|
+ monitor[i.id] = [i.value, i.updated, i.type]
|
|
|
+ cache.set('monitor', monitor)
|
|
|
+ return monitor
|
|
|
+
|
|
|
|
|
|
class Monitor(object):
|
|
|
- def __init__(self):
|
|
|
- self._cache_deleted = False
|
|
|
- self._items = {}
|
|
|
- self.refresh()
|
|
|
-
|
|
|
- def refresh(self):
|
|
|
- self._items = cache.get('monitor')
|
|
|
- if not self._items:
|
|
|
- self._items = {}
|
|
|
- for i in MonitorItem.objects.all():
|
|
|
- self._items[i.id] = [i.value, i.updated, i.type]
|
|
|
- cache.set('monitor', self._items)
|
|
|
+ def __init__(self, local):
|
|
|
+ self.thread = local
|
|
|
+
|
|
|
+ def monitor(self):
|
|
|
+ try:
|
|
|
+ return self.thread.monitor
|
|
|
+ except AttributeError:
|
|
|
+ self.thread.monitor = load_monitor()
|
|
|
+ return self.thread.monitor
|
|
|
+
|
|
|
+ def entry(self, key):
|
|
|
+ try:
|
|
|
+ return self.monitor()[key]
|
|
|
+ except KeyError:
|
|
|
+ raise Exception(u"Monitor entry \"%s\" could not be found." % key)
|
|
|
|
|
|
def __contains__(self, key):
|
|
|
- return key in self._items
|
|
|
+ return key in self.monitor()
|
|
|
+
|
|
|
+ def __getattr__(self, key):
|
|
|
+ return self.entry(key)[0]
|
|
|
|
|
|
def __getitem__(self, key):
|
|
|
- return self._items[key][0]
|
|
|
+ return self.entry(key)[0]
|
|
|
|
|
|
def __setitem__(self, key, value):
|
|
|
- self._items[key][0] = value
|
|
|
- self._items[key][1] = timezone.now()
|
|
|
- cache.set('monitor', self._items)
|
|
|
- sync_item = MonitorItem(
|
|
|
- id=key,
|
|
|
- value=value,
|
|
|
- type=self._items[key][2],
|
|
|
- updated=timezone.now()
|
|
|
- )
|
|
|
- sync_item.save(force_update=True)
|
|
|
+ self.thread.monitor_update.append((key, value))
|
|
|
return value
|
|
|
|
|
|
- def __delitem__(self, key):
|
|
|
- pass
|
|
|
-
|
|
|
def increase(self, key, i=1):
|
|
|
- self[key] = self[key] + i
|
|
|
+ self.thread.monitor_update.append((key, self[key] + i))
|
|
|
|
|
|
def decrease(self, key, i=1):
|
|
|
- self[key] = self[key] - i
|
|
|
+ self.thread.monitor_update.append((key, self[key] - i))
|
|
|
|
|
|
def get(self, key, default=None):
|
|
|
- if not key in self._items:
|
|
|
+ if not key in self.monitor():
|
|
|
return default
|
|
|
- return self._items[key][0]
|
|
|
+ return self.entry(key)[0]
|
|
|
|
|
|
def get_updated(self, key):
|
|
|
- if key in self._items:
|
|
|
- return self._items[key][1]
|
|
|
+ if key in self.monitor():
|
|
|
+ return self.entry(key)[1]
|
|
|
return None
|
|
|
|
|
|
def expired(self, key, seconds=5):
|
|
|
- return self._items[key][1] < (timezone.now() - timedelta(seconds=seconds))
|
|
|
+ return self.entry(key)[1] < (timezone.now() - timedelta(seconds=seconds))
|
|
|
|
|
|
def has_key(self, key):
|
|
|
- return key in self._items
|
|
|
+ return key in self.entry()
|
|
|
|
|
|
def keys(self):
|
|
|
- return self._items.keys()
|
|
|
+ return self.entry().keys()
|
|
|
|
|
|
def values(self):
|
|
|
- return self._items.values()
|
|
|
+ return self.entry().values()
|
|
|
|
|
|
def items(self):
|
|
|
- return self._items.items()
|
|
|
+ return self.entry().items()
|
|
|
|
|
|
def iterkeys(self):
|
|
|
- return self._items.iterkeys()
|
|
|
+ return self.entry().iterkeys()
|
|
|
|
|
|
def itervalues(self):
|
|
|
- return self._items.itervalues()
|
|
|
+ return self.entry().itervalues()
|
|
|
|
|
|
def iteritems(self):
|
|
|
- return self._items.iteritems()
|
|
|
+ return self.entry().iteritems()
|
|
|
+
|
|
|
+
|
|
|
+class UpdatingMonitor(object):
|
|
|
+ def __enter__(self):
|
|
|
+ _thread_local.monitor_update = []
|
|
|
+
|
|
|
+ def __exit__(self, type, value, traceback):
|
|
|
+ if _thread_local.monitor_update:
|
|
|
+ from misago.models import MonitorItem
|
|
|
+ for key, value in _thread_local.monitor_update:
|
|
|
+ MonitorItem.objects.filter(pk=key).update(_value=value, updated=timezone.now())
|
|
|
+ cache.delete('monitor')
|
|
|
+ _thread_local.monitor_update = None
|
|
|
+
|
|
|
+
|
|
|
+monitor = Monitor(_thread_local)
|