iop/apps/node/internal/adapters/registry.go
toki f01c7e5ecd refactor(node): CLI 실행 경계를 정리한다
터미널 세션 core와 CLI mode executor 경계를 분리해 후속 remote terminal bridge가 재사용할 내부 실행 기반을 만든다.

adapter 기본값과 vLLM experimental surface도 명시해 production 실행 경로가 mock fallback이나 미구현 실행으로 숨지 않게 한다.
2026-06-06 14:57:49 +09:00

97 lines
2.6 KiB
Go

package adapters
import (
"context"
"fmt"
"iop/apps/node/internal/runtime"
)
// LifecycleAdapter is an optional interface for adapters that need start/stop lifecycle management.
type LifecycleAdapter interface {
Start(ctx context.Context) error
Stop(ctx context.Context) error
}
// Registry holds all registered adapters by name.
type Registry struct {
adapters map[string]runtime.Adapter
order []string // insertion order for lifecycle and diagnostics
}
func NewRegistry() *Registry {
return &Registry{adapters: make(map[string]runtime.Adapter)}
}
// Register adds an adapter. The first registered adapter becomes the default.
func (r *Registry) Register(a runtime.Adapter) {
name := a.Name()
if _, exists := r.adapters[name]; !exists {
r.order = append(r.order, name)
}
r.adapters[name] = a
}
func (r *Registry) Get(name string) (runtime.Adapter, bool) {
a, ok := r.adapters[name]
return a, ok
}
// All returns all registered adapters in registration order.
func (r *Registry) All() []runtime.Adapter {
out := make([]runtime.Adapter, 0, len(r.order))
for _, name := range r.order {
out = append(out, r.adapters[name])
}
return out
}
// MustGet returns the adapter or panics — useful during bootstrap validation.
func (r *Registry) MustGet(name string) runtime.Adapter {
a, ok := r.Get(name)
if !ok {
panic(fmt.Sprintf("adapter %q not registered", name))
}
return a
}
// Start calls Start on all registered LifecycleAdapters in registration order.
// On failure, already-started adapters are stopped in reverse order before returning.
func (r *Registry) Start(ctx context.Context) error {
started := make([]string, 0, len(r.order))
for _, name := range r.order {
lc, ok := r.adapters[name].(LifecycleAdapter)
if !ok {
continue
}
if err := lc.Start(ctx); err != nil {
for i := len(started) - 1; i >= 0; i-- {
if startedLC, ok := r.adapters[started[i]].(LifecycleAdapter); ok {
_ = startedLC.Stop(context.Background())
}
}
return fmt.Errorf("adapter %q start: %w", name, err)
}
started = append(started, name)
}
return nil
}
// Stop calls Stop on all registered LifecycleAdapters in reverse registration order.
// All adapters are stopped even if some fail; the first error is returned.
func (r *Registry) Stop(ctx context.Context) error {
var firstErr error
for i := len(r.order) - 1; i >= 0; i-- {
name := r.order[i]
lc, ok := r.adapters[name].(LifecycleAdapter)
if !ok {
continue
}
if err := lc.Stop(ctx); err != nil {
if firstErr == nil {
firstErr = fmt.Errorf("adapter %q stop: %w", name, err)
}
}
}
return firstErr
}