Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deal better with database connection loss (Issue #6) #7

Merged
merged 1 commit into from
May 18, 2018
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Deal better with database connection loss (Issue #6)
    * Wrap all database operations (including reads) in an SQLAlchemy transaction
      per http://docs.sqlalchemy.org/en/latest/orm/session_basics.html#when-do-i-construct-a-session-when-do-i-commit-it-and-when-do-i-close-it
    * Add configuration parameters to set the pool_recycle and pool_pre_ping engine parameters
      defaults are to recycle in 30 minutes and to always ping
  • Loading branch information
oz-linden committed May 11, 2018
commit 60fa56cedb21193b6f423a98594da02bbe8ba15a
30 changes: 22 additions & 8 deletions sql.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4

import logging
from contextlib import contextmanager
from jsonpickle import encode, decode
from typing import Any
from sqlalchemy import (
Expand Down Expand Up @@ -35,27 +36,38 @@ def __init__(self, session, clazz):
self.session = session
self.clazz = clazz

@contextmanager
def _session_op(self):
try:
yield self.session
self.session.commit()
except:
self.session.rollback()
raise

def get(self, key: str) -> Any:
try:
return self.session.query(
self.clazz).filter(self.clazz._key == key).one().value
with self._session_op() as session:
result = session.query(self.clazz).filter(self.clazz._key == key).one().value
except NoResultFound:
raise KeyError("%s doesn't exists." % key)
return result

def remove(self, key: str):
try:
self.session.query(
self.clazz).filter(self.clazz._key == key).delete()
self.session.commit()
with self._session_op() as session:
session.query(self.clazz).filter(self.clazz._key == key).delete()
except NoResultFound:
raise KeyError("%s doesn't exists." % key)

def set(self, key: str, value: Any) -> None:
self.session.merge(self.clazz(key, value))
self.session.commit()
with self._session_op() as session:
session.merge(self.clazz(key, value))

def len(self):
return self.session.query(self.clazz).count()
with self._session_op() as session:
length = session.query(self.clazz).count()
return length

def keys(self):
return (kv.key for kv in self.session.query(self.clazz).all())
Expand Down Expand Up @@ -89,6 +101,8 @@ def __init__(self, bot_config):
else:
self._engine = create_engine(
config[DATA_URL_ENTRY],
pool_recycle=config.get('connection_recycle', 1800),
pool_pre_ping=config.get('connection_ping', True),
echo=bot_config.BOT_LOG_LEVEL == logging.DEBUG)
self._metadata = MetaData()
self._sessionmaker = sessionmaker()
Expand Down