diff --git a/spiffworkflow-backend/migrations/versions/04e43b3c9a50_.py b/spiffworkflow-backend/migrations/versions/04e43b3c9a50_.py new file mode 100644 index 00000000..072f4ba8 --- /dev/null +++ b/spiffworkflow-backend/migrations/versions/04e43b3c9a50_.py @@ -0,0 +1,36 @@ +"""empty message + +Revision ID: 04e43b3c9a50 +Revises: def2cbb0ca6b +Create Date: 2023-03-03 10:31:53.578474 + +""" +from alembic import op +import sqlalchemy as sa +from sqlalchemy.dialects import mysql + +# revision identifiers, used by Alembic. +revision = '04e43b3c9a50' +down_revision = 'def2cbb0ca6b' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.alter_column('bpmn_process_definition', 'type', + existing_type=mysql.VARCHAR(length=32), + nullable=True) + op.drop_index('ix_bpmn_process_definition_type', table_name='bpmn_process_definition') + op.add_column('process_instance', sa.Column('spiff_serializer_version', sa.String(length=50), nullable=True)) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_column('process_instance', 'spiff_serializer_version') + op.create_index('ix_bpmn_process_definition_type', 'bpmn_process_definition', ['type'], unique=False) + op.alter_column('bpmn_process_definition', 'type', + existing_type=mysql.VARCHAR(length=32), + nullable=False) + # ### end Alembic commands ### diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/bpmn_process_definition.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/bpmn_process_definition.py index d60a6c0d..c78fe4f9 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/bpmn_process_definition.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/bpmn_process_definition.py @@ -22,7 +22,8 @@ class BpmnProcessDefinitionModel(SpiffworkflowBaseDBModel): # process or subprocess # FIXME: will probably ignore for now since we do not strictly need it - type: str = db.Column(db.String(32), nullable=False, index=True) + # make this nullable false and index it once we actually start using it + type: str = db.Column(db.String(32), nullable=True) # TODO: remove these from process_instance bpmn_version_control_type: str = db.Column(db.String(50)) diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance.py index 44cfe806..e0fb3f3b 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance.py @@ -78,10 +78,12 @@ class ProcessInstanceModel(SpiffworkflowBaseDBModel): process_instance_data = relationship("ProcessInstanceDataModel", cascade="delete") bpmn_process_definition_id: int = db.Column( - ForeignKey(BpmnProcessDefinitionModel.id), nullable=True - ) # type: ignore + ForeignKey(BpmnProcessDefinitionModel.id), nullable=True # type: ignore + ) bpmn_process_definition = relationship(BpmnProcessDefinitionModel) + spiff_serializer_version = db.Column(db.String(50), nullable=True) + active_human_tasks = relationship( "HumanTaskModel", primaryjoin=( diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/task_definition.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/task_definition.py index 7d7c5087..dab5ae57 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/task_definition.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/task_definition.py @@ -23,10 +23,11 @@ class TaskDefinitionModel(SpiffworkflowBaseDBModel): id: int = db.Column(db.Integer, primary_key=True) bpmn_process_definition_id: int = db.Column( - ForeignKey(BpmnProcessDefinitionModel.id), nullable=False - ) # type: ignore + ForeignKey(BpmnProcessDefinitionModel.id), nullable=False # type: ignore + ) bpmn_process_definition = relationship(BpmnProcessDefinitionModel) + # bpmn_identifier: str = db.Column(db.String(255, collation='utf8mb4_0900_ai_cs'), nullable=False, index=True) 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) diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_processor.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_processor.py index eaf0e433..63e70d55 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_processor.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_processor.py @@ -552,13 +552,13 @@ class ProcessInstanceProcessor: # print(f"serialized_bpmn_definition.static_json: {serialized_bpmn_definition.static_json}") # loaded_json: dict = json.loads(serialized_bpmn_definition.static_json) # or "{}") - serialized_bpmn_definition = {} + serialized_bpmn_definition: dict = {} bpmn_process_definition = BpmnProcessDefinitionModel.query.filter_by( id=process_instance_model.bpmn_process_definition_id ).first() if bpmn_process_definition is not None: serialized_bpmn_definition = { - "serializer_version": cls.SERIALIZER_VERSION, + "serializer_version": process_instance_model.spiff_serializer_version, "spec": {}, "subprocess_specs": {}, } @@ -570,11 +570,12 @@ class ProcessInstanceProcessor: ).all() ) for ( - bpmn_process_subprocess_definition + bpmn_subprocess_definition ) in bpmn_process_subprocess_definitions: + spec = cls._get_definition_dict_for_bpmn_process_definition(bpmn_subprocess_definition) serialized_bpmn_definition["subprocess_specs"][ - bpmn_process_subprocess_definition.bpmn_identifier - ] = cls._get_definition_dict_for_bpmn_process_definition(bpmn_process_subprocess_definition) + bpmn_subprocess_definition.bpmn_identifier + ] = spec loaded_json: dict = serialized_bpmn_definition process_instance_data = process_instance_model.process_instance_data @@ -975,7 +976,6 @@ class ProcessInstanceProcessor: hash=new_hash_digest, bpmn_identifier=process_bpmn_identifier, properties_json=json.dumps(process_bpmn_properties), - type="process", ) db.session.add(bpmn_process_definition) @@ -988,7 +988,7 @@ class ProcessInstanceProcessor: ) db.session.add(task_definition) - if bpmn_process_definition_parent: + if bpmn_process_definition_parent is not None: bpmn_process_definition_relationship = ( BpmnProcessDefinitionRelationshipModel.query.filter_by( bpmn_process_definition_parent_id=bpmn_process_definition_parent.id, @@ -1003,21 +1003,7 @@ class ProcessInstanceProcessor: db.session.add(bpmn_process_definition_relationship) return bpmn_process_definition - def _add_bpmn_json_records_new(self) -> None: - """Adds serialized_bpmn_definition and process_instance_data records to the db session. - - Expects the save method to commit it. - """ - bpmn_dict = json.loads(self.serialize()) - bpmn_dict_keys = ("spec", "subprocess_specs", "serializer_version") - bpmn_spec_dict = {} - process_instance_data_dict = {} - for bpmn_key in bpmn_dict.keys(): - if bpmn_key in bpmn_dict_keys: - bpmn_spec_dict[bpmn_key] = bpmn_dict[bpmn_key] - else: - process_instance_data_dict[bpmn_key] = bpmn_dict[bpmn_key] - + def _add_bpmn_process_definitions(self, bpmn_spec_dict: dict) -> None: bpmn_process_definition_parent = self._store_bpmn_process_definition( bpmn_spec_dict["spec"] ) @@ -1029,28 +1015,25 @@ class ProcessInstanceProcessor: bpmn_process_definition_parent ) - # # FIXME: always save new hash until we get updated Spiff without loopresettask - # # if self.process_instance_model.serialized_bpmn_definition_id is None: - # new_hash_digest = sha256( - # json.dumps(bpmn_spec_dict, sort_keys=True).encode("utf8") - # ).hexdigest() - # serialized_bpmn_definition = SerializedBpmnDefinitionModel.query.filter_by( - # hash=new_hash_digest - # ).first() - # if serialized_bpmn_definition is None: - # serialized_bpmn_definition = SerializedBpmnDefinitionModel( - # hash=new_hash_digest, static_json=json.dumps(bpmn_spec_dict) - # ) - # db.session.add(serialized_bpmn_definition) - # if ( - # self.process_instance_model.serialized_bpmn_definition_id is None - # or self.process_instance_model.serialized_bpmn_definition.hash - # != new_hash_digest - # ): - # self.process_instance_model.serialized_bpmn_definition = ( - # serialized_bpmn_definition - # ) - # + def _add_bpmn_json_records_new(self) -> None: + """Adds serialized_bpmn_definition and process_instance_data records to the db session. + + Expects the save method to commit it. + """ + bpmn_dict = json.loads(self.serialize()) + bpmn_dict_keys = ("spec", "subprocess_specs", "serializer_version") + process_instance_data_dict = {} + bpmn_spec_dict = {} + for bpmn_key in bpmn_dict.keys(): + if bpmn_key in bpmn_dict_keys: + bpmn_spec_dict[bpmn_key] = bpmn_dict[bpmn_key] + else: + process_instance_data_dict[bpmn_key] = bpmn_dict[bpmn_key] + + # FIXME: always save new hash until we get updated Spiff without loopresettask + # if self.process_instance_model.bpmn_process_definition_id is None: + self._add_bpmn_process_definitions(bpmn_spec_dict) + # process_instance_data = None # if self.process_instance_model.process_instance_data_id is None: # process_instance_data = ProcessInstanceDataModel() @@ -1065,6 +1048,7 @@ class ProcessInstanceProcessor: """Saves the current state of this processor to the database.""" self._add_bpmn_json_records() self._add_bpmn_json_records_new() + self.process_instance_model.spiff_serializer_version = self.SERIALIZER_VERSION complete_states = [TaskState.CANCELLED, TaskState.COMPLETED] user_tasks = list(self.get_all_user_tasks()) diff --git a/spiffworkflow-backend/tests/data/dot_notation/diagram.bpmn b/spiffworkflow-backend/tests/data/dot_notation/diagram.bpmn index 5d682942..96bdce89 100644 --- a/spiffworkflow-backend/tests/data/dot_notation/diagram.bpmn +++ b/spiffworkflow-backend/tests/data/dot_notation/diagram.bpmn @@ -24,14 +24,14 @@ - + Flow_0dbnzbi - - + + Flow_0nt355i - + @@ -53,13 +53,13 @@ - + - +