40 lines
1.1 KiB
Python
40 lines
1.1 KiB
Python
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass
|
|
from typing import Protocol
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class NodeResult:
|
|
status: str
|
|
edge_result: str = "success"
|
|
output_metadata: dict[str, object] | None = None
|
|
telemetry: dict[str, object] | None = None
|
|
failure_evidence: dict[str, object] | None = None
|
|
pause_reason: str = ""
|
|
|
|
|
|
class NodeHandler(Protocol):
|
|
node_type: str
|
|
idempotent: bool
|
|
replay_safe: bool
|
|
destructive: bool
|
|
|
|
def run(self, context: object) -> NodeResult: ...
|
|
|
|
|
|
class NodeHandlerRegistry:
|
|
def __init__(self) -> None:
|
|
self._handlers: dict[str, NodeHandler] = {}
|
|
|
|
def register(self, handler: NodeHandler) -> None:
|
|
self._handlers[handler.node_type] = handler
|
|
|
|
def get(self, node_type: str) -> NodeHandler:
|
|
try:
|
|
return self._handlers[node_type]
|
|
except KeyError as exc:
|
|
raise KeyError(f"No graph node handler registered for {node_type}") from exc
|
|
|
|
def has(self, node_type: str) -> bool:
|
|
return node_type in self._handlers
|