package plugin import ( "fmt" "sync" ) // Registry is a thread-safe map that manages plugin registration. type Registry struct { mu sync.RWMutex plugins map[string]Plugin states map[string]PluginState } // NewRegistry creates a new empty plugin registry. func NewRegistry() *Registry { return &Registry{ plugins: make(map[string]Plugin), states: make(map[string]PluginState), } } // Register adds a plugin to the registry. func (r *Registry) Register(p Plugin) error { r.mu.Lock() defer r.mu.Unlock() name := p.Name() if _, exists := r.plugins[name]; exists { return fmt.Errorf("plugin %q is already registered", name) } r.plugins[name] = p r.states[name] = StateRegistered return nil } // Unregister removes a plugin from the registry. func (r *Registry) Unregister(name string) error { r.mu.Lock() defer r.mu.Unlock() if _, exists := r.plugins[name]; !exists { return fmt.Errorf("plugin %q is not registered", name) } delete(r.plugins, name) delete(r.states, name) return nil } // Get retrieves a plugin by name. func (r *Registry) Get(name string) (Plugin, bool) { r.mu.RLock() defer r.mu.RUnlock() p, ok := r.plugins[name] return p, ok } // List returns all registered plugins. func (r *Registry) List() []Plugin { r.mu.RLock() defer r.mu.RUnlock() plugins := make([]Plugin, 0, len(r.plugins)) for _, p := range r.plugins { plugins = append(plugins, p) } return plugins } // State returns the lifecycle state of a registered plugin. func (r *Registry) State(name string) PluginState { r.mu.RLock() defer r.mu.RUnlock() if state, ok := r.states[name]; ok { return state } return StateUnknown } // SetState updates the lifecycle state of a registered plugin. func (r *Registry) SetState(name string, state PluginState) { r.mu.Lock() defer r.mu.Unlock() if _, ok := r.plugins[name]; ok { r.states[name] = state } } // Count returns the number of registered plugins. func (r *Registry) Count() int { r.mu.RLock() defer r.mu.RUnlock() return len(r.plugins) }