[IMP] http session cleanup with gc

bzr revid: al@openerp.com-20121115011853-238vzfca9ssbiyi7
This commit is contained in:
Antony Lesuisse 2012-11-15 02:18:53 +01:00
parent 7629191431
commit 9bf94f677d
1 changed files with 30 additions and 23 deletions

View File

@ -11,6 +11,7 @@ import logging
import mimetypes
import os
import pprint
import random
import sys
import tempfile
import threading
@ -357,26 +358,13 @@ class Controller(object):
#----------------------------------------------------------
# Session context manager
#----------------------------------------------------------
STORES = {}
@contextlib.contextmanager
def session_context(request, storage_path, session_cookie='httpsessionid'):
session_store, session_lock = STORES.get(storage_path, (None, None))
if not session_store:
session_store = werkzeug.contrib.sessions.FilesystemSessionStore( storage_path)
session_lock = threading.Lock()
STORES[storage_path] = session_store, session_lock
sid = request.cookies.get(session_cookie)
if not sid:
sid = request.args.get('sid')
def session_context(request, session_store, session_lock, sid):
with session_lock:
if sid:
request.session = session_store.get(sid)
else:
request.session = session_store.new()
try:
yield request.session
finally:
@ -428,6 +416,18 @@ def session_context(request, storage_path, session_cookie='httpsessionid'):
session_store.save(request.session)
def session_gc(session_store):
if random.random() < 0.001:
# we keep session one week
last_week = time.time() - 60*60*24*7
for fname in os.listdir(session_store.path):
path = os.path.join(session_store.path, fname)
try:
if os.path.getmtime(path) < last_week:
os.unlink(path)
except OSError:
pass
#----------------------------------------------------------
# WSGI Application
#----------------------------------------------------------
@ -462,22 +462,23 @@ class Root(object):
"""Root WSGI application for the OpenERP Web Client.
"""
def __init__(self):
self.httpsession_cookie = 'httpsessionid'
self.addons = {}
static_dirs = self._load_addons()
app = werkzeug.wsgi.SharedDataMiddleware( self.dispatch, static_dirs)
self.dispatch = DisableCacheMiddleware(app)
# Setup http sessions
try:
username = getpass.getuser()
except Exception:
username = "unknown"
self.session_storage = os.path.join(tempfile.gettempdir(), "oe-sessions-" + username)
if not os.path.exists(self.session_storage):
os.mkdir(self.session_storage, 0700)
_logger.debug('HTTP sessions stored in: %s', self.session_storage)
path = os.path.join(tempfile.gettempdir(), "oe-sessions-" + username)
if not os.path.exists(path):
os.mkdir(path, 0700)
self.session_store = werkzeug.contrib.sessions.FilesystemSessionStore(path)
self.session_lock = threading.Lock()
_logger.debug('HTTP sessions stored in: %s', path)
def __call__(self, environ, start_response):
""" Handle a WSGI request
@ -500,8 +501,14 @@ class Root(object):
if not handler:
response = werkzeug.exceptions.NotFound()
else:
with session_context(request, self.session_storage, self.httpsession_cookie) as session:
result = handler( request)
sid = request.cookies.get('sid')
if not sid:
sid = request.args.get('sid')
session_gc(self.session_store)
with session_context(request, self.session_store, self.session_lock, sid) as session:
result = handler(request)
if isinstance(result, basestring):
headers=[('Content-Type', 'text/html; charset=utf-8'), ('Content-Length', len(result))]
@ -510,7 +517,7 @@ class Root(object):
response = result
if hasattr(response, 'set_cookie'):
response.set_cookie(self.httpsession_cookie, session.sid)
response.set_cookie('sid', session.sid)
return response(environ, start_response)