Files
api/app/workflow_engine.py
anhduy-tech 4fd1aae08f changes
2026-01-05 13:41:04 +07:00

84 lines
3.2 KiB
Python

from django.db import transaction
from app.models import Workflow, StepAction, Rule
from app.workflow_registry import ACTION_REGISTRY, validate_action_schema
from app.workflow_utils import resolve_value
@transaction.atomic
def execute_step(step: StepAction, context: dict):
print(f"\n>>> EXECUTING STEP: {step.step_code} (Order: {step.order})")
# Evaluate rules first
for rule in step.rules.filter(is_active=True):
if not evaluate_rule(rule, context):
print(f"Step {step.step_code} skipped due to rule failure.")
return {"step": step.step_code, "skipped": True, "reason": "rule_failed"}
results = []
# Lưu ý: step.actions thường là một list các dict
actions_list = step.actions if isinstance(step.actions, list) else []
for action in actions_list:
action_type = action.get("type")
params = action.get("params", {})
print(f" - Action Type: {action_type}")
if action_type not in ACTION_REGISTRY:
print(f" - ERROR: Action type '{action_type}' not registered!")
continue
try:
validate_action_schema(action_type, params)
handler = ACTION_REGISTRY[action_type]
# Thực thi handler
output = handler(params, context)
results.append({"action": action_type, "result": output})
# Lưu output cuối cùng vào context
context["last_result"] = output
except Exception as e:
print(f" - ERROR in action {action_type}: {str(e)}")
# Raise để transaction.atomic rollback nếu cần, hoặc xử lý tùy ý
raise e
return {"step": step.step_code, "executed": True, "results": results}
def evaluate_rule(rule: Rule, context: dict):
for condition in (rule.conditions or []):
left = resolve_value(condition.get("left"), context)
right = resolve_value(condition.get("right"), context)
op = condition.get("operator", "==")
print(f" Evaluating Rule: {left} {op} {right}")
if op == "IN" and left not in right: return False
if op == "==" and left != right: return False
if op == "!=" and left == right: return False
if op == ">" and not (left > right): return False
if op == "<" and not (left < right): return False
return True
def run_workflow(workflow_code: str, trigger: str, context: dict):
print(f"\n================ START WORKFLOW: {workflow_code} ================")
print(f"Trigger: {trigger} | Initial Context: {context}")
workflow = Workflow.objects.filter(code=workflow_code, is_active=True).first()
if not workflow:
print(f"Workflow '{workflow_code}' not found or inactive.")
raise Exception(f"Workflow '{workflow_code}' not found")
steps = workflow.steps.filter(trigger_event=trigger, is_active=True).order_by("order")
print(f"Found {steps.count()} active steps.")
outputs = []
for step in steps:
res = execute_step(step, context)
outputs.append(res)
print(f"================ FINISH WORKFLOW: {workflow_code} ================\n")
return outputs