From 5e7890f36fd5078e9dead52d2b1991ed1194af15 Mon Sep 17 00:00:00 2001 From: -LAN- Date: Tue, 4 Mar 2025 14:35:35 +0800 Subject: [PATCH] feat: enhance workflow deletion with error handling for in-use and draft workflows Signed-off-by: -LAN- --- api/controllers/console/app/workflow.py | 23 +++++++++++++---------- api/services/errors/workflow_service.py | 10 ++++++++++ api/services/workflow_service.py | 16 ++++++++++++---- 3 files changed, 35 insertions(+), 14 deletions(-) create mode 100644 api/services/errors/workflow_service.py diff --git a/api/controllers/console/app/workflow.py b/api/controllers/console/app/workflow.py index 4598c276e7..4af7564eef 100644 --- a/api/controllers/console/app/workflow.py +++ b/api/controllers/console/app/workflow.py @@ -27,7 +27,7 @@ from models.account import Account from models.model import AppMode from services.app_generate_service import AppGenerateService from services.errors.app import WorkflowHashNotEqualError -from services.workflow_service import WorkflowService +from services.workflow_service import DraftWorkflowDeletionError, WorkflowInUseError, WorkflowService logger = logging.getLogger(__name__) @@ -596,15 +596,18 @@ class WorkflowByIdApi(Resource): # Create a session and manage the transaction with Session(db.engine) as session: - success = workflow_service.delete_workflow( - session=session, workflow_id=workflow_id, tenant_id=app_model.tenant_id - ) - - if not success: - raise NotFound("Workflow not found or cannot be deleted") - - # Commit the transaction in the controller - session.commit() + try: + workflow_service.delete_workflow( + session=session, workflow_id=workflow_id, tenant_id=app_model.tenant_id + ) + # Commit the transaction in the controller + session.commit() + except ValueError as e: + raise NotFound(str(e)) + except WorkflowInUseError as e: + abort(400, description=str(e)) + except DraftWorkflowDeletionError as e: + abort(400, description=str(e)) return None, 204 diff --git a/api/services/errors/workflow_service.py b/api/services/errors/workflow_service.py new file mode 100644 index 0000000000..ea9b487568 --- /dev/null +++ b/api/services/errors/workflow_service.py @@ -0,0 +1,10 @@ +class WorkflowInUseError(ValueError): + """Raised when attempting to delete a workflow that's in use by an app""" + + pass + + +class DraftWorkflowDeletionError(ValueError): + """Raised when attempting to delete a draft workflow""" + + pass diff --git a/api/services/workflow_service.py b/api/services/workflow_service.py index 9b3a2527ac..31fdae491e 100644 --- a/api/services/workflow_service.py +++ b/api/services/workflow_service.py @@ -35,7 +35,8 @@ from models.workflow import ( WorkflowType, ) from services.errors.app import WorkflowHashNotEqualError -from services.workflow.workflow_converter import WorkflowConverter + +from .errors.workflow_service import DraftWorkflowDeletionError, WorkflowInUseError class WorkflowService: @@ -491,20 +492,27 @@ class WorkflowService: :param session: SQLAlchemy database session :param workflow_id: Workflow ID :param tenant_id: Tenant ID - :return: True if deletable, False if not found or in use + :return: True if successful + :raises: ValueError if workflow not found + :raises: WorkflowInUseError if workflow is in use + :raises: DraftWorkflowDeletionError if workflow is a draft version """ stmt = select(Workflow).where(Workflow.id == workflow_id, Workflow.tenant_id == tenant_id) workflow = session.scalar(stmt) if not workflow: - return False + raise ValueError(f"Workflow with ID {workflow_id} not found") + + # Check if workflow is a draft version + if workflow.version == "draft": + raise DraftWorkflowDeletionError("Cannot delete draft workflow versions") # Check if this workflow is currently referenced by an app stmt = select(App).where(App.workflow_id == workflow_id) app = session.scalar(stmt) if app: # Cannot delete a workflow that's currently in use by an app - return False + raise WorkflowInUseError(f"Cannot delete workflow that is currently in use by app '{app.name}'") session.delete(workflow) return True