Listeners e Observers de Entradas
Listeners e observers de entradas processam mutações do registro para padrões de tipos de entrada correspondentes.
Esta é uma referência de extensão em Go. Os exemplos de registro e configuração pressupõem um componente de boot, um manager, um transcoder e um tipo de configuração da aplicação já existentes.
Como Funciona
O boot coleta listeners e observers com seus padrões de tipo. Quando uma entrada muda:
- O registro emite um evento (
entry.create,entry.update,entry.delete) - Cada wrapper de listener compara o tipo da entrada ao padrão registrado
- Os handlers correspondentes recebem a entrada
- Os handlers processam ou rejeitam a entrada
Padrões de Tipo
Os handlers se inscrevem usando padrões:
| Padrão | Corresponde |
|---|---|
http.service |
Apenas correspondência exata |
http.* |
http.service, http.router, http.endpoint |
function.** |
function.lua, function.lua.bc |
Interface EntryListener
Handlers implementam registry.EntryListener:
type EntryListener interface {
Add(ctx context.Context, entry Entry) error
Update(ctx context.Context, entry Entry) error
Delete(ctx context.Context, entry Entry) error
}
Retornar um erro de Add, Update ou Delete rejeita a operação.
Listener vs Observer
| Tipo | Propósito | Pode Rejeitar |
|---|---|---|
| Listener | Handler primário | Sim |
| Observer | Handler secundário (logging, métricas) | Não |
handlers.RegisterListener("http.*", httpManager)
handlers.RegisterObserver("function.*", metricsCollector)
Erros de observers em Add, Update e Delete são ignorados e não emitem um evento de aceitação ou rejeição. Um listener ou observer que também implemente TransactionListener participa das barreiras de transação, nas quais um erro de Begin, Commit ou Discard rejeita essa fase da transação.
Registrando Handlers
Registre handlers durante boot:
func MyService() boot.Component {
return boot.New(boot.P{
Name: "myservice",
DependsOn: []boot.Name{core.RegistryName},
Load: func(ctx context.Context) (context.Context, error) {
handlers := bootpkg.GetHandlerRegistry(ctx)
handlers.RegisterListener("myservice.*", manager)
return ctx, nil
},
})
}
Decodificando Dados de Entrada
Use entry.DecodeEntryConfig de system/entry para deserializar dados da entrada. DecodeEntryConfigFromContext pega o transcoder do contexto em vez de recebê-lo como argumento, e DecodeEntryConfigRaw pula a resolução de placeholders:
func (m *Manager) Add(ctx context.Context, ent registry.Entry) error {
cfg, err := entry.DecodeEntryConfig[ComponentConfig](ctx, m.dtt, ent)
if err != nil {
return err
}
// Process cfg...
return nil
}
O decoder:
- Resolve placeholders
${env:...}e campos companheiros*_envcontra o registro de ambiente - Deserializa
entry.Dataem sua struct de config - Popula
IDeMetada entrada quando a struct os deixa vazios - Chama
InitDefaults()se implementado - Chama
Validate()se implementado
Estrutura de configuração
As configurações de entrada normalmente incluem:
type ComponentConfig struct {
ID registry.ID `json:"id"`
Meta attrs.Bag `json:"meta"`
Name string `json:"name"`
Timeout int `json:"timeout,omitempty"`
}
func (c *ComponentConfig) InitDefaults() {
if c.Timeout == 0 {
c.Timeout = 30
}
}
func (c *ComponentConfig) Validate() error {
if c.Name == "" {
return fmt.Errorf("name is required")
}
return nil
}
Suporte a Transações
Para operações atômicas através de múltiplas entradas, implemente TransactionListener:
type TransactionListener interface {
Begin(ctx context.Context) error
Commit(ctx context.Context) error
Discard(ctx context.Context) error
}
O registro chama Begin antes de processar um lote e, depois, Commit em caso de sucesso ou Discard em caso de falha.
Consulte também
- Registro — Armazenamento de entradas
- Arquitetura — Sequência de boot