From 5b3eb4327ce7ae09e455684dc6bc4430ba0de0a1 Mon Sep 17 00:00:00 2001 From: Automated Action Date: Fri, 23 May 2025 09:39:26 +0000 Subject: [PATCH] Fix database configuration to handle permission issues and improve error handling --- alembic.ini | 3 ++- app/core/config.py | 5 ++++- app/db/session.py | 53 ++++++++++++++++++++++++++++++++++++++-------- main.py | 22 ++++++++++++++++++- migrations/env.py | 4 ++++ 5 files changed, 75 insertions(+), 12 deletions(-) diff --git a/alembic.ini b/alembic.ini index 80b926f..170be6b 100644 --- a/alembic.ini +++ b/alembic.ini @@ -60,7 +60,8 @@ version_path_separator = os # Use os.pathsep. Default configuration used for ne # are written from script.py.mako # output_encoding = utf-8 -sqlalchemy.url = sqlite:////app/storage/db/db.sqlite +# This URL will be overridden by the value in env.py +sqlalchemy.url = sqlite:///db.sqlite [post_write_hooks] diff --git a/app/core/config.py b/app/core/config.py index 64aeb3f..7ae9896 100644 --- a/app/core/config.py +++ b/app/core/config.py @@ -1,3 +1,4 @@ +import os from pydantic_settings import BaseSettings from pathlib import Path @@ -9,7 +10,9 @@ class Settings(BaseSettings): VERSION: str = "0.1.0" # Database settings - DB_DIR: Path = Path("/app") / "storage" / "db" + # Use environment variable for database path or fall back to a directory + # relative to the current working directory for better compatibility + DB_DIR: Path = Path(os.environ.get("DB_DIR", os.path.join(os.getcwd(), "storage", "db"))) SQLALCHEMY_DATABASE_URL: str = f"sqlite:///{DB_DIR}/db.sqlite" class Config: diff --git a/app/db/session.py b/app/db/session.py index 14fc91c..72352b9 100644 --- a/app/db/session.py +++ b/app/db/session.py @@ -1,24 +1,59 @@ +import os +import logging +from pathlib import Path from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker +from sqlalchemy.exc import SQLAlchemyError from app.core.config import settings -# Ensure the database directory exists -DB_DIR = settings.DB_DIR -DB_DIR.mkdir(parents=True, exist_ok=True) +logger = logging.getLogger(__name__) -SQLALCHEMY_DATABASE_URL = settings.SQLALCHEMY_DATABASE_URL +# Ensure the database directory exists with proper error handling +try: + DB_DIR = settings.DB_DIR + DB_DIR.mkdir(parents=True, exist_ok=True) + logger.info(f"Database directory created at: {DB_DIR}") +except (PermissionError, OSError) as e: + # If we can't create the directory, log the error and try a fallback location + logger.error(f"Failed to create database directory at {DB_DIR}: {str(e)}") + # Fallback to a directory in the current working directory + DB_DIR = Path(os.getcwd()) / "db" + DB_DIR.mkdir(parents=True, exist_ok=True) + logger.info(f"Using fallback database directory: {DB_DIR}") -engine = create_engine( - SQLALCHEMY_DATABASE_URL, - connect_args={"check_same_thread": False} -) -SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) +# Create the database URL +SQLALCHEMY_DATABASE_URL = f"sqlite:///{DB_DIR}/db.sqlite" +logger.info(f"Using database URL: {SQLALCHEMY_DATABASE_URL}") + +# Create the engine with proper error handling +try: + engine = create_engine( + SQLALCHEMY_DATABASE_URL, + connect_args={"check_same_thread": False} + ) + SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) + logger.info("Database engine initialized successfully") +except SQLAlchemyError as e: + logger.error(f"Failed to initialize database engine: {str(e)}") + # Create a dummy engine and session for the app to at least start + # This will cause database operations to fail, but the app will start + engine = None + SessionLocal = None def get_db(): + if SessionLocal is None: + # If SessionLocal is None, the database engine failed to initialize + # Log an error and raise an exception + logger.error("Cannot get database session: Database engine not initialized") + raise SQLAlchemyError("Database engine not initialized") + db = SessionLocal() try: yield db + except SQLAlchemyError as e: + logger.error(f"Database error: {str(e)}") + raise finally: db.close() \ No newline at end of file diff --git a/main.py b/main.py index 9430f0c..648c20b 100644 --- a/main.py +++ b/main.py @@ -1,7 +1,27 @@ import uvicorn +import logging +import sys from app.core.app import create_app -app = create_app() +# Configure logging +logging.basicConfig( + level=logging.INFO, + format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", + handlers=[ + logging.StreamHandler(sys.stdout) + ] +) +logger = logging.getLogger(__name__) + +# Create FastAPI application +logger.info("Initializing FastAPI application") +try: + app = create_app() + logger.info("FastAPI application initialized successfully") +except Exception as e: + logger.error(f"Failed to initialize FastAPI application: {str(e)}") + # Re-raise the exception for supervisor to see + raise if __name__ == "__main__": uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=True) \ No newline at end of file diff --git a/migrations/env.py b/migrations/env.py index 92c3e0f..687086e 100644 --- a/migrations/env.py +++ b/migrations/env.py @@ -4,11 +4,15 @@ from sqlalchemy import engine_from_config from sqlalchemy import pool from alembic import context +from app.db.session import SQLALCHEMY_DATABASE_URL # this is the Alembic Config object, which provides # access to the values within the .ini file in use. config = context.config +# Override the sqlalchemy.url in the Alembic config with our actual URL +config.set_main_option("sqlalchemy.url", SQLALCHEMY_DATABASE_URL) + # Interpret the config file for Python logging. # This line sets up loggers basically. if config.config_file_name is not None: