Saltar al contenido

Cómo se mueve una ejecución ​

Una ejecución empieza en Inicio, sigue los cables de nodo en nodo y termina cuando todas las ramas han acabado y se ha llegado a Fin. Esta página explica las reglas que sigue; lo que hace cada nodo está en la referencia de los nodos, y los valores que viajan con ella, en datos.

Inicio y Fin ​

Un experimento tiene exactamente un Inicio y un Fin.

  • Inicio no tiene entrada. Se supera de inmediato, y su fila en la línea de tiempo da la semilla de la ejecución. Su salida puede tener varios cables: el experimento empieza entonces con ramas paralelas.
  • Toda rama que llega a Fin se detiene ahí. Fin se muestra como en ejecución desde la primera llegada y se supera una vez, después de que haya terminado la última rama — y no lo hace en absoluto si algún paso falló. Esa superación es lo que hace que la ejecución se considere Superado.
  • Una ejecución en la que todas las ramas terminaron sin error pero ninguna llegó a Fin falla con run.no_end.

Salidas y cables ​

El paso de un nodo termina eligiendo una salida, y la ejecución sigue cada cable de esa salida. La mayoría de los nodos tienen una salida, Salida; algunos eligen entre varias:

NodoSalidas que deben conectarseSalidas que pueden conectarse
Fin——
Rama paralelaRama 1, Rama 2—
Rama por estado, Rama por valorSí, No—
Todas las esperas (Esperar OSC, Esperar UDP, Esperar MQTT, Esperar solicitud HTTP, Esperar WebSocket)CoincideTiempo agotado
BucleCuerpo, HechoLímite
Todos los demás nodosSalida—

Para conectar, arrastra desde una salida hasta un nodo; si la sueltas en un lienzo vacío, añade ahí un nodo nuevo. Arrastrar desde una salida que ya tiene un cable añade otro. Agregar siguiente, la tecla A y el + de un cable insertan un nodo en el cable existente.

Un grafo sin terminar es un borrador: se guarda, pero no se ejecuta. Completa el grafo en la barra de herramientas dice qué falta y muestra el nodo. Consulta qué se comprueba antes de una ejecución.

Ramas paralelas ​

Varios cables desde una salida ​

Cuando una salida tiene varios cables — los de Inicio incluidos — cada nodo al que llevan se ejecuta a la vez. El primer cable continúa la rama; cada cable adicional inicia una rama paralela. Cada rama lleva su propia copia de las variables y de la última respuesta HTTP, así que lo que una rama define o recibe no lo ven las demás.

Rama paralela y unión ​

Rama paralela se supera de inmediato y sale por Rama 1 y Rama 2 — lo mismo que dos cables desde una salida, dibujado como un nodo.

Unir ramas espera todos los cables que llegan a él, y luego continúa como una sola rama con las copias fusionadas en el orden de esos cables:

  • las variables de todos ellos — en un nombre que definan dos ramas, gana el cable listado después en el experimento;
  • la respuesta HTTP del último cable, en ese orden, que traiga una;
  • para las esperas posteriores, la acción más temprana de sus últimas acciones.

El orden de los cables decide, nunca qué rama terminó primero por casualidad.

Une solo lo que se ejecuta en paralelo

Una unión cuenta sus cables, sin importar cómo llegaron a ejecutarse en paralelo: desde un Rama paralela, desde varios cables de una salida, desde caminos separados. Detrás de Sí y No de una bifurcación solo se ejecuta un camino, así que una unión alimentada por ambos espera una rama que nunca llega: la ejecución falla con run.join_waiting, indicando cuántos cables nunca se siguieron. Para reunir caminos alternativos, conéctalos directamente al siguiente nodo.

Un nodo que no es una unión, alcanzado por dos ramas paralelas, se ejecuta una vez por cada una de ellas.

Cuando falla un paso ​

El primer fallo hace fallar la ejecución. Las demás ramas no inician ningún paso nuevo: una repetición o una carga termina antes de tiempo, cualquier otro paso en el que estén se ejecuta hasta su final. Un fallo que encuentran mientras tanto se informa en la línea de tiempo, pero no es el error de la ejecución. Un paso que llegó a un tiempo de espera mientras había un cable Tiempo agotado no falló — consulta esperas.

Bifurcación ​

NodoSale por Sí cuando
Rama por estadola última respuesta HTTP en este camino tiene el estado dado
Rama por valorse cumple su comparación — consulta comparar valores

En caso contrario, cada uno sale por No. Una bifurcación por estado necesita una solicitud HTTP antes en todos los caminos; una bifurcación por valor necesita que los nombres que lee se conozcan allí. Cuando los caminos posteriores a Sí y No se reencuentran, el nodo donde se reencuentran se ejecuta una vez, y allí solo se conocen las variables definidas en ambos caminos (dónde se conoce una variable).

Reintentar ​

Un paso que envía o escucha puede volver a intentarlo cuando falla: activa reintentar si falla en sus propiedades.

AjusteQuéRangoValor inicial
Intentosintentos en total, el primero incluido1–103
Pausa, msla pausa antes del segundo intento0–60 000 ms500
Pausasiguales: todas las pausas iguales; que se duplican: cada pausa el doble que la anterior—iguales
  • Reintentar se aplica a Solicitud HTTP, Mensaje TCP, Publicación MQTT, Mensaje OSC, Datagrama UDP, Conectar WebSocket, Enviar por WebSocket y todas las esperas. Los demás nodos lo rechazan (node.retry_unsupported), y una solicitud HTTP bajo carga no admite Reintentar.
  • Ninguna pausa dura más de 60 s, diga lo que diga la duplicación.
  • Cada intento fallido aparece en la línea de tiempo como Reintentando, con su número y su motivo. El paso pasa entonces, o falla con el motivo del último intento.
  • Solo se repite la ejecución. Un campo cuya plantilla no se resuelve falla de inmediato.
  • Un envío que espera su respuesta vuelve a enviar. Una espera vuelve a esperar, contando desde la última acción de la rama como antes.
  • Una espera con un cable Tiempo agotado no falla por un tiempo de espera, así que no se reintenta: sigue Tiempo agotado.
  • Detener termina una pausa de inmediato.

Repetir ​

Un paso que envía puede enviar una y otra vez — un latido, un sondeo, un flujo constante — sin un bucle en el grafo: activa repetir el envío.

AjusteQuéRangoValor inicial
Repetirun número de veces o durante un tiempo—un número de veces
Vecesenvíos en total, el primero incluido2–10 00010
Durante, mscuánto tiempo seguir enviando, desde el primer envío1–300 000 ms10 000
Cada, msla pausa entre dos envíos10–60 000 ms1000
Jitter, mscada pausa es hasta esto más larga, al azar0–60 000 ms0
  • Repetir se aplica a Solicitud HTTP, Mensaje TCP, Publicación MQTT, Mensaje OSC, Datagrama UDP y Enviar por WebSocket (node.repeat_unsupported en los demás). Una solicitud HTTP tiene Repetir o carga, no ambas.
  • Cada envío se hace como se haría uno solo: sus plantillas se leen de nuevo — {{counter}} es el número del envío, {{now}} su hora — y Reintentar, cuando está activado, se aplica a cada envío. Un envío que espera una respuesta espera la suya.
  • Durante un tiempo, un envío solo se hace si puede empezar antes de que se acabe el tiempo.
  • El jitter se sortea a partir de la semilla de la ejecución: la misma semilla da las mismas pausas.
  • La línea de tiempo informa del progreso como Repitiendo como máximo una vez por segundo. El paso pasa tras el último envío, con el desenlace de ese envío; un envío que falla definitivamente hace fallar el paso.
  • Un fallo en otra rama termina los envíos; Detener termina una pausa de inmediato.

Debe caber en una ejecución: los envíos y sus pausas más largas ((count − 1) × (interval + jitter)) como máximo 300 s (node.repeat_too_long), y una repetición por tiempo como máximo 10 000 envíos (node.repeat_too_many).

Bucle ​

Bucle ejecuta los pasos de su salida Cuerpo una y otra vez; el último de ellos está conectado de vuelta al Bucle.

