init
This commit is contained in:
0
storage/__init__.py
Normal file
0
storage/__init__.py
Normal file
109
storage/database.py
Normal file
109
storage/database.py
Normal file
@@ -0,0 +1,109 @@
|
||||
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
|
||||
)
|
||||
67
storage/session_manager.py
Normal file
67
storage/session_manager.py
Normal file
@@ -0,0 +1,67 @@
|
||||
from sqlalchemy.orm import Session
|
||||
from datetime import datetime
|
||||
import json
|
||||
from typing import Optional
|
||||
|
||||
from models.debate import DebateSession
|
||||
from storage.database import DebateSessionDB, debate_session_from_db, debate_session_to_db
|
||||
|
||||
|
||||
class SessionManager:
|
||||
"""
|
||||
Manages debate sessions in storage
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
async def save_session(self, db: Session, session: DebateSession):
|
||||
"""
|
||||
Save a debate session to the database
|
||||
"""
|
||||
db_session = debate_session_to_db(session)
|
||||
db.add(db_session)
|
||||
db.commit()
|
||||
db.refresh(db_session)
|
||||
|
||||
async def get_session(self, db: Session, session_id: str) -> Optional[DebateSession]:
|
||||
"""
|
||||
Retrieve a debate session from the database
|
||||
"""
|
||||
db_session = db.query(DebateSessionDB).filter(DebateSessionDB.session_id == session_id).first()
|
||||
if not db_session:
|
||||
return None
|
||||
return debate_session_from_db(db_session)
|
||||
|
||||
async def update_session(self, db: Session, session: DebateSession):
|
||||
"""
|
||||
Update an existing debate session in the database
|
||||
"""
|
||||
db_session = db.query(DebateSessionDB).filter(DebateSessionDB.session_id == session.session_id).first()
|
||||
if db_session:
|
||||
db_session.topic = session.topic
|
||||
db_session.participants = json.dumps([p.dict() for p in session.participants])
|
||||
db_session.constraints = json.dumps(session.constraints.dict())
|
||||
db_session.rounds = json.dumps([r.dict() for r in session.rounds], default=str)
|
||||
db_session.status = session.status
|
||||
db_session.completed_at = session.completed_at
|
||||
db_session.summary = session.summary
|
||||
db_session.evidence_library = json.dumps([e.dict() for e in session.evidence_library], default=str) if session.evidence_library else None
|
||||
|
||||
db.commit()
|
||||
db.refresh(db_session)
|
||||
|
||||
async def list_sessions(self, db: Session):
|
||||
"""
|
||||
List all debate sessions
|
||||
"""
|
||||
db_sessions = db.query(DebateSessionDB).all()
|
||||
return [
|
||||
{
|
||||
"session_id": db_session.session_id,
|
||||
"topic": db_session.topic,
|
||||
"status": db_session.status,
|
||||
"created_at": db_session.created_at.isoformat() if db_session.created_at else None
|
||||
}
|
||||
for db_session in db_sessions
|
||||
]
|
||||
Reference in New Issue
Block a user