Initial commit (Clean history)
This commit is contained in:
83
app/workflow_engine.py
Normal file
83
app/workflow_engine.py
Normal file
@@ -0,0 +1,83 @@
|
||||
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 == "==" 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
|
||||
Reference in New Issue
Block a user