AjusteQuéRango
Iteraciones como máximoel máximo de iteraciones1–1000
detener antes siuna condición de salida: Valor, Condición, Esperado, como en Comprobar valoropcional
  1. Alcanzado desde fuera, el Bucle inicia la iteración 1 en Cuerpo.
  2. Cada vez que el cuerpo vuelve, se lee la condición de salida — después de la iteración, así que el cuerpo siempre se ejecuta al menos una vez y puede definir lo que comprueba.
  3. Cuando se cumple la condición, el Bucle sale por Hecho.
  4. Si no, empieza la siguiente iteración, mientras quede alguna.
  5. Cuando las iteraciones se acaban primero, el Bucle sale por Límite si está conectado, y hace fallar la ejecución con loop.limit si no lo está. Sin condición, el cuerpo se ejecuta en cada iteración y el Bucle sale por Hecho.

Dentro del cuerpo, {{counter}} es el número de la iteración, ya que cada nodo cuenta sus propias ejecuciones. La condición y los pasos posteriores a Hecho o Límite pueden usar lo que define cada iteración del cuerpo — por ejemplo, un estado que el cuerpo extrae; el cuerpo en sí solo ve lo que se conocía cuando se alcanzó el Bucle.

La plantilla Consultar hasta que esté listo pregunta a un dispositivo por su estado cada 0,3 s hasta que responde ready, como máximo 10 veces.

Qué puede contener un cuerpo ​

Un cuerpo se ejecuta como una sola rama, una iteración tras otra. El cable de vuelta al Bucle es el único ciclo que puede tener un experimento; cualquier otro es graph.cycle.

ReglaError
Algo en Cuerpo vuelve al Bucleloop.no_return
Cada salida del cuerpo tiene un solo cableloop.body_parallel
Cada salida del cuerpo sigue en el cuerpo o vuelve al Bucleloop.body_leaves
Solo la salida Cuerpo del Bucle entra en el cuerpoloop.body_entered
Ningún Inicio, Fin, Rama paralela, Unir ramas ni otro Bucle en el cuerpoloop.body_unsupported

Esperas ​

Una espera pasa cuando llega un mensaje que está esperando: Esperar OSC, Esperar UDP, Esperar MQTT, Esperar solicitud HTTP y Esperar WebSocket. Lo que coincide con cada una está en la referencia de los nodos; aquí se explica cómo escuchan.

Escuchar desde el principio ​

La ejecución abre aquello en lo que escuchan sus esperas antes de su primer paso, así que una respuesta más rápida que el paso siguiente no se pierde:

EsperaSe abre antes del primer paso
OSC, UDPun socket UDP por dirección Escuchar en (IP:puerto), compartido por todas las esperas que haya en ella
Solicitud HTTPun escucha por dirección — el emulador HTTP de la ejecución cuando hay uno; si no, uno que responde 204
MQTTuna conexión por bróker y filtro de temas, suscrita; los mensajes retenidos que el bróker reproduce entonces se ignoran
WebSocketnada: lee la conexión que abrió un Conectar WebSocket cuando se ejecutó

Como se abren primero, estas direcciones quedan fijadas antes de la ejecución: una espera OSC, UDP o HTTP escucha en un IP:port literal con un puerto distinto de 0, y el bróker y el tema de una espera MQTT solo aceptan parámetros. Un puerto que no se puede abrir — ocupado, o que no es una dirección de este equipo — detiene la ejecución antes de cualquier tráfico, en el campo de esa espera. Todo se cierra cuando termina la ejecución, sea como sea.

Qué mensajes cuentan ​

Una espera considera los mensajes que llegaron después de que empezara la última acción en su rama — la última solicitud, mensaje, publicación, conexión WebSocket o envío — o, antes de cualquier acción, después de que empezara la ejecución. Un mensaje anterior a la solicitud no cuenta, y una Pausa o una Marca de registro entre la solicitud y la espera no oculta su respuesta. Tras una unión, cuenta la acción más temprana de las últimas acciones de las ramas fusionadas.

Una espera toma el primer mensaje que coincide y lo consume: dos esperas nunca coinciden con el mismo mensaje.

Cada socket, suscripción o conexión guarda como máximo 1024 mensajes y 64 MiB para sus esperas; pasado eso, los más antiguos se descartan y se cuentan.

