Эта документация была автоматически переведена ИИ.
Тип узла, по сути, является операционной инструкцией. Различные инструкции представляют собой разные операции, выполняемые в рабочем процессе.
Аналогично триггерам, расширение типов узлов также делится на две части: серверную и клиентскую. Серверная часть должна реализовать логику для зарегистрированной инструкции, а клиентская — предоставить конфигурацию интерфейса для параметров узла, где находится эта инструкция.
Основное содержимое инструкции — это функция, то есть метод run в классе инструкции должен быть реализован для выполнения логики инструкции. В этой функции можно выполнять любые необходимые операции, например, операции с базой данных, файловые операции, вызовы сторонних API и так далее.
Все инструкции должны быть унаследованы от базового класса Instruction. Простейшая инструкция требует лишь реализации функции run:
И зарегистрируйте эту инструкцию в плагине рабочего процесса:
Значение статуса (status) в возвращаемом объекте инструкции является обязательным и должно быть одним из значений константы JOB_STATUS. Это значение определяет дальнейшее направление обработки данного узла в рабочем процессе. Обычно используется JOB_STATUS.RESOVLED, что означает успешное выполнение узла и продолжение выполнения последующих узлов. Если необходимо заранее сохранить результирующее значение, вы также можете вызвать метод processor.saveJob и вернуть его возвращаемый объект. Исполнитель сгенерирует запись о результате выполнения на основе этого объекта.
Если имеется конкретный результат выполнения, особенно данные, подготовленные для использования последующими узлами, его можно вернуть через свойство result и сохранить в объекте задачи узла:
Здесь node.config — это элемент конфигурации узла, который может быть любым необходимым значением. Он будет сохранен как поле типа JSON в соответствующей записи узла в базе данных.
Если в процессе выполнения могут возникнуть исключения, вы можете перехватить их заранее и вернуть статус ошибки:
Если предсказуемые исключения не будут перехвачены, движок рабочего процесса автоматически перехватит их и вернет статус ошибки, чтобы предотвратить сбой программы из-за необработанных исключений.
Когда требуется управление потоком или асинхронные (трудоемкие) операции ввода-вывода, метод run может вернуть объект со статусом JOB_STATUS.PENDING, предписывая исполнителю ожидать (приостановить выполнение) до завершения некоторой внешней асинхронной операции, а затем уведомить движок рабочего процесса о продолжении выполнения. Если функция run возвращает значение статуса "ожидание", то данная инструкция должна реализовать метод resume, иначе выполнение рабочего процесса не может быть возобновлено:
Здесь paymentService обозначает некий платежный сервис. В колбэке сервиса запускается возобновление выполнения соответствующей задачи рабочего процесса, а текущий процесс сначала завершается. Затем движок рабочего процесса создает новый процессор и передает его методу resume узла, чтобы продолжить выполнение ранее приостановленного узла.
Здесь "асинхронная операция" относится не к async функциям в JavaScript, а к операциям, которые не возвращают результат немедленно при взаимодействии с другими внешними системами, например, платежный сервис, которому требуется дождаться другого уведомления, чтобы узнать результат.
Статус выполнения узла влияет на успех или неудачу всего рабочего процесса. Обычно, при отсутствии ветвлений, сбой одного узла напрямую приводит к сбою всего рабочего процесса. Наиболее распространенный сценарий: если узел успешно выполнен, он переходит к следующему узлу в таблице узлов, пока не останется последующих узлов, после чего весь рабочий процесс завершается со статусом успеха.
Если в процессе выполнения какой-либо узел возвращает статус сбоя, движок будет обрабатывать это по-разному в зависимости от следующих двух ситуаций:
Узел, возвращающий статус сбоя, находится в основном рабочем процессе, то есть не находится ни в одном из ветвящихся процессов, запущенных вышестоящими узлами. В этом случае весь основной рабочий процесс будет считаться неудачным, и процесс завершится.
Узел, возвращающий статус сбоя, находится внутри ветвящегося процесса. В этом случае ответственность за определение следующего состояния процесса передается узлу, который открыл ветвь. Внутренняя логика этого узла определяет состояние последующего процесса, и это решение рекурсивно распространяется вверх до основного рабочего процесса.
В конечном итоге следующее состояние всего рабочего процесса определяется на узлах основного рабочего процесса. Если узел в основном рабочем процессе возвращает сбой, то весь рабочий процесс завершается со статусом сбоя.
Если какой-либо узел после выполнения возвращает статус "ожидание", то весь процесс выполнения будет временно прерван и приостановлен, ожидая события, определенного соответствующим узлом, для возобновления выполнения процесса. Например, узел "Ручной ввод": при достижении этого узла процесс приостанавливается со статусом "ожидание", ожидая ручного вмешательства для принятия решения о продолжении. Если введенный вручную статус — "одобрено", то выполнение продолжается по последующим узлам процесса; в противном случае обрабатывается согласно предыдущей логике сбоя.
Дополнительные статусы возврата инструкций можно найти в разделе "Справочник по API рабочих процессов".
В некоторых особых рабочих процессах может потребоваться завершить процесс непосредственно в определенном узле. Вы можете вернуть null, чтобы указать на выход из текущего процесса, и последующие узлы не будут выполняться.
Такая ситуация часто встречается в узлах управления потоком, например, в узле параллельного ветвления (ссылка на код), где процесс текущего узла завершается, но для каждой дочерней ветви запускаются новые процессы, которые продолжают выполнение.
:::warn{title=Предупреждение} Планирование ветвящихся рабочих процессов с помощью расширенных узлов имеет определенную сложность и требует тщательной обработки и всестороннего тестирования. :::
Определения различных параметров для типов узлов см. в разделе "Справочник по API рабочих процессов".
Аналогично триггерам, форма конфигурации для инструкции (типа узла) должна быть реализована на клиентской части.
Все инструкции должны быть унаследованы от базового класса Instruction. Связанные свойства и методы используются для настройки и использования узла.
Например, если нам нужно предоставить интерфейс конфигурации для узла типа "случайная числовая строка" (randomString), определенного выше на серверной части, который имеет параметр digit, представляющий количество цифр в случайном числе, мы будем использовать поле ввода числа в форме конфигурации для получения пользовательского ввода.
Идентификатор типа узла, зарегистрированный на клиентской части, должен совпадать с идентификатором на серверной части, иначе это приведет к ошибкам.
Вы могли заметить метод useVariables в приведенном выше примере. Если вам нужно использовать результат узла (часть result) в качестве переменной для последующих узлов, вам необходимо реализовать этот метод в унаследованном классе инструкции и вернуть объект, соответствующий типу VariableOption. Этот объект служит структурным описанием результата выполнения узла, предоставляя сопоставление имен переменных для выбора и использования в последующих узлах.
Тип VariableOption определяется следующим образом:
Ключевым является свойство value, которое представляет собой сегментированное значение пути имени переменной. label используется для отображения в интерфейсе, а children — для представления многоуровневой структуры переменной, что применяется, когда результат узла является глубоко вложенным объектом.
Используемая переменная внутри системы представляется в виде строкового шаблона пути, разделенного точками, например, {{jobsMapByNodeKey.2dw92cdf.abc}}. Здесь jobsMapByNodeKey представляет собой набор результатов всех узлов (внутренне определен, не требует обработки), 2dw92cdf — это key узла, а abc — это пользовательское свойство в объекте результата узла.
Кроме того, поскольку результат узла также может быть простым значением, при предоставлении переменных узла первый уровень обязательно должен быть описанием самого узла:
То есть, первый уровень — это key и заголовок узла. Например, в ссылке на код для узла вычисления, при использовании результата этого узла, параметры интерфейса будут следующими:

Когда результат узла представляет собой сложный объект, вы можете использовать children для дальнейшего описания вложенных свойств. Например, пользовательская инструкция может возвращать следующие данные JSON:
Тогда его можно вернуть с помощью метода useVariables следующим образом:
Таким образом, в последующих узлах вы сможете использовать следующий интерфейс для выбора переменных:

Когда структура в результате представляет собой массив глубоко вложенных объектов, вы также можете использовать children для описания пути, но он не может содержать индексы массива. Это связано с тем, что при обработке переменных в рабочем процессе NocoBase описание пути переменной для массива объектов автоматически преобразуется в плоский массив глубоких значений при использовании, и вы не можете получить доступ к конкретному значению по его индексу.
По умолчанию в рабочий процесс можно добавлять любые узлы. Однако в некоторых случаях узел может быть неприменим в определенных типах рабочих процессов или ветвей. В таких ситуациях вы можете настроить доступность узла с помощью isAvailable:
Метод isAvailable возвращает true, если узел доступен, и false, если он недоступен. Параметр ctx содержит контекстную информацию текущего узла, которую можно использовать для определения его доступности.
При отсутствии особых требований реализовывать метод isAvailable не нужно, так как узлы по умолчанию доступны. Наиболее распространенный сценарий, требующий настройки, — это когда узел может быть ресурсоемкой операцией и не подходит для выполнения в синхронном рабочем процессе. Вы можете использовать метод isAvailable для ограничения его использования. Например:
Определения различных параметров для типов узлов см. в разделе "Справочник по API рабочих процессов".