初步实现多project pipeline

This commit is contained in:
strepsiades
2026-04-07 14:45:19 +08:00
parent e3eab5ade1
commit 966f2e1270
11 changed files with 1083 additions and 169 deletions
@@ -0,0 +1,102 @@
from __future__ import annotations
import asyncio
from typing import List, Optional
from ..common.binding import BindingManager
from ..common.collection import DataCollection
from ..common.persistence_service import PersistenceService, ScopedPersistenceView
class ProjectScopeRuntime:
"""Thin runtime container for one scope execution."""
def __init__(
self,
*,
scope: str,
persistence_service: PersistenceService,
persistence_view: ScopedPersistenceView,
local_collection: DataCollection,
remote_collection: DataCollection,
binding_manager: BindingManager,
local_datasource,
remote_datasource,
global_runtime: Optional["ProjectScopeRuntime"] = None,
owns_persistence_service: bool = False,
) -> None:
self.scope = scope
self.persistence_service = persistence_service
self.persistence_view = persistence_view
self.local_collection = local_collection
self.remote_collection = remote_collection
self.binding_manager = binding_manager
self.local_datasource = local_datasource
self.remote_datasource = remote_datasource
self.global_runtime = global_runtime
self.owns_persistence_service = owns_persistence_service
self._closed = False
@property
def persistence_backend(self):
return self.persistence_service.backend
async def load(
self,
*,
node_types: List[str],
bootstrap_binding_node_types: Optional[List[str]] = None,
enable_persistence: bool = True,
ephemeral_node_types: Optional[List[str]] = None,
) -> None:
if not enable_persistence:
return
excluded_node_types = list(dict.fromkeys(ephemeral_node_types or [])) or None
await self.local_collection.load_from_persistence_excluding(excluded_node_types)
await self.remote_collection.load_from_persistence_excluding(excluded_node_types)
excluded = set(ephemeral_node_types or [])
binding_node_types = [
node_type
for node_type in dict.fromkeys([*node_types, *(bootstrap_binding_node_types or [])])
if node_type not in excluded
]
for node_type in binding_node_types:
await self.binding_manager.load_from_persistence(node_type)
async def persist(
self,
*,
enable_persistence: bool = True,
ephemeral_node_types: Optional[List[str]] = None,
) -> None:
if not enable_persistence:
return
await self.local_collection.persist(exclude_node_types=ephemeral_node_types)
await self.remote_collection.persist(exclude_node_types=ephemeral_node_types)
await self.binding_manager.persist(exclude_node_types=ephemeral_node_types)
async def unload(self) -> None:
await self.local_collection.unload()
await self.remote_collection.unload()
await self.binding_manager.unload()
async def close(self) -> None:
if self._closed:
return
self._closed = True
await self._safe_close("remote_datasource", self.remote_datasource.close())
await self._safe_close("local_datasource", self.local_datasource.close())
if self.owns_persistence_service:
await self._safe_close("persistence_service", self.persistence_service.close())
async def _safe_close(self, name: str, close_coro, timeout: float = 3.0) -> None:
try:
await asyncio.wait_for(close_coro, timeout=timeout)
except asyncio.TimeoutError:
return
except Exception:
return