OSWorkflow - Workflow Concepts

OTWorkflow is very unique compared to other workflow engines one might be familiar with. In order to completely grasp OSWorkflow and properly harness the features available, it is important that one understand the core concepts that form the foundation for OSWorkflow.

OTWorkflow - уникальный среди других движков workflow, его может изучить каждый. Для полного понимания OTWorkflow и всех его функций важно, чтобы каждый разбирался в основных понятиях, которые формируют фундамент OTWorkflow.

Steps, Status, and Actions

Каждый экземпляр процесса workflow может иметь один или несколько текущих шагов в любой момент времени. Каждый текущий шаг (step) имеет статус. Значения статуса (status values) каждого текущего шага (current steps) составляют статус workflow для данного экземпляра процесса. Значение статуса определяется разработчиком приложения и/или менеджером проекта. Значение статуса может быть, например "Underway (в процессе)", или "Queued (В очереди)".

Для работы workflow должен произойти переход (transition) в определенной state-машине, которая представляет собой экземпляр workflow. После того, как шаг (step) завершен, он перестает быть текущим (current). Обычно новый текущий шаг (step) создается незамедлительно, что поддерживает неприрывную работу workflow. Конечное значение статуса завершенного шага устанавливается с помощью аттрибута old-status. Это происходит до того, как осуществится переход в другой шаг (step). Old-status должен быть уже определен, когда происходит новый переход (transition) в запущенном процессе workflow. Можно использовать любое значение, которое вы пожелаете, но "Finished" обычно хорошо подходит для большинства приложений.

Сам переход (transition) является результатом действия (action). Шаг (step) может иметь множество действий (actions), связанных с ним. Какое именно действие (action) будет запущено, определяется конечным пользователем, внешним событием или оно запускается автоматически по какому-либо триггеру. В зависимости от того, какое действие (action) выполняется, совершается тот или иной переход (transition). Действия (actions) могут быть ограничены пользователями или группой пользователей или текущим состоянием workflow. Каждое действие должно иметь один безусловный результат (unconditional result) (результат по умолчанию) и любое количество условных результатов (conditional results).

Подводя итоги, workflow состоит из ряда шагов (Steps). Шаг (step) имеет текущий статус (current status) (например, Queued, Underway, или Finished). Шаг имеет набор действий (Actions), которые могут быть выполнены на данном шаге. Действие имеет условия (Conditions), при которых оно доступно для выполнения, а так же, функции (Functions) которые будут выполены. Действие имеет результат(unconditional result или conditional result), которое меняет состояние (state) процесса workflow и его текущий шаг.

Results, Joins, и Splits

Безусловные результат(Unconditional Result)

Для каждого действия (action) требуется, чтобы существовал хотя бы один результат (result), называемый безусловным результатом (unconditional-result). Результат - это ничто иное, как набор инструкций, предписаний (directives) , которые сообщают OTWorkflow, какую следующую задачу нужно выполнить. Это включает в себя переход (transition) из одного состояния (state) в следующий (или следующие) состояния в state machine, что поддерживает workflow в рабочем состоянии.

Условные результаты (Conditional Results)

Условные результаты (conditional result) это общий случай безусловного результата (unconditional result). Они полностью идентичны, за исключением того факта, что они требуют одного или нескольких дополнительных суб-элементов: условий (condition).

Первый Conditional Results у которого проверка условий в блоке conditions возвращает true, будет приводить к изменению состояния процесса workflow в результате совершенного пользователем действия.

Возможны 3 результата:

  • Новая комбинация шаг/статус
  • Разделение на две или более комбинаций шаг/статус (распараллеливание процессов)
  • Слияние, которое объединяет распараллелиные процессы новой одиночной процесс со своей комбинацией шаг/статус

В зависимости от того, какое поведение вы ожидаете, ваш xml файл workflow будет иметь разную структуру. Пожалуйста, прочитайте DTD (который содержит отличную документацию) в Приложении A для более подробной информации.

Один нюанс: в настоящее время разделении или слияние необязательно приводит непосредственно к разделению или слиянию.

Одиночный шаг/статус может быть определен следующим путем:

<unconditional-result old-status="Finished" step="2" status="Underway" owner="${someOwner}"/>

Атрибут owner может содержат идендификатор "владельца" нового шага. Кроме того, указав информацию о следующем состоянии (state), результат (results) так же может определить валидаторы (validators) и post-functions. Это будет обсуждаться ниже.

В некоторых случаях результат действия не требует перехода на следующий шаг. Такой результат может требовать устанвки значения шага в -1. Мы можем изменить пример выше чтобы остаться на текущем шаге (шагах):

<unconditional-result old-status="Finished" step="-1" 
                      status="Underway" owner="${someOwner}"/>

Разделение из одного состояния в множественные может достигаться следующим путем:

<unconditional-result split="1"/>
...
<splits>
  <split id="1">
    <unconditional-result old-status="Finished" step="2" 
                          status="Underway" owner="${someOwner}"/>
    <unconditional-result old-status="Finished" step="2" 
                          status="Underway" owner="${someOtherOwner}"/>
  </split>
