import copy import json from django.db import models from jeeves.base.models import BaseModel class DefinitionMixin: @property def definition(self): return json.loads(self._definition) @definition.setter def definition(self, value: dict): self._definition = json.dumps(value) class Flow(BaseModel, DefinitionMixin): name = models.CharField(max_length=64) _definition = models.TextField() def serialize(self): definition = copy.deepcopy(self.definition) definition["tasks"] = [task.serialize() for task in self.tasks] return {"name": self.name, "definition": definition} @property def tasks(self): for task_ref in self.definition["tasks"]: yield Task.objects.from_reference(task_ref) class TaskManager(models.Manager): def from_reference(self, reference): return self.get_queryset().get(pk=reference) class Task(DefinitionMixin, BaseModel): type = models.CharField(max_length=32) _definition = models.TextField() objects = TaskManager() def serialize(self): return {"type": self.type, "definition": self.definition} def run(self, message=None): from jeeves.tasks.shell import ShellTask runner = ShellTask(**self.definition) return Message(error=runner.execute(message)) class Run(DefinitionMixin, BaseModel): PENDING = "pending" FINISHED = "finished" RUN_STATUS = ((PENDING, PENDING.capitalize()), (FINISHED, FINISHED.capitalize())) status = models.CharField(max_length=32, choices=RUN_STATUS, default=PENDING) success = models.BooleanField(default=True) flow = models.ForeignKey(Flow, on_delete=models.CASCADE) _definition = models.TextField() _result = models.TextField(default="{}") @classmethod def execute_flow(cls, flow: Flow): run = cls() run.definition = flow.serialize() run.flow = flow message = None for task in run.flow.tasks: message = task.run(message=message) if message.error: run.success = False run._result = json.dumps(message.serialize()) break run.status = Run.FINISHED run.save() return run class Message: error: bool = False def __init__(self, error): self.error = error def __repr__(self): return f"" def serialize(self): return {"error": self.error} class Result: success: bool = True last_message: Message def __init__(self): self.steps = [] def __repr__(self): return f""" """ def to_dict(self): return {"success": self.success, "last_message": self.last_message.to_dict()}