エントリハンドラ
エントリハンドラはkindごとにレジストリエントリを処理します。エントリが追加、更新、削除されると、レジストリがマッチするハンドラにイベントをディスパッチします。
動作原理
レジストリはkindパターンからハンドラへのマップを維持。エントリが変更されると:
- レジストリがイベントを発行(
entry.create、entry.update、entry.delete) - ハンドラレジストリがエントリkindを登録されたパターンとマッチング
- マッチするハンドラがエントリを受信
- ハンドラがエントリを処理または拒否
Kindパターン
ハンドラはパターンを使用してサブスクライブ:
| パターン | マッチ |
|---|---|
http.service |
完全一致のみ |
http.* |
http.service、http.router、http.endpoint |
function.* |
function.lua、function.lua.bc |
EntryListenerインターフェース
ハンドラは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と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を使用してエントリデータをアンマーシャル:
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()を呼び出し
Config構造体
エントリ設定は通常以下を含む:
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を呼び出します。