Pular para o conteúdo

Supervisão

O supervisor gerencia ciclos de vida de serviços, tratando ordenação de inicialização, reinicializações automáticas e encerramento gracioso. Serviços com auto_start: true são iniciados quando a aplicação inicia.

Serviços se registram com o supervisor usando um bloco lifecycle. Para processos, use process.service para encapsular uma definição de processo:

# Definição de processo (o código)
- name: worker_process
kind: process.lua
source: file://worker.lua
method: main
# Serviço supervisionado (encapsula o processo com gerenciamento de ciclo de vida)
- name: worker
kind: process.service
process: app:worker_process
host: app:processes
lifecycle:
auto_start: true
start_timeout: 30s
stop_timeout: 10s
stable_threshold: 5s
depends_on:
- app:database
restart:
initial_delay: 2s
max_delay: 60s
max_attempts: 10
CampoPadrãoDescrição
auto_startfalseInicia automaticamente quando supervisor inicia
start_timeout10sTempo máximo permitido para inicialização
stop_timeout10sTempo máximo para encerramento gracioso
stable_threshold5sTempo de execução antes do serviço ser considerado estável
depends_on[]Serviços que devem estar executando primeiro

O supervisor resolve dependências de duas fontes:

  1. Dependências explícitas declaradas em depends_on
  2. Dependências extraídas do registro de referências de entradas (ex: database: app:db na sua configuração)
graph LR
A[HTTP Server] --> B[Router]
B --> C[Handler Function]
C --> D[Database]
C --> E[Cache]

Dependências iniciam antes dos dependentes. Se o Serviço C depende de A e B, ambos A e B devem alcançar o estado Running antes de C iniciar.

Você não precisa declarar entradas de infraestrutura como bancos de dados em depends_on. O supervisor extrai automaticamente dependências de referências do registro na configuração da sua entrada.

Quando um serviço falha, o supervisor tenta novamente com backoff exponencial:

lifecycle:
restart:
initial_delay: 1s # Espera da primeira tentativa
max_delay: 90s # Limite máximo de delay
backoff_factor: 2.0 # Multiplicador de delay por tentativa
jitter: 0.1 # +/-10% de randomização
max_attempts: 0 # 0 = tentativas infinitas
TentativaDelay BaseCom Jitter (+/-10%)
11s0.9s - 1.1s
22s1.8s - 2.2s
34s3.6s - 4.4s
48s7.2s - 8.8s
N90s81s - 99s (limitado)

Quando um serviço executa por mais tempo que stable_threshold, o contador de tentativas reseta. Isso previne que falhas transitórias escalem delays permanentemente.

Estes erros param tentativas de retry:

  • Cancelamento de contexto
  • Requisição de terminação explícita
  • Erros marcados como não-retentáveis

Serviços podem executar com uma identidade de segurança específica:

# Definição de processo
- name: admin_worker_process
kind: process.lua
source: file://admin_worker.lua
method: main
# Serviço supervisionado com contexto de segurança
- name: admin_worker
kind: process.service
process: app:admin_worker_process
host: app:processes
lifecycle:
auto_start: true
security:
actor:
id: "service:admin-worker"
meta:
role: admin
groups:
- app:admin_policies
policies:
- app:data_access

O contexto de segurança define:

CampoDescrição
actor.idString de identidade para este serviço
actor.metaMetadados chave-valor (role, permissões, etc.)
groupsGrupos de políticas a aplicar
policiesPolíticas individuais a aplicar

Código executando no serviço herda este contexto de segurança. O módulo security pode então verificar permissões:

local security = require("security")
if security.can("delete", "users") then
-- permitido
end
Quando nenhum contexto de segurança está configurado, o serviço executa sem um ator. No modo estrito (padrão), verificações de segurança falham. Configure um contexto de segurança para serviços que precisam de autorização.
stateDiagram-v2
[*] --> Inactive
Inactive --> Starting
Starting --> Running
Running --> Stopping
Stopping --> Stopped
Stopped --> [*]
Running --> Failed
Starting --> Failed
Failed --> Starting : retry

O supervisor transiciona serviços através destes estados:

EstadoDescrição
InactiveRegistrado mas não iniciado
StartingInicialização em progresso
RunningOperando normalmente
StoppingEncerramento gracioso em progresso
StoppedTerminado de forma limpa
FailedErro ocorreu, pode tentar novamente

Inicialização: Dependências primeiro, depois dependentes. Serviços no mesmo nível de dependência podem iniciar em paralelo.

Encerramento: Dependentes primeiro, depois dependências. Isso garante que serviços dependentes terminem antes de suas dependências pararem.

Inicialização: database -> cache -> handler -> http_server
Encerramento: http_server -> handler -> cache -> database