78 lines
2.5 KiB
Python
78 lines
2.5 KiB
Python
"""Engine lifecycle management for the CLI board."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import asyncio
|
|
from pathlib import Path
|
|
from typing import Any, Awaitable, Callable
|
|
|
|
from opc.core.config import OPCConfig, get_opc_home
|
|
from opc.engine import OPCEngine
|
|
|
|
ProgressCallback = Callable[[str], Awaitable[None] | Awaitable[Any]]
|
|
EventCallback = Callable[[Any], Awaitable[None]]
|
|
|
|
|
|
class EngineFacade:
|
|
"""Owns a single lazily-initialized OPCEngine for the CLI board process."""
|
|
|
|
def __init__(self, project_id: str | None = None) -> None:
|
|
self.project_id = project_id
|
|
self._config: OPCConfig | None = None
|
|
self._engine: OPCEngine | None = None
|
|
self._progress_callback: Callable[..., Awaitable[None]] | None = None
|
|
self._event_callback: EventCallback | None = None
|
|
self._init_lock = asyncio.Lock()
|
|
|
|
@property
|
|
def engine(self) -> OPCEngine | None:
|
|
return self._engine
|
|
|
|
@property
|
|
def store(self): # noqa: ANN201 - preserve simple property for callers
|
|
return self._engine.store if self._engine else None
|
|
|
|
@property
|
|
def opc_home(self) -> Path:
|
|
return get_opc_home()
|
|
|
|
def configure_callbacks(
|
|
self,
|
|
*,
|
|
progress_callback: Callable[..., Awaitable[None]] | None = None,
|
|
event_callback: EventCallback | None = None,
|
|
) -> None:
|
|
self._progress_callback = progress_callback
|
|
self._event_callback = event_callback
|
|
if self._engine is not None and progress_callback is not None:
|
|
self._engine.on_progress = progress_callback
|
|
|
|
async def ensure_ready(self) -> OPCEngine:
|
|
if self._engine is not None:
|
|
return self._engine
|
|
|
|
async with self._init_lock:
|
|
if self._engine is not None:
|
|
return self._engine
|
|
|
|
config_dir = get_opc_home() / "config"
|
|
self._config = OPCConfig.load(config_dir) if config_dir.exists() else OPCConfig()
|
|
engine = OPCEngine(
|
|
config=self._config,
|
|
project_id=self.project_id,
|
|
on_progress=self._progress_callback,
|
|
)
|
|
await engine.initialize()
|
|
if self._event_callback is not None:
|
|
engine.event_bus.subscribe_all(self._event_callback)
|
|
self._engine = engine
|
|
return engine
|
|
|
|
async def shutdown(self) -> None:
|
|
if self._engine is None:
|
|
return
|
|
engine = self._engine
|
|
self._engine = None
|
|
await engine.shutdown()
|
|
|