From 43bc82163ed73dade0dc42e98e6acd20f4359403 Mon Sep 17 00:00:00 2001 From: Dan Date: Mon, 5 Dec 2022 12:05:52 -0500 Subject: [PATCH] Setting things up so it's easy to switch databases using a local configuration file (still works with environment variables) Swtiched from a "joinedload" to a "selectinload" which removes a problem with groupby columns in Postgres and sqlite. (https://docs.sqlalchemy.org/en/14/orm/loading_relationships.html#selectin-eager-loading) --- .../spiffworkflow_backend/config/__init__.py | 14 +++++++------- .../spiffworkflow_backend/config/default.py | 4 ++++ .../routes/process_api_blueprint.py | 19 +++++++++++-------- 3 files changed, 22 insertions(+), 15 deletions(-) diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/config/__init__.py b/spiffworkflow-backend/src/spiffworkflow_backend/config/__init__.py index e51d16978..00f540566 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/config/__init__.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/config/__init__.py @@ -14,13 +14,13 @@ class ConfigurationError(Exception): def setup_database_uri(app: Flask) -> None: """Setup_database_uri.""" - if os.environ.get("SPIFFWORKFLOW_BACKEND_DATABASE_URI") is None: + if app.config.get("SPIFFWORKFLOW_BACKEND_DATABASE_URI") is None: database_name = f"spiffworkflow_backend_{app.config['ENV_IDENTIFIER']}" - if os.environ.get("SPIFF_DATABASE_TYPE") == "sqlite": + if app.config.get("SPIFF_DATABASE_TYPE") == "sqlite": app.config[ "SQLALCHEMY_DATABASE_URI" ] = f"sqlite:///{app.instance_path}/db_{app.config['ENV_IDENTIFIER']}.sqlite3" - elif os.environ.get("SPIFF_DATABASE_TYPE") == "postgres": + elif app.config.get("SPIFF_DATABASE_TYPE") == "postgres": app.config[ "SQLALCHEMY_DATABASE_URI" ] = f"postgresql://spiffworkflow_backend:spiffworkflow_backend@localhost:5432/{database_name}" @@ -33,7 +33,7 @@ def setup_database_uri(app: Flask) -> None: "SQLALCHEMY_DATABASE_URI" ] = f"mysql+mysqlconnector://root:{db_pswd}@localhost/{database_name}" else: - app.config["SQLALCHEMY_DATABASE_URI"] = os.environ.get( + app.config["SQLALCHEMY_DATABASE_URI"] = app.config.get( "SPIFFWORKFLOW_BACKEND_DATABASE_URI" ) @@ -73,9 +73,6 @@ def setup_config(app: Flask) -> None: else: app.config.from_pyfile(f"{app.instance_path}/config.py", silent=True) - setup_database_uri(app) - setup_logger(app) - app.config["PERMISSIONS_FILE_FULLPATH"] = None if app.config["SPIFFWORKFLOW_BACKEND_PERMISSIONS_FILE_NAME"]: app.config["PERMISSIONS_FILE_FULLPATH"] = os.path.join( @@ -92,5 +89,8 @@ def setup_config(app: Flask) -> None: if app.config["BPMN_SPEC_ABSOLUTE_DIR"] is None: raise ConfigurationError("BPMN_SPEC_ABSOLUTE_DIR config must be set") + setup_database_uri(app) + setup_logger(app) + thread_local_data = threading.local() app.config["THREAD_LOCAL_DATA"] = thread_local_data diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/config/default.py b/spiffworkflow-backend/src/spiffworkflow_backend/config/default.py index bb2cab582..79211c123 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/config/default.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/config/default.py @@ -60,3 +60,7 @@ SENTRY_TRACES_SAMPLE_RATE = environ.get( SPIFFWORKFLOW_BACKEND_LOG_LEVEL = environ.get( "SPIFFWORKFLOW_BACKEND_LOG_LEVEL", default="info" ) + +# Datbase Configuration +SPIFF_DATABASE_TYPE =environ.get("SPIFF_DATABASE_TYPE", default="mysql") # can also be sqlite, postgres +SPIFFWORKFLOW_BACKEND_DATABASE_URI=environ.get("SPIFFWORKFLOW_BACKEND_DATABASE_URI", default=None) # Overide above with specific sqlalchymy connection string. diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_api_blueprint.py b/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_api_blueprint.py index 739e689d2..78c12a90f 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_api_blueprint.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_api_blueprint.py @@ -30,7 +30,7 @@ from SpiffWorkflow.task import TaskState from sqlalchemy import and_ from sqlalchemy import asc from sqlalchemy import desc -from sqlalchemy.orm import joinedload +from sqlalchemy.orm import selectinload from spiffworkflow_backend.exceptions.process_entity_not_found_error import ( ProcessEntityNotFoundError, @@ -814,7 +814,7 @@ def process_instance_list( process_instance_query = ProcessInstanceModel.query # Always join that hot user table for good performance at serialization time. process_instance_query = process_instance_query.options( - joinedload(ProcessInstanceModel.process_initiator) + selectinload(ProcessInstanceModel.process_initiator) ) if report_filter.process_model_identifier is not None: @@ -928,13 +928,16 @@ def process_instance_list( UserGroupAssignmentModel.user_id == g.user.id ) - process_instances = ( - process_instance_query.group_by(ProcessInstanceModel.id) - .order_by( - ProcessInstanceModel.start_in_seconds.desc(), ProcessInstanceModel.id.desc() # type: ignore + try: + process_instances = ( + process_instance_query.group_by(ProcessInstanceModel.id) + .order_by( + ProcessInstanceModel.start_in_seconds.desc(), ProcessInstanceModel.id.desc() # type: ignore + ) + .paginate(page=page, per_page=per_page, error_out=False) ) - .paginate(page=page, per_page=per_page, error_out=False) - ) + except Exception as e: + print(e) results = list( map(