Adds /api/coord/* endpoints for real-time cross-session coordination: - coord_workflows: named units of work per project - coord_work_items: tasks within workflows with dependency chains - coord_session_locks: exclusive resource locks with auto-expiry (TTL) - coord_component_states: live component state per project (upsert) - coord_messages: cross-session messaging and broadcasts - /api/coord/status: cross-project snapshot endpoint Replaces PROJECT_STATE.md as the coordination layer for Claude sessions. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
64 lines
2.0 KiB
Python
64 lines
2.0 KiB
Python
"""Service layer for CoordComponentState."""
|
|
|
|
from typing import Optional
|
|
|
|
from fastapi import HTTPException, status
|
|
from sqlalchemy.dialects.mysql import insert
|
|
from sqlalchemy.orm import Session
|
|
|
|
from api.models.coord_component_state import CoordComponentState
|
|
from api.schemas.coord_component_state import CoordComponentStateUpsert
|
|
|
|
|
|
def get_component_states(
|
|
db: Session,
|
|
project_key: Optional[str] = None,
|
|
) -> list[CoordComponentState]:
|
|
"""Return all component states, optionally filtered by project."""
|
|
q = db.query(CoordComponentState)
|
|
if project_key:
|
|
q = q.filter(CoordComponentState.project_key == project_key)
|
|
return q.order_by(CoordComponentState.project_key, CoordComponentState.component).all()
|
|
|
|
|
|
def upsert_component_state(
|
|
db: Session,
|
|
project_key: str,
|
|
component: str,
|
|
data: CoordComponentStateUpsert,
|
|
) -> CoordComponentState:
|
|
"""Insert or update a component state using MariaDB ON DUPLICATE KEY UPDATE."""
|
|
try:
|
|
stmt = insert(CoordComponentState).values(
|
|
project_key=project_key,
|
|
component=component,
|
|
state=data.state,
|
|
version=data.version,
|
|
notes=data.notes,
|
|
updated_by=data.updated_by,
|
|
)
|
|
stmt = stmt.on_duplicate_key_update(
|
|
state=stmt.inserted.state,
|
|
version=stmt.inserted.version,
|
|
notes=stmt.inserted.notes,
|
|
updated_by=stmt.inserted.updated_by,
|
|
)
|
|
db.execute(stmt)
|
|
db.commit()
|
|
|
|
record = (
|
|
db.query(CoordComponentState)
|
|
.filter(
|
|
CoordComponentState.project_key == project_key,
|
|
CoordComponentState.component == component,
|
|
)
|
|
.first()
|
|
)
|
|
return record
|
|
except Exception as e:
|
|
db.rollback()
|
|
raise HTTPException(
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
detail=f"Failed to upsert component state: {e}"
|
|
)
|