Inclusive Gateway

Этот раздел перенесён из документации Camunda 7 и в дальнейшем будет доработан с учётом особенностей OpenBPM Engine

Inclusive Gateway можно рассматривать как комбинацию эксклюзивного и параллельного шлюзов. Как и в случае эксклюзивного шлюза, вы можете задавать условия на исходящих потоках операций, и Inclusive Gateway будет их вычислять. Однако главное отличие состоит в том, что Inclusive Gateway, подобно параллельному шлюзу, может принимать более одного потока операций.

Функциональность Inclusive Gateway основана на входящих и исходящих потоках операций:

  • разветвление (fork): вычисляются условия всех исходящих потоков операций, и для тех потоков, условия которых вычисляются как «true», эти потоки выполняются параллельно, создавая одно параллельное исполнение для каждого потока операций.

  • объединение (join): все параллельные исполнения, прибывающие на Inclusive Gateway, ожидают на шлюзе до тех пор, пока не прибудет исполнение по каждому из входящих потоков операций, имеющих токен процесса. Это важное отличие от параллельного шлюза. Иными словами, Inclusive Gateway будет ожидать только те входящие потоки операций, которые исполняются. После объединения процесс продолжается за объединяющим Inclusive Gateway.

Обратите внимание, что Inclusive Gateway может обладать поведением как разветвления, так и объединения, если у одного и того же Inclusive Gateway есть несколько входящих и исходящих потоков операций. В этом случае шлюз сначала объединит все входящие потоки операций, имеющие токен процесса, прежде чем разделиться на несколько параллельных путей исполнения для исходящих потоков операций, условия которых вычисляются как «true».

inclusive gateway

Для определения Inclusive Gateway требуется одна строка XML:

<inclusiveGateway id="myInclusiveGateway" />

Фактическое поведение (разветвление, объединение или оба) определяется потоками операций, соединёнными с Inclusive Gateway. Например, приведённая выше модель сводится к следующему XML:

<startEvent id="theStart" />
<sequenceFlow id="flow1" sourceRef="theStart" targetRef="fork" />

<inclusiveGateway id="fork" />
<sequenceFlow sourceRef="fork" targetRef="receivePayment" >
<conditionExpression xsi:type="tFormalExpression">${paymentReceived == false}</conditionExpression>
</sequenceFlow>
<sequenceFlow sourceRef="fork" targetRef="shipOrder" >
<conditionExpression xsi:type="tFormalExpression">${shipOrder == true}</conditionExpression>
</sequenceFlow>

<userTask id="receivePayment" name="Receive Payment" />
<sequenceFlow sourceRef="receivePayment" targetRef="join" />

<userTask id="shipOrder" name="Ship Order" />
<sequenceFlow sourceRef="shipOrder" targetRef="join" />

<inclusiveGateway id="join" />
<sequenceFlow sourceRef="join" targetRef="archiveOrder" />

<userTask id="archiveOrder" name="Archive Order" />
<sequenceFlow sourceRef="archiveOrder" targetRef="theEnd" />

<endEvent id="theEnd" />

В приведённом выше примере после запуска процесса создаются две задачи, если переменные процесса paymentReceived == false и shipOrder == true. Если как «true» вычисляется только одно из этих условий, будет создана лишь одна задача. Если ни одно условие не вычисляется как «true», выбрасывается исключение. Этого можно избежать, указав исходящий поток операций по умолчанию. В следующем примере будет создана одна задача — задача отгрузки заказа:

HashMap<String, Object> variableMap = new HashMap<String, Object>();
variableMap.put("receivedPayment", true);
variableMap.put("shipOrder", true);

ProcessInstance pi = runtimeService.startProcessInstanceByKey("forkJoin");

TaskQuery query = taskService.createTaskQuery()
                         .processInstanceId(pi.getId())
                         .orderByTaskName()
                         .asc();

List<Task> tasks = query.list();
assertEquals(1, tasks.size());

