Skip to content

feat(cf): blocked delete state with reason classification + latch - #5407

Merged
norman-abramovitz merged 3 commits into
cloudfoundry:developfrom
nabramovitz:refactor/delete-mechanism-inc3-blocked
Jun 2, 2026
Merged

feat(cf): blocked delete state with reason classification + latch#5407
norman-abramovitz merged 3 commits into
cloudfoundry:developfrom
nabramovitz:refactor/delete-mechanism-inc3-blocked

Conversation

@nabramovitz

Copy link
Copy Markdown
Contributor

What

Adds the blocked lifecycle state to the signal-native EntityDeleteController (Increment 3 of the common delete-mechanism work), so a delete that fails for a known precondition is surfaced distinctly from a transient failure and stops auto-retry loops.

  • classifyBlock(error) — pure classifier mapping a delete failure (either an HttpErrorResponse or a polled StratosJobError) to a BlockReason: 403forbidden, async/last_operation in-progress → operation-in-progress, CF-AssociationNotEmptyhas-dependents. Transient/5xx/generic-validation stay failure.
  • Controller emits a blocked terminal (with reason + error) instead of failure for classified cases, and latches the entity by cnsi:kind:guid. While latched, delete() short-circuits to blocked (re-emitting the stored reason/error, no server call) until an explicit clear(). isBlocked()/clear() expose the latch; a successful delete clears it defensively. Blocked runs no invalidation/cleanup and fires a delete-event state:'blocked' diagnostics counter.
  • runCfDelete throws on blocked too, so the stored CF error (e.g. association_not_empty) reaches the component snackbar instead of resolving silently.

Presentation of the blocked state (rendering the latch, wiring a UI clear()) is intentionally out of scope — it lands when a view adopts the lifecycle stream.

Testing

Full make check gate green (2389 frontend tests, 0 TS/build errors). TDD throughout — 22 controller tests, classifier and runCfDelete specs.

Pure classifier mapping a delete failure (HttpErrorResponse or polled
StratosJobError) to a BlockReason: 403 -> forbidden, async/last_operation
in progress -> operation-in-progress, CF-AssociationNotEmpty ->
has-dependents. Transient/5xx/generic-validation stay failure (undefined).
Mechanism-owned defaults so every caller gets the universal CF cases.
Classified delete failures (classifyBlock) now terminate as `blocked`
with a reason instead of `failure`, and latch the entity by
cnsi:kind:guid. While latched, delete() short-circuits to blocked
(re-emitting the stored reason+error, no server call) until clear().
isBlocked()/clear() expose the latch; a successful delete clears it
defensively. Blocked runs no invalidation/cleanup and fires a blocked
diagnostics counter.
runCfDelete now throws on a blocked terminal as well as failure, so the
stored CF error (e.g. association_not_empty) reaches the component catch
and snackbar instead of resolving silently.

@norman-abramovitz norman-abramovitz left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@norman-abramovitz
norman-abramovitz merged commit 524962b into cloudfoundry:develop Jun 2, 2026
12 checks passed
@nabramovitz
nabramovitz deleted the refactor/delete-mechanism-inc3-blocked branch June 17, 2026 08:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants