Scheduled node
Resumen
Sección titulada «Resumen»El nodo Scheduled es un tipo especial de nodo Action que se ejecuta periódicamente a intervalos regulares definidos por un planificador tipo cron. A diferencia de los nodos Action normales, que se ejecutan una vez cuando el flujo de trabajo llega a ellos, los nodos Scheduled se ejecutan repetidamente hasta que se cumplen ciertas condiciones o hasta que finaliza el flujo de trabajo.
Un nodo Scheduled se crea usando un nodo Action con un nombre que empieza por el prefijo reservado scheduled_. Cuando el motor de flujos de trabajo detecta este prefijo, trata automáticamente la acción como una tarea programada que el planificador cron del sistema ejecutará periódicamente.
Propiedades del nodo
Sección titulada «Propiedades del nodo»| Propiedad | Tipo | Descripción |
|---|---|---|
| Name | Texto | El nombre debe empezar por el prefijo scheduled_ seguido de un nombre descriptivo (por ejemplo, “scheduled_wait_for_child_workflows”, “scheduled_check_completion”). El prefijo indica al motor de flujos de trabajo que trate este nodo como una acción programada. |
| Id | Número | Identificador único asignado al nodo. Este valor se genera automáticamente por el sistema e identifica de forma única al nodo dentro de la definición de proceso. |
| Description | Área de texto | Campo opcional para aportar detalles adicionales o documentación sobre el propósito de la acción programada y la lógica que ejecuta. |
| Source position | Desplegable | No aplica. Los nodos Scheduled no tienen posiciones de origen ni destino, ya que no están conectados a otros nodos en el diagrama del flujo de trabajo. Se ejecutan periódicamente según la programación configurada. |
| Target position | Desplegable | No aplica. Los nodos Scheduled no tienen posiciones de origen ni destino. |
| Script definition | Editor de scripts | Contiene el código del script que el planificador ejecutará periódicamente. El script tiene acceso completo al contexto del flujo de trabajo, a las variables y a la API de OpenKM. Se puede acceder al editor de dos formas: - Área de texto: editar directamente en el campo de texto - Editor emergente: haga clic en el icono sobre el área de texto para abrir una ventana de edición más grande El editor admite autocompletado. Pulse Ctrl+Espacio mientras escribe para ver las opciones disponibles y sugerencias de código. |
Configuración de la programación de ejecución
Sección titulada «Configuración de la programación de ejecución»Los nodos Scheduled se ejecutan periódicamente según una tarea cron cuyo intervalo se puede configurar en el fichero de configuración workflow.properties mediante el parámetro:
scheduled.actions.rate=PT60SEste es el valor por defecto, que significa que los nodos Scheduled se ejecutan cada 60 segundos. El valor usa el formato de duración ISO 8601 (por ejemplo, PT30S para 30 segundos, PT2M para 2 minutos).
Caso de uso habitual: sincronización de flujos de trabajo padre-hijo
Sección titulada «Caso de uso habitual: sincronización de flujos de trabajo padre-hijo»Los nodos Scheduled son especialmente útiles cuando un flujo de trabajo padre necesita ejecutar varios flujos de trabajo hijos en paralelo y esperar a que todos finalicen antes de continuar. Este patrón se usa habitualmente en procesos de aprobación en paralelo, tareas distribuidas u operaciones en varias etapas.
El flujo típico de este patrón implica:
- Un flujo de trabajo padre se inicia y llega a un nodo Action que lanza varios flujos de trabajo hijos en paralelo
- El flujo de trabajo padre espera entonces en una tarea (normalmente sin asignar) mientras se ejecutan los flujos de trabajo hijos
- Cada flujo de trabajo hijo, al finalizar, notifica al padre estableciendo una variable en el contexto del padre
- Un nodo Scheduled en el flujo de trabajo padre comprueba periódicamente si todos los flujos de trabajo hijos han finalizado
- Cuando todos los flujos de trabajo hijos han terminado, el nodo Scheduled completa la tarea de espera mediante programación
- El flujo de trabajo padre continúa al siguiente paso

