Ticket #42 (closed defect: fixed)

Opened 3 months ago

Last modified 3 months ago

Use DB (SQLAlchemy) for sessions.

Reported by: ricky Owned by: ctrochalakis
Priority: major Milestone:
Component: Core Version:
Keywords: Cc:

Description

As I mentioned in #transifex, sessions in memory (or on disk) are hard to balance. Here's what we're doing with FAS (postgres):

model
=====
SessionTable = Table('session', metadata, autoload=True)
ass Session(SABase):
    '''Session'''
    pass
mapper(Session, SessionTable)

sql (postgres)
==============
create table session (
  id varchar(40) primary key,
  data text,
  expiration_time timestamp
);

controller
==========
class SQLAlchemyStorage:
    def __init__(self):
        pass

    def load(self, id):
        s = Session.query.get(id)
        if not s:
            return None
        expiration_time = s.expiration_time
        pickled_data = s.data
        data = pickle.loads(pickled_data.encode('utf-8'))
        return (data, expiration_time)

    def delete(self, id=None):
        if id is None:
            id = cherrypy.session.id
        s = Session.query.get(id)
        session.delete(s)
        session.flush()

    def save(self, id, data, expiration_time):
        pickled_data = pickle.dumps(data)
        s = Session.query.get(id)
        if not s:
            s = Session()
        s.id = id
        s.data = pickled_data
        s.expiration_time = expiration_time
        session.flush()

    def acquire_lock(self):
        pass

    def release_lock(self):
        pass

    def clean_up(self, sess):
        result = SessionTable.delete(
            SessionTable.c.expiration_time.__lt__(datetime.datetime.now())
            ).execute()

config.update({'session_filter.storage_class': SQLAlchemyStorage})

Change History

Changed 3 months ago by ctrochalakis

  • owner changed from Dimitris Glezos to ctrochalakis
  • status changed from new to accepted

Changed 3 months ago by ctrochalakis

  • status changed from accepted to closed
  • resolution set to fixed

Thanks ricky! This is really useful for a lot of reasons.

I pushed a slightly modified version of the above code in r361

The session_table columns are explicitly specified using sqlalchemy data types:

session_table = Table('session', metadata,
    Column('id', String(40), primary_key=True),
    Column('data', PickleType),
    Column('expiration_time', DateTime)
)

(I really wanted to use that fancy PickleType? :) )

I believe that this storage engine should be pushed upstream (turbogears).

Christos

Note: See TracTickets for help on using tickets.