엔트리 핸들러
엔트리 핸들러
섹션 제목: “엔트리 핸들러”엔트리 핸들러는 종류별로 레지스트리 엔트리를 처리합니다. 엔트리가 추가, 업데이트 또는 삭제되면 레지스트리는 매칭하는 핸들러에 이벤트를 디스패치합니다.
작동 방식
섹션 제목: “작동 방식”레지스트리는 종류 패턴에서 핸들러로의 맵을 유지합니다. 엔트리가 변경되면:
- 레지스트리가 이벤트 발생 (
entry.create,entry.update,entry.delete) - 핸들러 레지스트리가 등록된 패턴에 대해 엔트리 종류 매칭
- 매칭하는 핸들러가 엔트리를 받음
- 핸들러가 엔트리를 처리하거나 거부
종류 패턴
섹션 제목: “종류 패턴”핸들러는 패턴을 사용하여 구독합니다:
| 패턴 | 매칭 |
|---|---|
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에서 에러를 반환하면 엔트리가 거부됩니다.
리스너 vs 옵저버
섹션 제목: “리스너 vs 옵저버”| 타입 | 목적 | 거부 가능 |
|---|---|---|
| 리스너 | 기본 핸들러 | 예 |
| 옵저버 | 보조 핸들러 (로깅, 메트릭) | 아니오 |
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/entry의 entry.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}디코더는:
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를 호출합니다.