""" MySQL Connector. Manages interactions with MySQL for transcoder RDS databse. """ from contextlib import contextmanager from sqlalchemy import create_engine from sqlalchemy import pool from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import scoped_session from sqlalchemy.orm import sessionmaker from asset_transcoder import config from asset_transcoder.api import app def _create_engine(db_url): """Create engine based on config settings.""" if config.POOL_CLASS == pool.QueuePool and config.ENVIRONMENT: return create_engine( db_url, pool_size=config.POOL_SIZE, max_overflow=config.POOL_MAX_OVERFLOW, pool_recycle=config.POOL_RECYCLE_MS) return create_engine(db_url, poolclass=config.POOL_CLASS) asset_transcoder_db_engine = _create_engine(config.TRANSCODER_DB_URL) asset_transcoder_session_factory = sessionmaker(bind=asset_transcoder_db_engine) asset_transcoder_db_session = scoped_session(asset_transcoder_session_factory) sessions = (asset_transcoder_db_session, ) BaseModel = declarative_base() @app.teardown_request def remove_session(exception): """For scoped_session, explicitly close session at end of each request. Args: exception (object): When a teardown function was called because of an exception it will be passed an error object. """ for session in sessions: session.remove() @contextmanager def transcoder_db_session(read_only=False): """ Provide transactional scope around series of operations for ows_transcoder. Taken from http://docs.sqlalchemy.org/en/latest/orm/session_basics.html. This handles rollback and closing of session, so there is no need to do that throughout the code. Usage: with transcoder_database_session() as session: session.execute(query) """ session = asset_transcoder_db_session() try: yield session if not read_only: session.commit() except Exception: session.rollback() raise