pylons.database does not provide a way to set the SQLAlchemy
connection options beyond 'echo'.  But MySQL needs 'pool_recycle'
[1], and users may want to set other options in their config.  I tried
a few different ways and eventually came up with this.  It adds
"sqlalchemy.pool_recycle" and "sqlalchemy.echo_pool", and is
expandable for other options.  Would this approach be suitable for
pylons.database?  If so I'll make a Trac patch.

Two differences:

get_engine_conf() returns a dict of args for
sqlalchemy.create_engine() rather than a tuple of (uri, echo).

create_engine(), get_engine_conf(), and make_session() do not accept
args.  In pylons.database they take optional 'url' and 'echo' args
which override the values in the config file.  Does anybody actually
use this feature?  If so, I could make them take an arbitrary set of
**engine_args, which get_engine_conf() would not look up in the config
file.


[1] MySQL 5 unilaterally closes connections after N hours of idle
time, causing applications to raise a "mysql server has gone away"
exception if they later use the connection.  N is 8 by default; you
can set it in my.cnf but you can't disable it.  My existing Quixote
applications have a module-level connection so I restart them every 12
hours.  Having connections that automatically get recreated after a
few hours is my main motivation for moving to SQLAlchemy.

-- 
Mike Orr <[EMAIL PROTECTED]>

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"pylons-discuss" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/pylons-discuss?hl=en
-~----------~----~----~----~------~----~------~--~---

from paste.deploy.converters import asbool
from pylons.database import app_scope, get_engines
import pylons.util
import sqlalchemy
from sqlalchemy.ext import sessioncontext

__all__ = [
    "app_scope",
    "create_engine",
    "get_engine_conf",
    "get_engines",
    "make_session",
    "session_context",
    ]

def create_engine():
    """Create a SQLAlchemy db engine.

       Unlike pylons.database.create_engine, this version does not accept
       'uri' or 'echo' args.  
    """
    engine_conf = get_engine_conf()
    # Extract 'uri' to avoid exception in sqlalchemy.create_engine().
    uri = engine_conf.pop("uri")
    engine = sqlalchemy.create_engine(uri, **engine_conf)
    return engine

def get_engine_conf():
    """A version of pylons.database.get_engine_conf() with more config options.

       Return a dict of arguments suitable for sqlalchemy.create_engine().

       Unlike pylons.database.get_engine_conf, this version does not accept
       'uri' or 'echo' args.  It also fixes a parsing bug on the 'echo' var.
    """
    cg = pylons.util.config_get
    conf = {}
    conf["uri"] = cg("sqlalchemy.dburi")
    if not conf["uri"]:
        raise KeyError("config var 'sqlalchemy.dburi' is required")
    conf["echo"] = asbool(cg("sqlalchemy.echo", False))
    conf["echo_pool"] = asbool(cg("sqlalchemy.echo_pool", False))
    conf["pool_recycle"] = int(cg("sqlalchemy.pool_recycle", -1)) # Raises ValueError
    return conf

def make_session():
    """Return a SQLAlchemy session 

       Unlike pylons.database.make_session, this version does not accept
       'uri' or 'echo' args.
    """
    uri = pylons.util.config_get("sqlalchemy.dburi")
    db_engines = get_engines()
    if uri in db_engines:
        engine = db_engines[uri]
    else:
        engine = db_engines[uri] = create_engine()
    return sqlalchemy.create_session(bind_to=engine)

session_context = sessioncontext.SessionContext(make_session,
    scopefunc=app_scope)

Reply via email to