102 lines
3.6 KiB
Python
102 lines
3.6 KiB
Python
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 |