feat: add git-consistent memory gateway architecture
This commit is contained in:
115
gateway/app/main.py
Normal file
115
gateway/app/main.py
Normal file
@@ -0,0 +1,115 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import datetime, timezone
|
||||
import json
|
||||
from typing import Any
|
||||
|
||||
from fastapi import FastAPI, HTTPException
|
||||
from fastapi.responses import JSONResponse
|
||||
|
||||
from .config import Settings, get_settings
|
||||
from .git_manager import GitCommandError, GitManager
|
||||
from .locks import WorkspaceLockManager
|
||||
from .models import HealthResponse, QueryRequest, QueryResponse, StatusResponse, SyncRequest, SyncResponse, WorkspaceStatusItem
|
||||
from .qmd_client import QMDClient, QMDCommandError
|
||||
from .query_service import QueryService
|
||||
from .sync_service import SyncService
|
||||
from .workspace_manager import WorkspaceManager
|
||||
|
||||
|
||||
def create_app(
|
||||
settings: Settings | None = None,
|
||||
*,
|
||||
qmd_client: QMDClient | None = None,
|
||||
git_manager: GitManager | None = None,
|
||||
lock_manager: WorkspaceLockManager | None = None,
|
||||
) -> FastAPI:
|
||||
app = FastAPI(title="memory-gateway", version="0.1.0")
|
||||
|
||||
resolved_settings = settings or get_settings()
|
||||
workspace_manager = WorkspaceManager(
|
||||
workspaces_root=resolved_settings.workspaces_root,
|
||||
default_branch=resolved_settings.default_branch,
|
||||
qmd_index_prefix=resolved_settings.qmd_index_prefix,
|
||||
)
|
||||
resolved_git_manager = git_manager or GitManager(
|
||||
remote_url=resolved_settings.git_remote_url,
|
||||
mirror_path=resolved_settings.git_mirror_path,
|
||||
)
|
||||
resolved_qmd_client = qmd_client or QMDClient(
|
||||
qmd_binary=resolved_settings.qmd_binary,
|
||||
timeout_seconds=resolved_settings.qmd_timeout_seconds,
|
||||
xdg_cache_home=resolved_settings.xdg_cache_home,
|
||||
xdg_config_home=resolved_settings.xdg_config_home,
|
||||
)
|
||||
resolved_lock_manager = lock_manager or WorkspaceLockManager()
|
||||
|
||||
sync_service = SyncService(
|
||||
settings=resolved_settings,
|
||||
workspace_manager=workspace_manager,
|
||||
git_manager=resolved_git_manager,
|
||||
qmd_client=resolved_qmd_client,
|
||||
)
|
||||
query_service = QueryService(
|
||||
sync_service=sync_service,
|
||||
qmd_client=resolved_qmd_client,
|
||||
lock_manager=resolved_lock_manager,
|
||||
)
|
||||
|
||||
app.state.settings = resolved_settings
|
||||
app.state.sync_service = sync_service
|
||||
app.state.query_service = query_service
|
||||
|
||||
@app.exception_handler(ValueError)
|
||||
def handle_value_error(_: Any, exc: ValueError) -> JSONResponse:
|
||||
return JSONResponse(status_code=400, content={"ok": False, "error": str(exc)})
|
||||
|
||||
@app.exception_handler(GitCommandError)
|
||||
def handle_git_error(_: Any, exc: GitCommandError) -> JSONResponse:
|
||||
return JSONResponse(status_code=500, content={"ok": False, "error": str(exc)})
|
||||
|
||||
@app.exception_handler(QMDCommandError)
|
||||
def handle_qmd_error(_: Any, exc: QMDCommandError) -> JSONResponse:
|
||||
return JSONResponse(status_code=500, content={"ok": False, "error": str(exc)})
|
||||
|
||||
@app.get("/health", response_model=HealthResponse)
|
||||
def health() -> HealthResponse:
|
||||
return HealthResponse(ok=True, service="memory-gateway", timestamp=datetime.now(timezone.utc))
|
||||
|
||||
@app.post("/query", response_model=QueryResponse)
|
||||
def query(request: QueryRequest) -> QueryResponse:
|
||||
return app.state.query_service.handle_query(request)
|
||||
|
||||
@app.post("/sync", response_model=SyncResponse)
|
||||
def sync(request: SyncRequest) -> SyncResponse:
|
||||
return app.state.query_service.handle_sync(request)
|
||||
|
||||
@app.get("/status", response_model=StatusResponse)
|
||||
def status() -> StatusResponse:
|
||||
raw_states = app.state.sync_service.list_workspace_states()
|
||||
items: list[WorkspaceStatusItem] = []
|
||||
for row in raw_states:
|
||||
synced_at_raw = row.get("synced_at")
|
||||
if not synced_at_raw:
|
||||
continue
|
||||
items.append(
|
||||
WorkspaceStatusItem(
|
||||
branch=row["branch"],
|
||||
workspace=row["workspace"],
|
||||
commit_hash=row["commit_hash"],
|
||||
synced_at=datetime.fromisoformat(synced_at_raw),
|
||||
qmd_collection=row["qmd_collection"],
|
||||
)
|
||||
)
|
||||
|
||||
return StatusResponse(
|
||||
ok=True,
|
||||
default_branch=app.state.settings.default_branch,
|
||||
mirror_path=str(app.state.settings.git_mirror_path),
|
||||
workspaces=items,
|
||||
)
|
||||
|
||||
return app
|
||||
|
||||
|
||||
app = create_app()
|
||||
Reference in New Issue
Block a user