Skip to content

fix: Fixed resolutions reaching BLOCKED_DEADLOCK when a Step's state is modified externally#631

Open
DrRebus wants to merge 1 commit into
ovh:masterfrom
DrRebus:rtordjma/fix-resolution-deadlock
Open

fix: Fixed resolutions reaching BLOCKED_DEADLOCK when a Step's state is modified externally#631
DrRebus wants to merge 1 commit into
ovh:masterfrom
DrRebus:rtordjma/fix-resolution-deadlock

Conversation

@DrRebus

@DrRebus DrRebus commented Apr 29, 2026

Copy link
Copy Markdown
Contributor
  • What kind of change does this PR introduce? (Bug fix, feature, docs update, ...)
    Bug fix.

  • What is the current behavior? (You can also link to an open issue here)
    Resolutions can end up in the BLOCKED_DEADLOCK state when one of their Steps is updated through the API because no pruning is performed.
    Let's consider a simple task with 3 steps : Parent, Child1 and Child2. Child1 has the dependency Parent:DONE, Child2 has Parent:CUSTOM_STATE (see attached picture). If Parent has an issue and can't reach either the DONE or CUSTOM_STATE and we were to update its state manually to the DONE state for example, Child1 could be executed and Child2 should reach the PRUNE state. However, since no pruning is performed at this stage, Child2 stays in TODO forever and the resolution becomes BLOCKED_DEADLOCK

  • What is the new behavior (if this is a feature change)?
    Proactive pruning is performed whenever a resolution is run.

  • Does this PR introduce a breaking change? (What changes might users need to make in their application due to this PR?)
    Not that I am aware of.

  • Other information:

image

…is modified externally

Signed-off-by: Ruben Tordjman <144785435+DrRebus@users.noreply.github.com>
Comment thread engine/engine.go
}

{
// Making sure to prune steps whose dependencies were updated outside the engine (API, manually in DB, etc)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

We can also perform proactive pruning in the API's handlers whenever a resolution or step is updated, but doing it here also covers updates made in the database directly.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes a deadlock scenario where a resolution can incorrectly end up in BLOCKED_DEADLOCK after a step’s state is modified externally (e.g., via API/manual DB edit) by proactively pruning steps at resolution startup so that downstream steps with now-impossible dependency states are moved to PRUNE.

Changes:

  • Add a proactive pruning pass in initialize() before starting execution, to account for dependency/state changes done outside the engine.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread engine/engine.go
Comment on lines +364 to +367
stepsToCheck := map[string]bool{}
for stepName := range res.Steps {
stepsToCheck[stepName] = true
}
Comment thread engine/engine.go
Comment on lines +362 to +369
{
// Making sure to prune steps whose dependencies were updated outside the engine (API, manually in DB, etc)
stepsToCheck := map[string]bool{}
for stepName := range res.Steps {
stepsToCheck[stepName] = true
}
pruneSteps(res, stepsToCheck)
}
Comment thread engine/engine.go
Comment on lines +362 to +369
{
// Making sure to prune steps whose dependencies were updated outside the engine (API, manually in DB, etc)
stepsToCheck := map[string]bool{}
for stepName := range res.Steps {
stepsToCheck[stepName] = true
}
pruneSteps(res, stepsToCheck)
}
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.

3 participants