</splits>

Слияние - более сложный случай. Типичное слияние может выглядеть следующим образом:

<unconditional-result join="1"/>
...
<unconditional-result join="1"/>
...
<joins>
  <join id="1">
    <join id="1">
    <conditions type="AND">
      <condition type="phpshell">
        <arg name="script">
          'Finished' === jn.getStep(6).getStatus()
          &amp;&amp; 'Finished' === jn.getStep(8).getStatus()
        </arg>
      </condition>
    </conditions>
  </join>
  <unconditional-result old-status="Finished" status="Underway" 
                                 owner="test" step="2"/>
  </join>
</joins>

Пример выше может показаться непонятным, но важный момент, на который стоит обратить внимание в condition исользуется специальная переменная "jn", которая может быть использована для составления выражения и определения, где именно слияние должно произойти.

По существу, объявление этого выражения говорит "произвести объеденение распаралеленных процессов когда шаги с id 6 и 8 имеют статус Finished".

Внешние функции

OTWorkflow предлагает ряд стандартных решений для взаимодействия с внешними сервисами и для внедрения в workflow кода для работы с бизнес логикой.Это достигается с помощью "functions".

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

Существуют два тип функций: pre и post step functions.

Pre functions - это функции, которые выполняются до того, как workflow делает конкретный переход. Один из кейсов для использования pre function, это установка идендификатора того кто инициировал переход(caller), чтобы в последствие сохранить его, в случае осуществления успешного перехода.

Другой пример pre-function это функция, которая обновляет наболее часто вызываемое последнее действие.

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

Post functions имеют похожий диапазон применимости, как и pre functions, только они выполняются после того, как происходит изменение состояния процесса workflow. Примером post function может служить отправка писем заинтересованным сторонам, которые принимают участие в выполнении workflow. Например, когда для документа в шаге 'research' вызывается действие 'markReadyForReview', группа наблюдателей получает уведомления.

Есть много причин для использования pre and post functions. Одна из них, если пользователь кликнул на кнопку "done" дважды и отправил дважды вызов "execute action", а это действие имеет pre function, которая долго выполняется, тогда возможна ситуация, когда долгоработающая функция вызывается несколько раз, потому что переход (transition) не был еще совершен, и в этом случае OTWorkflow думает, что вызов функции второй раз корректен. Тогда необходимо сделать что бы данные функция была не pre, а post. Вообще pre функции для простых, быстрых действий. Тяжеловесные функции должны быть только post.

Функция может быть определена в двух назависимых местах: в шагах и действиях (steps and actions)

Обычно, pre или post function определяется в каком-либо действии. В большинстве случаев вместе с переходами по worflow, функции используются, чтобы сделать что-то, будь то уведомление, отправка email, или просто установка переменной для будущего использования. Следующая диаграмма поможет проиллюстрировать принцип действия функций:

Action Functions

В случае, когда pre и post functions определена в шагах, их использование немного отличается. Pre-functions определенная в шаге будет выполнена до того, как workflow перейдет на этот самый шаг. Стоит обратить внимание, что эти функции будут применены без разбора ко всем переходам, даже к тем, которые ведут на тот же самый шаг(например, переход используемый для изменения статуса шага с Queued на Underway будет причиной вызова всех объявленных pre-functions).

Аналогично post-functions для шага будут вызываться после того как произошел успешный переход из текущего шага, даже если осуществленный переход, ведет обратно на тот же самый шаг.

Следующая диаграмм иллюстрирует последовательность вызовов. Стоит обратить внимание, что блок описывающий action сокращен и вполне может содержать pre и post functions внутри себя.

Step Functions

Больше информации можно найти по ссылке Functions.

Trigger Functions

Trigger functions похожи на другие функции, отличие в том, что они не связаны только лишь с одним действием или шагом. Такие функции определяются с уникальным Id, который в дальнейшем может быть использован в внешнем планировщике, для вызова функции тригера по расписанию, либо по другому условию.

Trigger Functions - вызываются из внешнего источника, например из планировщика.

Больше информации Trigger functions.

Validators

Валидаторы

Валидаторы - это не более, чем код, который вызывается при совершение действия(action) и проверяет входные данные. Если входные данные валидны, то действие выполняется. Если же входные данные не валидны, тогда бросается исключение \OldTown\Workflow\Exception\InvalidInputException.

Валидаторы в использование похожи на функции. Больше информации Validators.

Registers

Регистры

Регистры - вспомогательные функции возвращающие объект, который может быть использован функциями для легкого доступа к общим объектам, особенно сущностям, которые участвуют в workflow. Объектом для регистра может быть любой тип объектов. Типичным примером таких объектов могут быть: Document, Metadata, Issue, и Task. Они используются только лишь для удобства и не добавляют дополнительных преимуществ для работы с OTWorkflow кроме как упростить жизнь разработчикам. Ниже приведен пример использования регистра (register):

    <registers>
        <register type="phpshell" variable-name="testCondition">
            <arg name="script">return 'abrakadabra';</arg>
        </register>
    </registers>
