LINUX.ORG.RU

Tornado Sessions - Закрывать или нет Connection в DataBase?

 , , ,


0

1

Странная ситуация. Пишу механизм сессий для Tornado в PostgreSQL. Логика вроде проста: в prepare() каждого запроса - смотрю, есть ли секурная кука sesion_id, если нет ее - создаю новую сессию, если есть - загружаю данные сессии из БД. Но вот не тут-то было.

class BaseHandler(tornado.web.RequestHandler):
    ''' от этого класса наследуются хендлеры '''
    def get_session(self):
        sessionId = self.get_secure_cookie("session_id")
        logger.debug("BaseHandler.get_session: %s" % sessionId)
        session = None
        if (sessionId == None) :
            session = SessionManager._create_session()
        else :
            session = SessionManager._load_session(sessionId)

        return session

    def prepare(self):
        self.session = self.get_session()


    def on_finish(self):
        sessionId = self.set_secure_cookie("session_id", self.session.session_id)
        SessionManager._save_session(self.session)


class SessionManager(Manager):

    @staticmethod
    def _create_session(sessionId=''):
        sessionId = SessionManager._create_session_id() if (not sessionId or sessionId == '') else sessionId
        logger.debug("SessionManager._create_session: %s" % sessionId)
        while (SessionManager._check_session_id_exists(sessionId)) :
            sessionId = SessionManager._create_session_id()

        s = Connection.getSession()
        session = Session(session_id = sessionId)
        session.restore_data()
        s.add(session)
        s.commit()
        #s.close()
        return session


    @staticmethod
    def _load_session(sessionId:str):
        logger.debug("SessionManager._load_session: %s" % sessionId)
        s = Connection.getSession()
        session = s.query(Session).filter(Session.session_id == sessionId).first()
        #s.close()
        if (session) :
            logger.debug("SessionManager._load_session: loaded")
        else :
            logger.debug("SessionManager._load_session: not found, creating a new one")
            session = SessionManager._create_session(sessionId)
        return session


    @staticmethod
    def _check_session_id_exists(sessionId:str):
        logger.debug("SessionManager._check_session_id: %s" % sessionId)
        s = Connection.getSession()
        if (s.query(Session).filter(Session.session_id == sessionId).first()) :
            s.close()
            return True
        else :
            s.close()
            return False


    @staticmethod
    def _save_session(session):
        session.pack_data()
        logger.debug("SessionManager._save_session: %s" % session.session_data)
        s = Connection.getSession()
        s.add(session)
        s.commit()
        s.close()

Проблема в закрытии connection-ов в БД. Если в _load_session и _create_session я их закрываю, то в _save_session получаю ошибку:

sqlalchemy.orm.exc.DetachedInstanceError: Instance <Session at 0x1cb43c82e80> is not bound to a Session; attribute refresh operation cannot proceed

А если я в _load_session и _create_session оставляю connection в БД открытым, то ошибка:

sqlalchemy.exc.InvalidRequestError: Object '<Session at 0x27ba5fa9e80>' is already attached to session '2' (this is '3')

Так как же быть? Как правильно подключать сессии в Tornado?

★★★★★

Вроде разобрался. Нужно использовать scoped_session:

session_factory = sessionmaker(bind=engine)
Session = scoped_session(session_factory)

#Session = sessionmaker(bind=engine) # так было, получал ошибки


class Connection(object):
    
    @staticmethod
    def getSession():
        return Session()

но теперь другой вопрос: on_finish() RequestHandler-а не сохраняет секурные куки. Т.е. не работает:

def on_finish(self):
        logging.debug("BaseHandler.on_finish: %s" % self.session.session_id)
        self.set_secure_cookie("my_session_id", self.session.session_id)
        sessionIdCheck = self.get_secure_cookie("my_session_id")
        logging.debug("BaseHandler.on_finish - check session id: %s" % sessionIdCheck)
        SessionManager._save_session(self.session)

в консоль пишет:

BaseHandler.on_finish - check session id: None

Где нужно это делать тогда?

bvn13 ★★★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.