refactor(gateway): restructure gateway with new dependency injection and services

Reorganize app/gateway/ with:
- common/ - lifespan management
- dependencies/ - FastAPI dependency injection (db, checkpointer, repositories, stream_bridge)
- services/runs/ - run execution services (facade_factory, input adapters, store operations)
- registrar.py - router registration
- router.py - main router setup

Simplify app.py to use the new modular structure.
Remove deprecated utils.py.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
rayhpeng
2026-04-22 11:27:08 +08:00
parent 274255b1a5
commit 39a575617b
24 changed files with 1120 additions and 371 deletions
@@ -0,0 +1,11 @@
"""App-owned runs store adapters."""
from .create_store import AppRunCreateStore
from .delete_store import AppRunDeleteStore
from .query_store import AppRunQueryStore
__all__ = [
"AppRunCreateStore",
"AppRunDeleteStore",
"AppRunQueryStore",
]
@@ -0,0 +1,38 @@
"""App-owned durable run creation adapter."""
from __future__ import annotations
from deerflow.runtime.runs.store import RunCreateStore
from deerflow.runtime.runs.types import RunRecord
from app.infra.storage import ThreadMetaStorage
from app.infra.storage.runs import RunWriteRepository
class AppRunCreateStore(RunCreateStore):
"""Write the initial durable row for a newly created run."""
def __init__(self, repo: RunWriteRepository, thread_meta_storage: ThreadMetaStorage | None = None) -> None:
self._repo = repo
self._thread_meta_storage = thread_meta_storage
async def create_run(self, record: RunRecord) -> None:
await self._repo.create(
run_id=record.run_id,
thread_id=record.thread_id,
assistant_id=record.assistant_id,
status=str(record.status),
metadata=record.metadata,
follow_up_to_run_id=record.follow_up_to_run_id,
created_at=record.created_at,
)
if self._thread_meta_storage is not None and record.assistant_id:
thread = await self._thread_meta_storage.ensure_thread(
thread_id=record.thread_id,
assistant_id=record.assistant_id,
)
if thread.assistant_id != record.assistant_id:
await self._thread_meta_storage.sync_thread_assistant_id(
thread_id=record.thread_id,
assistant_id=record.assistant_id,
)
@@ -0,0 +1,17 @@
"""App-owned durable run deletion adapter."""
from __future__ import annotations
from deerflow.runtime.runs.store import RunDeleteStore
from app.infra.storage.runs import RunDeleteRepository
class AppRunDeleteStore(RunDeleteStore):
"""Delete durable run rows via the app storage adapter."""
def __init__(self, repo: RunDeleteRepository) -> None:
self._repo = repo
async def delete_run(self, run_id: str) -> bool:
return await self._repo.delete(run_id)
@@ -0,0 +1,47 @@
"""App-owned durable run query adapter."""
from __future__ import annotations
from deerflow.runtime.runs.store import RunQueryStore
from deerflow.runtime.runs.types import RunRecord, RunStatus
from app.infra.storage.runs import RunReadRepository, RunRow
class AppRunQueryStore(RunQueryStore):
"""Map app-side durable run rows into harness RunRecord DTOs."""
def __init__(self, repo: RunReadRepository) -> None:
self._repo = repo
async def get_run(self, run_id: str) -> RunRecord | None:
row = await self._repo.get(run_id)
if row is None:
return None
return self._to_run_record(row)
async def list_runs(
self,
thread_id: str,
*,
limit: int = 100,
) -> list[RunRecord]:
rows = await self._repo.list_by_thread(thread_id, limit=limit)
return [self._to_run_record(row) for row in rows]
def _to_run_record(self, row: RunRow) -> RunRecord:
return RunRecord(
run_id=row["run_id"],
thread_id=row["thread_id"],
assistant_id=row.get("assistant_id"),
status=RunStatus(row.get("status", "pending")),
temporary=False,
multitask_strategy=row.get("multitask_strategy", "reject"),
metadata=row.get("metadata", {}),
follow_up_to_run_id=row.get("follow_up_to_run_id"),
created_at=row.get("created_at", ""),
updated_at=row.get("updated_at", ""),
started_at=row.get("started_at"),
ended_at=row.get("ended_at"),
error=row.get("error"),
)