Параллельный шлюз

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

Шлюзы также можно использовать для моделирования параллелизма в процессе. Самый простой шлюз для введения параллелизма в модель процесса — параллельный шлюз (Parallel Gateway), который позволяет разветвлять выполнение на несколько путей или объединять несколько входящих путей выполнения.

parallel gateway

Поведение параллельного шлюза основано на входящих и исходящих потоках операций (sequence flow):

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

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

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

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

Важное отличие от других типов шлюзов в том, что параллельный шлюз не вычисляет условия. Если на потоке операций, соединённом с параллельным шлюзом, заданы условия, они просто игнорируются.

Для определения параллельного шлюза достаточно одной строки XML:

<parallelGateway id="myParallelGateway" />

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

Например, приведённая выше модель сводится к следующему XML:

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

<parallelGateway id="fork" />
<sequenceFlow sourceRef="fork" targetRef="receivePayment" />
<sequenceFlow sourceRef="fork" targetRef="shipOrder" />

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

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

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

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

<endEvent id="theEnd" />

В приведённом примере после запуска процесса создаются две задачи:

ProcessInstance pi = runtimeService.startProcessInstanceByKey("forkJoin");
TaskQuery query = taskService.createTaskQuery()
                         .processInstanceId(pi.getId())
                         .orderByTaskName()
                         .asc();

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

Task task1 = tasks.get(0);
assertEquals("Receive Payment", task1.getName());
Task task2 = tasks.get(1);
assertEquals("Ship Order", task2.getName());

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

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

parallel gateway unbalanced

Расширения OpenBPM

Атрибуты

camunda:asyncBefore, camunda:asyncAfter, camunda:exclusive, camunda:jobPriority

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

camunda:failedJobRetryTimeCycle, camunda:executionListener

Ограничения

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

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

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

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

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