...
    <initial-actions>
        <action id="100" name="StartWorkflow">
            <restrict-to>
                <conditions>
                    <condition type="phpshell">
                        <arg name="script">
                            return 'abrakadabra' === $transientVars['testCondition'];
                        </arg>
                    </condition>
                </conditions>
            </restrict-to>
            <results>
                <unconditional-result old-status="Finished" status="Underway" step="2"/>
            </results>
        </action>
    </initial-actions>
...

Conditions

Условия

Условия, такие как validators, registers, и functions, могут быть реализованы в разных языках и технологиях. Условия могут группироваться используя логику AND или OR. Условия, как правило используются в условных результатах (conditional results), для определения нужно ли осуществить переход.

Условия очень похожи на функции, за исключением что они всегда возвращают boolean Больше информаций Conditions.

Variable Interpolation

Переменная интерполяция

Во всех функциях, условиях, валидаторах, и регистрах можно использовать аргументы (args) для влияния на выолнеямый код. Точно так же как status, old-status, и owner в дексприпторах workflow все аргументы анализируются для динамического преобразования. Значение аргумента может быть полученно, когда он описывается конструкцией ${foo}.

OTWorkflow распознает такую декларацию значения аргумента и сначала ищет в transientVars значение для ключа с именем foo. Если этот ключ не существует, в transient variable, то тогда ищется в PropertySet установленным для процесса workflow. Если PropertySet не содержит указанного ключа, тото значением переменной становится null.

Есть важный момент при работе с аргументами, если аргумент установлен с использование конструкции ${foo}, тип значения аргумента, будет не обязательно строкой. По факту он будет совпадать с типом которыый переменной взятой из transientVars или PropertySet. Тем не менее, если аргумент - это набор символов и конструкций вида ${foo}, весь аргумент преобразуется в строку. Это значит, что два аргумента ниже имеют отличия, в том, что foo - это объект Date, а bar - это строка String:

<arg name="foo">${someDate}</arg>
<arg name="bar"> ${someDate} </arg> <!-- обратите внимание на лишние пробелы -->

Permissions and Restrictions

Разрешения и ограничения

Permissions могут быть использованны в внешних приложениях, для проверки может ли пользователь совершить определенное действие. Permissions не имеют прямого отношения к движку workflow, но они полезны для реализации приложений, основанных на OTWorkflow.

Например, система документооборота может иметь набор разрешений "file-write-permission" доступных для определенной группы пользователей на шаге (stage) "Document Edit".

В таком случае приложение может использовать API для определения, могут ли файлы модифицироваться или нет. Это полезно, поскольку возможно несколько состояний (states) workflow, где применяются разрешения "file-write-permission", поэтому вместо того, чтобы проверять конкретные шаги или условия, достаточно лишь проверить конкретные Permissions.

Permissions и действия(actions) вместе используют концепцию ограничений(restrictions). *Ограничение(restrictions) - это не более, чем одно или несколько условий(conditions).

Auto actions

Автоматические действия

Иногда требуется действия, которые должны быть выполнены автоматически по определенным условиям. Это например полезно, при попытке добавить автоматизацию процессов Workflow. Чтобы добиться этого,необходимо к действиям добавить атрибут auto="true".

Integrating with Abstract Entities

Интеграция с абстрактными сущностями

Поскольку OTWorkflow не является решением из коробки, важно вести разработку вашего проекта с корректным использованием OTWorkflow. Рекомендуется вашим основными объектам (Сущность), таким как "Document" или "Order", давать новый аттрибуты: workflowId.

Таким образом когда новый Document или Order будут созданы, они будут связаны с состоянием процесса workflow.

Workflow Instance State

Состояние экземпляра рабочего процесса

Иногда бывает необходимо определить состояние (state) экземпляря workflow, а не текущего шага. OTWorkflow предлагает ряд таких "мета-состояний" в которых может находиться экземпляр процесса workflow. Могут быть следующие состояния: CREATED ACTIVATED SUSPENDED KILLED COMPLETED*.

Когда экземпляр рабочего процесса workflow создается впервые, она находится в состоянии(state) CREATED.

После того, как совершаются различные действия, он автоматические переводится в состояние(state) ACTIVATED.

Если тот кто совершает действия по изменению состояния процесса workflow (caller) явно не изменяет состояние процесса workflow, то процесс останется в этом состояние, пока не будет однозначно завершен.

В этом случае процес workflow автоматически переходит в состояние COMPLETED

Однако, до тех пор, пока процесс workflow в состоянии ACTIVATED, тот кто совершает действия по изменению состояния процесса workflow (caller) может убить или приостановить процесс workflow (установить KILLED или SUSPENDED). Процесс workflow с состоянием KILLED не будет доступен для дальнейших действий, и будет навсегда оставаться в том состоянии, которое было на момент установки процессу статуса KILLED.

Workflow который был приостоновлен будет заморожен и над ним нельзя будет выполнять действия до тех пор пока его состояние вновь не переведут в ACTIVATED.