- Migrated from HIVE branding to WHOOSH across all components - Enhanced backend API with new services: AI models, BZZZ integration, templates, members - Added comprehensive testing suite with security, performance, and integration tests - Improved frontend with new components for project setup, AI models, and team management - Updated MCP server implementation with WHOOSH-specific tools and resources - Enhanced deployment configurations with production-ready Docker setups - Added comprehensive documentation and setup guides - Implemented age encryption service and UCXL integration 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
82 lines
2.6 KiB
Python
82 lines
2.6 KiB
Python
from sqlalchemy import create_engine, event, text
|
|
from sqlalchemy.ext.declarative import declarative_base
|
|
from sqlalchemy.orm import sessionmaker
|
|
from sqlalchemy.pool import QueuePool
|
|
from sqlalchemy.exc import DisconnectionError
|
|
import os
|
|
import time
|
|
import logging
|
|
|
|
# Enhanced database configuration with connection pooling
|
|
DATABASE_URL = os.getenv("DATABASE_URL", "postgresql://postgres:whoosh123@whoosh_postgres:5432/whoosh")
|
|
|
|
# Create engine with connection pooling and reliability features
|
|
if "sqlite" in DATABASE_URL:
|
|
engine = create_engine(
|
|
DATABASE_URL,
|
|
connect_args={"check_same_thread": False},
|
|
pool_pre_ping=True
|
|
)
|
|
else:
|
|
engine = create_engine(
|
|
DATABASE_URL,
|
|
poolclass=QueuePool,
|
|
pool_size=10,
|
|
max_overflow=20,
|
|
pool_pre_ping=True,
|
|
pool_recycle=3600,
|
|
echo=False
|
|
)
|
|
|
|
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
|
|
|
|
Base = declarative_base()
|
|
|
|
@event.listens_for(engine, "connect")
|
|
def set_sqlite_pragma(dbapi_connection, connection_record):
|
|
"""Set SQLite pragma for foreign key support"""
|
|
if "sqlite" in DATABASE_URL:
|
|
cursor = dbapi_connection.cursor()
|
|
cursor.execute("PRAGMA foreign_keys=ON")
|
|
cursor.close()
|
|
|
|
def get_db():
|
|
"""Database session dependency with proper error handling"""
|
|
db = SessionLocal()
|
|
try:
|
|
yield db
|
|
except DisconnectionError as e:
|
|
logging.error(f"Database disconnection error: {e}")
|
|
db.rollback()
|
|
raise
|
|
except Exception as e:
|
|
logging.error(f"Database error: {e}")
|
|
db.rollback()
|
|
raise
|
|
finally:
|
|
db.close()
|
|
|
|
def test_database_connection():
|
|
"""Test database connectivity"""
|
|
try:
|
|
with engine.connect() as conn:
|
|
result = conn.execute(text("SELECT 1"))
|
|
return True
|
|
except Exception as e:
|
|
logging.error(f"Database connection test failed: {e}")
|
|
return False
|
|
|
|
def init_database_with_retry(max_retries=5, retry_delay=2):
|
|
"""Initialize database with retry logic"""
|
|
for attempt in range(max_retries):
|
|
try:
|
|
Base.metadata.create_all(bind=engine)
|
|
logging.info("Database initialized successfully")
|
|
return True
|
|
except Exception as e:
|
|
if attempt == max_retries - 1:
|
|
logging.error(f"Database initialization failed after {max_retries} attempts: {e}")
|
|
raise
|
|
logging.warning(f"Database initialization attempt {attempt + 1} failed: {e}")
|
|
time.sleep(retry_delay ** attempt)
|
|
return False |