Pular para o conteúdo

Gerenciamento de Processos

Crie, monitore e comunique-se com processos filhos. Implementa padrões de modelo de atores com passagem de mensagens, supervisão e gerenciamento de ciclo de vida.

A variável global process está sempre disponível — não requer require() nem precisa aparecer em modules:.

Obter o ID do frame atual ou ID do processo:

local frame_id = process.id() -- Identificador da cadeia de chamadas
local pid = process.pid() -- ID do processo

Enviar mensagem(s) para um processo por PID ou nome registrado:

local ok, err = process.send(destination, topic, ...)
ParâmetroTipoDescrição
destinationstringPID ou nome registrado
topicstringNome do tópico (não pode começar com @)
...anyValores do payload

Permissão: process.send no PID de destino

-- Spawn básico
local pid, err = process.spawn(id, host, ...)
-- Com monitoramento (receber eventos EXIT)
local pid, err = process.spawn_monitored(id, host, ...)
-- Com link (receber LINK_DOWN em saída anormal)
local pid, err = process.spawn_linked(id, host, ...)
-- Ambos linked e monitored
local pid, err = process.spawn_linked_monitored(id, host, ...)
ParâmetroTipoDescrição
idstringID fonte do processo (ex: "app.workers:handler")
hoststringID do host (ex: "app:processes")
...anyArgumentos passados para o processo criado

Permissões:

  • process.spawn no id do processo
  • process.host no id do host
  • process.spawn.monitored no id do processo (para variantes monitored)
  • process.spawn.linked no id do processo (para variantes linked)
-- Terminar forçadamente um processo
local ok, err = process.terminate(destination)
-- Solicitar cancelamento gracioso com motivo opcional
local ok, err = process.cancel(destination, "encerrando")
ParâmetroTipoDescrição
destinationstringPID ou nome registrado
reasonstringMotivo opcional entregue ao alvo

Permissões: process.terminate, process.cancel no PID de destino

Monitorar ou linkar a um processo existente:

-- Monitoramento: receber eventos EXIT quando o alvo sair
local ok, err = process.monitor(destination)
local ok, err = process.unmonitor(destination)
-- Link: bidirecional, receber LINK_DOWN em saída anormal
local ok, err = process.link(destination)
local ok, err = process.unlink(destination)

Permissões: process.monitor, process.unmonitor, process.link, process.unlink no PID de destino

local options = process.get_options()
local ok, err = process.set_options({trap_links = true})
CampoTipoDescrição
trap_linksbooleanSe eventos LINK_DOWN são entregues ao channel de eventos

Obter channels para receber mensagens e eventos de ciclo de vida:

local inbox = process.inbox() -- Objetos Message do tópico @inbox
local events = process.events() -- Eventos de ciclo de vida do tópico @events
ConstanteDescrição
process.event.CANCELCancelamento solicitado
process.event.EXITProcesso monitorado saiu
process.event.LINK_DOWNProcesso linked terminou anormalmente
CampoTipoDescrição
kindstringConstante de tipo de evento
fromstringPID de origem
resultanyPara EXIT: o valor retornado (presente em saída normal)
erroranyPara EXIT: o erro (presente em saída anormal)
reasonstringPara CANCEL: motivo pelo qual o processo está sendo cancelado

Inscrever-se em tópicos customizados:

local ch = process.listen(topic, options)
process.unlisten(ch)
ParâmetroTipoDescrição
topicstringNome do tópico (não pode começar com @)
options.messagebooleanSe true, recebe objetos Message; se false, payloads raw

Ao receber do inbox ou com {message = true}:

local msg = inbox:receive()
msg:topic() -- string: nome do tópico
msg:from() -- string|nil: PID do remetente
msg:payload() -- Payload: wrapper (chame :data() para extrair)
msg:payload():data() -- any: valor real do payload

Criar um processo, aguardar seu resultado e retornar:

local result, err = process.exec(id, host, ...)

Permissões: process.exec no id do processo, process.host no id do host

Atualizar o processo atual para uma nova definição preservando o PID:

-- Upgrade para nova versão, passando estado
process.upgrade(id, ...)
-- Manter mesma definição, re-executar com novo estado
process.upgrade(nil, preserved_state)

Criar um spawner com contexto customizado para processos filhos:

local spawner = process.with_context({request_id = "123"})

Permissão: process.context em “context”

process.with_options(options) cria um spawner que carrega opções de tempo de spawn (ex: um seletor de rede) em vez de valores de contexto:

local spawner = process.with_options({network = "app:tor_proxy"})
OpçãoTipoDescrição
networkstringID de registro de uma entrada network.* para as conexões de saída do processo filho

Permissão: process.context em “context”; selecionar uma rede requer adicionalmente network.select nesse ID de rede.

SpawnBuilder é imutável - cada método retorna uma nova instância:

spawner:with_context(values) -- Adicionar valores de contexto
spawner:with_actor(actor) -- Definir ator de segurança
spawner:with_scope(scope) -- Definir escopo de segurança
spawner:with_name(name) -- Definir nome do processo
spawner:with_message(topic, ...) -- Enfileirar mensagem para enviar após spawn
spawner:with_options(options) -- Mesclar opções de spawn (ex. network)

