unique bpmn process ids (#927)
* remove SpecReferenceCache * make sure strings are sometimes unique * lint * more random Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --------- Co-authored-by: burnettk <burnettk@users.noreply.github.com> Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
This commit is contained in:
parent
4cb1f33ac9
commit
711da2b048
|
@ -23,9 +23,6 @@ from spiffworkflow_backend.models.principal import PrincipalModel # noqa: F401
|
||||||
|
|
||||||
|
|
||||||
from spiffworkflow_backend.models.human_task import HumanTaskModel # noqa: F401
|
from spiffworkflow_backend.models.human_task import HumanTaskModel # noqa: F401
|
||||||
from spiffworkflow_backend.models.spec_reference import (
|
|
||||||
SpecReferenceCache,
|
|
||||||
) # noqa: F401
|
|
||||||
from spiffworkflow_backend.models.cache_generation import (
|
from spiffworkflow_backend.models.cache_generation import (
|
||||||
CacheGenerationModel,
|
CacheGenerationModel,
|
||||||
) # noqa: F401
|
) # noqa: F401
|
||||||
|
|
|
@ -59,7 +59,6 @@ class Reference:
|
||||||
return os.path.join(self.relative_location, self.file_name).replace("/", os.sep)
|
return os.path.join(self.relative_location, self.file_name).replace("/", os.sep)
|
||||||
|
|
||||||
|
|
||||||
# SpecReferenceCache
|
|
||||||
class ReferenceCacheModel(SpiffworkflowBaseDBModel):
|
class ReferenceCacheModel(SpiffworkflowBaseDBModel):
|
||||||
"""A cache of information about all the Processes and Decisions defined in all files."""
|
"""A cache of information about all the Processes and Decisions defined in all files."""
|
||||||
|
|
||||||
|
|
|
@ -1,85 +0,0 @@
|
||||||
from dataclasses import dataclass
|
|
||||||
|
|
||||||
from flask_marshmallow import Schema # type: ignore
|
|
||||||
from marshmallow import INCLUDE
|
|
||||||
from sqlalchemy import UniqueConstraint
|
|
||||||
|
|
||||||
from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel
|
|
||||||
from spiffworkflow_backend.models.db import db
|
|
||||||
|
|
||||||
|
|
||||||
class SpecReferenceNotFoundError(Exception):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass()
|
|
||||||
class SpecReference:
|
|
||||||
"""File Reference Information.
|
|
||||||
|
|
||||||
Includes items such as the process id and name for a BPMN,
|
|
||||||
or the Decision id and Decision name for a DMN file. There may be more than
|
|
||||||
one reference that points to a particular file - if for instance, there are
|
|
||||||
three executable processes in a collaboration within a BPMN Diagram.
|
|
||||||
"""
|
|
||||||
|
|
||||||
identifier: str # The id of the process or decision. "Process_1234"
|
|
||||||
display_name: str # The name of the process or decision. "Invoice Submission"
|
|
||||||
process_model_id: str
|
|
||||||
type: str # can be 'process' or 'decision'
|
|
||||||
file_name: str # The name of the file where this process or decision is defined.
|
|
||||||
relative_path: str # The path to the file.
|
|
||||||
has_lanes: bool # If this is a process, whether it has lanes or not.
|
|
||||||
is_executable: bool # Whether this process or decision is designated as executable.
|
|
||||||
is_primary: bool # Whether this is the primary process of a process model
|
|
||||||
messages: dict # Any messages defined in the same file where this process is defined.
|
|
||||||
correlations: dict # Any correlations defined in the same file with this process.
|
|
||||||
start_messages: list # The names of any messages that would start this process.
|
|
||||||
called_element_ids: list # The element ids of any called elements
|
|
||||||
|
|
||||||
|
|
||||||
class SpecReferenceCache(SpiffworkflowBaseDBModel):
|
|
||||||
"""A cache of information about all the Processes and Decisions defined in all files."""
|
|
||||||
|
|
||||||
__tablename__ = "spec_reference_cache"
|
|
||||||
__table_args__ = (UniqueConstraint("identifier", "type", name="_identifier_type_unique"),)
|
|
||||||
id = db.Column(db.Integer, primary_key=True)
|
|
||||||
identifier = db.Column(db.String(255), index=True)
|
|
||||||
display_name = db.Column(db.String(255), index=True)
|
|
||||||
process_model_id = db.Column(db.String(255), index=True)
|
|
||||||
type = db.Column(db.String(255), index=True) # either 'process' or 'decision'
|
|
||||||
file_name = db.Column(db.String(255))
|
|
||||||
relative_path = db.Column(db.String(255))
|
|
||||||
has_lanes = db.Column(db.Boolean())
|
|
||||||
is_executable = db.Column(db.Boolean())
|
|
||||||
is_primary = db.Column(db.Boolean())
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def from_spec_reference(cls, ref: SpecReference) -> "SpecReferenceCache":
|
|
||||||
return cls(
|
|
||||||
identifier=ref.identifier,
|
|
||||||
display_name=ref.display_name,
|
|
||||||
process_model_id=ref.process_model_id,
|
|
||||||
type=ref.type,
|
|
||||||
file_name=ref.file_name,
|
|
||||||
has_lanes=ref.has_lanes,
|
|
||||||
is_executable=ref.is_executable,
|
|
||||||
is_primary=ref.is_primary,
|
|
||||||
relative_path=ref.relative_path,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class SpecReferenceSchema(Schema): # type: ignore
|
|
||||||
class Meta:
|
|
||||||
model = SpecReference
|
|
||||||
fields = [
|
|
||||||
"identifier",
|
|
||||||
"display_name",
|
|
||||||
"process_group_id",
|
|
||||||
"process_model_id",
|
|
||||||
"type",
|
|
||||||
"file_name",
|
|
||||||
"has_lanes",
|
|
||||||
"is_executable",
|
|
||||||
"is_primary",
|
|
||||||
]
|
|
||||||
unknown = INCLUDE
|
|
|
@ -1,7 +1,9 @@
|
||||||
"""APIs for dealing with process groups, process models, and process instances."""
|
"""APIs for dealing with process groups, process models, and process instances."""
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
|
import random
|
||||||
import re
|
import re
|
||||||
|
import string
|
||||||
from hashlib import sha256
|
from hashlib import sha256
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
|
@ -83,6 +85,15 @@ def process_model_create(
|
||||||
with open(template_file) as f:
|
with open(template_file) as f:
|
||||||
contents = f.read()
|
contents = f.read()
|
||||||
process_model_id_for_bpmn_file = process_model_info.id.split("/")[-1]
|
process_model_id_for_bpmn_file = process_model_info.id.split("/")[-1]
|
||||||
|
|
||||||
|
# convert dashes to underscores for process id
|
||||||
|
underscored_process_id = process_model_id_for_bpmn_file.replace("-", "_")
|
||||||
|
|
||||||
|
# make process id unique by adding random string to add
|
||||||
|
fuzz = "".join(random.SystemRandom().choice(string.ascii_lowercase + string.digits) for _ in range(7))
|
||||||
|
process_id_with_fuzz = f"Process_{underscored_process_id}_{fuzz}"
|
||||||
|
contents = contents.replace("Process_replace_me_just_for_template", process_id_with_fuzz)
|
||||||
|
|
||||||
SpecFileService.update_file(process_model_info, f"{process_model_id_for_bpmn_file}.bpmn", contents.encode())
|
SpecFileService.update_file(process_model_info, f"{process_model_id_for_bpmn_file}.bpmn", contents.encode())
|
||||||
|
|
||||||
_commit_and_push_to_git(f"User: {g.user.username} created process model {process_model_info.id}")
|
_commit_and_push_to_git(f"User: {g.user.username} created process model {process_model_info.id}")
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:spiffworkflow="http://spiffworkflow.org/bpmn/schema/1.0/core" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" id="Definitions_96f6665" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="3.0.0-dev">
|
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:spiffworkflow="http://spiffworkflow.org/bpmn/schema/1.0/core" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" id="Definitions_96f6665" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="3.0.0-dev">
|
||||||
<bpmn:process id="Process_ynixgwm" isExecutable="true">
|
<bpmn:process id="Process_replace_me_just_for_template" isExecutable="true">
|
||||||
<bpmn:startEvent id="StartEvent_1">
|
<bpmn:startEvent id="StartEvent_1">
|
||||||
<bpmn:outgoing>Flow_17db3yp</bpmn:outgoing>
|
<bpmn:outgoing>Flow_17db3yp</bpmn:outgoing>
|
||||||
</bpmn:startEvent>
|
</bpmn:startEvent>
|
||||||
|
@ -27,7 +27,7 @@ You can also change the text you are reading here by updating the *Instructions*
|
||||||
</bpmn:manualTask>
|
</bpmn:manualTask>
|
||||||
</bpmn:process>
|
</bpmn:process>
|
||||||
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
|
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
|
||||||
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_ynixgwm">
|
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_replace_me_just_for_template">
|
||||||
<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
|
<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
|
||||||
<dc:Bounds x="179" y="159" width="36" height="36" />
|
<dc:Bounds x="179" y="159" width="36" height="36" />
|
||||||
</bpmndi:BPMNShape>
|
</bpmndi:BPMNShape>
|
||||||
|
|
|
@ -166,7 +166,7 @@ class TestNestedGroups(BaseTest):
|
||||||
data=json.dumps(ProcessGroupSchema().dump(process_group_c)),
|
data=json.dumps(ProcessGroupSchema().dump(process_group_c)),
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_process_model_create(
|
def test_process_model_create_nested(
|
||||||
self,
|
self,
|
||||||
app: Flask,
|
app: Flask,
|
||||||
client: FlaskClient,
|
client: FlaskClient,
|
||||||
|
|
|
@ -173,6 +173,9 @@ class TestProcessApi(BaseTest):
|
||||||
assert model_display_name == process_model.display_name
|
assert model_display_name == process_model.display_name
|
||||||
assert 0 == process_model.display_order
|
assert 0 == process_model.display_order
|
||||||
assert 1 == len(ProcessModelService.get_process_groups())
|
assert 1 == len(ProcessModelService.get_process_groups())
|
||||||
|
assert process_model.primary_file_name == f"{process_model_id}.bpmn"
|
||||||
|
assert process_model.primary_process_id
|
||||||
|
assert process_model.primary_process_id.startswith(f"Process_{process_model_id}")
|
||||||
|
|
||||||
# add bpmn file to the model
|
# add bpmn file to the model
|
||||||
bpmn_file_name = "sample.bpmn"
|
bpmn_file_name = "sample.bpmn"
|
||||||
|
|
Loading…
Reference in New Issue