from sqlalchemy import Column, Integer, String, DateTime, Text from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import sessionmaker from datetime import datetime import json from models.debate import DebateSession from exceptions import ServiceNotConfiguredError from services.config_service import ConfigService Base = declarative_base() class DebateSessionDB(Base): __tablename__ = "debate_sessions" id = Column(Integer, primary_key=True, index=True) session_id = Column(String(255), unique=True, index=True, nullable=False) topic = Column(Text, nullable=False) participants = Column(Text, nullable=False) # JSON string constraints = Column(Text, nullable=False) # JSON string rounds = Column(Text, nullable=False) # JSON string status = Column(String(50), nullable=False) created_at = Column(DateTime, nullable=False) completed_at = Column(DateTime, nullable=True) summary = Column(Text, nullable=True) evidence_library = Column(Text, nullable=True) # JSON string # --------------------------------------------------------------------------- # Lazy engine / session factory # --------------------------------------------------------------------------- _engine = None _SessionLocal = None def _get_engine(): from sqlalchemy import create_engine global _engine if _engine is None: db_url = ConfigService.get_database_url() if not db_url: raise ServiceNotConfiguredError("数据库未配置") _engine = create_engine(db_url) return _engine def _get_session_factory(): global _SessionLocal if _SessionLocal is None: _SessionLocal = sessionmaker( autocommit=False, autoflush=False, bind=_get_engine() ) return _SessionLocal def init_db(): """Create all tables if DB is configured; silently skip otherwise.""" if not ConfigService.is_db_configured(): print("WARNING: Database not configured, skipping table creation.") return try: from db_models import Base as ApiBase engine = _get_engine() Base.metadata.create_all(bind=engine) ApiBase.metadata.create_all(bind=engine) except Exception as e: global _engine, _SessionLocal print(f"WARNING: Database connection failed, skipping table creation: {e}") if _engine is not None: _engine.dispose() _engine = None _SessionLocal = None def debate_session_from_db(db_session) -> DebateSession: """Convert database session to Pydantic model.""" evidence_library = [] if db_session.evidence_library: evidence_library = json.loads(db_session.evidence_library) return DebateSession( session_id=db_session.session_id, topic=db_session.topic, participants=json.loads(db_session.participants), constraints=json.loads(db_session.constraints), rounds=json.loads(db_session.rounds), status=db_session.status, created_at=db_session.created_at, completed_at=db_session.completed_at, summary=db_session.summary, evidence_library=evidence_library ) def debate_session_to_db(session: DebateSession) -> DebateSessionDB: """Convert Pydantic model to database model.""" return DebateSessionDB( session_id=session.session_id, topic=session.topic, participants=json.dumps([p.dict() for p in session.participants]), constraints=json.dumps(session.constraints.dict()), rounds=json.dumps([r.dict() for r in session.rounds], default=str), status=session.status, created_at=session.created_at, completed_at=session.completed_at, summary=session.summary, evidence_library=json.dumps([e.dict() for e in session.evidence_library], default=str) if session.evidence_library else None )