Files
gyxx-flow/src/gyxx_flow/workflow/factory.py
T

88 lines
2.7 KiB
Python

"""Shared catalog-to-LangGraph workflow composition."""
from __future__ import annotations
from dataclasses import dataclass
from gyxx_flow.adapters.native import DeferredModuleCommandStep, ModuleCommandFactory
from gyxx_flow.catalog import WorkflowEntry
from .model import StepDefinition, WorkflowDefinition
@dataclass(frozen=True, slots=True)
class _ConfiguredStep:
step_id: str
entry: str
args: tuple[str, ...]
depends_on: tuple[str, ...]
run_after_failure: bool = False
timeout_seconds: float | None = None
replay_policy: str | None = None
def build_catalog_workflow(
entry: WorkflowEntry,
*,
default_step_id: str,
timeout_seconds: float,
resource: str,
command_factory: ModuleCommandFactory | None = None,
official_notification: bool = False,
independent_step_resources: bool = False,
default_replay_policy: str = "guarded",
) -> WorkflowDefinition:
"""Build one executable graph without adding one class per business task."""
if entry.steps:
configured_steps = entry.steps
else:
configured_steps = (
_ConfiguredStep(
step_id=default_step_id,
entry=entry.entry,
args=entry.args,
depends_on=(),
),
)
definitions: list[StepDefinition] = []
for configured in configured_steps:
action_kwargs = {
"command_entry": configured.entry,
"command_args": configured.args,
}
if command_factory is not None:
action_kwargs["command_factory"] = command_factory
action = DeferredModuleCommandStep(entry, **action_kwargs)
step_resources = (
(f"{resource}:{configured.step_id}",)
if independent_step_resources
else (resource,)
)
definitions.append(
StepDefinition(
configured.step_id,
action,
depends_on=configured.depends_on,
timeout_seconds=(
configured.timeout_seconds
if configured.timeout_seconds is not None
else timeout_seconds
),
max_attempts=1,
resources=step_resources,
production_sink=True,
official_notification=official_notification,
replay_policy=(
getattr(configured, "replay_policy", None)
or default_replay_policy
),
run_after_failure=getattr(configured, "run_after_failure", False),
)
)
return WorkflowDefinition(entry.workflow_id, tuple(definitions))
__all__ = ["build_catalog_workflow"]