Gestión de Procesos
El global process permite crear procesos, enviar mensajes, monitorizar, enlazar, asignar nombres y controlar el ciclo de vida.
Está disponible sin require() y no necesita incluirse en modules:.
Esta es una referencia de API. Sus bloques de formas de llamada usan marcadores como id, host, destination, topic y name para valores proporcionados por el código de la aplicación; no son programas independientes. Las llamadas mostradas con un resultado err devuelven su valor documentado en caso de éxito o un centinela de fallo más error; el centinela suele ser nil, mientras que process.set_options devuelve false. El flujo de control de la aplicación debe manejar el error.
Información del proceso
Lee el ID del frame actual o el ID del proceso:
local frame_id, err = process.id() -- Registry ID of the current function, process, or workflow definition
if err then return nil, err end
local pid, err = process.pid() -- Process ID
if err then return nil, err end
Envío de mensajes
Envía uno o varios valores de payload a un proceso por PID o nombre registrado:
local ok, err = process.send(destination, topic, ...)
| Parámetro | Tipo | Descripción |
|---|---|---|
destination |
string | PID o nombre registrado |
topic |
string | Nombre del tema (no puede comenzar con @) |
... |
any | Valores de payload |
Permiso: process.send sobre el PID destino
Creación de procesos
-- Basic spawn
local pid, err = process.spawn(id, host, ...)
-- With monitoring (receive EXIT events)
local pid, err = process.spawn_monitored(id, host, ...)
-- With linking (receive LINK_DOWN on abnormal exit)
local pid, err = process.spawn_linked(id, host, ...)
-- Both linked and monitored
local pid, err = process.spawn_linked_monitored(id, host, ...)
| Parámetro | Tipo | Descripción |
|---|---|---|
id |
string | ID de fuente del proceso (ej., "app.workers:handler") |
host |
string | ID del host (ej., "app:processes") |
... |
any | Argumentos pasados al proceso lanzado |
Todas las variantes requieren process.spawn sobre el ID del proceso. Las variantes monitorizadas también requieren process.spawn.monitored, y las variantes enlazadas requieren process.spawn.linked. En runtime v0.3.32a, solo spawn() a nivel de módulo comprueba process.host sobre el ID del host; las variantes especializadas a nivel de módulo no realizan esa comprobación de permiso del host.
Control de procesos
-- Forcefully terminate a process
local ok, err = process.terminate(destination)
-- Request graceful cancellation with an optional reason
local ok, err = process.cancel(destination, "shutting down")
| Parámetro | Tipo | Descripción |
|---|---|---|
destination |
string | PID o nombre registrado |
reason |
string | Motivo opcional entregado al destino |
Permisos: process.terminate, process.cancel sobre el PID destino
Monitorización y enlaces
Añade o elimina la monitorización y los enlaces de un proceso existente:
-- Monitoring: receive EXIT events when target exits
local ok, err = process.monitor(destination)
local ok, err = process.unmonitor(destination)
-- Linking: bidirectional, receive LINK_DOWN on abnormal exit
local ok, err = process.link(destination)
local ok, err = process.unlink(destination)
Permisos: process.monitor, process.unmonitor, process.link, process.unlink sobre el PID destino
Opciones del proceso
local options = process.get_options()
local ok, err = process.set_options({trap_links = true})
| Campo | Tipo | Descripción |
|---|---|---|
trap_links |
boolean | Si los eventos LINK_DOWN se entregan al canal de eventos |
upgradable |
boolean | Optar por eventos OUTDATED cuando se invalida el código del proceso |
Buzón y eventos
Usa los canales de buzón y eventos para recibir mensajes y eventos de ciclo de vida:
local inbox = process.inbox() -- Message objects from @inbox topic
local events = process.events() -- Lifecycle events from @events topic
Tipos de evento
| Constante | Descripción |
|---|---|
process.event.CANCEL |
Cancelación solicitada |
process.event.EXIT |
Proceso monitorizado ha salido |
process.event.LINK_DOWN |
Proceso enlazado terminó de forma anormal |
process.event.OUTDATED |
El código del proceso o una dependencia importada cambió en el registro |
Campos del Evento
| Campo | Tipo | Descripción |
|---|---|---|
kind |
string | Constante del tipo de evento |
from |
string | PID de origen (ausente para OUTDATED) |
result |
table | Para EXIT/LINK_DOWN: un registro {value, error}; el valor de retorno del proceso está en result.value y cualquier error en result.error |
reason |
string | Para CANCEL: por qué se está cancelando el proceso |
sources |
string[] | Para OUTDATED: IDs del registro que cambiaron o fueron afectados transitivamente |
OUTDATED se entrega solo a los procesos que optan por él con process.set_options({upgradable = true}). Varias invalidaciones se combinan en un único evento pendiente que contiene la unión de sus sources. Maneja el evento llamando a process.upgrade.
Suscripción a temas
Suscríbete a un tema de mensajes personalizado:
local ch, err = process.listen(topic, options)
if err then return nil, err end
local ok, err = process.unlisten(ch)
if err then return nil, err end
| Parámetro | Tipo | Descripción |
|---|---|---|
topic |
string | Nombre del tema (no puede comenzar con @) |
options.message |
boolean | Si es true, recibe objetos Message; si es false, payloads sin procesar |
Objetos de mensaje
El buzón y los listeners configurados con {message = true} devuelven objetos de mensaje:
local msg = inbox:receive()
msg:topic() -- string: nombre del tema
msg:from() -- string: PID del remitente (cadena vacia cuando se desconoce)
msg:payload() -- Payload: wrapper (llamar :data() para extraer); nil cuando esta vacio, tabla de wrappers para varios valores
msg:payload():data() -- any: valor actual del payload
Llamada síncrona
process.exec crea un proceso y espera su resultado:
local result, err = process.exec(id, host, ...)
Permisos: process.exec sobre el id del proceso, process.host sobre el id del host
Actualización de procesos :id=process-upgrade
Actualiza el proceso actual conservando su PID:
Los dos fragmentos siguientes son formas de llamada alternativas, no operaciones secuenciales.
-- Upgrade to new version, passing state
process.upgrade(id, ...)
-- Keep same definition, re-run with new state
process.upgrade(nil, preserved_state)
process.upgrade es una transferencia de control terminal: borra la ejecución actual e inicia la definición solicitada con el mismo PID. El código posterior a la llamada no se ejecuta en la ejecución anterior.
Spawner con contexto
Crea un spawner que proporciona contexto personalizado a los procesos hijos:
local spawner = process.with_context({request_id = "123"})
Permiso: process.context sobre "context"
Spawner con opciones
process.with_options(options) crea un spawner con opciones de creación, como un selector de red, en lugar de valores de contexto:
local spawner = process.with_options({network = "app:tor_proxy"})
| Opción | Tipo | Descripción |
|---|---|---|
network |
string | ID de registro de una entrada network.* a usar para las conexiones salientes del hijo |
terminal |
string | Concesión de viewport que asocia un terminal virtual al hijo |
Permiso: process.context sobre "context"; seleccionar una red adicionalmente requiere network.select sobre ese ID de red.
Asociación de Terminal
Una concesión terminal proviene de viewport:grant() y le da al hijo un puerto de terminal propio, de modo que puede usar el módulo TTY exactamente como lo haría en un terminal host:
local view = assert(tty.viewport({width = 80, height = 24}))
local child = assert(process.with_options({terminal = assert(view:grant())})
:spawn_monitored("app:child", "app:workers"))
La concesión es de un solo uso y se consume en la admisión: un inicio rechazado la deja sin resolver y reutilizable, un hijo que resuelve el puerto la consume permanentemente, y un host que no soporta asociaciones de terminal rechaza el spawn en lugar de descartar la opción. El proceso que hace el spawn sigue leyendo los frames del hijo a través del viewport que creó. Consulte Terminal.
Métodos de SpawnBuilder
SpawnBuilder es inmutable; cada método de configuración devuelve una instancia nueva:
spawner:with_context(values) -- Añadir valores de contexto
spawner:with_actor(actor) -- Establecer actor de seguridad
spawner:with_scope(scope) -- Establecer ámbito de seguridad
spawner:with_name(name) -- Registrar el nombre al iniciar; si esta tomado, spawn devuelve el PID existente y los mensajes en cola van a el
spawner:with_message(topic, ...) -- Encolar mensaje a enviar tras el spawn
spawner:with_options(options) -- Fusionar opciones de spawn (ej., network)
Permiso: process.security sobre "security" para :with_actor() y :with_scope()
Métodos de Spawn del Spawner
spawner:spawn(id, host, ...)
spawner:spawn_monitored(id, host, ...)
spawner:spawn_linked(id, host, ...)
spawner:spawn_linked_monitored(id, host, ...)
Todos los métodos de creación de SpawnBuilder requieren process.host sobre el ID del host, además de los permisos aplicables process.spawn, process.spawn.monitored y process.spawn.linked.
Exec del Spawner
local result, err = spawner:exec(id, host, ...)
Este método ejecuta el proceso de destino de forma síncrona con el contexto, el actor y el ámbito del builder, y devuelve su resultado. Un worker diferido puede usar with_actor y with_scope para ejecutarse con la identidad de un propietario.
Permisos: process.exec sobre el id del proceso, process.host sobre el id del host
Registro de nombres
Registra un proceso con un nombre para que los llamadores puedan usarlo en lugar de su PID. Las funciones que aceptan un destination, incluidas send, terminate, cancel, monitor y link, también aceptan nombres registrados.
local ok, err = process.registry.register(name) -- self, local scope
local pid, err = process.registry.lookup(name)
local ok, err = process.registry.unregister(name)
Ámbito
El argumento opcional scope selecciona la garantía de consistencia del nombre y su valor predeterminado es LOCAL. Consulta la Guía del clúster para ver el modelo completo.
| Constante | Visibilidad | Garantía |
|---|---|---|
process.registry.LOCAL |
solo este nodo | Instantáneo, local al nodo |
process.registry.EVENTUAL |
en todo el clúster | Eventualmente consistente (gossip) |
process.registry.CONSISTENT |
en todo el clúster | Singleton linealizable (Raft) |
process.registry.STRONG |
en todo el clúster | Consistente + reconocimiento de cada nodo activo |
En un nodo independiente, solo está disponible LOCAL; los ámbitos del clúster requieren clustering.
register
local ok, err = process.registry.register(name, pid, scope)
| Parámetro | Tipo | Requerido | Por defecto | Descripción |
|---|---|---|---|---|
name |
string | sí | Nombre a registrar | |
pid |
string | no | self | PID a registrar; por defecto el proceso que llama |
scope |
number | no | LOCAL |
Una de las constantes de ámbito anteriores |
Devuelve true en éxito, o nil, error en fallo. Los conflictos (nombre ya registrado a un PID diferente) devuelven errors.ALREADY_EXISTS. Registrar el mismo nombre al mismo PID es idempotente. Un registro STRONG bloquea hasta que cada nodo activo reconoce o el plazo de reserva expira; en tiempo de espera devuelve un error.
Registrar en nombre de un PID diferente requiere adicionalmente el permiso process.registry.foreign sobre el PID destino.
lookup
local pid, err = process.registry.lookup(name)
Devuelve la cadena del PID registrado, o nil, error con la clase errors.NOT_FOUND cuando el nombre no está registrado.
unregister
local ok, err = process.registry.unregister(name, scope)
scope tiene como valor predeterminado LOCAL y debe coincidir con el ámbito bajo el que se registró el nombre. Para CONSISTENT y STRONG, el proceso propietario es el único autorizado a cancelar el registro; cancelar un nombre que pertenece a otro PID devuelve false. Los nombres también se liberan automáticamente cuando el proceso propietario termina (y, para los ámbitos de clúster, cuando su nodo abandona el clúster), por lo que la cancelación explícita del registro sirve para liberarlos antes.
Permisos
Las comprobaciones de permisos evalúan el actor de seguridad del llamador frente al recurso de destino.
Evaluación de políticas
Las políticas pueden permitir o denegar una operación según:
- Actor: El principal de seguridad que hace la solicitud
- Acción: La operación que se realiza (ej.,
process.send) - Recurso: El destino (PID, id de proceso, id de host, o nombre)
- Atributos: Contexto adicional incluyendo
pid(ID del proceso que llama)
Referencia de permisos
| Permiso | Funciones | Recurso |
|---|---|---|
process.spawn |
spawn*() |
id del proceso |
process.spawn.monitored |
spawn_monitored(), spawn_linked_monitored() |
id del proceso |
process.spawn.linked |
spawn_linked(), spawn_linked_monitored() |
id del proceso |
process.host |
spawn() a nivel de módulo, todos los métodos de creación de SpawnBuilder, exec() |
id del host |
process.send |
send() |
PID destino |
process.exec |
exec() |
id del proceso |
process.terminate |
terminate() |
PID destino |
process.cancel |
cancel() |
PID destino |
process.monitor |
monitor() |
PID destino |
process.unmonitor |
unmonitor() |
PID destino |
process.link |
link() |
PID destino |
process.unlink |
unlink() |
PID destino |
process.context |
with_context(), with_options() |
"context" |
process.security |
:with_actor(), :with_scope() |
"security" |
process.registry.register |
registry.register() |
nombre |
process.registry.unregister |
registry.unregister() |
nombre |
process.registry.foreign |
registry.register() |
PID destino |
Los ámbitos de nombres del clúster se autorizan mediante variantes de estas acciones con el ámbito como sufijo (process.registry.register.eventual, .consistent, .strong y las acciones unregister correspondientes), de modo que una política puede conceder por separado los nombres locales y los nombres en todo el clúster.
Varios permisos
Algunas operaciones requieren múltiples permisos:
| Operación | Permisos requeridos |
|---|---|
spawn() |
process.spawn + process.host |
spawn_monitored() a nivel de módulo |
process.spawn + process.spawn.monitored |
spawn_linked() a nivel de módulo |
process.spawn + process.spawn.linked |
spawn_linked_monitored() a nivel de módulo |
process.spawn + process.spawn.monitored + process.spawn.linked |
SpawnBuilder:spawn() |
process.spawn + process.host |
SpawnBuilder:spawn_monitored() |
process.spawn + process.spawn.monitored + process.host |
SpawnBuilder:spawn_linked() |
process.spawn + process.spawn.linked + process.host |
SpawnBuilder:spawn_linked_monitored() |
process.spawn + process.spawn.monitored + process.spawn.linked + process.host |
exec() |
process.exec + process.host |
| spawn con actor/ámbito personalizado | permisos de spawn + process.security |
Errores
| Condición | Tipo |
|---|---|
| No se encontró contexto | errors.INTERNAL |
| Contexto de frame no encontrado | errors.INTERNAL |
| Argumentos requeridos faltantes | errors.INVALID |
Prefijo de tema reservado (@) |
errors.INVALID |
| El destino no es ni un PID ni un nombre registrado | errors.NOT_FOUND |
| Nombre no registrado | errors.NOT_FOUND |
| Permiso denegado | errors.PERMISSION_DENIED |
| Nombre ya registrado | errors.ALREADY_EXISTS |
Consulta Manejo de errores para trabajar con errores.
Véase también
- Canales - Coordinación de corrutinas dentro del proceso
- Cola de mensajes - Mensajería basada en colas
- Funciones - Invocación de funciones
- Supervisión - Gestión del ciclo de vida de procesos
- Clúster - Ámbitos de nombres y nombres en todo el clúster