Browse Source

s/ejdb/tinydb, clear eventmodel, some testing

towards a better db!
boyska 9 years ago
parent
commit
6f0c335d2d
4 changed files with 82 additions and 34 deletions
  1. 1 1
      README.rst
  2. 37 32
      larigira/event.py
  3. 43 0
      larigira/tests/test_db.py
  4. 1 1
      setup.py

+ 1 - 1
README.rst

@@ -16,7 +16,7 @@ Software stack
 * python2
   * gevent as an async framework
   * flask to provide web interface and rpc
-* ejdb as an embedded database
+* tinydb as an embedded database
 
 Why? (aka design features)
 --------------------------

+ 37 - 32
larigira/event.py

@@ -12,21 +12,50 @@ from datetime import datetime, timedelta
 
 import gevent
 from gevent.queue import Queue
+from tinydb import TinyDB
 
 from eventutils import ParentedLet
 from timegen import timegenerate
 from audiogen import audiogenerate
 
 
+class EventModel(object):
+    def __init__(self, uri):
+        self.uri = uri
+        self.db = TinyDB(uri)
+        self.actions = self.db.table('actions')
+        self.alarms = self.db.table('alarms')
+
+    def get_action_by_id(self, action_id):
+        return self.actions.get(eid=action_id)
+
+    def get_alarm_by_id(self, alarm_id):
+        return self.alarms.get(eid=alarm_id)
+
+    def get_actions_by_alarm(self, alarm):
+        for action_id in alarm.get('actions', []):
+            yield self.get_action_by_id(action_id)
+
+    def get_all_alarms(self):
+        return self.alarms.all()
+
+    def get_all_alarms_expanded(self):
+        for alarm in self.get_all_alarms():
+            for action in self.get_actions_by_alarm(alarm):
+                yield alarm, action
+
+    def add_event(self, alarm, actions):
+        action_ids = [self.actions.insert(a) for a in actions]
+        alarm['actions'] = action_ids
+        return self.alarms.insert(alarm)
+
+
 class EventSource(ParentedLet):
     def __init__(self, queue, uri):
         ParentedLet.__init__(self, queue)
-        import pyejdb
         self.log = logging.getLogger(self.__class__.__name__)
         self.log.debug('uri is %s' % uri)
-        self.ejdb = pyejdb.EJDB(uri,
-                                pyejdb.JBOREADER | pyejdb.JBOLCKNB |
-                                pyejdb.JBOTRUNC)
+        self.model = EventModel(uri)
         self.log.debug('opened %s' % uri)
 
     def parent_msg(self, kind, *args):
@@ -38,40 +67,16 @@ class EventSource(ParentedLet):
             msg = ParentedLet.parent_msg(self, kind, *args)
         return msg
 
-    def _get_actions_by_alarm(self, alarm):
-        if 'actions' not in alarm:
-            return
-        for action_id in alarm['actions']:
-            with self.ejdb.find('actions',
-                                {'_id': action_id}) as subcur:
-                for action in subcur:
-                    yield action
-
-    def _get_by_alarmid(self, alarmid):
-        with self.ejdb.find('alarms', {'_id': alarmid}) as cur:
-            if len(cur) > 1:
-                self.log.warn("Found more than one alarm with given id")
-            for alarm in cur:
-                for action in self._get_actions_by_alarm(alarm):
-                    yield alarm, action
-
-    def reload(self):
-        with self.ejdb.find('alarms', {}) as cur:
-            for alarm in cur:
-                self.log.info('%s\t%s' % (alarm['kind'],
-                                          ', '.join(alarm.keys())))
-                for action in self._get_actions_by_alarm(alarm):
-                    yield alarm, action
-
-    def reload_id(self, event_id):
+    def reload_id(self, alarm_id):
         '''
         Check if the event is still valid, and put "add" messages on queue
         '''
-        for alarm, action in self._get_by_alarmid(event_id):
+        alarm = self.model.get_alarm_by_id(alarm_id)
+        for action in self.model.get_actions_by_alarm(alarm):
             self.send_to_parent('add', alarm, action)
 
     def do_business(self):
-        for alarm, action in self.reload():
+        for alarm, action in self.model.get_all_alarms_expanded():
             yield ('add', alarm, action)
 
 

+ 43 - 0
larigira/tests/test_db.py

@@ -0,0 +1,43 @@
+from __future__ import print_function
+import tempfile
+import os
+
+from gevent import monkey
+monkey.patch_all(subprocess=True)
+
+import pytest
+
+from larigira.event import EventModel
+
+
+@pytest.yield_fixture
+def db():
+    fname = tempfile.mktemp(suffix='.json', prefix='larigira-test')
+    yield EventModel(uri=fname)
+    os.unlink(fname)
+
+
+def test_empty(db):
+    assert len(db.get_all_alarms()) == 0
+
+
+def test_add_basic(db):
+    assert len(db.get_all_alarms()) == 0
+    alarm_id = db.add_event(dict(kind='frequency', interval=60*3, start=1),
+                            [dict(kind='mpd', paths=['foo.mp3'], howmany=1)])
+    assert len(db.get_all_alarms()) == 1
+    assert db.get_alarm_by_id(alarm_id) is not None
+    assert len(tuple(db.get_actions_by_alarm(
+        db.get_alarm_by_id(alarm_id)))) == 1
+
+
+def test_add_multiple_alarms(db):
+    assert len(db.get_all_alarms()) == 0
+    alarm_id = db.add_event(dict(kind='frequency', interval=60*3, start=1),
+                            [dict(kind='mpd', paths=['foo.mp3'], howmany=1),
+                             dict(kind='foo', a=3)])
+    assert len(db.get_all_alarms()) == 1
+    assert db.get_alarm_by_id(alarm_id) is not None
+    assert len(db.actions.all()) == 2
+    assert len(tuple(db.get_actions_by_alarm(
+        db.get_alarm_by_id(alarm_id)))) == 2

+ 1 - 1
setup.py

@@ -40,7 +40,7 @@ setup(name='larigira',
           'gevent',
           'flask',
           'python-mpd2',
-          'pyejdb'
+          'tinydb'
       ],
       tests_require=['pytest', 'pytest-timeout'],
       cmdclass={'test': PyTest},