fix: command node single debug run

- Added FIXME comments to indicate the need for unifying runtime config checking in AdvancedChatAppGenerator and WorkflowAppGenerator.
- Introduced sandbox management in WorkflowService with proper error handling for sandbox release.
- Enhanced runtime feature handling in the workflow execution process.
This commit is contained in:
Harry
2026-01-07 15:22:12 +08:00
parent 1a203031e0
commit 094c9fd802
3 changed files with 39 additions and 15 deletions

View File

@ -513,6 +513,7 @@ class AdvancedChatAppGenerator(MessageBasedAppGenerator):
if workflow is None:
raise ValueError("Workflow not found")
# FIXME: Consolidate runtime config checking into a unified location.
runtime = workflow.features_dict.get("runtime")
graph_engine_layers = ()
if isinstance(runtime, dict) and runtime.get("enabled"):

View File

@ -488,6 +488,7 @@ class WorkflowAppGenerator(BaseAppGenerator):
if workflow is None:
raise ValueError("Workflow not found")
# FIXME: Consolidate runtime config checking into a unified location.
runtime = workflow.features_dict.get("runtime")
if isinstance(runtime, dict) and runtime.get("enabled"):
graph_engine_layers = (*graph_engine_layers, SandboxLayer())

View File

@ -1,4 +1,5 @@
import json
import logging
import time
import uuid
from collections.abc import Callable, Generator, Mapping, Sequence
@ -15,6 +16,7 @@ from core.file import File
from core.repositories import DifyCoreRepositoryFactory
from core.variables import Variable
from core.variables.variables import VariableUnion
from core.virtual_environment.factory import SandboxFactory, SandboxType
from core.workflow.entities import WorkflowNodeExecution
from core.workflow.enums import ErrorStrategy, WorkflowNodeExecutionMetadataKey, WorkflowNodeExecutionStatus
from core.workflow.errors import WorkflowNodeRunFailedError
@ -46,6 +48,8 @@ from services.workflow.workflow_converter import WorkflowConverter
from .errors.workflow_service import DraftWorkflowDeletionError, WorkflowInUseError
from .workflow_draft_variable_service import DraftVariableSaver, DraftVarLoader, WorkflowDraftVariableService
logger = logging.getLogger(__name__)
class WorkflowService:
"""
@ -693,22 +697,40 @@ class WorkflowService:
else:
enclosing_node_id = None
run = WorkflowEntry.single_step_run(
workflow=draft_workflow,
node_id=node_id,
user_inputs=user_inputs,
user_id=account.id,
variable_pool=variable_pool,
variable_loader=variable_loader,
)
# FIXME: Consolidate runtime config checking into a unified location.
runtime = draft_workflow.features_dict.get("runtime")
sandbox = None
if isinstance(runtime, dict) and runtime.get("enabled"):
sandbox = SandboxFactory.create(sandbox_type=SandboxType.DOCKER)
# run draft workflow node
start_at = time.perf_counter()
node_execution = self._handle_single_step_result(
invoke_node_fn=lambda: run,
start_at=start_at,
node_id=node_id,
)
try:
node, generator = WorkflowEntry.single_step_run(
workflow=draft_workflow,
node_id=node_id,
user_inputs=user_inputs,
user_id=account.id,
variable_pool=variable_pool,
variable_loader=variable_loader,
)
# FIXME: Use a proper dependency injection pattern for sandbox.
if sandbox:
node.sandbox = sandbox # type: ignore[attr-defined]
# Run draft workflow node
start_at = time.perf_counter()
node_execution = self._handle_single_step_result(
invoke_node_fn=lambda: (node, generator),
start_at=start_at,
node_id=node_id,
)
finally:
# Release sandbox after node execution
if sandbox:
try:
sandbox.release_environment()
except Exception:
logger.exception("Failed to release sandbox")
# Set workflow_id on the NodeExecution
node_execution.workflow_id = draft_workflow.id