Обработчики записей
Обработчики записей
Заголовок раздела «Обработчики записей»Обработчики записей обрабатывают записи реестра по kind. При добавлении, обновлении или удалении записей реестр диспатчит события соответствующим обработчикам.
Принцип работы
Заголовок раздела «Принцип работы»Реестр поддерживает карту паттернов kind к обработчикам. При изменении записи:
- Реестр отправляет событие (
entry.create,entry.update,entry.delete) - Реестр обработчиков сопоставляет kind записи с зарегистрированными паттернами
- Соответствующие обработчики получают запись
- Обработчики обрабатывают или отклоняют запись
Паттерны kind
Заголовок раздела «Паттерны kind»Обработчики подписываются с использованием паттернов:
| Паттерн | Совпадает |
|---|---|
http.service | Только точное совпадение |
http.* | http.service, http.router, http.endpoint |
function.* | function.lua, function.lua.bc |
Интерфейс Entry Listener
Заголовок раздела «Интерфейс Entry Listener»Обработчики реализуют 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}Возврат ошибки из Add отклоняет запись.
Listener vs Observer
Заголовок раздела «Listener vs Observer»| Тип | Назначение | Может отклонить |
|---|---|---|
| Listener | Основной обработчик | Да |
| Observer | Вторичный обработчик (логирование, метрики) | Нет |
handlers.RegisterListener("http.*", httpManager)handlers.RegisterObserver("function.*", metricsCollector)Регистрация обработчиков
Заголовок раздела «Регистрация обработчиков»Регистрация обработчиков при загрузке:
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.DecodeEntryConfig из internal/entry для десериализации данных записи. Этот хелпер находится в internal/, поэтому импортируется только внутри модуля runtime; расширения вне дерева должны скопировать этот шаблон или использовать транскодер напрямую:
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 } // Обработка cfg... return nil}Декодер:
- Десериализует
entry.Dataв вашу структуру конфига - Заполняет
IDиMetaиз записи - Вызывает
InitDefaults(), если реализован - Вызывает
Validate(), если реализован
Структура конфига
Заголовок раздела «Структура конфига»Конфиги записей обычно включают:
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}Поддержка транзакций
Заголовок раздела «Поддержка транзакций»Для атомарных операций над несколькими записями реализуйте TransactionListener:
type TransactionListener interface { Begin(ctx context.Context) Commit(ctx context.Context) Discard(ctx context.Context)}Реестр вызывает Begin перед обработкой пакета, затем Commit при успехе или Discard при неудаче.
См. также
Заголовок раздела «См. также»- Реестр — хранение записей
- Архитектура — последовательность загрузки