From 971de5cb7c751926e05bfc74bd92488fe9f3fa9e Mon Sep 17 00:00:00 2001 From: jasquat Date: Thu, 2 Mar 2023 16:31:21 -0500 Subject: [PATCH] created models to hold the bpmn_json w/ burnettk --- .../models/bpmn_process.py | 25 ++++ .../models/bpmn_process_definition.py | 27 ++++ .../bpmn_process_definition_relationship.py | 14 ++ .../spiffworkflow_backend/models/json_data.py | 16 ++ .../models/serialized_bpmn_definition.py | 4 +- .../models/spiff_step_details.py | 138 ++++++++++++++++++ .../src/spiffworkflow_backend/models/task.py | 38 ++++- .../models/task_definition.py | 23 +++ 8 files changed, 283 insertions(+), 2 deletions(-) create mode 100644 spiffworkflow-backend/src/spiffworkflow_backend/models/bpmn_process.py create mode 100644 spiffworkflow-backend/src/spiffworkflow_backend/models/bpmn_process_definition.py create mode 100644 spiffworkflow-backend/src/spiffworkflow_backend/models/bpmn_process_definition_relationship.py create mode 100644 spiffworkflow-backend/src/spiffworkflow_backend/models/json_data.py create mode 100644 spiffworkflow-backend/src/spiffworkflow_backend/models/task_definition.py diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/bpmn_process.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/bpmn_process.py new file mode 100644 index 000000000..b704ce92e --- /dev/null +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/bpmn_process.py @@ -0,0 +1,25 @@ +from __future__ import annotations +from sqlalchemy import ForeignKey +from spiffworkflow_backend.models.bpmn_process_definition import BpmnProcessDefinitionModel + +from spiffworkflow_backend.models.db import db +from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel + + +# properties_json attributes: +# "last_task", # guid generated by spiff +# "root", # guid generated by spiff +# "success", # boolean +# "bpmn_messages", # if top-level process +# "correlations", # if top-level process +class BpmnProcessModel(SpiffworkflowBaseDBModel): + __tablename__ = "bpmn_process" + id: int = db.Column(db.Integer, primary_key=True) + + parent_process_id: int = db.Column(ForeignKey("BpmnProcessModel.id"), nullable=True) + + properties_json: dict = db.Column(db.JSON, nullable=False) + json_data_hash: str = db.Column(db.String(255), nullable=False, index=True) + + # subprocess or top_level_process + process_type: str = db.Column(db.String(30), nullable=False) diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/bpmn_process_definition.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/bpmn_process_definition.py new file mode 100644 index 000000000..54d70c9fc --- /dev/null +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/bpmn_process_definition.py @@ -0,0 +1,27 @@ +from __future__ import annotations + +from spiffworkflow_backend.models.db import db +from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel + + +# contents of top-level attributes from spiff: +# "subprocess_specs", +# "spec", +# +# each subprocess will have its own row in this table. +# there is a join table to link them together: bpmn_process_definition_relationship +class BpmnProcessDefinitionModel(SpiffworkflowBaseDBModel): + __tablename__ = "bpmn_process_definition" + id: int = db.Column(db.Integer, primary_key=True) + + # this is a sha256 hash of spec and serializer_version + hash: str = db.Column(db.String(255), nullable=False, index=True, unique=True) + + properties_json: str = db.Column(db.JSON, nullable=False) + + # process or subprocess + type: str = db.Column(db.String(32), nullable=False, index=True) + + # TODO: remove these from process_instance + bpmn_version_control_type: str = db.Column(db.String(50)) + bpmn_version_control_identifier: str = db.Column(db.String(255)) diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/bpmn_process_definition_relationship.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/bpmn_process_definition_relationship.py new file mode 100644 index 000000000..80f5c9bb2 --- /dev/null +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/bpmn_process_definition_relationship.py @@ -0,0 +1,14 @@ +from __future__ import annotations +from sqlalchemy.orm import deferred +from sqlalchemy import ForeignKey +from spiffworkflow_backend.models.bpmn_process_definition import BpmnProcessDefinitionModel + +from spiffworkflow_backend.models.db import db +from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel + + +class BpmnProcessDefinitionRelationshipModel(SpiffworkflowBaseDBModel): + __tablename__ = "bpmn_process_definition_relationship" + id: int = db.Column(db.Integer, primary_key=True) + bpmn_process_definition_parent_id: int = db.Column(ForeignKey(BpmnProcessDefinitionModel.id), nullable=False) # type: ignore + bpmn_process_definition_child_id: int = db.Column(ForeignKey(BpmnProcessDefinitionModel.id), nullable=False) # type: ignore diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/json_data.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/json_data.py new file mode 100644 index 000000000..1e03b9ff3 --- /dev/null +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/json_data.py @@ -0,0 +1,16 @@ +from __future__ import annotations +from sqlalchemy.orm import deferred +from sqlalchemy import ForeignKey +from spiffworkflow_backend.models.bpmn_process_definition import BpmnProcessDefinitionModel + +from spiffworkflow_backend.models.db import db +from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel + + +class JsonDataModel(SpiffworkflowBaseDBModel): + __tablename__ = "json_data" + id: int = db.Column(db.Integer, primary_key=True) + + # this is a sha256 hash of spec and serializer_version + hash: str = db.Column(db.String(255), nullable=False, index=True, unique=True) + data: dict = db.Column(db.JSON, nullable=False) diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/serialized_bpmn_definition.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/serialized_bpmn_definition.py index 5a3d983e9..5ccb71466 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/serialized_bpmn_definition.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/serialized_bpmn_definition.py @@ -15,8 +15,10 @@ from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel # runtime # "bpmn_messages", # "correlations", -# "data", # "subprocesses", +# +# also in subprocesses +# "data", # "tasks" # "last_task", # guid generated by spiff # "root", # guid generated by spiff diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/spiff_step_details.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/spiff_step_details.py index 713bd3cd8..503b2a418 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/spiff_step_details.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/spiff_step_details.py @@ -10,6 +10,144 @@ from spiffworkflow_backend.models.db import db from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel from spiffworkflow_backend.models.process_instance import ProcessInstanceModel +# process_instance: +# process_model_definition_id +# process_id + + +# "bpmn_messages", +# "correlations", +# "subprocesses", <-- omit from json +# +# also in subprocesses +# "data", +# "tasks" <-- omit from json +# "last_task", # guid generated by spiff +# "root", # guid generated by spiff +# "success", # boolean +# +# runtime_json: +# "last_task", # guid generated by spiff +# "root", # guid generated by spiff +# "success", # boolean +# "bpmn_messages", # if top-level process +# "correlations", # if top-level process +# process: +# id +# parent_process_id +# runtime_json <-- minus tasks and subproceses +# type <-- subprocess, top_level_process +# data + +# runtime_json: +# "id": "a56e1403-2838-4f03-a31f-f99afe16f38d", +# "parent": null, +# "children": [ +# "af6ba340-71e7-46d7-b2d4-e3db1751785d" +# ], +# "last_state_change": 1677775475.18116, +# "state": 32, +# "task_spec": "Root", +# "triggered": false, +# "workflow_name": "Process_category_number_one_call_activity_call_activity_test_bd2e724", +# "internal_data": {}, +# "data": {} +# task: +# id +# guid +# process_id +# task_definition_id +# state <-- store string value +# runtime_json +# data + +# ### workflow +# "io_specification": null, +# "data_objects": {}, +# "correlation_keys": {}, +# "typename": "BpmnProcessSpec" +# "name": "Process_category_number_one_call_activity_call_activity_test_bd2e724", +# "description": "Process_category_number_one_call_activity_call_activity_test_bd2e724", +# "file": "call_activity_test.bpmn", +# "task_specs": {} + +# ### definition +# "Root": { +# "id": "Process_category_number_one_call_activity_call_activity_test_bd2e724_8", +# "name": "Root", +# "description": "", +# "manual": false, +# "internal": false, +# "lookahead": 2, +# "inputs": [], +# "outputs": [], +# "typename": "Simple" +# } +# ## runtime +# "a56e1403-2838-4f03-a31f-f99afe16f38d": { +# "id": "a56e1403-2838-4f03-a31f-f99afe16f38d", +# "parent": null, +# "children": [ +# "af6ba340-71e7-46d7-b2d4-e3db1751785d" +# ], +# "last_state_change": 1677775475.18116, +# "state": 32, +# "task_spec": "Root", +# "triggered": false, +# "workflow_name": "Process_category_number_one_call_activity_call_activity_test_bd2e724", +# "internal_data": {}, +# "data": {} +# }, + + +# ### definition +# "StartEvent_1": { +# "id": "Process_category_number_one_call_activity_call_activity_test_bd2e724_4", +# "name": "StartEvent_1", +# "description": null, +# "manual": false, +# "internal": false, +# "lookahead": 2, +# "inputs": [ +# "Start" +# ], +# "outputs": [ +# "same_process_model" +# ], +# "lane": null, +# "documentation": null, +# "position": { +# "x": 179, +# "y": 159 +# }, +# "data_input_associations": [], +# "data_output_associations": [], +# "io_specification": null, +# "event_definition": { +# "internal": false, +# "external": false, +# "typename": "NoneEventDefinition" +# }, +# "typename": "StartEvent", +# "extensions": {} +# }, +# ## runtime +# "b86b5552-c541-4afe-b200-db0190439f38": { +# "id": "b86b5552-c541-4afe-b200-db0190439f38", +# "parent": "af6ba340-71e7-46d7-b2d4-e3db1751785d", +# "children": [ +# "e9525f55-794f-450d-b5da-bee1951f99fc" +# ], +# "last_state_change": 1677775475.1963174, +# "state": 32, +# "task_spec": "StartEvent_1", +# "triggered": false, +# "workflow_name": "Process_category_number_one_call_activity_call_activity_test_bd2e724", +# "internal_data": { +# "event_fired": true +# }, +# "data": {} +# }, @dataclass class SpiffStepDetailsModel(SpiffworkflowBaseDBModel): diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/task.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/task.py index 148df2310..326ea5b45 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/task.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/task.py @@ -1,5 +1,10 @@ """Task.""" import enum +from dataclasses import dataclass +from sqlalchemy import ForeignKey +from spiffworkflow_backend.models.bpmn_process import BpmnProcessModel +from spiffworkflow_backend.models.db import db +from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel from typing import Any from typing import Optional from typing import Union @@ -7,7 +12,8 @@ from typing import Union import marshmallow from marshmallow import Schema from marshmallow_enum import EnumField # type: ignore -from SpiffWorkflow.task import TaskStateNames # type: ignore +from SpiffWorkflow.task import TaskStateNames +from spiffworkflow_backend.models.task_definition import TaskDefinitionModel # type: ignore class MultiInstanceType(enum.Enum): @@ -19,6 +25,36 @@ class MultiInstanceType(enum.Enum): sequential = "sequential" +# properties_json attributes: +# "id": "a56e1403-2838-4f03-a31f-f99afe16f38d", +# "parent": null, +# "children": [ +# "af6ba340-71e7-46d7-b2d4-e3db1751785d" +# ], +# "last_state_change": 1677775475.18116, +# "state": 32, +# "task_spec": "Root", +# "triggered": false, +# "workflow_name": "Process_category_number_one_call_activity_call_activity_test_bd2e724", +# "internal_data": {}, +@dataclass +class TaskModel(SpiffworkflowBaseDBModel): + __tablename__ = "task" + id: int = db.Column(db.Integer, primary_key=True) + guid: str = db.Column(db.String(36), nullable=False, unique=True, index=True) + bpmn_process_id: int = db.Column( + ForeignKey(BpmnProcessModel.id), nullable=False # type: ignore + ) + + # find this by looking up the "workflow_name" and "task_spec" from the properties_json + task_definition_id: int = db.Column( + ForeignKey(TaskDefinitionModel.id), nullable=False # type: ignore + ) + state: str = db.Column(db.String(10), nullable=False) + properties_json: dict = db.Column(db.JSON, nullable=False) + json_data_hash: str = db.Column(db.String(255), nullable=False, index=True) + + class Task: """Task.""" diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/task_definition.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/task_definition.py new file mode 100644 index 000000000..7e809d3fd --- /dev/null +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/task_definition.py @@ -0,0 +1,23 @@ +from __future__ import annotations +from sqlalchemy import UniqueConstraint +from sqlalchemy import ForeignKey +from spiffworkflow_backend.models.bpmn_process_definition import BpmnProcessDefinitionModel + +from spiffworkflow_backend.models.db import db +from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel + + +class TaskDefinitionModel(SpiffworkflowBaseDBModel): + __tablename__ = "task_definition" + __table_args__ = ( + UniqueConstraint( + "bpmn_process_definition_id", "bpmn_identifier", name="task_definition_unique" + ), + ) + + id: int = db.Column(db.Integer, primary_key=True) + bpmn_process_definition_id: int = db.Column(ForeignKey(BpmnProcessDefinitionModel.id), nullable=False) # type: ignore + + bpmn_identifier: str = db.Column(db.String(255), nullable=False, index=True) + properties_json: dict = db.Column(db.JSON, nullable=False) + typename: str = db.Column(db.String(255), nullable=False)