Clean up process references when deleting models and groups (#1561)
This commit is contained in:
parent
afd598bb8f
commit
10e9511cfc
|
@ -12,6 +12,7 @@ from flask.wrappers import Response
|
||||||
from spiffworkflow_backend.exceptions.api_error import ApiError
|
from spiffworkflow_backend.exceptions.api_error import ApiError
|
||||||
from spiffworkflow_backend.exceptions.error import NotAuthorizedError
|
from spiffworkflow_backend.exceptions.error import NotAuthorizedError
|
||||||
from spiffworkflow_backend.exceptions.process_entity_not_found_error import ProcessEntityNotFoundError
|
from spiffworkflow_backend.exceptions.process_entity_not_found_error import ProcessEntityNotFoundError
|
||||||
|
from spiffworkflow_backend.models.db import db
|
||||||
from spiffworkflow_backend.models.process_group import ProcessGroup
|
from spiffworkflow_backend.models.process_group import ProcessGroup
|
||||||
from spiffworkflow_backend.models.process_group import ProcessGroupSchema
|
from spiffworkflow_backend.models.process_group import ProcessGroupSchema
|
||||||
from spiffworkflow_backend.routes.process_api_blueprint import _commit_and_push_to_git
|
from spiffworkflow_backend.routes.process_api_blueprint import _commit_and_push_to_git
|
||||||
|
@ -19,6 +20,7 @@ from spiffworkflow_backend.routes.process_api_blueprint import _un_modify_modifi
|
||||||
from spiffworkflow_backend.services.authorization_service import AuthorizationService
|
from spiffworkflow_backend.services.authorization_service import AuthorizationService
|
||||||
from spiffworkflow_backend.services.process_model_service import ProcessModelService
|
from spiffworkflow_backend.services.process_model_service import ProcessModelService
|
||||||
from spiffworkflow_backend.services.process_model_service import ProcessModelWithInstancesNotDeletableError
|
from spiffworkflow_backend.services.process_model_service import ProcessModelWithInstancesNotDeletableError
|
||||||
|
from spiffworkflow_backend.services.spec_file_service import SpecFileService
|
||||||
from spiffworkflow_backend.services.user_service import UserService
|
from spiffworkflow_backend.services.user_service import UserService
|
||||||
|
|
||||||
|
|
||||||
|
@ -49,6 +51,11 @@ def process_group_delete(modified_process_group_id: str) -> flask.wrappers.Respo
|
||||||
|
|
||||||
try:
|
try:
|
||||||
ProcessModelService.process_group_delete(process_group_id)
|
ProcessModelService.process_group_delete(process_group_id)
|
||||||
|
|
||||||
|
# can't do this in the ProcessModelService due to circular imports
|
||||||
|
SpecFileService.clear_caches_for_process_group(process_group_id)
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
except ProcessModelWithInstancesNotDeletableError as exception:
|
except ProcessModelWithInstancesNotDeletableError as exception:
|
||||||
raise ApiError(
|
raise ApiError(
|
||||||
error_code="existing_instances",
|
error_code="existing_instances",
|
||||||
|
|
|
@ -112,7 +112,12 @@ def process_model_delete(
|
||||||
) -> flask.wrappers.Response:
|
) -> flask.wrappers.Response:
|
||||||
process_model_identifier = modified_process_model_identifier.replace(":", "/")
|
process_model_identifier = modified_process_model_identifier.replace(":", "/")
|
||||||
try:
|
try:
|
||||||
|
process_model = _get_process_model(process_model_identifier)
|
||||||
ProcessModelService.process_model_delete(process_model_identifier)
|
ProcessModelService.process_model_delete(process_model_identifier)
|
||||||
|
|
||||||
|
# can't do this in the ProcessModelService due to circular imports
|
||||||
|
SpecFileService.clear_caches_for_process_model(process_model)
|
||||||
|
db.session.commit()
|
||||||
except ProcessModelWithInstancesNotDeletableError as exception:
|
except ProcessModelWithInstancesNotDeletableError as exception:
|
||||||
raise ApiError(
|
raise ApiError(
|
||||||
error_code="existing_instances",
|
error_code="existing_instances",
|
||||||
|
|
|
@ -275,6 +275,36 @@ class SpecFileService(FileSystemService):
|
||||||
|
|
||||||
ProcessCallerService.clear_cache_for_process_ids(reference_cache_ids)
|
ProcessCallerService.clear_cache_for_process_ids(reference_cache_ids)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def clear_caches_for_process_group(process_group_id: str) -> None:
|
||||||
|
records = (
|
||||||
|
db.session.query(ReferenceCacheModel)
|
||||||
|
.filter(ReferenceCacheModel.relative_location.like(f"{process_group_id}/%")) # type: ignore
|
||||||
|
.all()
|
||||||
|
)
|
||||||
|
|
||||||
|
reference_cache_ids = []
|
||||||
|
|
||||||
|
for record in records:
|
||||||
|
reference_cache_ids.append(record.id)
|
||||||
|
db.session.delete(record)
|
||||||
|
|
||||||
|
ProcessCallerService.clear_cache_for_process_ids(reference_cache_ids)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def clear_caches_for_process_model(process_model_info: ProcessModelInfo) -> None:
|
||||||
|
records = (
|
||||||
|
db.session.query(ReferenceCacheModel).filter(ReferenceCacheModel.relative_location == process_model_info.id).all()
|
||||||
|
)
|
||||||
|
|
||||||
|
reference_cache_ids = []
|
||||||
|
|
||||||
|
for record in records:
|
||||||
|
reference_cache_ids.append(record.id)
|
||||||
|
db.session.delete(record)
|
||||||
|
|
||||||
|
ProcessCallerService.clear_cache_for_process_ids(reference_cache_ids)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def update_process_cache(ref: Reference) -> None:
|
def update_process_cache(ref: Reference) -> None:
|
||||||
process_id_lookup = (
|
process_id_lookup = (
|
||||||
|
|
|
@ -0,0 +1,127 @@
|
||||||
|
from flask.app import Flask
|
||||||
|
from flask.testing import FlaskClient
|
||||||
|
from spiffworkflow_backend.models.task import TaskModel # noqa: F401
|
||||||
|
from spiffworkflow_backend.models.user import UserModel
|
||||||
|
|
||||||
|
from tests.spiffworkflow_backend.helpers.base_test import BaseTest
|
||||||
|
|
||||||
|
|
||||||
|
class TestProcessCallers(BaseTest):
|
||||||
|
def test_references_after_process_model_create(
|
||||||
|
self,
|
||||||
|
app: Flask,
|
||||||
|
client: FlaskClient,
|
||||||
|
with_db_and_bpmn_file_cleanup: None,
|
||||||
|
with_super_admin_user: UserModel,
|
||||||
|
) -> None:
|
||||||
|
self.create_group_and_model_with_bpmn(
|
||||||
|
client=client,
|
||||||
|
user=with_super_admin_user,
|
||||||
|
process_group_id="test_group_two",
|
||||||
|
process_model_id="call_activity_nested",
|
||||||
|
bpmn_file_location="call_activity_nested",
|
||||||
|
)
|
||||||
|
|
||||||
|
response = client.get(
|
||||||
|
"/v1.0/processes",
|
||||||
|
headers=self.logged_in_headers(with_super_admin_user),
|
||||||
|
)
|
||||||
|
|
||||||
|
assert response.status_code == 200
|
||||||
|
assert response.json is not None
|
||||||
|
assert isinstance(response.json, list)
|
||||||
|
assert len(response.json) == 4
|
||||||
|
|
||||||
|
response = client.get(
|
||||||
|
"/v1.0/processes/callers/Level2",
|
||||||
|
headers=self.logged_in_headers(with_super_admin_user),
|
||||||
|
)
|
||||||
|
|
||||||
|
assert response.status_code == 200
|
||||||
|
assert response.json is not None
|
||||||
|
assert isinstance(response.json, list)
|
||||||
|
assert len(response.json) == 1
|
||||||
|
|
||||||
|
def test_references_after_process_model_delete(
|
||||||
|
self,
|
||||||
|
app: Flask,
|
||||||
|
client: FlaskClient,
|
||||||
|
with_db_and_bpmn_file_cleanup: None,
|
||||||
|
with_super_admin_user: UserModel,
|
||||||
|
) -> None:
|
||||||
|
self.create_group_and_model_with_bpmn(
|
||||||
|
client=client,
|
||||||
|
user=with_super_admin_user,
|
||||||
|
process_group_id="test_group_two",
|
||||||
|
process_model_id="call_activity_nested",
|
||||||
|
bpmn_file_location="call_activity_nested",
|
||||||
|
)
|
||||||
|
|
||||||
|
response = client.delete(
|
||||||
|
"/v1.0/process-models/test_group_two:call_activity_nested",
|
||||||
|
headers=self.logged_in_headers(with_super_admin_user),
|
||||||
|
)
|
||||||
|
|
||||||
|
assert response.status_code == 200
|
||||||
|
|
||||||
|
response = client.get(
|
||||||
|
"/v1.0/processes",
|
||||||
|
headers=self.logged_in_headers(with_super_admin_user),
|
||||||
|
)
|
||||||
|
|
||||||
|
assert response.status_code == 200
|
||||||
|
assert response.json is not None
|
||||||
|
assert isinstance(response.json, list)
|
||||||
|
assert len(response.json) == 0
|
||||||
|
|
||||||
|
response = client.get(
|
||||||
|
"/v1.0/processes/callers/Level2",
|
||||||
|
headers=self.logged_in_headers(with_super_admin_user),
|
||||||
|
)
|
||||||
|
|
||||||
|
assert response.status_code == 200
|
||||||
|
assert response.json is not None
|
||||||
|
assert isinstance(response.json, list)
|
||||||
|
assert len(response.json) == 0
|
||||||
|
|
||||||
|
def test_references_after_process_group_delete(
|
||||||
|
self,
|
||||||
|
app: Flask,
|
||||||
|
client: FlaskClient,
|
||||||
|
with_db_and_bpmn_file_cleanup: None,
|
||||||
|
with_super_admin_user: UserModel,
|
||||||
|
) -> None:
|
||||||
|
self.create_group_and_model_with_bpmn(
|
||||||
|
client=client,
|
||||||
|
user=with_super_admin_user,
|
||||||
|
process_group_id="test_group_two",
|
||||||
|
process_model_id="call_activity_nested",
|
||||||
|
bpmn_file_location="call_activity_nested",
|
||||||
|
)
|
||||||
|
|
||||||
|
response = client.delete(
|
||||||
|
"/v1.0/process-groups/test_group_two",
|
||||||
|
headers=self.logged_in_headers(with_super_admin_user),
|
||||||
|
)
|
||||||
|
|
||||||
|
assert response.status_code == 200
|
||||||
|
|
||||||
|
response = client.get(
|
||||||
|
"/v1.0/processes",
|
||||||
|
headers=self.logged_in_headers(with_super_admin_user),
|
||||||
|
)
|
||||||
|
|
||||||
|
assert response.status_code == 200
|
||||||
|
assert response.json is not None
|
||||||
|
assert isinstance(response.json, list)
|
||||||
|
assert len(response.json) == 0
|
||||||
|
|
||||||
|
response = client.get(
|
||||||
|
"/v1.0/processes/callers/Level2",
|
||||||
|
headers=self.logged_in_headers(with_super_admin_user),
|
||||||
|
)
|
||||||
|
|
||||||
|
assert response.status_code == 200
|
||||||
|
assert response.json is not None
|
||||||
|
assert isinstance(response.json, list)
|
||||||
|
assert len(response.json) == 0
|
Loading…
Reference in New Issue