Hello.

We run our web application in cherrypy. I have just found that all our threads
share *one* DB connection! A web page contains several AJAX calls, each queries
the database. However only one runs at a time because the threads share DB
connection.

Notes to the code below:
* We run postgres 9.1 via psycopg2.
* db.init() creates engine with pool_size of 5 by default.
* scoped_session() ensures that each thread gets its own session object.
* See our module session and its use.

I have no idea what is wrong. Please help me diagnose this! Note that OS monitor
shows several cherrypy threads, each gets its share, so the cherrypy setup seems
to be OK.


Thank you in advance,

Ladislav Lenart


####################
# Snippet of db.py #
####################

def init(conn_string, echo=False, base=None, pool_size=5):
    engine = create_engine(conn_string, echo=echo, pool_size=pool_size)
    session.init(engine)
    if base is None:
        base = Base
        _import_model()
    base.metadata.bind = engine
    return engine


#########################
# Snippet of session.py #
#########################

_Session = None

def init(engine):
    global _Session
    _Session = scoped_session(sessionmaker(bind=engine, autoflush=False))


class _SessionContext(object):
    def __init__(self):
        self._level = 0

    def __enter__(self):
        if self._level == 0:
            self._session = _Session()
        self._level += 1
        return self._session

    def __exit__(self, type_, value, traceback):
        self._level -= 1
        if self._level == 0:
            self._session.close()
            self._session = None

_thread_local = local()

def get_session():
    ctx = getattr(_thread_local, 'session_context', None)
    if ctx:
        return ctx
    ctx = _SessionContext()
    _thread_local.session_context = ctx
    return ctx


def use(fun):
    """Decorator that creates SQLAlchemy session to use in inner method and
    cleans it up afterwards. It is safe for nested calls.
    Session is just closed, any commits or rollbacks must be handled
    explicitly in a decorated method.
    """
    def wrapper(*args, **kwargs):
        with get_session():
            return fun(*args, **kwargs)
    return wrapper


# DB session wrappers for standard session functions. Add more as you see fit.

def query(*args, **kwargs):
    return _Session().query(*args, **kwargs)

def add(*args, **kwargs):
    return _Session().add(*args, **kwargs)

def add_all(*args, **kwargs):
    return _Session().add_all(*args, **kwargs)

def delete(*args, **kwargs):
    """NOTE: DO NOT USE THIS DIRECTLY! USE obj.delete() instead."""
    return _Session().delete(*args, **kwargs)

def execute(*args, **kwargs):
    return _Session().execute(*args, **kwargs)

def flush(*args, **kwargs):
    return _Session().flush(*args, **kwargs)

def commit(*args, **kwargs):
    return _Session().commit(*args, **kwargs)

def rollback(*args, **kwargs):
    return _Session().rollback(*args, **kwargs)

def close(*args, **kwargs):
    return _Session().close(*args, **kwargs)


#########
# USAGE #
#########

@session.use
def handle_ajax1(...):
    session.query(...)
    session.commit()

@session.use
def handle_ajax2(...):
    session.query(...)
    session.commit()

-- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at http://groups.google.com/group/sqlalchemy?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to