feat(graph-engine): make layer runtime state non-null and bound early (#30552)

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
This commit is contained in:
-LAN-
2026-01-05 16:43:42 +08:00
committed by GitHub
parent 591ca05c84
commit 6f8bd58e19
11 changed files with 105 additions and 38 deletions

View File

@ -35,6 +35,7 @@ from core.model_runtime.entities.llm_entities import LLMUsage
from core.workflow.entities.pause_reason import SchedulingPause
from core.workflow.enums import WorkflowExecutionStatus
from core.workflow.graph_engine.entities.commands import GraphEngineCommand
from core.workflow.graph_engine.layers.base import GraphEngineLayerNotInitializedError
from core.workflow.graph_events.graph import GraphRunPausedEvent
from core.workflow.runtime.graph_runtime_state import GraphRuntimeState
from core.workflow.runtime.graph_runtime_state_protocol import ReadOnlyGraphRuntimeState
@ -569,10 +570,10 @@ class TestPauseStatePersistenceLayerTestContainers:
"""Test that layer requires proper initialization before handling events."""
# Arrange
layer = self._create_pause_state_persistence_layer()
# Don't initialize - graph_runtime_state should not be set
# Don't initialize - graph_runtime_state should be uninitialized
event = GraphRunPausedEvent(reasons=[SchedulingPause(message="test pause")])
# Act & Assert - Should raise AttributeError
with pytest.raises(AttributeError):
# Act & Assert - Should raise GraphEngineLayerNotInitializedError
with pytest.raises(GraphEngineLayerNotInitializedError):
layer.on_event(event)

View File

@ -15,6 +15,7 @@ from core.app.layers.pause_state_persist_layer import (
from core.variables.segments import Segment
from core.workflow.entities.pause_reason import SchedulingPause
from core.workflow.graph_engine.entities.commands import GraphEngineCommand
from core.workflow.graph_engine.layers.base import GraphEngineLayerNotInitializedError
from core.workflow.graph_events.graph import (
GraphRunFailedEvent,
GraphRunPausedEvent,
@ -209,8 +210,9 @@ class TestPauseStatePersistenceLayer:
assert layer._session_maker is session_factory
assert layer._state_owner_user_id == state_owner_user_id
assert not hasattr(layer, "graph_runtime_state")
assert not hasattr(layer, "command_channel")
with pytest.raises(GraphEngineLayerNotInitializedError):
_ = layer.graph_runtime_state
assert layer.command_channel is None
def test_initialize_sets_dependencies(self):
session_factory = Mock(name="session_factory")
@ -295,7 +297,7 @@ class TestPauseStatePersistenceLayer:
mock_factory.assert_not_called()
mock_repo.create_workflow_pause.assert_not_called()
def test_on_event_raises_attribute_error_when_graph_runtime_state_is_none(self):
def test_on_event_raises_when_graph_runtime_state_is_uninitialized(self):
session_factory = Mock(name="session_factory")
layer = PauseStatePersistenceLayer(
session_factory=session_factory,
@ -305,7 +307,7 @@ class TestPauseStatePersistenceLayer:
event = TestDataFactory.create_graph_run_paused_event()
with pytest.raises(AttributeError):
with pytest.raises(GraphEngineLayerNotInitializedError):
layer.on_event(event)
def test_on_event_asserts_when_workflow_execution_id_missing(self, monkeypatch: pytest.MonkeyPatch):

View File

@ -0,0 +1,56 @@
from __future__ import annotations
import pytest
from core.workflow.graph_engine import GraphEngine
from core.workflow.graph_engine.command_channels import InMemoryChannel
from core.workflow.graph_engine.layers.base import (
GraphEngineLayer,
GraphEngineLayerNotInitializedError,
)
from core.workflow.graph_events import GraphEngineEvent
from ..test_table_runner import WorkflowRunner
class LayerForTest(GraphEngineLayer):
def on_graph_start(self) -> None:
pass
def on_event(self, event: GraphEngineEvent) -> None:
pass
def on_graph_end(self, error: Exception | None) -> None:
pass
def test_layer_runtime_state_raises_when_uninitialized() -> None:
layer = LayerForTest()
with pytest.raises(GraphEngineLayerNotInitializedError):
_ = layer.graph_runtime_state
def test_layer_runtime_state_available_after_engine_layer() -> None:
runner = WorkflowRunner()
fixture_data = runner.load_fixture("simple_passthrough_workflow")
graph, graph_runtime_state = runner.create_graph_from_fixture(
fixture_data,
inputs={"query": "test layer state"},
)
engine = GraphEngine(
workflow_id="test_workflow",
graph=graph,
graph_runtime_state=graph_runtime_state,
command_channel=InMemoryChannel(),
)
layer = LayerForTest()
engine.layer(layer)
outputs = layer.graph_runtime_state.outputs
ready_queue_size = layer.graph_runtime_state.ready_queue_size
assert outputs == {}
assert isinstance(ready_queue_size, int)
assert ready_queue_size >= 0