-
Notifications
You must be signed in to change notification settings - Fork 627
UN-151 [FIX] Block workflow deletion at backend when in use by pipelines/APIs #1969
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -991,6 +991,46 @@ def make_async_result(obj: AsyncResult) -> dict[str, Any]: | |
| } | ||
|
|
||
| USAGE_DISPLAY_LIMIT = 5 | ||
| USAGE_MESSAGE_DISPLAY_LIMIT = 3 | ||
|
|
||
| @staticmethod | ||
| def build_workflow_in_use_message(workflow_name: str, usage: dict[str, Any]) -> str: | ||
| """Builds a user-facing message listing pipelines/APIs blocking deletion. | ||
|
|
||
| Matches the format used by the frontend so direct API callers see the | ||
| same details about which pipelines/API deployments are using the WF. | ||
| """ | ||
| pipelines = usage.get("pipelines") or [] | ||
| api_names = usage.get("api_names") or [] | ||
| pipeline_count = usage.get("pipeline_count", 0) | ||
| api_count = usage.get("api_count", 0) | ||
|
|
||
| if (pipeline_count + api_count) == 0: | ||
| return f"Cannot delete `{workflow_name}` as it is currently in use." | ||
|
Comment on lines
+1008
to
+1009
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Prompt To Fix With AIThis is a comment left during a code review.
Path: backend/workflow_manager/workflow_v2/workflow_helper.py
Line: 1008-1009
Comment:
**Unreachable fallback branch**
`build_workflow_in_use_message` is only called from `perform_destroy` after `can_update_workflow` has already returned `can_update=False`, which only occurs when `pipeline_count + api_count > 0`. The zero-count branch (line 1008–1009) therefore cannot be reached via the current call site and silently returns a generic message if it ever were, which could mask the real cause. Consider either removing this branch (trusting the caller contract) or converting it to an `AssertionError`/log to make the invariant explicit.
How can I resolve this? If you propose a fix, please make it concise. |
||
|
|
||
| limit = WorkflowHelper.USAGE_MESSAGE_DISPLAY_LIMIT | ||
| lines: list[str] = [] | ||
|
|
||
| if api_names: | ||
| shown = list(api_names)[:limit] | ||
| for name in shown: | ||
| lines.append(f"- `{name}` (API Deployment)") | ||
| remaining = api_count - len(shown) | ||
| if remaining > 0: | ||
| lines.append(f"- ...and {remaining} more API deployment(s)") | ||
|
|
||
| if pipelines: | ||
| shown = list(pipelines)[:limit] | ||
| for p in shown: | ||
| name = p.get("pipeline_name") | ||
| p_type = p.get("pipeline_type") | ||
| lines.append(f"- `{name}` ({p_type} Pipeline)") | ||
|
Comment on lines
+1025
to
+1027
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Prompt To Fix With AIThis is a comment left during a code review.
Path: backend/workflow_manager/workflow_v2/workflow_helper.py
Line: 1025-1027
Comment:
**Raw enum key used as pipeline type label**
`pipeline_type` is stored as the `PipelineType` TextChoices key (`"ETL"`, `"TASK"`, `"DEFAULT"`, `"APP"`), so the message would read `DEFAULT Pipeline` or `APP Pipeline` for those types — labels that may be unclear to API callers. The `.values()` queryset in `can_update_workflow` returns the raw DB value rather than the human-readable label (`"Default"`, `"App"`). Consider mapping the raw key to the display label (e.g. via `PipelineType(p_type).label` where `PipelineType` is imported from `pipeline_v2.models`) before constructing the line.
How can I resolve this? If you propose a fix, please make it concise. |
||
| remaining = pipeline_count - len(shown) | ||
| if remaining > 0: | ||
| lines.append(f"- ...and {remaining} more pipeline(s)") | ||
|
|
||
| details = "\n".join(lines) | ||
| return f"Cannot delete `{workflow_name}` as it is used in:\n{details}" | ||
|
|
||
| @staticmethod | ||
| def can_update_workflow(workflow_id: str) -> dict[str, Any]: | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
perform_destroycan_update_workflowopens withWorkflow.objects.get(pk=workflow_id)to reload the object, butinstancepassed intoperform_destroyis already the fully-loadedWorkflowrow (fetched byget_object()earlier in the DRF lifecycle). This adds an extra round-trip. Ifcan_update_workflowis also called from the existingcan_updateendpoint with only an ID string, consider adding an overload or internal helper that accepts either aWorkflowinstance or an ID soperform_destroycan skip the redundant lookup.Prompt To Fix With AI