Permissão: process.security em “security” para :with_actor() e :with_scope()

spawner:spawn(id, host, ...)
spawner:spawn_monitored(id, host, ...)
spawner:spawn_linked(id, host, ...)
spawner:spawn_linked_monitored(id, host, ...)

Mesmas permissões que funções spawn do módulo.

Registrar um processo sob um nome e alcançá-lo por esse nome em vez de seu PID. Qualquer função que aceite um destination (send, terminate, cancel, monitor, link, …) aceita um nome registrado no lugar de um PID.

local ok, err = process.registry.register(name) -- self, escopo local
local pid, err = process.registry.lookup(name)
local ok, err = process.registry.unregister(name)

O argumento opcional scope seleciona a garantia de consistência do nome. O padrão é LOCAL. Os quatro escopos e suas garantias estão descritos no Guia de Cluster; resumidamente:

ConstanteVisibilidadeGarantia
process.registry.LOCALapenas este nóInstantâneo, local ao nó
process.registry.EVENTUALtodo o clusterEventualmente consistente (gossip)
process.registry.CONSISTENTtodo o clusterSingleton linearizável (Raft)
process.registry.STRONGtodo o clusterConsistente + todos os nós ativos reconhecem

Em um nó standalone apenas LOCAL é significativo; os escopos de cluster requerem clustering.

local ok, err = process.registry.register(name, pid, scope)
ParâmetroTipoObrigatórioPadrãoDescrição
namestringsimNome a registrar
pidstringnãoselfPID a registrar; padrão é o processo chamador
scopenumbernãoLOCALUm dos constantes de escopo acima

Retorna true em caso de sucesso, ou nil, error em caso de falha. Conflitos (nome já registrado para um PID diferente sob um escopo de cluster) retornam errors.ALREADY_EXISTS. Registrar o mesmo nome para o mesmo PID é idempotente. Um registro STRONG bloqueia até que todos os nós ativos reconheçam ou o prazo da reserva expire; em timeout retorna um erro.

Registrar em nome de um PID diferente requer adicionalmente a permissão process.registry.foreign no PID alvo.

local pid, err = process.registry.lookup(name)

Retorna a string PID registrada, ou nil, error com tipo errors.NOT_FOUND quando o nome não está registrado.

local ok, err = process.registry.unregister(name, scope)

scope tem padrão LOCAL e deve corresponder ao escopo sob o qual o nome foi registrado. Para CONSISTENT e STRONG, o processo proprietário é o autorizado a cancelar o registro; cancelar o registro de um nome pertencente a outro PID retorna false. Nomes também são liberados automaticamente quando o processo proprietário sai (e, para escopos de cluster, quando seu nó parte), portanto o unregister explícito é para liberação antecipada.

Permissões controlam o que um processo chamador pode fazer. Todas as verificações usam o contexto de segurança do chamador (ator) contra o recurso alvo.

Políticas podem permitir/negar baseado em:

  • Actor: O principal de segurança fazendo a requisição
  • Action: A operação sendo realizada (ex: process.send)
  • Resource: O alvo (PID, id do processo, id do host ou nome)
  • Attributes: Contexto adicional incluindo pid (ID do processo do chamador)
PermissãoFunçõesRecurso
process.spawnspawn*()id do processo
process.spawn.monitoredspawn_monitored(), spawn_linked_monitored()id do processo
process.spawn.linkedspawn_linked(), spawn_linked_monitored()id do processo
process.hostspawn*(), exec()id do host
process.sendsend()PID de destino
process.execexec()id do processo
process.terminateterminate()PID de destino
process.cancelcancel()PID de destino
process.monitormonitor()PID de destino
process.unmonitorunmonitor()PID de destino
process.linklink()PID de destino
process.unlinkunlink()PID de destino
process.contextwith_context()”context”
process.security:with_actor(), :with_scope()”security”
process.registry.registerregistry.register()nome
process.registry.unregisterregistry.unregister()nome
process.registry.foreignregistry.register()PID de destino

Escopos de nome de cluster são autorizados por variantes com sufixo de escopo dessas ações (process.registry.register.eventual, .consistent, .strong e as ações unregister correspondentes), de modo que uma política pode conceder nomeação local separadamente de nomeação em todo o cluster.

Algumas operações requerem múltiplas permissões:

OperaçãoPermissões Requeridas
spawn()process.spawn + process.host
spawn_monitored()process.spawn + process.spawn.monitored + process.host
spawn_linked()process.spawn + process.spawn.linked + process.host
spawn_linked_monitored()process.spawn + process.spawn.monitored + process.spawn.linked + process.host
exec()process.exec + process.host
spawn com ator/escopo customizadopermissões de spawn + process.security
CondiçãoTipo
Contexto não encontradoerrors.INVALID
Contexto de frame não encontradoerrors.INVALID
Argumentos requeridos ausenteserrors.INVALID
Prefixo de tópico reservado (@)errors.INVALID
Formato de duração inválidoerrors.INVALID
Nome não registradoerrors.NOT_FOUND
Permissão negadaerrors.PERMISSION_DENIED
Nome já registradoerrors.ALREADY_EXISTS

Veja Error Handling para trabalhar com erros.