Implement cleanup for sessions
[cascardo/ipsilon.git] / ipsilon / util / sessions.py
old mode 100755 (executable)
new mode 100644 (file)
index b724471..5a9854b
@@ -1,24 +1,56 @@
-#!/usr/bin/python
-#
-# Copyright (C) 2014  Ipsilon project Contributors, for licensee see COPYING
+# Copyright (C) 2014 Ipsilon project Contributors, for license see COPYING
 
 import base64
 from cherrypy.lib.sessions import Session
-from ipsilon.util.data import SqlStore, SqlQuery
+from ipsilon.util.data import Store, SqlQuery
 import threading
+import datetime
 try:
     import cPickle as pickle
 except ImportError:
     import pickle
 
 
-SESSION_COLUMNS = ['id', 'data', 'expiration_time']
+SESSION_TABLE = {'columns': ['id', 'data', 'expiration_time'],
+                 'primary_key': ('id', ),
+                 'indexes': [('expiration_time',)]
+                 }
+
+
+class SessionStore(Store):
+    def _initialize_schema(self):
+        q = self._query(self._db, 'sessions', SESSION_TABLE,
+                        trans=False)
+        q.create()
+        q._con.close()  # pylint: disable=protected-access
+
+    def _upgrade_schema(self, old_version):
+        if old_version == 1:
+            # In schema version 2, we added indexes and primary keys
+            # pylint: disable=protected-access
+            table = self._query(self._db, 'sessions', SESSION_TABLE,
+                                trans=False)._table
+            self._db.add_constraint(table.primary_key)
+            for index in table.indexes:
+                self._db.add_index(index)
+            return 2
+        else:
+            raise NotImplementedError()
+
+    def _cleanup(self):
+        # pylint: disable=protected-access
+        table = SqlQuery(self._db, 'sessions', SESSION_TABLE)._table
+        # pylint: disable=no-value-for-parameter
+        d = table.delete().where(table.c.expiration_time
+                                 <= datetime.datetime.now())
+        return d.execute().rowcount
 
 
 class SqlSession(Session):
 
     dburi = None
     _db = None
+    _store = None
     _proto = 2
     locks = {}
 
@@ -30,15 +62,17 @@ class SqlSession(Session):
             if k == 'storage_dburi':
                 cls.dburi = v
 
-        cls._db = SqlStore(cls.dburi)
+        cls._store = SessionStore(database_url=cls.dburi)
+        # pylint: disable=protected-access
+        cls._db = cls._store._db
 
     def _exists(self):
-        q = SqlQuery(self._db, 'sessions', SESSION_COLUMNS)
+        q = SqlQuery(self._db, 'sessions', SESSION_TABLE)
         result = q.select({'id': self.id})
         return True if result.fetchone() else False
 
     def _load(self):
-        q = SqlQuery(self._db, 'sessions', SESSION_COLUMNS)
+        q = SqlQuery(self._db, 'sessions', SESSION_TABLE)
         result = q.select({'id': self.id})
         r = result.fetchone()
         if r:
@@ -48,7 +82,7 @@ class SqlSession(Session):
     def _save(self, expiration_time):
         q = None
         try:
-            q = SqlQuery(self._db, 'sessions', SESSION_COLUMNS, trans=True)
+            q = SqlQuery(self._db, 'sessions', SESSION_TABLE, trans=True)
             q.delete({'id': self.id})
             data = pickle.dumps((self._data, expiration_time), self._proto)
             q.insert((self.id, base64.b64encode(data), expiration_time))
@@ -59,7 +93,7 @@ class SqlSession(Session):
             raise
 
     def _delete(self):
-        q = SqlQuery(self._db, 'sessions', SESSION_COLUMNS)
+        q = SqlQuery(self._db, 'sessions', SESSION_TABLE)
         q.delete({'id': self.id})
 
     # copy what RamSession does for now