Skip to content

bug: Retry edge overlaps its source node #279

Description

@fantonangeli

Describe the Bug

In a workflow containing a node with a loop edge, the edge overlaps the node when selected.

Image

Steps to reproduce

  1. Open the Diagram Editor.
  2. Load this workflow:
{
  "document" : {
    "dsl" : "1.0.0",
    "namespace" : "org-acme",
    "name" : "build-task",
    "version" : "0.0.1",
    "metadata" : {
      "io.quarkiverse.flow.identifier.class" : "org.acme.orchestrator.workflow.TaskWorkflow"
    }
  },
  "schedule" : {
    "on" : {
      "one" : {
        "with" : {
          "type" : "org.acme.build.task.started"
        },
        "correlate" : { }
      }
    }
  },
  "do" : [ {
    "extractAndReconcile" : {
      "input" : {
        "from" : {
          "type" : "io.quarkiverse.flow.dsl.types.TypedFunction",
          "value" : {
            "function" : {
              "capturingClass" : "org/acme/orchestrator/workflow/TaskWorkflow",
              "functionalInterfaceClass" : "io/quarkiverse/flow/dsl/types/SerializableFunction",
              "functionalInterfaceMethodName" : "apply",
              "functionalInterfaceMethodSignature" : "(Ljava/lang/Object;)Ljava/lang/Object;",
              "implClass" : "org/acme/orchestrator/workflow/TaskWorkflow",
              "implMethodName" : "lambda$descriptor$4c93d011$2",
              "implMethodSignature" : "(Lcom/fasterxml/jackson/databind/JsonNode;)Lcom/fasterxml/jackson/databind/JsonNode;",
              "implMethodKind" : 6,
              "instantiatedMethodType" : "(Lcom/fasterxml/jackson/databind/JsonNode;)Lcom/fasterxml/jackson/databind/JsonNode;",
              "capturedArgCount" : 0
            },
            "argClass" : "com.fasterxml.jackson.databind.JsonNode"
          }
        }
      },
      "call" : "Java",
      "with" : {
        "function" : {
          "type" : "java.lang.invoke.SerializedLambda",
          "value" : {
            "capturingClass" : "org/acme/orchestrator/workflow/TaskWorkflow",
            "functionalInterfaceClass" : "io/quarkiverse/flow/dsl/types/SerializableFunction",
            "functionalInterfaceMethodName" : "apply",
            "functionalInterfaceMethodSignature" : "(Ljava/lang/Object;)Ljava/lang/Object;",
            "implClass" : "org/acme/orchestrator/workflow/TaskWorkflow",
            "implMethodName" : "lambda$descriptor$4c93d011$1",
            "implMethodSignature" : "(Lorg/acme/orchestrator/model/BuildTask;)Lorg/acme/orchestrator/model/BuildTask;",
            "implMethodKind" : 5,
            "instantiatedMethodType" : "(Lorg/acme/orchestrator/model/BuildTask;)Lorg/acme/orchestrator/model/BuildTask;",
            "capturedArgCount" : 1,
            "capturedArgs" : [ {
              "type" : "org.acme.orchestrator.workflow.TaskWorkflow",
              "value" : { }
            } ]
          }
        },
        "inputClass" : {
          "type" : "java.util.Optional",
          "value" : {
            "type" : "java.lang.Class",
            "value" : "org.acme.orchestrator.model.BuildTask"
          }
        },
        "outputClass" : {
          "type" : "java.util.Optional",
          "value" : {
            "type" : "java.lang.Class",
            "value" : "org.acme.orchestrator.model.BuildTask"
          }
        }
      }
    }
  }, {
    "execute" : {
      "call" : "Java",
      "with" : {
        "function" : {
          "type" : "java.lang.invoke.SerializedLambda",
          "value" : {
            "capturingClass" : "org/acme/orchestrator/workflow/TaskWorkflow",
            "functionalInterfaceClass" : "io/quarkiverse/flow/dsl/types/SerializableFunction",
            "functionalInterfaceMethodName" : "apply",
            "functionalInterfaceMethodSignature" : "(Ljava/lang/Object;)Ljava/lang/Object;",
            "implClass" : "org/acme/orchestrator/workflow/TaskWorkflow",
            "implMethodName" : "lambda$descriptor$4c93d011$3",
            "implMethodSignature" : "(Lorg/acme/orchestrator/model/BuildTask;)Lorg/acme/orchestrator/model/TaskExecutionContext;",
            "implMethodKind" : 5,
            "instantiatedMethodType" : "(Lorg/acme/orchestrator/model/BuildTask;)Lorg/acme/orchestrator/model/TaskExecutionContext;",
            "capturedArgCount" : 1,
            "capturedArgs" : [ {
              "type" : "org.acme.orchestrator.workflow.TaskWorkflow",
              "value" : { }
            } ]
          }
        },
        "inputClass" : {
          "type" : "java.util.Optional",
          "value" : {
            "type" : "java.lang.Class",
            "value" : "org.acme.orchestrator.model.BuildTask"
          }
        },
        "outputClass" : {
          "type" : "java.util.Optional",
          "value" : {
            "type" : "java.lang.Class",
            "value" : "org.acme.orchestrator.model.TaskExecutionContext"
          }
        }
      }
    }
  }, {
    "isTaskCompleted?" : {
      "metadata" : {
        "predicate-switch-item-0" : {
          "type" : "io.quarkiverse.flow.dsl.types.TypedPredicate",
          "value" : {
            "pred" : {
              "capturingClass" : "org/acme/orchestrator/workflow/TaskWorkflow",
              "functionalInterfaceClass" : "io/quarkiverse/flow/dsl/types/SerializablePredicate",
              "functionalInterfaceMethodName" : "test",
              "functionalInterfaceMethodSignature" : "(Ljava/lang/Object;)Z",
              "implClass" : "org/acme/orchestrator/workflow/TaskWorkflow",
              "implMethodName" : "lambda$descriptor$8ed2dda0$1",
              "implMethodSignature" : "(Lorg/acme/orchestrator/model/TaskExecutionContext;)Z",
              "implMethodKind" : 6,
              "instantiatedMethodType" : "(Lorg/acme/orchestrator/model/TaskExecutionContext;)Z",
              "capturedArgCount" : 0
            },
            "argClass" : "org.acme.orchestrator.model.TaskExecutionContext"
          }
        }
      },
      "switch" : [ {
        "switch-item-0" : {
          "then" : "taskCompleted"
        }
      }, {
        "default" : {
          "then" : "checkRetry"
        }
      } ]
    }
  }, {
    "checkRetry" : {
      "then" : "retryExecute",
      "call" : "Java",
      "with" : {
        "function" : {
          "type" : "java.lang.invoke.SerializedLambda",
          "value" : {
            "capturingClass" : "org/acme/orchestrator/workflow/TaskWorkflow",
            "functionalInterfaceClass" : "io/quarkiverse/flow/dsl/types/SerializableConsumer",
            "functionalInterfaceMethodName" : "accept",
            "functionalInterfaceMethodSignature" : "(Ljava/lang/Object;)V",
            "implClass" : "org/acme/orchestrator/workflow/TaskWorkflow",
            "implMethodName" : "lambda$descriptor$3bdcc3b3$1",
            "implMethodSignature" : "(Lorg/acme/orchestrator/model/TaskExecutionContext;)V",
            "implMethodKind" : 6,
            "instantiatedMethodType" : "(Lorg/acme/orchestrator/model/TaskExecutionContext;)V",
            "capturedArgCount" : 0
          }
        },
        "inputClass" : {
          "type" : "java.util.Optional",
          "value" : {
            "type" : "java.lang.Class",
            "value" : "org.acme.orchestrator.model.TaskExecutionContext"
          }
        },
        "outputClass" : {
          "type" : "java.util.Optional"
        }
      }
    }
  }, {
    "retryExecute" : {
      "then" : "isTaskCompleted?",
      "call" : "Java",
      "with" : {
        "function" : {
          "type" : "java.lang.invoke.SerializedLambda",
          "value" : {
            "capturingClass" : "org/acme/orchestrator/workflow/TaskWorkflow",
            "functionalInterfaceClass" : "io/quarkiverse/flow/dsl/types/SerializableFunction",
            "functionalInterfaceMethodName" : "apply",
            "functionalInterfaceMethodSignature" : "(Ljava/lang/Object;)Ljava/lang/Object;",
            "implClass" : "org/acme/orchestrator/workflow/TaskWorkflow",
            "implMethodName" : "lambda$descriptor$4c93d011$4",
            "implMethodSignature" : "(Lorg/acme/orchestrator/model/TaskExecutionContext;)Lorg/acme/orchestrator/model/TaskExecutionContext;",
            "implMethodKind" : 5,
            "instantiatedMethodType" : "(Lorg/acme/orchestrator/model/TaskExecutionContext;)Lorg/acme/orchestrator/model/TaskExecutionContext;",
            "capturedArgCount" : 1,
            "capturedArgs" : [ {
              "type" : "org.acme.orchestrator.workflow.TaskWorkflow",
              "value" : { }
            } ]
          }
        },
        "inputClass" : {
          "type" : "java.util.Optional",
          "value" : {
            "type" : "java.lang.Class",
            "value" : "org.acme.orchestrator.model.TaskExecutionContext"
          }
        },
        "outputClass" : {
          "type" : "java.util.Optional",
          "value" : {
            "type" : "java.lang.Class",
            "value" : "org.acme.orchestrator.model.TaskExecutionContext"
          }
        }
      }
    }
  }, {
    "taskCompleted" : {
      "call" : "Java",
      "with" : {
        "function" : {
          "type" : "java.lang.invoke.SerializedLambda",
          "value" : {
            "capturingClass" : "org/acme/orchestrator/workflow/TaskWorkflow",
            "functionalInterfaceClass" : "io/quarkiverse/flow/dsl/types/SerializableConsumer",
            "functionalInterfaceMethodName" : "accept",
            "functionalInterfaceMethodSignature" : "(Ljava/lang/Object;)V",
            "implClass" : "org/acme/orchestrator/workflow/TaskWorkflow",
            "implMethodName" : "lambda$descriptor$3bdcc3b3$2",
            "implMethodSignature" : "(Lorg/acme/orchestrator/model/TaskExecutionContext;)V",
            "implMethodKind" : 6,
            "instantiatedMethodType" : "(Lorg/acme/orchestrator/model/TaskExecutionContext;)V",
            "capturedArgCount" : 0
          }
        },
        "inputClass" : {
          "type" : "java.util.Optional",
          "value" : {
            "type" : "java.lang.Class",
            "value" : "org.acme.orchestrator.model.TaskExecutionContext"
          }
        },
        "outputClass" : {
          "type" : "java.util.Optional"
        }
      }
    }
  }, {
    "extractResult" : {
      "call" : "Java",
      "with" : {
        "function" : {
          "type" : "java.lang.invoke.SerializedLambda",
          "value" : {
            "capturingClass" : "org/acme/orchestrator/workflow/TaskWorkflow",
            "functionalInterfaceClass" : "io/quarkiverse/flow/dsl/types/SerializableFunction",
            "functionalInterfaceMethodName" : "apply",
            "functionalInterfaceMethodSignature" : "(Ljava/lang/Object;)Ljava/lang/Object;",
            "implClass" : "org/acme/orchestrator/model/TaskExecutionContext",
            "implMethodName" : "result",
            "implMethodSignature" : "()Lorg/acme/orchestrator/model/TaskResult;",
            "implMethodKind" : 5,
            "instantiatedMethodType" : "(Lorg/acme/orchestrator/model/TaskExecutionContext;)Lorg/acme/orchestrator/model/TaskResult;",
            "capturedArgCount" : 0
          }
        },
        "inputClass" : {
          "type" : "java.util.Optional",
          "value" : {
            "type" : "java.lang.Class",
            "value" : "org.acme.orchestrator.model.TaskExecutionContext"
          }
        },
        "outputClass" : {
          "type" : "java.util.Optional",
          "value" : {
            "type" : "java.lang.Class",
            "value" : "org.acme.orchestrator.model.TaskResult"
          }
        }
      }
    }
  }, {
    "emitCompletion" : {
      "then" : "end",
      "emit" : {
        "event" : {
          "with" : {
            "type" : "org.acme.build.task.completed",
            "datacontenttype" : "application/json",
            "data" : {
              "function" : { },
              "argClass" : "org.acme.orchestrator.model.TaskResult"
            }
          }
        }
      }
    }
  } ]
}
  1. Locate the retryExecute and select the gray edge
  2. Observe the retry edge from retryExecute is overlapping the node

Expected Behavior

The edge should not overlap the node and should be attached to the node's top

Editor Version

1.0.0

Platform

Web / Browser

Additional Context

This has been spotted on Quarkus Flow using the resilient-task-orchestrator example

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

Projects

Status
Backlog

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions