111 lines
2.8 KiB
Python
111 lines
2.8 KiB
Python
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"<Message error={self.error}>"
|
|
|
|
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"""<Result
|
|
success={self.success}
|
|
last_message={self.last_message}>
|
|
"""
|
|
|
|
def to_dict(self):
|
|
return {"success": self.success, "last_message": self.last_message.to_dict()}
|