mirror of
https://pagure.io/fm-orchestrator.git
synced 2026-04-14 15:49:46 +08:00
Since ComponentBuildTrace(s) get created with db_session.commit() call, is is not possible to commit more items in bulk if they already have been flushed. Current unit-tests' setup can be significantly sped up if items can be quickly flushed on the fly and bulk-commited only once at the end. Moreover in general it seems more appropriate/safer to handle this in before_flush as any implicit or accidental flush could cause new build traces not to be created at all. As flush is implicitly called before every commit anyway, this change shouldn't pose any harm.
85 lines
3.0 KiB
Python
85 lines
3.0 KiB
Python
# -*- coding: utf-8 -*-
|
|
# SPDX-License-Identifier: MIT
|
|
from __future__ import absolute_import
|
|
|
|
import sqlalchemy.event
|
|
from sqlalchemy.pool import NullPool
|
|
from sqlalchemy.orm import scoped_session, sessionmaker
|
|
|
|
from module_build_service.common.config import conf
|
|
from module_build_service.common.models import (
|
|
session_before_flush_handlers, send_message_after_module_build_state_change
|
|
)
|
|
|
|
__all__ = ("db_session",)
|
|
|
|
|
|
def _setup_event_listeners(db_session):
|
|
"""
|
|
Starts listening for events related to the database session.
|
|
"""
|
|
event_hooks = (
|
|
("before_flush", session_before_flush_handlers),
|
|
("after_commit", send_message_after_module_build_state_change),
|
|
)
|
|
|
|
for event, handler in event_hooks:
|
|
if not sqlalchemy.event.contains(db_session, event, handler):
|
|
sqlalchemy.event.listen(db_session, event, handler)
|
|
|
|
# initialize DB event listeners from the monitor module
|
|
from module_build_service.common.monitor import db_hook_event_listeners
|
|
|
|
db_hook_event_listeners(db_session.bind.engine)
|
|
|
|
|
|
def apply_engine_options(conf):
|
|
options = {
|
|
"configuration": {"sqlalchemy.url": conf.sqlalchemy_database_uri},
|
|
}
|
|
if conf.sqlalchemy_database_uri.startswith("sqlite://"):
|
|
options.update({
|
|
# For local module build, MBS is actually a multi-threaded
|
|
# application. The command submitting a module build runs in its
|
|
# own thread, and the backend build workflow, implemented as a
|
|
# fedmsg consumer on top of fedmsg-hub, runs in separate threads.
|
|
# So, disable this option in order to allow accessing data which
|
|
# was written from another thread.
|
|
"connect_args": {"check_same_thread": False},
|
|
|
|
# Both local module build and running tests requires a file-based
|
|
# SQLite database, we do not use a connection pool for these two
|
|
# scenarios.
|
|
"poolclass": NullPool,
|
|
})
|
|
else:
|
|
# TODO - we could use ZopeTransactionExtension() here some day for
|
|
# improved safety on the backend.
|
|
pool_options = {}
|
|
|
|
# Apply pool options SQLALCHEMY_* set in MBS config.
|
|
# Abbrev sa stands for SQLAlchemy.
|
|
def apply_mbs_option(mbs_config_key, sa_config_key):
|
|
value = getattr(conf, mbs_config_key, None)
|
|
if value is not None:
|
|
pool_options[sa_config_key] = value
|
|
|
|
apply_mbs_option("sqlalchemy_pool_size", "pool_size")
|
|
apply_mbs_option("sqlalchemy_pool_timeout", "pool_timeout")
|
|
apply_mbs_option("sqlalchemy_pool_recycle", "pool_recycle")
|
|
apply_mbs_option("sqlalchemy_max_overflow", "max_overflow")
|
|
|
|
options.update(pool_options)
|
|
|
|
return options
|
|
|
|
|
|
engine_opts = apply_engine_options(conf)
|
|
engine = sqlalchemy.engine_from_config(**engine_opts)
|
|
session_factory = sessionmaker(bind=engine)
|
|
|
|
# This is the global, singleton database Session that could be used to operate
|
|
# database queries.
|
|
db_session = scoped_session(session_factory)
|
|
_setup_event_listeners(db_session)
|