feat(api): allow deleting terminal bank operations with control-plane support#2777
Open
chethanuk wants to merge 3 commits into
Open
feat(api): allow deleting terminal bank operations with control-plane support#2777chethanuk wants to merge 3 commits into
chethanuk wants to merge 3 commits into
Conversation
nicoloboschi
requested changes
Jul 20, 2026
nicoloboschi
left a comment
Collaborator
There was a problem hiding this comment.
let's call the endpoint
/delete
@app.delete(
"/v1/default/banks/{bank_id}/operations/{operation_id}/delete",
Maintainer review on vectorize-io#2777 asked for the hard-delete endpoint to live at /delete rather than /record. Renames the path segment end-to-end: dataplane route + log message, tests, OpenAPI spec (and its skills mirror), and the generated Python/TypeScript/Go clients. The route's operation_id is explicitly "delete_operation", so no generated symbol names change -- only the path string. Go and Python generated output was verified byte-identical against the pinned openapi-generator v7.10.0.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
There is no way to remove terminal (
failed/cancelled/completed) async operation rows.DELETE …/operations/{id}is bound to cancel, which only flipspending → cancelledand returns 409 for anything else — the row never leaves the table, so failed operations pile up in the control plane with no cleanup path and no navigation to the document they produced.Fixes #2677
Fix
DELETE /v1/default/banks/{bank_id}/operations/{operation_id}/delete: status-guarded hard delete for terminal states only, implemented as a single bank-scopedDELETE … RETURNING(no TOCTOU window with a concurrent retry). 404 when missing, 409 for non-terminal states. The existing cancel route is untouched.delete_operation+BankWriteOperation.DELETE_OPERATION(operation-validator aware).result_metadata.document_idis present — the navigation path the issue reporter asked for.flowchart LR subgraph cp [Control plane] U["Operations table / dialog<br/>(Delete on terminal rows)"] --> C["client.deleteOperation()"] C --> B["BFF DELETE /api/banks/{bankId}/operations/{id}"] end B --> S["SDK deleteOperation"] S --> R["DELETE …/operations/{id}/delete"] R --> G{"status ∈ failed |<br/>cancelled | completed?"} G -->|yes| D["single bank-scoped<br/>DELETE … RETURNING"] G -->|"no (pending/processing)"| X["409 — use cancel<br/>(unchanged route)"] D --> P["row gone on next poll"]Semantics: cancel vs delete
DELETE …/operations/{id}pending → cancelled(soft, unchanged)DELETE …/operations/{id}/deleteA review bot suggested the control plane was calling the cancel verb — that's a mix-up of the BFF namespace with the dataplane path: the BFF's
DELETE /api/banks/{bankId}/operations/{id}handler calls the generated SDK, which requests…/operations/{id}/delete; cancel lives on a separate BFF route (/api/operations/{bankId}).Review fixes folded in
@validate_callondelete_operationand had dropped the decorator fromretry_operation(silently losing runtime arg validation there).…/operations/{operation_id}/record→…/operations/{operation_id}/deleteper maintainer review; OpenAPI spec and Go/Python/TypeScript clients regenerated (no client symbol names changed — they derive from the explicitoperation_id="delete_operation", not the path)."Failed to delete operation"registered infailureErrorKeysso error payloads localize like every sibling operation endpoint (keys already existed in all 10 locales).How to test
Manual E2E: retain a doc so an operation ends
failed→ Operations → detail → View Document (whendocument_idset) → Delete → row disappears on next poll; cancel of apendingop still works via the old route.Test evidence
Run post-rebase on upstream
main(52b893b93), squashed branch:pytest tests/test_operation_status.py tests/test_operation_progress.py -n0npm testnpm run i18n:checkruff check/format --check/ty checkon touched modulesOut of scope
processingoperations — tracked upstream in Stop hook resends entire session transcript every retain call (O(N²) growth) — still present in 0.7.4 #2644 / Crash-interrupted operations are re-claimed indefinitely — claim attempts never count toward max_attempts (poison-pill regrind loop) #2675; the status guard deliberately excludesprocessing.delete_documentdoes not cascade to operations (separate issue).completeddespite a deleted failed child. Parent linkage lives in JSONresult_metadata(no FK). If maintainers prefer a hard guard, the clean shape is aNOT EXISTS (non-terminal parent)predicate folded into the same single-statement DELETE — happy to add it in this PR on request.