Tiempo de espera ​

Tiempo de espera, ms es 1–120 000 ms, 2000 al principio. Cuando nada coincide a tiempo:

  • con un cable Tiempo agotado, la espera lo sigue;
  • sin él, el paso falla con wait.timeout, que dice cuántos otros mensajes llegaron mientras tanto — un patrón equivocado se ve distinto de un dispositivo en silencio — y, en su detalle, cuántos mensajes más antiguos se descartaron cuando la cola estaba llena.

La variable de la espera — reply, o request para HTTP — solo existe tras Coincide. Cuando el Inspector está capturando, el paso también enlaza la trama con la que coincidió: consulta la línea de tiempo.

Una respuesta en el mismo paso ​

Un Mensaje OSC o un Datagrama UDP pueden esperar su propia respuesta: activa esperar una respuesta.

AjusteQuéValor inicial
Respuesta en (IP:puerto)la dirección en la que se espera la respuesta; el puerto 0 es cualquier puerto libre0.0.0.0:0
Patrón de dirección de respuesta (OSC), Carga útil de respuesta (UDP)qué debe ser la respuesta, como en la espera correspondientecualquiera
Tiempo de espera, ms1–120 000 ms2000
Variable de respuestala variable en la que se escribe la respuestareply

El socket de Respuesta en (IP:puerto) se abre antes del primer paso, como el de una espera, y el mensaje sale desde él: se oye a un dispositivo que responde al propio puerto del emisor, y a uno que responde a un puerto fijo cuando ese puerto es el indicado. El paso pasa con una respuesta que coincide, y la variable existe tras su salida. No hay salida Tiempo agotado: ninguna respuesta a tiempo hace fallar el paso, y Reintentar puede volver a enviar. Para bifurcar por silencio, usa una espera aparte.

Qué se comprueba antes de una ejecución ​

El editor comprueba el experimento mientras lo editas; el botón Ejecutar lo comprueba una vez más. Un problema nombra el nodo, y el campo cuando lo hay.

ReglaError
El experimento tiene un nombredoc.name_required
1–64 nodos, exactamente un Inicio y un Findoc.node_count, doc.start_end_count
Inicio no tiene entradagraph.start_input
Un cable lleva a otro nodo que existedoc.connection_invalid
El mismo cable no está dos vecesdoc.connection_duplicate
Cada salida que debe conectarse lo estágraph.outputs_required
Un nodo no tiene cable en una salida que no tienegraph.port_unexpected
Se llega a cada nodo desde Iniciograph.unreachable
Ningún ciclo salvo el cable de vuelta de un Buclegraph.cycle, y las reglas del cuerpo
Una comprobación o Extraer tiene una solicitud HTTP antes en todos los caminos; una solicitud bajo carga no cuentagraph.needs_http
Cada plantilla se analiza, y cada nombre que usa se conoce en todos los caminostemplate.*, name.* — consulta datos
Cada campo está presente y en rangonode.*
Un nodo que nombra a otro — Cambiar degradación, Emulador caído/activo, los nodos WebSocket — nombra uno que está ahí, y un nodo WebSocket va después de su conexiónimpair.relay_unknown, emulator.node_unknown, ws.connection_unknown, ws.connection_after
Dos de los sockets de la ejecución no comparten un puertoconsulta fallos

La ejecución comprueba después lo que necesita para empezar: cada secreto guardado, cada puerto abierto. Hasta que todo se cumple, no se ejecuta ningún paso y no se envía nada.

Límite de tiempo ​

Una ejecución dura como máximo 300 s. Una que siga en marcha entonces se detiene y falla con run.timeout. Desde la línea de comandos y la API el límite puede ser más corto, 1–300 s.

Detener ​

Mientras una ejecución avanza, el botón Ejecutar es Detener. Detener termina la ejecución de inmediato: cada rama, cada pausa de Reintentar o Repetir, cada espera y cada carga — las solicitudes en curso se descartan. Sus sockets, suscripciones, emuladores y relés se cierran, y sus conexiones WebSocket envían una trama de cierre. Detener todo en la cabecera hace lo mismo con todas las tareas. Una ejecución detenida no guarda ningún informe; consulta ejecuciones.