Improve gateway support

Created on 26 November 2022, about 2 years ago
Updated 12 June 2024, 6 months ago

Problem/Motivation

In some models, actually and quite many, we have multiple successors to an object and the order of processing actually matters, but we still can put them in a sequence. Here is an example in descriptive format:

  • Starting with a pre-save entity event
  • if field1 equals 1, add an item to a list token
  • in all cases, continue with a long chain of actions and finally do something with the list token

In this scenario, it is important that the conditional action to add something to the list token gets executed first, before processing the second successors to that event. But BPMN doesn't provide any means to control the order of processing. With gateways we could, as they allow parallel chains that all comes back together and wait for each other to continue processing after each of the alternatives have been processed.

Other cases are if-then-else constructions that are really hard to build in BPMN, unless gateways were fully supported.

Proposed resolution

A good overview and explanation of gateway types can be found at https://www.visual-paradigm.com/guide/bpmn/bpmn-gateway-types

There are 7 gateway types, 3 of which are a combination of an event and another gateway type. I suggest to not implement them (yet) as the same can be achieved with an event followed by a gateway.

The 4 important gateway types are:

  • Exclusive: this is the default in BPMN.iO and only the first successor with a valid condition will be executed.
  • Inclusive: all successors with a valid condition will be executed in the order they have been defined
  • Parallel: same as inclusive, but each fork is being executed in parallel instead of sequentially - I suggest we skip this one as we don't support parallel processing in PHP (yet)
  • Complex: it's not clear to me, how this is different from exclusive or inclusive gateways. The example shows that a flow can reach the same complex gateway more than once. But nothing is saying that this couldn't happen with the others, either. Therefore, it seems to be unnecessary overhead and we should skip that too.

That leaves us with the implementation of the exclusive and inclusive gateway, both in 2 way: diverging and converging, where the latter is only relevant for inclusive gateways.

What's not clear yet and needs discussion:

  • Do we have to migrate existing models to convert exclusive gateways into inclusive ones? This is because it is very likely that if the gateway has been used already, the user assumed that to be inclusive.
  • Do we have to implement that into the ECA Core Modeller as well? If not, what's the fallback behaviour when a BPMN model gets imported into a CM model?
  • Do we have to validate models such that 2 pairing gateways are always of the same type? I haven't found anything in the spec for that.
  • The documentation states, that an exclusive gateway must have one fork with a valid condition; otherwise an exception should be thrown. How should we handle that in ECA? Throwing (and logging) the exception and then continue processing? Or should ECA stop processing everything, including all other events?
✨ Feature request
Status

Active

Version

2.1

Component

Code

Created by

