concurrent foreach preparation, types, validation, refactors
This commit is contained in:
@@ -75,7 +75,12 @@ def _validate_nodes(
|
||||
)
|
||||
elif isinstance(node, ForeachNode):
|
||||
validate_foreach_node(
|
||||
node, index, report, state_root_fields, input_root_fields
|
||||
node,
|
||||
index,
|
||||
report,
|
||||
state_root_fields,
|
||||
input_root_fields,
|
||||
workflow,
|
||||
)
|
||||
elif isinstance(node, InterruptNode):
|
||||
validate_interrupt_node(
|
||||
|
||||
@@ -21,6 +21,7 @@ class ValidationIssueCode(StrEnum):
|
||||
EMPTY_CONDITION_ARGS = "empty_condition_args"
|
||||
INVALID_CONDITION_PATH = "invalid_condition_path"
|
||||
INVALID_FOREACH_SOURCE = "invalid_foreach_source"
|
||||
INVALID_FOREACH_COLLECT_DESTINATION = "invalid_foreach_collect_destination"
|
||||
INVALID_INTERRUPT_SOURCE = "invalid_interrupt_source"
|
||||
INVALID_INTERRUPT_DESTINATION = "invalid_interrupt_destination"
|
||||
|
||||
|
||||
@@ -13,7 +13,10 @@ def declared_outcomes_for_step(step: Step, node_defs: dict[str, NodeDef]) -> set
|
||||
if step.type == "condition":
|
||||
return {"true", "false"}
|
||||
if step.type == "foreach":
|
||||
return {"loop", "done"}
|
||||
outcomes = {"loop", "done"}
|
||||
if step.item_error.action in {"skip", "collect"}:
|
||||
outcomes.add("completed_with_errors")
|
||||
return outcomes
|
||||
if step.type == "join":
|
||||
return {"done"}
|
||||
if isinstance(step, InterruptNode):
|
||||
|
||||
@@ -149,6 +149,7 @@ def validate_foreach_node(
|
||||
report: ValidationReport,
|
||||
state_root_fields: set[str],
|
||||
input_root_fields: set[str],
|
||||
workflow: Workflow,
|
||||
) -> None:
|
||||
if not is_valid_source_path(node.over, state_root_fields, input_root_fields):
|
||||
report.add(
|
||||
@@ -156,6 +157,27 @@ def validate_foreach_node(
|
||||
f"nodes[{index}].over",
|
||||
"foreach source path must start with input. or state. and reference a declared root field",
|
||||
)
|
||||
if node.item_error.action != "collect":
|
||||
return
|
||||
collect_to = node.item_error.collect_to
|
||||
if collect_to is None:
|
||||
return
|
||||
destination_root = _state_destination_root(collect_to)
|
||||
state_fields = workflow.state_schema.field_index()
|
||||
field = state_fields.get(collect_to)
|
||||
if destination_root is None or destination_root not in state_root_fields:
|
||||
report.add(
|
||||
ValidationIssueCode.INVALID_FOREACH_COLLECT_DESTINATION,
|
||||
f"nodes[{index}].item_error.collect_to",
|
||||
"collect_to must start with state. and reference a declared state field",
|
||||
)
|
||||
return
|
||||
if field is None or field.type != "array":
|
||||
report.add(
|
||||
ValidationIssueCode.INVALID_FOREACH_COLLECT_DESTINATION,
|
||||
f"nodes[{index}].item_error.collect_to",
|
||||
"collect_to must reference a declared array state field",
|
||||
)
|
||||
|
||||
|
||||
def validate_interrupt_node(
|
||||
|
||||
Reference in New Issue
Block a user