Task task = tasks.get(0);
assertEquals("Ship Order", task.getName());

После завершения этой задачи второй Inclusive Gateway объединяет два исполнения, и, поскольку имеется только один исходящий поток операций, параллельные пути исполнения не создаются, и активной остаётся только задача Archive Order.

Обратите внимание, что Inclusive Gateway не обязан быть «сбалансированным» (то есть иметь совпадающее число входящих/исходящих потоков операций у соответствующих Inclusive Gateway). Inclusive Gateway просто ожидает все входящие потоки операций и создаёт параллельный путь исполнения для каждого исходящего потока операций, не подвергаясь влиянию других конструкций в модели процесса.

Поведение, специфичное для Camunda 7

Обратите внимание, что в реализации Inclusive Gateway в Camunda 7 действуют следующие правила:

  • Если объединение ожидает токен, но этот токен идёт по процессу иным путём, так что он больше не может достичь объединения (например, из-за граничного события, прерывающего поток), то объединение не сработает.

  • Объединение срабатывает, когда:

  • получено число токенов, большее или равное числу входящих потоков операций. При этом токены не обязательно должны достигать шлюза по разным потокам операций.

  • получено число токенов, меньшее числа входящих потоков операций, и больше нет токенов, способных прибыть на шлюз.

Следующие примеры показывают, при каких условиях Inclusive Gateway инициирует объединение:

  1. В следующем сценарии Parallel Gateway 1 создаёт три токена исполнения, но в Inclusive Gateway объединяются только два потока операций. В этом сценарии Inclusive Gateway сработает даже при наличии всего двух токенов, поскольку токены от Task 1 и Task 2 были объединены в один токен с помощью Parallel Gateway 2. inclusive gateway scenario 1

  2. В этом сценарии Parallel Gateway 1 создаёт два токена исполнения, а в Inclusive Gateway объединяются три потока операций. В этом сценарии Inclusive Gateway сработает при трёх токенах, поскольку Parallel Gateway 2 разделяет единственный токен от Task 1 на два отдельных токена для Task 3 и Task 4. inclusive gateway scenario 2

  3. На приведённой ниже диаграмме параллельный шлюз создаёт два токена исполнения. Первый токен исполнения будет ожидать на User Task 1, а второй достигнет Inclusive Gateway. Inclusive Gateway сработает сразу для первого токена, а затем повторно для второго токена, так как оба токена прибывают по одному и тому же потоку операций. В результате будет создано два экземпляра User Task 2, которые потребуется завершить. inclusive gateway scenario 3

  4. В последнем сценарии параллельный шлюз создаёт два токена исполнения. Первый токен исполнения будет ожидать на User Task 1, а второй достигнет Inclusive Gateway 2 и будет ожидать срабатывания шлюза. Однако Inclusive Gateway 2 не сработает для объединения до тех пор, пока не будет завершена User Task 1 и второй токен не прибудет на шлюз. В результате Inclusive Gateway 2 сработает только один раз вместо двух. Согласно спецификации BPMN 2.0, поскольку оба токена проходят по одному и тому же потоку операций (true), Inclusive Gateway должен был бы сработать дважды. В итоге из-за такого поведения потребуется завершить только один экземпляр User Task 2 вместо ожидаемых двух. В подобных случаях рекомендуется использовать Exclusive Gateway вместо Inclusive Gateway 1. inclusive gateway scenario 4

Расширения OpenBPM Engine

Атрибуты

Элементы расширений

Ограничения

Атрибут camunda:exclusive учитывается только в том случае, если атрибут camunda:asyncBefore или camunda:asyncAfter установлен в значение true

Дополнительные ресурсы

Лицензия и атрибуция

Эта документация была создана на базе материала "Camunda 7 Docs" от Camunda, находится под лицензией Creative Commons Attribution-ShareAlike 3.0 Unported License .

Оригинал документации: https://docs.camunda.org