πŸ‡©πŸ‡ͺGermany jurgenhaas Gottmadingen

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • πŸ‡©πŸ‡ͺGermany danielspeicher Steisslingen

    My thoughts:

    I see the point to analyze the requirement in general, means to not stick to the term "gateway", which is provided by BPMN.

    We just have Events, Conditions and Actions, which is fine.

    I think there is basically one key decision to make. Do we introduce a new "type" in addition to Event, Condition, Action? Or can we use one of the existing components, like the Condition, to fulfill the requirements?

    Currently, what I like in ECA, is the simplicity, a condition can be true or false and an action gets executed and returns nothing (concerning the execute method). So if we use an existing component, I am afraid to lose that, because we mix up things. An advantage, on the other side, is that we do not have to migrate existing models in case of introducing a new "type" of condition.

    I think we should go for a general concept in ECA, which behave like the two gateways in BPMN JΓΌrgen mentioned above. Of course, we do not have to use the name "gateway" and try to be as general as possible.

    In existing BPMN models, there are already gateways (exclusive) in use, so we can extend it by creating a new one (inclusive).

    So, for me, a minor argument is the name of the module (ECA). People use it because of its power and functionality.

    Do we have to migrate existing models to convert exclusive gateways into inclusive ones? This is because it is very likely that if the gateway has been used already, the user assumed that to be inclusive.

    Yes, I think that is very likely.

    Do we have to implement that into the ECA Core Modeller as well? If not, what's the fallback behaviour when a BPMN model gets imported into a CM model?

    Tough question. I do not have an answer yet, but I tend to say "yes, we must implement that into the Core modeler."

    Do we have to validate models such that 2 pairing gateways are always of the same type? I haven't found anything in the spec for that.

    I honestly do not know yet.

    The documentation states, that an exclusive gateway must have one fork with a valid condition; otherwise an exception should be thrown. How should we handle that in ECA? Throwing (and logging) the exception and then continue processing? Or should ECA stop processing everything, including all other events?

    If the model is "wrong", means it can produce wrong results, we should throw an exception and explain why.

  • πŸ‡©πŸ‡ͺGermany jurgenhaas Gottmadingen

    This is excellent feedback, thanks a lot @danielspeicher for this.

    I suggest, that we keep the question of "Do we need an object like e.g. a gateway or should the type of condition be defined elsewhere" aside for now and come back to this later. Also, the details on edge cases, let's address them later. With all the research we've done so far, let's have a look into use cases.

    What is called "inclusive" and "exclusive" gateways above, transforms into the following PHP logic:

    inclusive:

    if ($condition1) {
      // do something
    }
    if ($condition2) {
      // do something
    }
    if ($condition3) {
      // do something
    }
    if ($condition4) {
      // do something
    }
    

    In other words, each event or action has any number of successors, each of which with its own condition. All successors with an asserted condition will be executed.

    exclusive:

    if ($condition1) {
      // do something
    }
    elseif ($condition2) {
      // do something
    }
    elseif ($condition3) {
      // do something
    }
    else {
      // do something
    }
    

    Again, each event or action has any number of successor, but only the first one with an asserted condition will be executed. The last successor in this example doesn't even have any condition, it'll only be executed if none of the conditions get asserted.

    Having said that, and we've seen that in many other cases before, the order of the successors is really relevant. This leads to the proposal to also introduce a "weight" property for all actions in a model. This allows modellers to explicitly define the order in which the actions should be processed, i.e. in which order their conditions should be asserted.

    However, from my understanding, these 2 scenarios are sufficient for what we need to implement. Before we move on, we should verify if that assumption is correct or what's missing. Here is how we should do that:

    • Ask the ECA use base. There are more than 130 members in the Slack channel and they have a great understanding on their needs and if this is enough or what's missing
    • Review all the models we've build or reviewed to see, if we find any more use cases, that should be simplified
  • πŸ‡©πŸ‡ͺGermany mxh Offenburg

    Maybe we can find a way to improve handling of conditions in general.

    Although I got used to it, the current state of how to add "void" conditions and actions is weird:

    • When adding a successor action without any condition, it is sufficient to just add an arrow to connect between the two actions. No further specifying needed, it already behaves like a "void" or "always true" condition.
    • When needing multiple conditions to assert, I need to connect the two conditions with the "Void" action by adding the action component, and then I need to specify the void action.

    So two different mechanics that have the same purpose.

    We have lots of if-else cases. To achieve those cases, we currently need to add basically the same condition twice - one time for the "true" scenario, and then the same one but negated for the "false" scenario. This is cumbersome and prone for errors.

    Looking at it, this feels like we maybe need to improve condition handling. And when improving it, the described cases in #4 will probably be achieved too.

    When thinking about conditions, entity queries come into my mind. They allow nested grouping of conditions. A condition group is always defined as an AND group or an OR group. Maybe it makes sense that ECA supports a similar mechanic.

  • πŸ‡¨πŸ‡­Switzerland berdir Switzerland

    Started to use ECA very recently in a project and just realized that the exclusive gateway is not what the UI tells me it is, which made me sad ;) As #5 said, an if-else is a pretty common use case and faking that with if A / if !A and B is tedious and especially with 3+ cases.

    So supporting an exclusive gateway would be very useful indeed. I can't quite wrap my head around the other types at the moment, We can't really do parallel processing or so, so I don't really see the difference between the using a gateway at all or just having multiple successors on the event/action.

    > The documentation states, that an exclusive gateway must have one fork with a valid condition; otherwise an exception should be thrown. How should we handle that in ECA?

    From a user (me) perspective, that requirement seems to make things unnecessarily complicated, an if/elseif without an else is perfectly valid and enough for many cases, having this would make it necessary to add bogus void actions to such a case. It's also hard to validate, as you can't really know during modeling if one of the conditions will always be true or if it needs a no-condition successor.

  • πŸ‡©πŸ‡ͺGermany jurgenhaas Gottmadingen

    Thanks @Berdir for your feedback, that's much appreciated. I fully agree with all you've just said, and I hope to get started on this one in the next couple of weeks.

  • πŸ‡¨πŸ‡­Switzerland berdir Switzerland

    There is one thing that just came up in a discussion here.

    You can create exclusive gateways right now and there are existing models with them.

    If you suddenly change how they work then that's going to break some cases, for example when people didn't understood how they are meant to work.

    Will probably require at least a big warning or maybe a Setting for existing sites to opt into the correct behavior.

  • πŸ‡©πŸ‡ͺGermany jurgenhaas Gottmadingen
  • πŸ‡©πŸ‡ͺGermany jurgenhaas Gottmadingen
  • πŸ‡©πŸ‡ͺGermany jurgenhaas Gottmadingen
Production build 0.71.5 2024