Spaces:
Sleeping
Sleeping
File size: 4,316 Bytes
1cff830 bfe88a9 4809b28 292f6be bfe88a9 4809b28 bfe88a9 4809b28 465ba2d 292f6be 4809b28 bfe88a9 465ba2d 4809b28 292f6be 4809b28 bfe88a9 4809b28 bfe88a9 292f6be 4809b28 1cff830 292f6be bfe88a9 4809b28 465ba2d 4809b28 465ba2d 4809b28 465ba2d 1cff830 465ba2d 292f6be 465ba2d 292f6be 465ba2d 292f6be 4809b28 1cff830 292f6be 4809b28 292f6be 1cff830 465ba2d bfe88a9 1cff830 bfe88a9 1cff830 292f6be 4809b28 1cff830 465ba2d 1cff830 465ba2d bfe88a9 1cff830 4809b28 1cff830 292f6be bfe88a9 1cff830 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
# app/database.py
import os
from databases import Database
from dotenv import load_dotenv
from sqlalchemy import create_engine, MetaData, Table, Column, Integer, String, text
import logging
from urllib.parse import urlparse, urlunparse, parse_qs, urlencode
load_dotenv()
logger = logging.getLogger(__name__)
# --- Database URL Configuration ---
# --- CHANGE THIS LINE: Use the /tmp directory ---
DEFAULT_DB_PATH = "/tmp/app.db" # Store DB in the temporary directory
raw_db_url = os.getenv("DATABASE_URL", f"sqlite+aiosqlite:///{DEFAULT_DB_PATH}")
# --- (Rest of the URL parsing and async Database setup remains the same) ---
final_database_url = raw_db_url
if raw_db_url.startswith("sqlite+aiosqlite"):
parsed_url = urlparse(raw_db_url)
query_params = parse_qs(parsed_url.query)
if 'check_same_thread' not in query_params:
query_params['check_same_thread'] = ['False']
new_query = urlencode(query_params, doseq=True)
final_database_url = urlunparse(parsed_url._replace(query=new_query))
logger.info(f"Using final async DB URL: {final_database_url}")
else:
logger.info(f"Using non-SQLite async DB URL: {final_database_url}")
database = Database(final_database_url)
metadata = MetaData()
users = Table(
"users",
metadata,
Column("id", Integer, primary_key=True),
Column("email", String, unique=True, index=True, nullable=False),
Column("hashed_password", String, nullable=False),
)
# --- Synchronous Engine for Initial Table Creation ---
sync_db_url = final_database_url.replace("+aiosqlite", "")
logger.info(f"Using synchronous DB URL for initial check/create: {sync_db_url}")
engine = create_engine(sync_db_url)
# --- Directory and Table Creation Logic ---
db_file_path = ""
if sync_db_url.startswith("sqlite"):
# Path should be absolute starting with /tmp/
path_part = sync_db_url.split("sqlite:///")[-1].split("?")[0]
db_file_path = path_part # Should be /tmp/app.db
if db_file_path:
# --- CHANGE THIS LINE: Check writability of the /tmp directory ---
db_dir = os.path.dirname(db_file_path) # Should be /tmp
logger.info(f"Ensuring database directory exists: {db_dir}")
try:
# /tmp should always exist, but check writability
if not os.path.exists(db_dir):
# This would be very strange, but log it.
logger.error(f"CRITICAL: Directory {db_dir} does not exist!")
# No need to create /tmp usually
if not os.access(db_dir, os.W_OK):
# If even /tmp isn't writable, something is very wrong with the environment
logger.error(f"CRITICAL: Directory {db_dir} is not writable! Cannot create database.")
else:
logger.info(f"Database directory {db_dir} appears writable.")
except OSError as e:
logger.error(f"Error accessing database directory {db_dir}: {e}")
except Exception as e:
logger.error(f"Unexpected error checking directory {db_dir}: {e}")
# --- (Rest of the table creation logic and async functions remain the same) ---
try:
logger.info("Attempting to connect with sync engine to check/create table...")
with engine.connect() as connection:
try:
connection.execute(text("SELECT 1 FROM users LIMIT 1"))
logger.info("Users table already exists.")
except Exception as table_check_exc:
logger.warning(f"Users table check failed ({type(table_check_exc).__name__}), attempting creation...")
metadata.create_all(bind=engine)
logger.info("Users table created (or creation attempted).")
except Exception as e:
# This *should* finally succeed if /tmp is writable
logger.exception(f"CRITICAL: Failed to connect/create database tables using sync engine: {e}")
# Async connect/disconnect functions
async def connect_db():
try:
await database.connect()
logger.info(f"Database connection established (async): {final_database_url}")
except Exception as e:
logger.exception(f"Failed to establish async database connection: {e}")
raise
async def disconnect_db():
try:
await database.disconnect()
logger.info("Database connection closed (async).")
except Exception as e:
logger.exception(f"Error closing async database connection: {e}") |