Entry-Listener und -Observer
Entry-Listener und -Observer verarbeiten Registry-Mutationen für passende Entry-Kind-Muster.
Diese Seite ist eine Go-Erweiterungsreferenz. Die Ausschnitte für Registrierung und Konfiguration setzen eine vorhandene Boot-Komponente, einen Manager, einen Transcoder und einen Anwendungskonfigurationstyp voraus.
Funktionsweise
Boot sammelt Listener und Observer samt ihren Kind-Mustern. Wenn sich ein Eintrag ändert:
- Registry emittiert Event (
entry.create,entry.update,entry.delete) - Jeder Listener-Wrapper gleicht den Entry-Kind mit seinem registrierten Muster ab
- Passende Handler erhalten den Eintrag
- Handler verarbeiten oder lehnen den Eintrag ab
Kind-Patterns
Handler subscriben mit Patterns:
| Muster | Treffer |
|---|---|
http.service |
Nur exakter Match |
http.* |
http.service, http.router, http.endpoint |
function.** |
function.lua, function.lua.bc |
EntryListener-Interface
Handler implementieren 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
}
Gibt Add, Update oder Delete einen Fehler zurück, wird die jeweilige Operation abgelehnt.
Listener vs Observer
| Typ | Zweck | Kann ablehnen |
|---|---|---|
| Listener | Primärer Handler | Ja |
| Observer | Sekundärer Handler (Logging, Metriken) | Nein |
handlers.RegisterListener("http.*", httpManager)
handlers.RegisterObserver("function.*", metricsCollector)
Fehler eines Observers aus Add, Update und Delete werden ignoriert und erzeugen weder ein Accept- noch ein Reject-Event. Implementiert ein Listener oder Observer zusätzlich TransactionListener, nimmt er an Transaktionsbarrieren teil. Ein Fehler aus Begin, Commit oder Discard lehnt die jeweilige Transaktionsphase ab.
Handler registrieren
Handler während Boot registrieren:
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
},
})
}
Entry-Daten dekodieren
Verwenden Sie entry.DecodeEntryConfig aus system/entry, um Entry-Daten zu unmarshallen. DecodeEntryConfigFromContext nimmt den Transcoder aus dem Kontext statt als Argument, und DecodeEntryConfigRaw überspringt die Platzhalterauflösung:
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
}
Der Decoder:
- Löst
${env:...}-Platzhalter und*_env-Begleitfelder gegen die Environment-Registry auf - Unmarshalled
entry.Datain Ihre Config-Struct - Befüllt
IDundMetaaus dem Entry, wenn die Struct sie leer lässt - Ruft
InitDefaults()auf wenn implementiert - Ruft
Validate()auf wenn implementiert
Config-Struktur
Entry-Configs beinhalten typischerweise:
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
}
Transaktions-Support
Für atomare Operationen über mehrere Einträge implementieren Sie TransactionListener:
type TransactionListener interface {
Begin(ctx context.Context) error
Commit(ctx context.Context) error
Discard(ctx context.Context) error
}
Die Registry ruft Begin vor Verarbeitung eines Batches auf, dann Commit bei Erfolg oder Discard bei Fehler.
Siehe auch
- Registry – Speicherung von Einträgen
- Architektur – Boot-Sequenz