Arquitetura
Wippy é um sistema em camadas construído em Go. Componentes inicializam em ordem de dependência, comunicam-se através de um barramento de eventos e executam processos Lua via um scheduler de work-stealing.
Camadas
| Camada | Componentes |
|---|---|
| Aplicação | Processos Lua, funções, workflows |
| Runtime | Motor Lua (gopher-lua), 50+ módulos |
| Serviços | HTTP, Queue, Storage, Temporal |
| Sistema | Topology, Factory, Functions, Contracts |
| Núcleo | Scheduler, Registry, Dispatcher, EventBus, Relay |
| Infraestrutura | AppContext, Logger, Transcoder |
Cada camada depende apenas das camadas abaixo dela. A camada Núcleo fornece primitivas fundamentais, enquanto Serviços constroem abstrações de nível mais alto.
Sequência de Boot
A inicialização da aplicação prossegue em quatro fases.
Fase 1: Infraestrutura
Cria infraestrutura central antes de qualquer componente carregar:
| Componente | Propósito |
|---|---|
| AppContext | Dicionário selado para referências de componentes |
| EventBus | Pub/sub para comunicação entre componentes |
| Transcoder | Serialização de payload (JSON, YAML, Lua) |
| Logger | Logging estruturado com streaming de eventos |
| Relay | Roteamento de mensagens (Node, Router, Mailbox) |
Fase 2: Carregamento de Componentes
O Loader resolve dependências via ordenação topológica e carrega componentes nível por nível. Componentes no mesmo nível carregam em paralelo.
Os componentes core (PIDGen, Dispatcher, Registry, Finder, Supervisor) inicializam primeiro, seguidos pelos componentes de sistema (Topology, Lifecycle, Factory, Functions, Contracts). Os níveis concretos são calculados em tempo de execução a partir do grafo de dependências, então a ordenação se adapta à medida que componentes são adicionados ou removidos.
Cada componente se anexa ao contexto durante Load, disponibilizando serviços para componentes dependentes.
Fase 3: Ativação
Após todos os componentes carregarem:
- Congelar Dispatcher - Bloqueia registro de handlers de comando para lookups sem lock
- Selar AppContext - Nenhuma escrita mais permitida, habilita leituras sem lock
- Iniciar Componentes - Chama
Start()em cada componente com interfaceStarter
Fase 4: Carregamento de Entradas
Entradas do registro (de arquivos YAML) são carregadas e validadas:
- Entradas parseadas dos arquivos do projeto
- Estágios de pipeline transformam entradas (override, link, bytecode)
- Serviços marcados
auto_start: truecomeçam a executar - Supervisor monitora serviços registrados
Componentes
Componentes são serviços Go que participam do ciclo de vida da aplicação.
Fases do Ciclo de Vida
| Fase | Método | Propósito |
|---|---|---|
| Load | Load(ctx) (ctx, error) |
Inicializar e anexar ao contexto |
| Start | Start(ctx) error |
Iniciar operação ativa |
| Stop | Stop(ctx) error |
Shutdown gracioso |
Componentes declaram dependências. O loader constrói um grafo acíclico direcionado e executa em ordem topológica. Shutdown ocorre em ordem reversa.
Componentes Padrão
| Componente | Dependências | Propósito |
|---|---|---|
| PIDGen | nenhuma | Geração de ID de processo |
| Dispatcher | PIDGen | Despacho de handlers de comando |
| Registry | Dispatcher | Armazenamento e versionamento de entradas |
| Finder | Registry | Lookup e busca de entradas |
| Supervisor | Registry | Políticas de reinício de serviço |
| Topology | Supervisor | Árvore pai/filho de processos |
| Lifecycle | Topology | Gerenciamento de ciclo de vida de serviços |
| Factory | Lifecycle | Spawn de processos |
| Functions | Factory | Chamadas de funções stateless |
Event Bus
Pub/sub assíncrono para comunicação entre componentes.
Design
- Goroutine única de dispatcher processa todos os eventos
- Entrega de ações baseada em fila previne bloqueio de publishers
- Pattern matching suporta tópicos exatos e wildcards (
*) - Ciclo de vida baseado em contexto vincula inscrições a cancelamento
Fluxo de Eventos
sequenceDiagram
participant P as Publisher
participant B as EventBus
participant S as Subscribers
P->>B: Publish(topic, data)
B->>B: Match patterns
B->>S: Queue action
S->>S: Execute callback
Tópicos Comuns
Os tópicos têm o formato <system>:<kind>. Os sistemas integrados publicam:
| Sistema | Kind | Propósito |
|---|---|---|
registry |
entry.create, entry.update, entry.delete, entry.accept, entry.reject |
Mutações de entradas |
registry |
registry.begin, registry.commit, registry.discard |
Limites de transação |
process |
factory.register, factory.delete, factory.accept, factory.reject |
Registro de factory para tipos de processo |
supervisor |
service.register, service.remove, service.update, service.start, service.stop |
Ciclo de vida de serviço |
Registry
Armazenamento versionado para definições de entradas.
Recursos
- Estado Versionado - Cada mutação cria nova versão
- Histórico - Histórico em SQLite para trilha de auditoria
- Observação - Observar entradas específicas para mudanças
- Orientado a Eventos - Publica eventos em mutações
Ciclo de Vida de Entrada
flowchart LR
YAML[YAML Files] --> Parser
Parser --> Stages[Pipeline Stages]
Stages --> Registry
Registry --> Validation
Validation --> Active
Estágios de pipeline transformam entradas:
| Estágio | Propósito |
|---|---|
| Override | Aplicar overrides de config |
| Disable | Remover entradas por padrão |
| Link | Resolver requirements e dependências |
| Bytecode | Compilar Lua para bytecode |
| EmbedFS | Coletar entradas de filesystem |
Relay
Roteamento de mensagens entre processos através de nós.
Roteamento de Três Níveis
flowchart LR
subgraph Router
Local[Local Node] --> Peer[Peer Nodes]
Peer --> Inter[Internode]
end
Local -.- L[Same process]
Peer -.- P[Same cluster]
Inter -.- I[Remote]
- Local - Entrega direta dentro do mesmo nó
- Peer - Encaminhar para nós peer no cluster
- Internode - Rotear para nós remotos via rede
Mailbox
Cada nó tem uma mailbox com pool de workers:
- Hashing FNV-1a atribui remetentes a workers
- Preserva ordenação de mensagens por remetente
- Workers processam mensagens concorrentemente
- Back-pressure quando fila enche
AppContext
Dicionário selado para referências de componentes.
| Propriedade | Comportamento |
|---|---|
| Antes de selar | Escritas de thread única durante a inicialização |
| Após selar | Leituras sem lock, panic em escrita |
| Chaves duplicadas | Panic |
| Type safety | Funções getter tipadas |
Componentes anexam serviços durante a fase Load. Após boot completar, AppContext é selado para performance ótima de leitura.
Shutdown
Shutdown gracioso prossegue em ordem reversa de dependência:
- SIGINT/SIGTERM aciona shutdown
- Supervisor para serviços gerenciados
- Componentes com interface
StopperrecebemStop() - Limpeza de infraestrutura
Segundo sinal força saída imediata.
Veja Também
- Scheduler - Execução de processos
- Event Bus - Sistema pub/sub
- Registry - Gerenciamento de estado
- Command Dispatch - Tratamento de yields