Ejemplos de implementación
Sección titulada «Ejemplos de implementación»Ejemplo 1: flujo de trabajo padre - lanzar flujos de trabajo hijos
Sección titulada «Ejemplo 1: flujo de trabajo padre - lanzar flujos de trabajo hijos»Este nodo Action del flujo de trabajo padre crea e inicia varios flujos de trabajo hijos en paralelo:
import com.openkm.sdk4j.impl.OKMWebservices;import com.openkm.sdk4j.bean.*;import com.openkm.okmflow.util.*;import com.openkm.okmflow.bean.*;import com.openkm.util.*;
// Load constantsClass Constants = ScriptUtils.evaluateFromNode("library_request_contants");//Load librariesClass baseLibrary = ScriptUtils.evaluateFromNode("library_global_base");
// Get the workflow process definition iddef processDefinition = WorkflowUtils.getProcessDefinitionByName("Manager-voting");long managerPdId = processDefinition.getId();
// Load data from the contextdef uuid = baseLibrary.getContextValue(context, Constants.CONTEXT_UUID);def initiator = baseLibrary.getInitiatorId(context);def managerSelect = baseLibrary.getContextValue(context, Constants.CONTEXT_MANAGERS);def managerList = managerSelect.value.tokenize(";");long processInstanceId = baseLibrary.getProcessInstanceId(context);
// Keep user list in the contextbaseLibrary.setContextValue(context, Constants.CONTEXT_MANAGERS_LIST, managerList);
// Run parallel workflowsdef actorNum = 0;managerList.each { manager -> actorNum++; def props = [uuid: uuid, initiator: initiator, actor: manager, srcProcInsId: processInstanceId]; def result = WorkflowUtils.runProcessDefinition(managerPdId, props); context.put("pi_" + manager, result.get());}
// Keep numbers of manager in the contextbaseLibrary.setContextValue(context, Constants.CONTEXT_ACTOR_NUM, actorNum);Ejemplo 2: flujo de trabajo hijo - notificar al padre al finalizar
Sección titulada «Ejemplo 2: flujo de trabajo hijo - notificar al padre al finalizar»Este nodo Action, presente en cada flujo de trabajo hijo, notifica al padre cuando finaliza:
import com.openkm.sdk4j.impl.OKMWebservices;import com.openkm.sdk4j.bean.*;import com.openkm.okmflow.util.*;import com.openkm.okmflow.bean.*;import com.openkm.util.*;
// Load constantsClass Constants = ScriptUtils.evaluateFromNode("library_request_contants");// Load libraryClass baseLibrary = ScriptUtils.evaluateFromNode("library_global_base");
// Notify the parent workflow that the workflow has finished.def piId = baseLibrary.getContextValue(context, Constants.CONTEXT_SOURCE_PROCESS_INSTANCE_ID);def actor = baseLibrary.getContextValue(context, Constants.CONTEXT_ACTOR);def wfVar = Constants.VARIABLE_STATUS_PREFIX + actor;WorkflowUtils.addProcessInstanceVariable(piId, wfVar, Constants.STATUS_ENDED);Ejemplo 3: flujo de trabajo padre - comprobación programada de finalización
Sección titulada «Ejemplo 3: flujo de trabajo padre - comprobación programada de finalización»Este nodo Scheduled del flujo de trabajo padre comprueba periódicamente si todos los flujos de trabajo hijos han finalizado y, cuando es así, completa la tarea de espera:
import com.openkm.sdk4j.impl.OKMWebservices;import com.openkm.sdk4j.bean.*;import com.openkm.okmflow.util.*;import com.openkm.okmflow.bean.*;import com.openkm.util.*;
// Load constantsClass Constants = ScriptUtils.evaluateFromNode("library_request_contants");//Load librariesClass baseLibrary = ScriptUtils.evaluateFromNode("library_global_base");
// Load data from the contextlong processInstanceId = baseLibrary.getProcessInstanceId(context);def managerList = baseLibrary.getContextValue(context, Constants.CONTEXT_MANAGERS_LIST);def actorNum = baseLibrary.getContextValue(context, Constants.CONTEXT_ACTOR_NUM);def uuid = baseLibrary.getContextValue(context, Constants.CONTEXT_UUID);def props = [uuid: uuid];def actorResp = 0;
// When managers completed the sub workflow and task is the waiting task, must complete itString waitingTask = "Waiting Task";def taskInstance = WorkflowUtils.getCurrentTaskInstance(processInstanceId);if (waitingTask.equals(taskInstance.getName())) { if (managerList != null) { managerList.each { manager -> def wfVar = Constants.VARIABLE_STATUS_PREFIX + manager; if (context.get(wfVar) != null) { actorResp++; } } } else { // Never should go into because managerList should not be empty }
if (actorResp == actorNum) { // All the managers have answered WorkflowUtils.setTaskInstanceValues(processInstanceId, waitingTask, null, props); } else { // Still waiting for managers }}En este patrón:
- El nodo Action lanza N flujos de trabajo hijos y guarda su número y listado en el contexto del padre
- El flujo de trabajo padre espera en una tarea sin asignar (“Waiting Task”)
- Cada flujo de trabajo hijo notifica al padre añadiendo una variable de estado al finalizar
- El nodo Scheduled se ejecuta cada minuto (o en el intervalo configurado), comprobando si todos los flujos de trabajo hijos han finalizado
- Cuando se han recibido todas las respuestas, el nodo Scheduled completa la tarea de espera mediante programación, permitiendo que el flujo de trabajo padre continúe
Acceso a las variables de contexto
Sección titulada «Acceso a las variables de contexto»Los scripts de los nodos Scheduled tienen acceso completo a todas las variables de contexto del flujo de trabajo. Puede:
- Leer variables existentes usando métodos de ayuda o directamente desde el contexto
- Crear nuevas variables almacenando valores en el contexto
- Modificar valores de variables existentes
- Comprobar la presencia de variables establecidas por flujos de trabajo hijos u otros procesos
Normalmente se accede a las variables mediante métodos de ayuda de biblioteca (como en los ejemplos anteriores) o directamente a través del objeto de contexto de ejecución del flujo de trabajo.
Buenas prácticas
Sección titulada «Buenas prácticas»- Use nombres descriptivos que indiquen claramente el propósito de la acción programada (por ejemplo,
scheduled_check_approvals,scheduled_sync_child_workflows) - Mantenga los scripts programados eficientes: se ejecutan repetidamente, así que optimícelos para el rendimiento
- Incluya condiciones de salida temprana para evitar procesamiento innecesario cuando no se cumplen las condiciones
- Sea prudente con la frecuencia de ejecución: una ejecución demasiado frecuente puede afectar al rendimiento del sistema
- Registre los eventos importantes dentro de los scripts programados para facilitar la resolución de problemas
- Pruebe a fondo la lógica programada para asegurarse de que gestiona todos los casos límite
- Documente la frecuencia de ejecución esperada y las condiciones en el campo Description
- Considere los escenarios de timeout: ¿qué ocurre si los flujos de trabajo hijos nunca finalizan?
- Use lógica condicional para evitar que la acción programada se ejecute indefinidamente