콘텐츠로 이동

엔트리 핸들러

엔트리 핸들러는 종류별로 레지스트리 엔트리를 처리합니다. 엔트리가 추가, 업데이트 또는 삭제되면 레지스트리는 매칭하는 핸들러에 이벤트를 디스패치합니다.

레지스트리는 종류 패턴에서 핸들러로의 맵을 유지합니다. 엔트리가 변경되면:

  1. 레지스트리가 이벤트 발생 (entry.create, entry.update, entry.delete)
  2. 핸들러 레지스트리가 등록된 패턴에 대해 엔트리 종류 매칭
  3. 매칭하는 핸들러가 엔트리를 받음
  4. 핸들러가 엔트리를 처리하거나 거부

핸들러는 패턴을 사용하여 구독합니다:

패턴매칭
http.service정확한 매칭만
http.*http.service, http.router, http.endpoint
function.*function.lua, function.lua.bc

핸들러는 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에서 에러를 반환하면 엔트리가 거부됩니다.

타입목적거부 가능
리스너기본 핸들러
옵저버보조 핸들러 (로깅, 메트릭)아니오
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
},
})
}

엔트리 데이터를 언마샬하려면 internal/entryentry.DecodeEntryConfig를 사용합니다. 이 헬퍼는 internal/ 아래에 있으므로 런타임 모듈 내부에서만 임포트할 수 있습니다. 트리 외부 확장은 패턴을 복사하거나 트랜스코더를 직접 사용해야 합니다:

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. 엔트리에서 IDMeta 채움
  3. 구현되어 있으면 InitDefaults() 호출
  4. 구현되어 있으면 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를 호출합니다.