跳转到内容

Entry Handler

Entry handler 按 kind 处理 registry entry。当 entry 被添加、更新或删除时,registry 将事件分发给匹配的 handler。

Registry 维护 kind 模式到 handler 的映射。当 entry 变更时:

  1. Registry 发出事件(entry.create, entry.update, entry.delete
  2. Handler registry 将 entry kind 与注册的模式匹配
  3. 匹配的 handler 接收 entry
  4. Handler 处理或拒绝 entry

Handler 使用模式订阅:

模式匹配
http.service仅完全匹配
http.*http.service, http.router, http.endpoint
function.*function.lua, function.lua.bc

Handler 实现 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 返回错误会拒绝该 entry。

类型用途可以拒绝
Listener主要 handler
Observer次要 handler(日志、指标)
handlers.RegisterListener("http.*", httpManager)
handlers.RegisterObserver("function.*", metricsCollector)

在启动期间注册 handler:

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
},
})
}

使用 internal/entry 中的 entry.DecodeEntryConfig 反序列化 entry 数据。该辅助函数位于 internal/ 下,因此只能在 runtime 模块内部导入;树外扩展必须复制该模式或直接使用 transcoder:

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
}

解码器:

  1. entry.Data 反序列化到你的配置结构体
  2. 从 entry 填充 IDMeta
  3. 如果实现了 InitDefaults() 则调用
  4. 如果实现了 Validate() 则调用

Entry 配置通常包括:

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
}

对于跨多个 entry 的原子操作,实现 TransactionListener

type TransactionListener interface {
Begin(ctx context.Context)
Commit(ctx context.Context)
Discard(ctx context.Context)
}

Registry 在处理批次前调用 Begin,然后在成功时调用 Commit 或在失败时调用 Discard