Hello everyone!

The topic of a MySQL session implementation has come up here several times in the past. We have recently written one in-house and have been running it on a production infrastructure for some time without incident. As it seems a fairly common component which people can benefit from, it's being provided below for consideration.

Currently this was built directly into Session.py and takes configuration options through httpd.conf. Clearly this could be something which may need to be completely segmented from mod_python given the reliance on MySQL being installed. Hopefully this can get the conversation going.

Please note that no connection pooling has been implemented in this version, and the benefits of doing this may or may not prove valuable depending on the scope of its use. For our clustered session environment it was unnecessary.

httpd.conf example:
       PythonOption session                             MySQLSession
       PythonOption session.db                       sessions
       PythonOption session.db_host             db.whatever.com
       PythonOption session.db_user             user
       PythonOption session.db_password   pass
       PythonOption session.timeout               3600

Mahalo,
earle.

33d32
< import MySQLdb
704,829d702
<
< ######################################################################## ###
< ## MySQLSession
<
< class MySQLSession(BaseSession):
<
<     def __init__(self, req, sid=0, secret=None, timeout=0, lock=1):
<
<         self.db = None
<         self.db_host = None
<         self.db_user = None
<         self.db_password = None
<         self.timeout = timeout
<         self.req = req
<
<         opts = req.get_options()
<
<         # parse httpd.conf for DB information
<         for opt in [ 'db', 'db_host', 'db_user', 'db_password' ]:
<             if opts.has_key('.'.join([ 'session', opt ])):
<                 setattr(self, opt, opts['.'.join([ 'session', opt ])])
<             else:
< self.req.log_error("MySQLSession: missing PythonOption: session.%s" % (opt, ),
<                             apache.APLOG_NOTICE)
<
< raise apache.SERVER_RETURN, apache.HTTP_INTERNAL_SERVER_ERROR
<
<         if opts.has_key('session.timeout'):
<             self.timeout = opts['session.timeout']
<
<         BaseSession.__init__(self, req, sid=sid, secret=secret,
<                              timeout=timeout, lock=lock)
<
<     def do_cleanup(self):
<
<         data = [self._req.server, ]
<
<         self._req.register_cleanup(mysqldb_cleanup, data)
< self._req.log_error("MySQLSession: registered database cleanup.",
<                             apache.APLOG_NOTICE)
<
<     def do_load(self):
< self.conn = MySQLdb.connect(host = self.db_host, user = self.db_user, < passwd = self.db_password, db = self.db, use_unicode=1,
<                                     init_command="set names utf8")
<
<         self.cursor = self.conn.cursor(MySQLdb.cursors.DictCursor)
<
<         try:
< self.cursor.execute("SELECT * FROM session WHERE id=% s" , self._sid)
<             res = self.cursor.fetchone()
<
<             if res is not None and res.has_key('data'):
<                 retVal = cPickle.loads(res['data'].tostring())
<             else:
<                 retVal = None
<         except:
<             retVal = None
<
<         self.cursor.close()
<         self.conn.close()
<
<         return retVal
<
<     def do_save(self, dict):
< self.conn = MySQLdb.connect(host = self.db_host, user = self.db_user, < passwd = self.db_password, db = self.db, use_unicode=1,
<                                     init_command="set names utf8")
<
<         self.cursor = self.conn.cursor(MySQLdb.cursors.DictCursor)
< self.cursor.execute("SELECT * from session where id=%s" , self._sid)
<
<         res = self.cursor.fetchone()
<
<         if res is None:
< self.cursor.execute("INSERT INTO session (id, data, created, accessed, timeout) VALUES (%s, %s, NOW(), NOW(), %s)", (self._sid, cPickle.dumps(dict), self._timeout, ))
<         else:
< self.cursor.execute("UPDATE session SET data=%s, accessed=NOW() WHERE id=%s" , (cPickle.dumps(dict), self._sid, ))
<
<
<         self.cursor.close()
<         self.conn.close()
<
<
<     def do_delete(self):
< self.conn = MySQLdb.connect(host = self.db_host, user = self.db_user, < passwd = self.db_password, db = self.db, use_unicode=1,
<                                     init_command="set names utf8")
<
<         self.cursor = self.conn.cursor(MySQLdb.cursors.DictCursor)
<
< self.cursor.execute("DELETE FROM session WHERE id=%s", (self._sid,))
<
<         self.cursor.close()
<         self.conn.close()
<
<
< def mysqldb_cleanup(data):
<     try:
< conn = MySQLdb.connect(host = self.db_host, user = self.db_user, < passwd = self.db_password, db = self.db, use_unicode=1,
<                            init_command="set names utf8")
<
<         cursor = conn.cursor(MySQLdb.cursors.DictCursor)
<         server = data
<
<         expired = []
<
< sessions = cursor.execute("SELECT *, UNIXTIME(accessed) AS uaccessed, UNIXTIME(created) AS ucreated FROM session")
<
<         for session in sessions:
< if ((time.time() - session['accessed']) > session ['timeout']):
<                 expired.append(session)
<
<         for session in expired:
< cursor.execute("DELETE FROM session WHERE id=%s", (session['id'],))
<
<     except:
<         pass
<
<     try:
<         cursor.close()
<         conn.cose()
<     except:
<         pass
<
<
856,857d728
<     elif sess_type == 'MySQLSession':
<        sess = MySQLSession





Reply via email to